private boolean existsUnsupported() { Check.isTrue(Thread.holdsLock(mLock), "Must be synchronized"); for (Product product : mProducts) { if (!product.supported) { return true; } } return false; } }
BillingSupportedRequest(@Nonnull String product, int apiVersion, @Nullable Bundle extraParams) { super(BILLING_SUPPORTED, apiVersion); Check.isTrue(extraParams == null || apiVersion >= Billing.V7, "#isBillingSupportedExtraParams only works in Billing API v7 or higher"); mProduct = product; mExtraParams = extraParams; }
static void checkSupported(@Nonnull String product) { Check.isTrue(ALL.contains(product), "Unsupported product: " + product); } }
void setSkus(@Nonnull List<Sku> skus) { Check.isTrue(mSkus.isEmpty(), "Must be called only once"); mSkus.addAll(skus); }
ChangePurchaseRequest(@Nonnull String product, @Nonnull List<String> oldSkus, @Nonnull String newSku, @Nullable String payload) { super(RequestType.CHANGE_PURCHASE, Billing.V5); Check.isTrue(!oldSkus.isEmpty(), "There must be at least one old SKU to be changed"); mProduct = product; mOldSkus = new ArrayList<>(oldSkus); mNewSku = newSku; mPayload = payload; }
void removeListener(@Nonnull PlayStoreListener listener) { synchronized (mLock) { Check.isTrue(mListeners.contains(listener), "Listener " + listener + " is not in the list"); mListeners.remove(listener); if (mListeners.size() == 0) { mContext.unregisterReceiver(this); } } }
void addListener(@Nonnull PlayStoreListener listener) { synchronized (mLock) { Check.isTrue(!mListeners.contains(listener), "Listener " + listener + " is already in the list"); mListeners.add(listener); if (mListeners.size() == 1) { mContext.registerReceiver(this, new IntentFilter(ACTION)); } } }
@Nonnull static String makeInClause(int count) { Check.isTrue(count > 0, "Should be positive"); final StringBuilder sb = new StringBuilder(count * 2 + 1); sb.append("("); sb.append("?"); for (int i = 1; i < count; i++) { sb.append(",?"); } sb.append(")"); return sb.toString(); }
@Override public int changeSubscription(@Nonnull List<Sku> oldSkus, @Nonnull Sku newSku, @Nullable String payload, @Nonnull PurchaseFlow purchaseFlow) { Check.isTrue(ProductTypes.SUBSCRIPTION.equals(newSku.id.product), "Only subscriptions can be downgraded/upgraded"); final List<String> oldSkuIds = new ArrayList<>(oldSkus.size()); for (Sku oldSku : oldSkus) { Check.isTrue(oldSku.id.product.equals(newSku.id.product), "Product type can't be changed"); oldSkuIds.add(oldSku.id.code); } return changeSubscription(oldSkuIds, newSku.id.code, payload, purchaseFlow); }
@Override public void run() { Check.isTrue(Thread.holdsLock(mLock), "Must be synchronized"); // for each product we wait for: // 1. onReady to be called // 2. loadPurchased to be finished // 3. loadSkus to be finished mCount = ProductTypes.ALL.size() * 3; mCheckout.whenReady(this); }
public CachingRequestListener(@Nonnull Request<R> request, @Nonnull RequestListener<R> listener) { super(listener); Check.isTrue(mCache.hasCache(), "Cache must exist"); mRequest = request; }
/** * Same as {@link #loadSkus(String, List)}. */ @Nonnull public Request loadSkus(@Nonnull String product, @Nonnull String... skus) { Check.isTrue(skus.length > 0, "No SKUs listed, can't load them"); return loadSkus(product, Arrays.asList(skus)); }
private void onDone() { Check.isTrue(Thread.holdsLock(mLock), "Must be synchronized"); if (mCallback == null) { return; } mTasks.remove(this); mCallback.onLoaded(mProducts); mCallback = null; }
MainThread(@Nonnull Handler handler) { Check.isTrue(handler.getLooper() == Looper.getMainLooper(), "Should be main application thread handler"); mHandler = handler; }
private void countDown() { Check.isTrue(Thread.holdsLock(mLock), "Must be synchronized"); countDown(1); }
/** * Same as {@link #loadSkus(String, List)} with one element in the list. */ @Nonnull public Request loadSkus(@Nonnull String product, @Nonnull String sku) { ProductTypes.checkSupported(product); Check.isNotEmpty(sku); final List<String> list = mSkus.get(product); Check.isTrue(!list.contains(sku), "Adding same SKU is not allowed"); list.add(sku); return this; }
void setPurchases(@Nonnull List<Purchase> purchases) { Check.isTrue(mPurchases.isEmpty(), "Must be called only once"); mPurchases.addAll(Purchases.neutralize(purchases)); sort(mPurchases, PurchaseComparator.latestFirst()); }
private static boolean isNeutralized(@Nonnull List<Purchase> purchases, @Nonnull Purchase purchase) { Check.isTrue(purchase.state == Purchase.State.PURCHASED, "Must be PURCHASED"); for (int i = 1; i < purchases.size(); i++) { final Purchase same = purchases.get(i); if (same.sku.equals(purchase.sku)) { switch (same.state) { case PURCHASED: // found same later purchase => obviously there is a bug somewhere as user can't own // several purchases with same SKU. For now let's skip the item Billing.warning("Two purchases with same SKU found: " + purchase + " and " + same); break; case CANCELLED: case REFUNDED: case EXPIRED: // neutralization found => need to remove it purchases.remove(i); break; } return true; } } return false; }
@Nullable private Skus getSkuDetails(@Nonnull IInAppBillingService service, @Nonnull String packageName, ArrayList<String> skuBatch) throws RemoteException, RequestException { Check.isTrue(skuBatch.size() <= MAX_SIZE_PER_REQUEST, "SKU list is too big"); final Bundle skusBundle = new Bundle(); skusBundle.putStringArrayList("ITEM_ID_LIST", skuBatch); final Bundle bundle = service.getSkuDetails(Billing.V3, packageName, mProduct, skusBundle); if (!handleError(bundle)) { return Skus.fromBundle(bundle, mProduct); } return null; }