Finished huawei inapps

This commit is contained in:
max-klaus 2020-10-03 20:48:55 +03:00
parent a9aa1e5776
commit ec53a8fc12
10 changed files with 226 additions and 140 deletions

3
OsmAnd/.gitignore vendored
View file

@ -13,10 +13,13 @@ libs/it.unibo.alice.tuprolog-tuprolog-3.2.1.jar
libs/commons-codec-commons-codec-1.11.jar
libs/OsmAndCore_android-0.1-SNAPSHOT.jar
# Huawei
libs/huawei-*.jar
huaweidrmlib/
HwDRM_SDK_*
drm_strings.xml
agconnect-services.json
OsmAndHms.jks
# copy_widget_icons.sh
res/drawable-large/map_*

View file

@ -28,10 +28,15 @@ android {
signingConfigs {
development {
storeFile file("../keystores/debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
storeFile file('OsmAndHms.jks')
keyAlias 'OsmAndHms'
keyPassword 'targeting'
storePassword 'targeting'
// storeFile file("../keystores/debug.keystore")
// storePassword "android"
// keyAlias "androiddebugkey"
// keyPassword "android"
}
publishing {

View file

@ -226,6 +226,16 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
});
}
@Override
public void manageSubscription(@NonNull Context ctx, @Nullable String sku) {
String url = "https://play.google.com/store/account/subscriptions?package=" + ctx.getPackageName();
if (!Algorithms.isEmpty(sku)) {
url += "&sku=" + sku;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
ctx.startActivity(intent);
}
@Nullable
private SkuDetails getSkuDetails(@NonNull String sku) {
List<SkuDetails> skuDetailsList = this.skuDetailsList;

View file

@ -37,7 +37,7 @@ import java.security.spec.X509EncodedKeySpec;
public class CipherUtil {
private static final String TAG = "CipherUtil";
private static final String SIGN_ALGORITHMS = "SHA256WithRSA";
private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAooen3X9jSWarxugznzzMSvp4zir1Pg6uPOm7fqlLOL0Ix52e5FpeotMx871pQ9hrCkiyFg2e6UxD8IXXjvK6QJQbjNJ2jIfKkCusm90yloSEfvyLeiq5y7zg4+DoPglHi8RxZ9y308YIqnRDoslfGm5DnWa8RKUvFRVRiu1p3FN4SYIa/FWLtS5yygemtqMJi8I14V7xqQ5wExCGeSA6j1/AAWXEwZncJwKn0BTXQSvwVBPBRM5ksgt4q+Sc484ZIbntATyxsUipnEBFxq1OXn5Zw5/vVxUC8RSyDMQ/kC2RaEcFtA1tlIIjIdurbpNg3tyViPfQUQndvOs4nDrFzwIDAQAB";
private static final String PUBLIC_KEY = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAsB+oH8rYQncwpTqGa0kS/5E725HJrq2sW1ThAZtmorYVi52Yt9PmZvNDz7284ol9C2skrKQR34eIer8Tr7Qqq3mlNo+/LVUpq9sa++kB2glaG6jj5NNjM3w4nVYHFIYkd5AQhodJgmqFvnp2s7r7YmyQVXZSehei5bA1G70Bs+El9cSv9shNNGTCaU3ARUu2hy3Ltkc/ov7/ZYYpiwjbyD3cmoMh9jO1++zztXb2phjv1h9zeJOp1i6HsotZll+c9J4jjV3GhrF+ZJm5WrSzGLDLtwSldRpMZFxrSvAJJstjzhDz3LpUM+nPV3HZ5VQ/xosmwWYmiibo89E1gw8p73NTBXHzuQMJcTJ6vTjD8LeMskpXHZUAGhifmFLGN1LbNP9662ulCV12kIbXuzWCwwi/h0DWqmnjKmLvzc88e4BrGrp2zZUnHz7m15voPG+4cQ3z9+cwS4gEI3SUTiFyQGE539SO/11VkkQAJ8P7du1JFNqQw5ZEW3AoE1iUsp5XAgMBAAE=";
/**
* the method to check the signature for the data returned from the interface
@ -65,7 +65,7 @@ public class CipherUtil {
java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
signature.initVerify(pubKey);
signature.update(content.getBytes("utf-8"));
signature.update(content.getBytes("UTF-8"));
boolean bverify = signature.verify(Base64.decode(sign, Base64.DEFAULT));
return bverify;

View file

@ -8,6 +8,9 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.hmf.tasks.Task;
import com.huawei.hms.iap.Iap;
import com.huawei.hms.iap.IapClient;
import com.huawei.hms.iap.entity.InAppPurchaseData;
@ -18,12 +21,15 @@ import com.huawei.hms.iap.entity.ProductInfo;
import com.huawei.hms.iap.entity.ProductInfoResult;
import com.huawei.hms.iap.entity.PurchaseIntentResult;
import com.huawei.hms.iap.entity.PurchaseResultInfo;
import com.huawei.hms.iap.entity.StartIapActivityReq;
import com.huawei.hms.iap.entity.StartIapActivityResult;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.inapp.InAppPurchases.InAppPurchase;
import net.osmand.plus.inapp.InAppPurchases.InAppSubscription;
import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionIntroductoryInfo;
import net.osmand.plus.inapp.InAppPurchasesImpl.InAppPurchaseLiveUpdatesOldSubscription;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference;
import net.osmand.util.Algorithms;
@ -109,6 +115,7 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
public void run(InAppPurchaseHelper helper) {
try {
ProductInfo productInfo = getProductInfo(productId);
if (productInfo != null) {
IapRequestHelper.createPurchaseIntent(getIapClient(), productInfo.getProductId(),
IapClient.PriceType.IN_APP_NONCONSUMABLE, new IapApiCallback<PurchaseIntentResult>() {
@Override
@ -136,6 +143,9 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
commandDone();
}
});
} else {
commandDone();
}
} catch (Exception e) {
complain("Cannot launch full version purchase!");
logError("purchaseFullVersion Error", e);
@ -148,13 +158,42 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
@Override
public void purchaseFullVersion(@NonNull final Activity activity) throws UnsupportedOperationException {
notifyShowProgress(InAppPurchaseTaskType.PURCHASE_FULL_VERSION);
exec(InAppPurchaseTaskType.PURCHASE_FULL_VERSION, getPurchaseInAppCommand(activity, ""));
exec(InAppPurchaseTaskType.PURCHASE_FULL_VERSION, getPurchaseInAppCommand(activity, purchases.getFullVersion().getSku()));
}
@Override
public void purchaseDepthContours(@NonNull final Activity activity) throws UnsupportedOperationException {
notifyShowProgress(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS);
exec(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS, getPurchaseInAppCommand(activity, ""));
exec(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS, getPurchaseInAppCommand(activity, purchases.getDepthContours().getSku()));
}
@Override
public void manageSubscription(@NonNull Context ctx, @Nullable String sku) {
if (uiActivity != null) {
StartIapActivityReq req = new StartIapActivityReq();
if (!Algorithms.isEmpty(sku)) {
req.setSubscribeProductId(sku);
req.setType(StartIapActivityReq.TYPE_SUBSCRIBE_EDIT_ACTIVITY);
} else {
req.setType(StartIapActivityReq.TYPE_SUBSCRIBE_MANAGER_ACTIVITY);
}
Task<StartIapActivityResult> task = getIapClient().startIapActivity(req);
task.addOnSuccessListener(new OnSuccessListener<StartIapActivityResult>() {
@Override
public void onSuccess(StartIapActivityResult result) {
logDebug("startIapActivity: onSuccess");
Activity activity = (Activity) uiActivity;
if (result != null && AndroidUtils.isActivityNotDestroyed(activity)) {
result.startActivity(activity);
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
logDebug("startIapActivity: onFailure");
}
});
}
}
@Nullable
@ -285,16 +324,18 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
protected InAppCommand getRequestInventoryCommand() {
return new InAppCommand() {
@Override
protected void commandDone() {
super.commandDone();
inventoryRequested = false;
}
@Override
public void run(InAppPurchaseHelper helper) {
logDebug("Setup successful. Querying inventory.");
try {
productInfos = new ArrayList<>();
if (uiActivity != null) {
obtainOwnedSubscriptions();
} else {
commandDone();
}
} catch (Exception e) {
logError("queryInventoryAsync Error", e);
notifyDismissProgress(InAppPurchaseTaskType.REQUEST_INVENTORY);
@ -326,6 +367,7 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
}
private void obtainOwnedInApps(final String continuationToken) {
if (uiActivity != null) {
// Query users' purchased non-consumable products.
IapRequestHelper.obtainOwnedPurchases(getIapClient(), IapClient.PriceType.IN_APP_NONCONSUMABLE,
continuationToken, new IapApiCallback<OwnedPurchasesResult>() {
@ -346,10 +388,13 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
commandDone();
}
});
} else {
commandDone();
}
}
private void obtainSubscriptionsInfo() {
if (uiActivity != null) {
Set<String> productIds = new HashSet<>();
List<InAppSubscription> subscriptions = purchases.getLiveUpdates().getAllSubscriptions();
for (InAppSubscription s : subscriptions) {
@ -360,12 +405,9 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
IapClient.PriceType.IN_APP_SUBSCRIPTION, new IapApiCallback<ProductInfoResult>() {
@Override
public void onSuccess(final ProductInfoResult result) {
if (result == null) {
logError("obtainSubscriptionsInfo: ProductInfoResult is null");
commandDone();
return;
}
if (result != null && result.getProductInfoList() != null) {
productInfos.addAll(result.getProductInfoList());
}
obtainInAppsInfo();
}
@ -378,9 +420,13 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
commandDone();
}
});
} else {
commandDone();
}
}
private void obtainInAppsInfo() {
if (uiActivity != null) {
Set<String> productIds = new HashSet<>();
for (InAppPurchase purchase : getInAppPurchases().getAllInAppPurchases(false)) {
productIds.add(purchase.getSku());
@ -392,15 +438,10 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
IapClient.PriceType.IN_APP_NONCONSUMABLE, new IapApiCallback<ProductInfoResult>() {
@Override
public void onSuccess(ProductInfoResult result) {
if (result == null || result.getProductInfoList() == null) {
logError("obtainInAppsInfo: ProductInfoResult is null");
commandDone();
return;
}
if (result != null && result.getProductInfoList() != null) {
productInfos.addAll(result.getProductInfoList());
}
processInventory();
commandDone();
}
@Override
@ -412,6 +453,9 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
commandDone();
}
});
} else {
commandDone();
}
}
private void processInventory() {
@ -579,7 +623,20 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
if (resultCode == Activity.RESULT_OK) {
PurchaseResultInfo result = SubscriptionUtils.getPurchaseResult(activity, data);
if (result != null) {
if (OrderStatusCode.ORDER_STATE_SUCCESS == result.getReturnCode()) {
switch (result.getReturnCode()) {
case OrderStatusCode.ORDER_STATE_CANCEL:
logDebug("Purchase cancelled");
break;
case OrderStatusCode.ORDER_STATE_FAILED:
inventoryRequestPending = true;
logDebug("Purchase failed");
break;
case OrderStatusCode.ORDER_PRODUCT_OWNED:
inventoryRequestPending = true;
logDebug("Product already owned");
break;
case OrderStatusCode.ORDER_STATE_SUCCESS:
inventoryRequestPending = true;
InAppPurchaseData purchaseData = SubscriptionUtils.getInAppPurchaseData(null,
result.getInAppPurchaseData(), result.getInAppDataSignature());
if (purchaseData != null) {
@ -588,8 +645,9 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
} else {
logDebug("Purchase failed");
}
} else if (OrderStatusCode.ORDER_STATE_CANCEL == result.getReturnCode()) {
logDebug("Purchase cancelled");
break;
default:
break;
}
} else {
logDebug("Purchase failed");
@ -611,7 +669,12 @@ public class InAppPurchaseHelperImpl extends InAppPurchaseHelper {
case OrderStatusCode.ORDER_STATE_CANCEL:
logDebug("Order has been canceled");
break;
case OrderStatusCode.ORDER_STATE_FAILED:
inventoryRequestPending = true;
logDebug("Order has been failed");
break;
case OrderStatusCode.ORDER_PRODUCT_OWNED:
inventoryRequestPending = true;
logDebug("Product already owned");
break;
case OrderStatusCode.ORDER_STATE_SUCCESS:

View file

@ -5,6 +5,8 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.huawei.hms.iap.entity.ProductInfo;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
@ -26,8 +28,18 @@ public class InAppPurchasesImpl extends InAppPurchases {
fullVersion = FULL_VERSION;
depthContours = DEPTH_CONTOURS_FREE;
contourLines = CONTOUR_LINES_FREE;
liveUpdates = new LiveUpdatesInAppPurchasesFree();
inAppPurchases = new InAppPurchase[] { fullVersion, depthContours, contourLines };
liveUpdates = new LiveUpdatesInAppPurchasesFree();
for (InAppSubscription s : liveUpdates.getAllSubscriptions()) {
if (s instanceof InAppPurchaseLiveUpdatesMonthly) {
if (s.isDiscounted()) {
discountedMonthlyLiveUpdates = s;
} else {
monthlyLiveUpdates = s;
}
}
}
}
@Override
@ -57,7 +69,7 @@ public class InAppPurchasesImpl extends InAppPurchases {
private static class InAppPurchaseFullVersion extends InAppPurchase {
private static final String SKU_FULL_VERSION_PRICE = "osmand_full_version_price";
private static final String SKU_FULL_VERSION_PRICE = "net.osmand.huawei.full";
InAppPurchaseFullVersion() {
super(SKU_FULL_VERSION_PRICE);
@ -71,7 +83,7 @@ public class InAppPurchasesImpl extends InAppPurchases {
private static class InAppPurchaseDepthContoursFree extends InAppPurchaseDepthContours {
private static final String SKU_DEPTH_CONTOURS_FREE = "net.osmand.seadepth";
private static final String SKU_DEPTH_CONTOURS_FREE = "net.osmand.huawei.seadepth";
InAppPurchaseDepthContoursFree() {
super(SKU_DEPTH_CONTOURS_FREE);
@ -80,7 +92,7 @@ public class InAppPurchasesImpl extends InAppPurchases {
private static class InAppPurchaseContourLinesFree extends InAppPurchaseContourLines {
private static final String SKU_CONTOUR_LINES_FREE = "net.osmand.contourlines";
private static final String SKU_CONTOUR_LINES_FREE = "net.osmand.huawei.contourlines";
InAppPurchaseContourLinesFree() {
super(SKU_CONTOUR_LINES_FREE);
@ -89,7 +101,7 @@ public class InAppPurchasesImpl extends InAppPurchases {
private static class InAppPurchaseLiveUpdatesMonthlyFree extends InAppPurchaseLiveUpdatesMonthly {
private static final String SKU_LIVE_UPDATES_MONTHLY_HW_FREE = "net.osmand.test.monthly";
private static final String SKU_LIVE_UPDATES_MONTHLY_HW_FREE = "net.osmand.huawei.monthly";
InAppPurchaseLiveUpdatesMonthlyFree() {
super(SKU_LIVE_UPDATES_MONTHLY_HW_FREE, 1);
@ -108,7 +120,7 @@ public class InAppPurchasesImpl extends InAppPurchases {
private static class InAppPurchaseLiveUpdates3MonthsFree extends InAppPurchaseLiveUpdates3Months {
private static final String SKU_LIVE_UPDATES_3_MONTHS_HW_FREE = "net.osmand.test.3months";
private static final String SKU_LIVE_UPDATES_3_MONTHS_HW_FREE = "net.osmand.huawei.3months";
InAppPurchaseLiveUpdates3MonthsFree() {
super(SKU_LIVE_UPDATES_3_MONTHS_HW_FREE, 1);
@ -127,7 +139,7 @@ public class InAppPurchasesImpl extends InAppPurchases {
private static class InAppPurchaseLiveUpdatesAnnualFree extends InAppPurchaseLiveUpdatesAnnual {
private static final String SKU_LIVE_UPDATES_ANNUAL_HW_FREE = "net.osmand.test.annual";
private static final String SKU_LIVE_UPDATES_ANNUAL_HW_FREE = "net.osmand.huawei.annual";
InAppPurchaseLiveUpdatesAnnualFree() {
super(SKU_LIVE_UPDATES_ANNUAL_HW_FREE, 1);

View file

@ -120,9 +120,8 @@ public class SubscriptionUtils {
}
} else {
Log.e(TAG, "check the data signature fail");
}
return getFailedPurchaseResultInfo();
}
default:
Log.e(TAG, "returnCode: " + returnCode + " , errMsg: " + errMsg);
break;

View file

@ -428,7 +428,7 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
buttonCancelView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
manageSubscription(ctx, s.getSku());
purchaseHelper.manageSubscription(ctx, s.getSku());
}
});
div.setVisibility(View.VISIBLE);
@ -538,15 +538,6 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
}
}
private void manageSubscription(@NonNull Context ctx, @Nullable String sku) {
String url = "https://play.google.com/store/account/subscriptions?package=" + ctx.getPackageName();
if (!Algorithms.isEmpty(sku)) {
url += "&sku=" + sku;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
private ViewGroup buildPlanTypeCard(@NonNull Context ctx, ViewGroup container) {
if (getPlanTypeFeatures().length == 0) {
return null;

View file

@ -2,6 +2,7 @@ package net.osmand.plus.inapp;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.text.TextUtils;
@ -265,6 +266,8 @@ public abstract class InAppPurchaseHelper {
public abstract void purchaseDepthContours(@NonNull final Activity activity) throws UnsupportedOperationException;
public abstract void manageSubscription(@NonNull Context ctx, @Nullable String sku);
@SuppressLint("StaticFieldLeak")
private class LiveUpdatesPurchaseTask extends AsyncTask<Void, Void, String> {

View file

@ -73,7 +73,7 @@ public abstract class InAppPurchases {
public InAppSubscription getPurchasedMonthlyLiveUpdates() {
if (monthlyLiveUpdates.isAnyPurchased()) {
return monthlyLiveUpdates;
} else if (discountedMonthlyLiveUpdates.isAnyPurchased()) {
} else if (discountedMonthlyLiveUpdates != null && discountedMonthlyLiveUpdates.isAnyPurchased()) {
return discountedMonthlyLiveUpdates;
}
return null;