diff --git a/android/java/org/chromium/chrome/browser/vpn/activities/BraveVpnPlansActivity.java b/android/java/org/chromium/chrome/browser/vpn/activities/BraveVpnPlansActivity.java index e8f0477dbbf..2f41f262343 100644 --- a/android/java/org/chromium/chrome/browser/vpn/activities/BraveVpnPlansActivity.java +++ b/android/java/org/chromium/chrome/browser/vpn/activities/BraveVpnPlansActivity.java @@ -20,6 +20,7 @@ import androidx.appcompat.app.ActionBar; import androidx.appcompat.widget.Toolbar; import androidx.viewpager.widget.ViewPager; +import com.android.billingclient.api.ProductDetails; import com.android.billingclient.api.SkuDetails; import com.google.android.material.tabs.TabLayout; @@ -32,6 +33,8 @@ import org.chromium.chrome.browser.vpn.utils.BraveVpnUtils; import org.chromium.chrome.browser.vpn.utils.InAppPurchaseWrapper; import org.chromium.ui.widget.Toast; +import java.util.Map; + public class BraveVpnPlansActivity extends BraveVpnParentActivity { private BraveFirstRunFlowSequencer mFirstRunFlowSequencer; private ProgressBar mPlanProgress; @@ -79,64 +82,130 @@ public class BraveVpnPlansActivity extends BraveVpnParentActivity { removedValueText.setPaintFlags( removedValueText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); - SkuDetails monthlySkuDetails = InAppPurchaseWrapper.getInstance().getSkuDetails( - getPackageName().equals(BraveConstants.BRAVE_PRODUCTION_PACKAGE_NAME) - ? InAppPurchaseWrapper.RELEASE_MONTHLY_SUBSCRIPTION - : InAppPurchaseWrapper.NIGHTLY_MONTHLY_SUBSCRIPTION); - - SkuDetails yearlySkuDetails = InAppPurchaseWrapper.getInstance().getSkuDetails( - getPackageName().equals(BraveConstants.BRAVE_PRODUCTION_PACKAGE_NAME) - ? InAppPurchaseWrapper.RELEASE_YEARLY_SUBSCRIPTION - : InAppPurchaseWrapper.NIGHTLY_YEARLY_SUBSCRIPTION); TextView monthlySubscriptionText = findViewById(R.id.monthly_subscription_text); monthlySubscriptionText.setText( String.format(getResources().getString(R.string.monthly_subscription), "")); + TextView monthlySubscriptionAmountText = + findViewById(R.id.monthly_subscription_amount_text); + mMonthlySelectorLayout = findViewById(R.id.monthly_selector_layout); - if (monthlySkuDetails != null && yearlySkuDetails != null) { - mMonthlySelectorLayout = findViewById(R.id.monthly_selector_layout); - mMonthlySelectorLayout.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - InAppPurchaseWrapper.getInstance().purchase( - BraveVpnPlansActivity.this, monthlySkuDetails); - } - }); + InAppPurchaseWrapper.getInstance().queryProductDetailsAsync( + InAppPurchaseWrapper.SubscriptionType.MONTHLY, + new InAppPurchaseWrapper.QueryProductDetailsResponse() { + @Override + public void onProductDetails(Map productDetailsMap) { + ProductDetails monthlyProductDetails = productDetailsMap.get( + InAppPurchaseWrapper.getInstance().getProductId( + InAppPurchaseWrapper.SubscriptionType.MONTHLY)); + if (monthlyProductDetails != null) { + mMonthlySelectorLayout.setOnClickListener(v + -> InAppPurchaseWrapper.getInstance().initiatePurchase( + BraveVpnPlansActivity.this, monthlyProductDetails)); + if (monthlyProductDetails.getSubscriptionOfferDetails() != null) { + monthlySubscriptionAmountText.setText( + String.format(getResources().getString( + R.string.monthly_subscription_amount), + monthlyProductDetails.getSubscriptionOfferDetails() + .get(0) + .getPricingPhases() + .getPricingPhaseList() + .get(0) + .getFormattedPrice())); + } + } + } + }); - TextView monthlySubscriptionAmountText = - findViewById(R.id.monthly_subscription_amount_text); - monthlySubscriptionAmountText.setText( - String.format(getResources().getString(R.string.monthly_subscription_amount), - monthlySkuDetails.getPrice())); + TextView yearlySubscriptionAmountText = findViewById(R.id.yearly_subscription_amount_text); + mYearlySelectorLayout = findViewById(R.id.yearly_selector_layout); - mYearlySelectorLayout = findViewById(R.id.yearly_selector_layout); - mYearlySelectorLayout.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - InAppPurchaseWrapper.getInstance().purchase( - BraveVpnPlansActivity.this, yearlySkuDetails); - } - }); + InAppPurchaseWrapper.getInstance().queryProductDetailsAsync( + InAppPurchaseWrapper.SubscriptionType.YEARLY, + new InAppPurchaseWrapper.QueryProductDetailsResponse() { + @Override + public void onProductDetails(Map productDetailsMap) { + ProductDetails yearlyProductDetails = productDetailsMap.get( + InAppPurchaseWrapper.getInstance().getProductId( + InAppPurchaseWrapper.SubscriptionType.YEARLY)); + if (yearlyProductDetails != null) { + mYearlySelectorLayout.setOnClickListener(v + -> InAppPurchaseWrapper.getInstance().initiatePurchase( + BraveVpnPlansActivity.this, yearlyProductDetails)); + if (yearlyProductDetails.getSubscriptionOfferDetails() != null) { + yearlySubscriptionAmountText.setText( + String.format(getResources().getString( + R.string.yearly_subscription_amount), + yearlyProductDetails.getSubscriptionOfferDetails() + .get(0) + .getPricingPhases() + .getPricingPhaseList() + .get(0) + .getFormattedPrice())); + } + } + } + }); - TextView yearlySubscriptionAmountText = - findViewById(R.id.yearly_subscription_amount_text); - yearlySubscriptionAmountText.setText( - String.format(getResources().getString(R.string.yearly_subscription_amount), - yearlySkuDetails.getPrice())); - BraveVpnUtils.showProgressDialog(BraveVpnPlansActivity.this, - getResources().getString(R.string.vpn_connect_text)); - mIsVerification = true; - verifySubscription(); - } else { - Toast.makeText(BraveVpnPlansActivity.this, R.string.purchased_failed, Toast.LENGTH_LONG) - .show(); - } + BraveVpnUtils.showProgressDialog( + BraveVpnPlansActivity.this, getResources().getString(R.string.vpn_connect_text)); + mIsVerification = true; + verifySubscription(); + + // SkuDetails monthlySkuDetails = InAppPurchaseWrapper.getInstance().getSkuDetails( + // getPackageName().equals(BraveConstants.BRAVE_PRODUCTION_PACKAGE_NAME) + // ? InAppPurchaseWrapper.RELEASE_MONTHLY_SUBSCRIPTION + // : InAppPurchaseWrapper.NIGHTLY_MONTHLY_SUBSCRIPTION); + + // SkuDetails yearlySkuDetails = InAppPurchaseWrapper.getInstance().getSkuDetails( + // getPackageName().equals(BraveConstants.BRAVE_PRODUCTION_PACKAGE_NAME) + // ? InAppPurchaseWrapper.RELEASE_YEARLY_SUBSCRIPTION + // : InAppPurchaseWrapper.NIGHTLY_YEARLY_SUBSCRIPTION); + + // if (monthlySkuDetails != null && yearlySkuDetails != null) { + // mMonthlySelectorLayout = findViewById(R.id.monthly_selector_layout); + // mMonthlySelectorLayout.setOnClickListener(new View.OnClickListener() { + // @Override + // public void onClick(View v) { + // InAppPurchaseWrapper.getInstance().purchase( + // BraveVpnPlansActivity.this, monthlySkuDetails); + // } + // }); + + // TextView monthlySubscriptionAmountText = + // findViewById(R.id.monthly_subscription_amount_text); + // monthlySubscriptionAmountText.setText( + // String.format(getResources().getString(R.string.monthly_subscription_amount), + // monthlySkuDetails.getPrice())); + + // mYearlySelectorLayout = findViewById(R.id.yearly_selector_layout); + // mYearlySelectorLayout.setOnClickListener(new View.OnClickListener() { + // @Override + // public void onClick(View v) { + // InAppPurchaseWrapper.getInstance().purchase( + // BraveVpnPlansActivity.this, yearlySkuDetails); + // } + // }); + + // TextView yearlySubscriptionAmountText = + // findViewById(R.id.yearly_subscription_amount_text); + // yearlySubscriptionAmountText.setText( + // String.format(getResources().getString(R.string.yearly_subscription_amount), + // yearlySkuDetails.getPrice())); + // BraveVpnUtils.showProgressDialog(BraveVpnPlansActivity.this, + // getResources().getString(R.string.vpn_connect_text)); + // mIsVerification = true; + // verifySubscription(); + // } else { + // Toast.makeText(BraveVpnPlansActivity.this, R.string.purchased_failed, + // Toast.LENGTH_LONG) + // .show(); + // } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_brave_vpn, menu); MenuItem item = menu.findItem(R.id.restore); - item.setVisible(true); if (mShouldShowRestoreMenu) { mShouldShowRestoreMenu = false; item.setVisible(true); diff --git a/android/java/org/chromium/chrome/browser/vpn/utils/InAppPurchaseWrapper.java b/android/java/org/chromium/chrome/browser/vpn/utils/InAppPurchaseWrapper.java index 887817222c2..6e2be711089 100644 --- a/android/java/org/chromium/chrome/browser/vpn/utils/InAppPurchaseWrapper.java +++ b/android/java/org/chromium/chrome/browser/vpn/utils/InAppPurchaseWrapper.java @@ -8,7 +8,6 @@ package org.chromium.chrome.browser.vpn.utils; import static com.android.billingclient.api.BillingClient.BillingResponseCode.OK; -import static com.android.billingclient.api.BillingClient.SkuType.SUBS; import android.app.Activity; import android.content.Context; @@ -22,16 +21,18 @@ import com.android.billingclient.api.BillingClient; import com.android.billingclient.api.BillingClientStateListener; import com.android.billingclient.api.BillingFlowParams; import com.android.billingclient.api.BillingResult; +import com.android.billingclient.api.ProductDetails; import com.android.billingclient.api.Purchase; import com.android.billingclient.api.PurchasesResponseListener; import com.android.billingclient.api.PurchasesUpdatedListener; +import com.android.billingclient.api.QueryProductDetailsParams; import com.android.billingclient.api.QueryPurchasesParams; -import com.android.billingclient.api.SkuDetails; -import com.android.billingclient.api.SkuDetailsParams; +import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.chrome.R; import org.chromium.chrome.browser.BraveRewardsNativeWorker; +import org.chromium.chrome.browser.util.BraveConstants; import org.chromium.ui.widget.Toast; import java.util.ArrayList; @@ -50,21 +51,21 @@ public class InAppPurchaseWrapper { private BillingClient mBillingClient; private int mRetryCount; - private final Map mSkusWithSkuDetails = new HashMap<>(); - - public SkuDetails getSkuDetails(String sku) { - return mSkusWithSkuDetails.get(sku); - } - - public static final List NIGHTLY_SUBS_SKUS = new ArrayList<>( + public static final List NIGHTLY_SUBS_PRODUCT_IDS = new ArrayList<>( Arrays.asList(NIGHTLY_MONTHLY_SUBSCRIPTION, NIGHTLY_YEARLY_SUBSCRIPTION)); - public static final List RELEASE_SUBS_SKUS = new ArrayList<>( + public static final List RELEASE_SUBS_PRODUCT_IDS = new ArrayList<>( Arrays.asList(RELEASE_MONTHLY_SUBSCRIPTION, RELEASE_YEARLY_SUBSCRIPTION)); private static volatile InAppPurchaseWrapper sInAppPurchaseWrapper; private static Object mutex = new Object(); + public enum SubscriptionType { MONTHLY, YEARLY } + + public interface QueryProductDetailsResponse { + default void onProductDetails(Map productDetails) {} + } + private MutableLiveData> mutablePurchases = new MutableLiveData(); private LiveData> purchases = mutablePurchases; private void setPurchases(List purchases) { @@ -128,25 +129,38 @@ public class InAppPurchaseWrapper { return false; } - private void querySkuDetailsAsync(List skuList) { - SkuDetailsParams params = SkuDetailsParams.newBuilder() - .setSkusList(skuList) - .setType(BillingClient.SkuType.SUBS) - .build(); - mBillingClient.querySkuDetailsAsync(params, (billingResult, skuDetailsList) -> { - if (billingResult.getResponseCode() == OK && skuDetailsList != null) { - for (SkuDetails skuDetails : skuDetailsList) { - mSkusWithSkuDetails.put(skuDetails.getSku(), skuDetails); - } - } - }); + public String getProductId(SubscriptionType subscriptionType) { + boolean isReleaseBuild = ContextUtils.getApplicationContext().getPackageName().equals( + BraveConstants.BRAVE_PRODUCTION_PACKAGE_NAME); + if (isReleaseBuild) { + return subscriptionType == SubscriptionType.MONTHLY ? RELEASE_MONTHLY_SUBSCRIPTION + : RELEASE_YEARLY_SUBSCRIPTION; + } else { + return subscriptionType == SubscriptionType.MONTHLY ? NIGHTLY_MONTHLY_SUBSCRIPTION + : NIGHTLY_YEARLY_SUBSCRIPTION; + } } - public void queryPurchases(PurchasesResponseListener purchasesResponseListener) { - mBillingClient.queryPurchasesAsync(QueryPurchasesParams.newBuilder() - .setProductType(BillingClient.ProductType.SUBS) - .build(), - purchasesResponseListener); + public void queryProductDetailsAsync(SubscriptionType subscriptionType, + QueryProductDetailsResponse queryProductDetailsResponse) { + Map productDetails = new HashMap<>(); + List products = new ArrayList<>(); + products.add(QueryProductDetailsParams.Product.newBuilder() + .setProductId(getProductId(subscriptionType)) + .setProductType(BillingClient.ProductType.SUBS) + .build()); + QueryProductDetailsParams queryProductDetailsParams = + QueryProductDetailsParams.newBuilder().setProductList(products).build(); + + mBillingClient.queryProductDetailsAsync( + queryProductDetailsParams, (billingResult, productDetailsList) -> { + if (billingResult.getResponseCode() == OK) { + for (ProductDetails productDetail : productDetailsList) { + productDetails.put(productDetail.getProductId(), productDetail); + } + queryProductDetailsResponse.onProductDetails(productDetails); + } + }); } public void queryPurchases() { @@ -156,12 +170,20 @@ public class InAppPurchaseWrapper { (billingResult, list) -> { setPurchases(list); }); } - public void purchase(Activity activity, SkuDetails skuDetails) { - BillingFlowParams billingFlowParams = - BillingFlowParams.newBuilder().setSkuDetails(skuDetails).build(); + public void initiatePurchase(Activity activity, ProductDetails productDetails) { + String offerToken = productDetails.getSubscriptionOfferDetails().get(0).getOfferToken(); + List productDetailsParamsList = new ArrayList<>(); + productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder() + .setProductDetails(productDetails) + .setOfferToken(offerToken) + .build()); - int responseCode = - mBillingClient.launchBillingFlow(activity, billingFlowParams).getResponseCode(); + BillingFlowParams billingFlowParams = + BillingFlowParams.newBuilder() + .setProductDetailsParamsList(productDetailsParamsList) + .build(); + + BillingResult billingResult = mBillingClient.launchBillingFlow(activity, billingFlowParams); } public void processPurchases(Context context, List purchases) { @@ -244,9 +266,7 @@ public class InAppPurchaseWrapper { public void onBillingSetupFinished(@NonNull BillingResult billingResult) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { retryCount = 0; - querySkuDetailsAsync(NIGHTLY_SUBS_SKUS); - querySkuDetailsAsync(RELEASE_SUBS_SKUS); } } }; -} \ No newline at end of file +} diff --git a/build/android/config.gni b/build/android/config.gni index b06338b489d..33082e1acf4 100644 --- a/build/android/config.gni +++ b/build/android/config.gni @@ -63,7 +63,6 @@ brave_chrome_java_deps = [ "//brave/third_party/android_deps:google_play_services_safetynet_java", "//brave/third_party/zxing:zxing_java", "//third_party/android_deps:com_android_support_support_annotations_java", - "//third_party/android_deps:com_google_auto_value_auto_value_annotations_java", "//third_party/android_deps:com_google_code_gson_gson_java", "//third_party/android_deps:google_firebase_firebase_messaging_java", "//third_party/android_deps:google_play_services_vision_common_java", diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index 28c22209ac9..2c6ada7bf06 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn @@ -60,7 +60,6 @@ android_aar_prebuilt( info_path = "libs/com_google_android_datatransport_transport_backend_cct/com_google_android_datatransport_transport_backend_cct.info" deps = [ ":com_google_android_datatransport_transport_runtime_java", - "//third_party/android_deps:com_google_auto_value_auto_value_annotations_java", "//third_party/android_deps:google_firebase_firebase_messaging_java", "//third_party/androidx:androidx_annotation_annotation_java", ] @@ -72,7 +71,6 @@ android_aar_prebuilt( info_path = "libs/com_google_android_datatransport_transport_runtime/com_google_android_datatransport_transport_runtime.info" deps = [ ":com_google_firebase_firebase_encoders_proto_java", - "//third_party/android_deps:com_google_auto_value_auto_value_annotations_java", "//third_party/android_deps:google_firebase_firebase_messaging_java", "//third_party/android_deps:javax_inject_javax_inject_java", "//third_party/androidx:androidx_annotation_annotation_java",