[android] Implemented bookmark payment activity/fragment prototype and link with purchase controller

This commit is contained in:
Александр Зацепин 2018-11-02 14:45:17 +03:00 committed by yoksnod
parent 57c25cea2a
commit 8d17725509
10 changed files with 279 additions and 28 deletions

View file

@ -447,6 +447,7 @@
android:label="@string/ugc_route_tags_screen_label">
</activity>
<activity android:name="com.mapswithme.maps.ugc.routes.UgcRouteSharingOptionsActivity"/>
<activity android:name=".purchase.BookmarkPaymentActivity"/>
<service
android:name="com.mapswithme.maps.background.WorkerService"
android:permission="android.permission.BIND_JOB_SERVICE"

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<Button
android:id="@+id/query_inapps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Query inapps"/>
<Button
android:id="@+id/buy_inapp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy inapps"/>
<Button
android:id="@+id/consume_apps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Consume apps"/>
</LinearLayout>

View file

@ -39,6 +39,7 @@ public class BookmarksCatalogFragment extends BaseWebViewMwmFragment
implements TargetFragmentCallback
{
public static final String EXTRA_BOOKMARKS_CATALOG_URL = "bookmarks_catalog_url";
static final int REQ_CODE_PAY_BOOKMARK = 1;
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC);
private static final String TAG = BookmarksCatalogFragment.class.getSimpleName();
@ -156,7 +157,7 @@ public class BookmarksCatalogFragment extends BaseWebViewMwmFragment
}
catch (MalformedURLException e)
{
LOGGER.e(TAG, "Failed to download bookmark, url: " + url, e);
LOGGER.e(TAG, "Failed to download bookmark, url: " + url);
return false;
}
}

View file

@ -12,6 +12,7 @@ import com.mapswithme.maps.R;
import com.mapswithme.maps.auth.Authorizer;
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
import com.mapswithme.maps.bookmarks.data.PaymentData;
import com.mapswithme.maps.purchase.BookmarkPaymentActivity;
import com.mapswithme.util.log.Logger;
import com.mapswithme.util.log.LoggerFactory;
@ -66,11 +67,11 @@ class DefaultBookmarkDownloadController implements BookmarkDownloadController,
if (mActivity == null)
throw new AssertionError("Already detached! Call attach.");
mActivity = null;
mAuthorizer.detach();
mDownloadCompleteReceiver.detach();
mDownloadCompleteReceiver.unregister(getActivityOrThrow().getApplication());
BookmarkManager.INSTANCE.removeCatalogListener(mCatalogListener);
mActivity = null;
}
@NonNull
@ -108,9 +109,8 @@ class DefaultBookmarkDownloadController implements BookmarkDownloadController,
throw new IllegalStateException("Download url must be non-null if payment required!");
PaymentData data = parsePaymentData(mDownloadUrl);
//TODO: pass data and show payment UI.
Toast.makeText(getActivityOrThrow(), "Payment required. Ui coming soon!",
Toast.LENGTH_SHORT).show();
BookmarkPaymentActivity.start(getActivityOrThrow(), data,
BookmarksCatalogFragment.REQ_CODE_PAY_BOOKMARK);
}
@NonNull

View file

@ -1,9 +1,11 @@
package com.mapswithme.maps.bookmarks.data;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public class PaymentData
public class PaymentData implements Parcelable
{
@NonNull
private final String mServerId;
@ -26,6 +28,30 @@ public class PaymentData
mAuthorName = authorName;
}
private PaymentData(Parcel in)
{
mServerId = in.readString();
mProductId = in.readString();
mName = in.readString();
mImgUrl = in.readString();
mAuthorName = in.readString();
}
public static final Creator<PaymentData> CREATOR = new Creator<PaymentData>()
{
@Override
public PaymentData createFromParcel(Parcel in)
{
return new PaymentData(in);
}
@Override
public PaymentData[] newArray(int size)
{
return new PaymentData[size];
}
};
@NonNull
public String getServerId()
{
@ -55,4 +81,20 @@ public class PaymentData
{
return mAuthorName;
}
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeString(mServerId);
dest.writeString(mProductId);
dest.writeString(mName);
dest.writeString(mImgUrl);
dest.writeString(mAuthorName);
}
}

View file

@ -4,6 +4,13 @@ import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.android.billingclient.api.Purchase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
abstract class AbstractPurchaseController<V, B, UiCallback> implements PurchaseController<UiCallback>
{
@NonNull
@ -12,12 +19,16 @@ abstract class AbstractPurchaseController<V, B, UiCallback> implements PurchaseC
private final BillingManager<B> mBillingManager;
@Nullable
private UiCallback mUiCallback;
@NonNull
private final List<String> mProductIds;
AbstractPurchaseController(@NonNull PurchaseValidator<V> validator,
@NonNull BillingManager<B> billingManager)
@NonNull BillingManager<B> billingManager,
@NonNull String... productIds)
{
mValidator = validator;
mBillingManager = billingManager;
mProductIds = Collections.unmodifiableList(Arrays.asList(productIds));
}
@Override
@ -78,6 +89,38 @@ abstract class AbstractPurchaseController<V, B, UiCallback> implements PurchaseC
return mBillingManager;
}
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
@NonNull
public List<String> getProductIds()
{
return mProductIds;
}
@NonNull
final List<Purchase> filterByProductIds(@NonNull List<Purchase> purchases)
{
List<Purchase> result = new ArrayList<>();
for (Purchase purchase: purchases)
{
if (getProductIds().contains(purchase.getSku()))
result.add(purchase);
}
return Collections.unmodifiableList(result);
}
@Nullable
final Purchase findTargetPurchase(@NonNull List<Purchase> purchases)
{
for (Purchase purchase: purchases)
{
if (getProductIds().contains(purchase.getSku()))
return purchase;
}
return null;
}
abstract void onInitialize(@NonNull Activity activity);
abstract void onDestroy();

View file

@ -2,7 +2,6 @@ package com.mapswithme.maps.purchase;
import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.android.billingclient.api.BillingClient;
@ -15,8 +14,6 @@ import com.mapswithme.util.log.Logger;
import com.mapswithme.util.log.LoggerFactory;
import com.mapswithme.util.statistics.Statistics;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
class AdsRemovalPurchaseController extends AbstractPurchaseController<ValidationCallback,
@ -28,15 +25,12 @@ class AdsRemovalPurchaseController extends AbstractPurchaseController<Validation
private final ValidationCallback mValidationCallback = new AdValidationCallbackImpl();
@NonNull
private final PlayStoreBillingCallback mBillingCallback = new PlayStoreBillingCallbackImpl();
@NonNull
private final List<String> mProductIds;
AdsRemovalPurchaseController(@NonNull PurchaseValidator<ValidationCallback> validator,
@NonNull BillingManager<PlayStoreBillingCallback> billingManager,
@NonNull String... productIds)
{
super(validator, billingManager);
mProductIds = Collections.unmodifiableList(Arrays.asList(productIds));
}
@Override
@ -57,7 +51,7 @@ class AdsRemovalPurchaseController extends AbstractPurchaseController<Validation
@Override
public void queryPurchaseDetails()
{
getBillingManager().queryProductDetails(mProductIds);
getBillingManager().queryProductDetails(getProductIds());
}
private void validatePurchase(@NonNull String purchaseData)
@ -110,7 +104,7 @@ class AdsRemovalPurchaseController extends AbstractPurchaseController<Validation
@Override
public void onPurchaseSuccessful(@NonNull List<Purchase> purchases)
{
for (Purchase purchase : purchases)
for (Purchase purchase : filterByProductIds(purchases))
{
LOGGER.i(TAG, "Validating purchase '" + purchase.getSku() + "' on backend server...");
validatePurchase(purchase.getOriginalJson());
@ -173,16 +167,5 @@ class AdsRemovalPurchaseController extends AbstractPurchaseController<Validation
validatePurchase(purchaseData);
}
@Nullable
private Purchase findTargetPurchase(@NonNull List<Purchase> purchases)
{
for (Purchase purchase: purchases)
{
if (mProductIds.contains(purchase.getSku()))
return purchase;
}
return null;
}
}
}

View file

@ -0,0 +1,29 @@
package com.mapswithme.maps.purchase;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import com.mapswithme.maps.base.BaseMwmFragmentActivity;
import com.mapswithme.maps.bookmarks.data.PaymentData;
public class BookmarkPaymentActivity extends BaseMwmFragmentActivity
{
public static void start(@NonNull Activity activity, @NonNull PaymentData paymentData,
int requestCode)
{
Intent intent = new Intent(activity, BookmarkPaymentActivity.class);
Bundle args = new Bundle();
args.putParcelable(BookmarkPaymentFragment.ARG_PAYMENT_DATA, paymentData);
intent.putExtras(args);
activity.startActivityForResult(intent, requestCode);
}
@Override
protected Class<? extends Fragment> getFragmentClass()
{
return BookmarkPaymentFragment.class;
}
}

View file

@ -0,0 +1,82 @@
package com.mapswithme.maps.purchase;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmFragment;
import com.mapswithme.maps.bookmarks.data.PaymentData;
public class BookmarkPaymentFragment extends BaseMwmFragment
{
static final String ARG_PAYMENT_DATA = "arg_payment_data";
@SuppressWarnings("NullableProblems")
@NonNull
private PurchaseController<BookmarkPurchaseCallback> mPurchaseController;
@NonNull
private BookmarkPurchaseCallback mPurchaseCallback = new BookmarkPurchaseCallbackImpl();
@SuppressWarnings("NullableProblems")
@NonNull
private PaymentData mPaymentData;
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args == null)
throw new IllegalStateException("Args must be provided for payment fragment!");
PaymentData paymentData = args.getParcelable(ARG_PAYMENT_DATA);
if (paymentData == null)
throw new IllegalStateException("Payment data must be provided for payment fragment!");
mPaymentData = paymentData;
mPurchaseController = PurchaseFactory.createBookmarkPurchaseController(mPaymentData.getProductId());
mPurchaseController.initialize(getActivity());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
Bundle savedInstanceState)
{
View root = inflater.inflate(R.layout.fragment_bookmark_payment, container, false);
// TODO: temporary launch of billing flow.
root.findViewById(R.id.buy_inapp).setOnClickListener(v -> mPurchaseController.launchPurchaseFlow(mPaymentData.getProductId()));
root.findViewById(R.id.query_inapps).setOnClickListener(v -> mPurchaseController.queryPurchaseDetails());
root.findViewById(R.id.consume_apps).setOnClickListener(v -> {
});
return root;
}
@Override
public void onStart()
{
super.onStart();
mPurchaseController.addCallback(mPurchaseCallback);
}
@Override
public void onStop()
{
super.onStop();
mPurchaseController.removeCallback();
}
@Override
public void onDestroy()
{
super.onDestroy();
mPurchaseController.destroy();
}
private static class BookmarkPurchaseCallbackImpl implements BookmarkPurchaseCallback
{
// TODO: coming soon.
}
}

View file

@ -3,26 +3,35 @@ package com.mapswithme.maps.purchase;
import android.app.Activity;
import android.support.annotation.NonNull;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.SkuDetails;
import java.util.List;
class BookmarkPurchaseController extends AbstractPurchaseController<ValidationCallback,
PlayStoreBillingCallback, BookmarkPurchaseCallback>
{
@NonNull
private final PlayStoreBillingCallback mBillingCallback = new PlayStoreBillingCallbackImpl();
BookmarkPurchaseController(@NonNull PurchaseValidator<ValidationCallback> validator,
@NonNull BillingManager<PlayStoreBillingCallback> billingManager,
@NonNull String... productIds)
{
super(validator, billingManager);
// TODO: coming soon.
super(validator, billingManager, productIds);
}
@Override
void onInitialize(@NonNull Activity activity)
{
getBillingManager().addCallback(mBillingCallback);
// TODO: coming soon.
}
@Override
void onDestroy()
{
getBillingManager().removeCallback(mBillingCallback);
// TODO: coming soon.
}
@ -31,4 +40,43 @@ class BookmarkPurchaseController extends AbstractPurchaseController<ValidationCa
{
// TODO: coming soon.
}
private class PlayStoreBillingCallbackImpl implements PlayStoreBillingCallback
{
@Override
public void onPurchaseDetailsLoaded(@NonNull List<SkuDetails> details)
{
}
@Override
public void onPurchaseSuccessful(@NonNull List<Purchase> purchases)
{
}
@Override
public void onPurchaseFailure(int error)
{
}
@Override
public void onPurchaseDetailsFailure()
{
}
@Override
public void onStoreConnectionFailed()
{
}
@Override
public void onPurchasesLoaded(@NonNull List<Purchase> purchases)
{
}
}
}