Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[in_app_purchase] Enable -Werror for Android #3403

Merged
merged 2 commits into from Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -24,16 +24,12 @@
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.PriceChangeFlowParams;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchaseHistoryRecord;
import com.android.billingclient.api.PurchaseHistoryResponseListener;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.QueryPurchaseHistoryParams;
import com.android.billingclient.api.QueryPurchasesParams;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import java.util.HashMap;
Expand All @@ -55,7 +51,9 @@ class MethodCallHandlerImpl
private final Context applicationContext;
private final MethodChannel methodChannel;

private HashMap<String, SkuDetails> cachedSkus = new HashMap<>();
// TODO(stuartmorgan): Migrate this code. See TODO on querySkuDetailsAsync.
@SuppressWarnings("deprecation")
private HashMap<String, com.android.billingclient.api.SkuDetails> cachedSkus = new HashMap<>();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having to inline namespaces everywhere is the most annoying part of the change, but having -Werror is more important IMO. And all of this will go away when the code is migrated to v5.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v5 of what?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v5 of the Google Play Billing Library, which this plugin wraps.


/** Constructs the MethodCallHandlerImpl */
MethodCallHandlerImpl(
Expand Down Expand Up @@ -185,21 +183,29 @@ private void isReady(MethodChannel.Result result) {
result.success(billingClient.isReady());
}

// TODO(garyq): Migrate to new subscriptions API: https://developer.android.com/google/play/billing/migrate-gpblv5
// TODO(stuartmorgan): Migrate to new subscriptions API. See:
// - https://developer.android.com/google/play/billing/migrate-gpblv5
// - https://github.com/flutter/flutter/issues/114265
// - https://github.com/flutter/flutter/issues/107370
@SuppressWarnings("deprecation")
private void querySkuDetailsAsync(
final String skuType, final List<String> skusList, final MethodChannel.Result result) {
if (billingClientError(result)) {
return;
}

SkuDetailsParams params =
SkuDetailsParams.newBuilder().setType(skuType).setSkusList(skusList).build();
com.android.billingclient.api.SkuDetailsParams params =
com.android.billingclient.api.SkuDetailsParams.newBuilder()
.setType(skuType)
.setSkusList(skusList)
.build();
billingClient.querySkuDetailsAsync(
params,
new SkuDetailsResponseListener() {
new com.android.billingclient.api.SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(
BillingResult billingResult, List<SkuDetails> skuDetailsList) {
BillingResult billingResult,
List<com.android.billingclient.api.SkuDetails> skuDetailsList) {
updateCachedSkus(skuDetailsList);
final Map<String, Object> skuDetailsResponse = new HashMap<>();
skuDetailsResponse.put("billingResult", Translator.fromBillingResult(billingResult));
Expand All @@ -220,7 +226,9 @@ private void launchBillingFlow(
if (billingClientError(result)) {
return;
}
SkuDetails skuDetails = cachedSkus.get(sku);
// TODO(stuartmorgan): Migrate this code. See TODO on querySkuDetailsAsync.
@SuppressWarnings("deprecation")
com.android.billingclient.api.SkuDetails skuDetails = cachedSkus.get(sku);
if (skuDetails == null) {
result.error(
"NOT_FOUND",
Expand Down Expand Up @@ -258,6 +266,8 @@ private void launchBillingFlow(
return;
}

// TODO(stuartmorgan): Migrate this code. See TODO on querySkuDetailsAsync.
@SuppressWarnings("deprecation")
BillingFlowParams.Builder paramsBuilder =
BillingFlowParams.newBuilder().setSkuDetails(skuDetails);
if (accountId != null && !accountId.isEmpty()) {
Expand Down Expand Up @@ -401,16 +411,21 @@ public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
});
}

private void updateCachedSkus(@Nullable List<SkuDetails> skuDetailsList) {
// TODO(stuartmorgan): Migrate this code. See TODO on querySkuDetailsAsync.
@SuppressWarnings("deprecation")
private void updateCachedSkus(
@Nullable List<com.android.billingclient.api.SkuDetails> skuDetailsList) {
if (skuDetailsList == null) {
return;
}

for (SkuDetails skuDetails : skuDetailsList) {
for (com.android.billingclient.api.SkuDetails skuDetails : skuDetailsList) {
cachedSkus.put(skuDetails.getSku(), skuDetails);
}
}

// TODO(stuartmorgan): Migrate this code. See TODO on querySkuDetailsAsync.
@SuppressWarnings("deprecation")
private void launchPriceChangeConfirmationFlow(String sku, MethodChannel.Result result) {
if (activity == null) {
result.error(
Expand All @@ -428,7 +443,7 @@ private void launchPriceChangeConfirmationFlow(String sku, MethodChannel.Result
// is handled by the `billingClientError()` call.
assert billingClient != null;

SkuDetails skuDetails = cachedSkus.get(sku);
com.android.billingclient.api.SkuDetails skuDetails = cachedSkus.get(sku);
if (skuDetails == null) {
result.error(
"NOT_FOUND",
Expand All @@ -439,8 +454,10 @@ private void launchPriceChangeConfirmationFlow(String sku, MethodChannel.Result
return;
}

PriceChangeFlowParams params =
new PriceChangeFlowParams.Builder().setSkuDetails(skuDetails).build();
com.android.billingclient.api.PriceChangeFlowParams params =
new com.android.billingclient.api.PriceChangeFlowParams.Builder()
.setSkuDetails(skuDetails)
.build();
billingClient.launchPriceChangeConfirmationFlow(
activity,
params,
Expand Down
Expand Up @@ -9,7 +9,6 @@
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchaseHistoryRecord;
import com.android.billingclient.api.SkuDetails;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Currency;
Expand All @@ -19,7 +18,9 @@

/** Handles serialization of {@link com.android.billingclient.api.BillingClient} related objects. */
/*package*/ class Translator {
static HashMap<String, Object> fromSkuDetail(SkuDetails detail) {
// TODO(stuartmorgan): Migrate this code. See TODO on MethodCallHandlerImpl.querySkuDetailsAsync.
@SuppressWarnings("deprecation")
static HashMap<String, Object> fromSkuDetail(com.android.billingclient.api.SkuDetails detail) {
HashMap<String, Object> info = new HashMap<>();
info.put("title", detail.getTitle());
info.put("description", detail.getDescription());
Expand All @@ -40,21 +41,25 @@ static HashMap<String, Object> fromSkuDetail(SkuDetails detail) {
return info;
}

// TODO(stuartmorgan): Migrate this code. See TODO on MethodCallHandlerImpl.querySkuDetailsAsync.
@SuppressWarnings("deprecation")
static List<HashMap<String, Object>> fromSkuDetailsList(
@Nullable List<SkuDetails> skuDetailsList) {
@Nullable List<com.android.billingclient.api.SkuDetails> skuDetailsList) {
if (skuDetailsList == null) {
return Collections.emptyList();
}

ArrayList<HashMap<String, Object>> output = new ArrayList<>();
for (SkuDetails detail : skuDetailsList) {
for (com.android.billingclient.api.SkuDetails detail : skuDetailsList) {
output.add(fromSkuDetail(detail));
}
return output;
}

static HashMap<String, Object> fromPurchase(Purchase purchase) {
HashMap<String, Object> info = new HashMap<>();
// TODO(stuartmorgan): Migrate this code. See TODO on MethodCallHandlerImpl.querySkuDetailsAsync.
@SuppressWarnings("deprecation")
List<String> skus = purchase.getSkus();
info.put("orderId", purchase.getOrderId());
info.put("packageName", purchase.getPackageName());
Expand All @@ -79,6 +84,8 @@ static HashMap<String, Object> fromPurchase(Purchase purchase) {
static HashMap<String, Object> fromPurchaseHistoryRecord(
PurchaseHistoryRecord purchaseHistoryRecord) {
HashMap<String, Object> info = new HashMap<>();
// TODO(stuartmorgan): Migrate this code. See TODO on MethodCallHandlerImpl.querySkuDetailsAsync.
@SuppressWarnings("deprecation")
List<String> skus = purchaseHistoryRecord.getSkus();
info.put("purchaseTime", purchaseHistoryRecord.getPurchaseTime());
info.put("purchaseToken", purchaseHistoryRecord.getPurchaseToken());
Expand Down
Expand Up @@ -15,6 +15,7 @@
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
Expand All @@ -25,18 +26,23 @@ public class InAppPurchasePluginTest {

static final String PROXY_PACKAGE_KEY = "PROXY_PACKAGE";

@SuppressWarnings("deprecation")
@Mock
PluginRegistry.Registrar mockRegistrar; // For v1 embedding

@Mock Activity activity;
@Mock Context context;
@Mock PluginRegistry.Registrar mockRegistrar; // For v1 embedding
@Mock BinaryMessenger mockMessenger;
@Mock Application mockApplication;
@Mock Intent mockIntent;
@Mock ActivityPluginBinding activityPluginBinding;
@Mock FlutterPlugin.FlutterPluginBinding flutterPluginBinding;

AutoCloseable mockCloseable;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mockCloseable = MockitoAnnotations.openMocks(this);
when(mockRegistrar.activity()).thenReturn(activity);
when(mockRegistrar.messenger()).thenReturn(mockMessenger);
when(mockRegistrar.context()).thenReturn(context);
Expand All @@ -46,6 +52,11 @@ public void setUp() {
when(flutterPluginBinding.getApplicationContext()).thenReturn(context);
}

@After
public void tearDown() throws Exception {
mockCloseable.close();
}

@Test
public void registerWith_doNotCrashWhenRegisterContextIsActivity_V1Embedding() {
when(mockRegistrar.context()).thenReturn(activity);
Expand Down