Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/in_app_purchase/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## 0.2.1+1

* Android: Do not register if Activity is null.
* Android: Require Activity only to use launchBillingFlow method.

## 0.2.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static io.flutter.plugins.inapppurchase.Translator.fromSkuDetailsList;

import android.app.Activity;
import android.content.Context;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
Expand All @@ -35,8 +36,9 @@
public class InAppPurchasePlugin implements MethodCallHandler {
private static final String TAG = "InAppPurchasePlugin";
private @Nullable BillingClient billingClient;
private BillingClientFactory factory;
private final Activity activity;
private final BillingClientFactory factory;
private final Registrar registrar;
private final Context applicationContext;
private final MethodChannel channel;

@VisibleForTesting
Expand Down Expand Up @@ -65,21 +67,18 @@ static final class MethodNames {

/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final Activity activity = registrar.activity();
if (activity == null) {
return;
}
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/in_app_purchase");

final BillingClientFactory factory = new BillingClientFactory();
final InAppPurchasePlugin plugin = new InAppPurchasePlugin(factory, activity, channel);
final InAppPurchasePlugin plugin = new InAppPurchasePlugin(factory, registrar, channel);
channel.setMethodCallHandler(plugin);
}

public InAppPurchasePlugin(
BillingClientFactory factory, Activity activity, MethodChannel channel) {
public InAppPurchasePlugin(BillingClientFactory factory, Registrar registrar, MethodChannel channel) {
this.applicationContext = registrar.context();
this.registrar = registrar;
this.factory = factory;
this.activity = activity;
this.channel = channel;
}

Expand Down Expand Up @@ -117,9 +116,10 @@ public void onMethodCall(MethodCall call, Result result) {
}
}


private void startConnection(final int handle, final Result result) {
if (billingClient == null) {
billingClient = factory.createBillingClient(activity, channel);
billingClient = factory.createBillingClient(applicationContext, channel);
}

billingClient.startConnection(
Expand Down Expand Up @@ -197,6 +197,17 @@ private void launchBillingFlow(String sku, @Nullable String accountId, Result re
null);
return;
}
final Activity activity = registrar.activity();

if (activity == null) {
result.error(
"ACTIVITY_UNAVAILABLE",
"Details for sku "
+ sku
+ " are not available. This method requires to be run with the app in foreground.",
null);
return;
}

BillingFlowParams.Builder paramsBuilder =
BillingFlowParams.newBuilder().setSkuDetails(skuDetails);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.Context;
import androidx.annotation.Nullable;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClient.BillingResponse;
Expand Down Expand Up @@ -58,36 +59,22 @@
import org.mockito.Spy;

public class InAppPurchasePluginTest {
InAppPurchasePlugin plugin;
private InAppPurchasePlugin plugin;
@Mock BillingClient mockBillingClient;
@Mock MethodChannel mockMethodChannel;
@Spy Result result;
@Mock PluginRegistry.Registrar registrar;
@Mock Activity activity;
@Mock BinaryMessenger messenger;
@Mock BillingClientFactory factory;


@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(factory.createBillingClient(any(), any())).thenReturn(mockBillingClient);

plugin = new InAppPurchasePlugin(factory, activity, mockMethodChannel);
plugin = new InAppPurchasePlugin(factory, registrar, mockMethodChannel);
}

@Test
public void doNotRegisterWithoutActivityAvailable() {
InAppPurchasePlugin.registerWith(registrar);
verify(registrar, never()).messenger();
}

@Test
public void registerWithoutActivityAvailable() {
when(registrar.messenger()).thenReturn(messenger);
when(registrar.activity()).thenReturn(activity);
InAppPurchasePlugin.registerWith(registrar);
verify(registrar).messenger();
}

@Test
public void invalidMethod() {
Expand Down Expand Up @@ -236,6 +223,7 @@ public void querySkuDetailsAsync_clientDisconnected() {

@Test
public void launchBillingFlow_ok_nullAccountId() {
when(registrar.activity()).thenReturn(activity);
// Fetch the sku details first and then prepare the launch billing flow call
String skuId = "foo";
queryForSkus(singletonList(skuId));
Expand All @@ -262,8 +250,27 @@ public void launchBillingFlow_ok_nullAccountId() {
verify(result, times(1)).success(responseCode);
}

@Test
public void launchBillingFlow_ok_null_Activity() {
// Fetch the sku details first and then prepare the launch billing flow call
String skuId = "foo";
String accountId = "account";
queryForSkus(singletonList(skuId));
HashMap<String, Object> arguments = new HashMap<>();
arguments.put("sku", skuId);
arguments.put("accountId", accountId);
MethodCall launchCall = new MethodCall(LAUNCH_BILLING_FLOW, arguments);

plugin.onMethodCall(launchCall, result);

// Verify we pass the response code to result
verify(result).error(contains("ACTIVITY_UNAVAILABLE"), contains("foreground"), any());
verify(result, never()).success(any());
}

@Test
public void launchBillingFlow_ok_AccountId() {
when(registrar.activity()).thenReturn(activity);
// Fetch the sku details first and query the method call
String skuId = "foo";
String accountId = "account";
Expand Down