private boolean checkCache(@Nonnull Request request) { if (!mCache.hasCache()) { return false; } final String key = request.getCacheKey(); if (key == null) { return false; } final Cache.Entry entry = mCache.get(request.getType().getCacheKey(key)); if (entry == null) { return false; } request.onSuccess(entry.data); return true; }
public void cancel() { synchronized (this) { if (mRequest != null) { Billing.debug("Cancelling request: " + mRequest); mRequest.cancel(); } mRequest = null; } }
protected void onSuccess(@Nonnull R result) { final RequestListener<R> l = getListener(); if (l != null) { if (checkListenerCalled()) return; l.onSuccess(result); } }
@Test public void testShouldError() throws Exception { final Request request = newRequest(); final RequestListener l = mock(RequestListener.class); request.setListener(l); final Bundle bundle = newBundle(BILLING_UNAVAILABLE); final IInAppBillingService service = mock(IInAppBillingService.class); when(service.isBillingSupported(anyInt(), anyString(), anyString())).thenReturn(BILLING_UNAVAILABLE); when(service.consumePurchase(anyInt(), anyString(), anyString())).thenReturn(BILLING_UNAVAILABLE); when(service.getPurchases(anyInt(), anyString(), anyString(), anyString())).thenReturn(bundle); when(service.getPurchaseHistory(anyInt(), anyString(), anyString(), anyString(), any(Bundle.class))).thenReturn(bundle); when(service.getSkuDetails(anyInt(), anyString(), anyString(), any(Bundle.class))).thenReturn(bundle); when(service.getBuyIntent(anyInt(), anyString(), anyString(), anyString(), anyString())).thenReturn(bundle); request.start(service, "testse"); verify(l).onError(eq(BILLING_UNAVAILABLE), any(Exception.class)); verify(l, never()).onSuccess(any()); }
<R> int runWhenConnected(@Nonnull Request<R> request, @Nullable RequestListener<R> listener, @Nullable Object tag) { if (listener != null) { if (mCache.hasCache()) { listener = new CachingRequestListener<>(request, listener); } request.setListener(listener); } if (tag != null) { request.setTag(tag); } mPendingRequests.add(onConnectedService(request)); connect(); return request.getId(); }
@Override public void onSuccess(@Nonnull R result) { final String key = mRequest.getCacheKey(); final RequestType type = mRequest.getType(); if (key != null) { final long now = currentTimeMillis(); final Cache.Entry entry = new Cache.Entry(result, now + type.expiresIn); mCache.putIfNotExist(type.getCacheKey(key), entry); } switch (type) { case PURCHASE: case CHANGE_PURCHASE: case CONSUME_PURCHASE: // these requests might affect the state of purchases => we need to invalidate caches. // see Billing#onPurchaseFinished() also mCache.removeAll(RequestType.GET_PURCHASES.getCacheKeyType()); break; } super.onSuccess(result); }
@Override public String toString() { final String cacheKey = getCacheKey(); if (!TextUtils.isEmpty(cacheKey)) { return getClass().getSimpleName() + "(" + cacheKey + ")"; } else { return getClass().getSimpleName(); } }
@Override public int getId() { synchronized (this) { return mRequest != null ? mRequest.getId() : -1; } }
@Nullable @Override public Object getTag() { synchronized (this) { return mRequest != null ? mRequest.getTag() : null; } }
protected final boolean handleError(@Nullable Bundle bundle) { final int response = bundle != null ? bundle.getInt("RESPONSE_CODE") : ResponseCodes.ERROR; return handleError(response); }
@Override public void onError(int response, @Nonnull Exception e) { final RequestType type = mRequest.getType(); // sometimes it is possible that cached data is not synchronized with data on Google Play => we can // clear caches if such situation occurs switch (type) { case PURCHASE: case CHANGE_PURCHASE: if (response == ITEM_ALREADY_OWNED) { mCache.removeAll(RequestType.GET_PURCHASES.getCacheKeyType()); } break; case CONSUME_PURCHASE: if (response == ITEM_NOT_OWNED) { mCache.removeAll(RequestType.GET_PURCHASES.getCacheKeyType()); } break; } super.onError(response, e); } }
@Test public void testShouldSuccess() throws Exception { final Request r = newRequest(); final RequestListener l = mock(RequestListener.class); r.setListener(l); final IInAppBillingService service = mock(IInAppBillingService.class); when(service.isBillingSupported(anyInt(), anyString(), anyString())).thenReturn(OK); when(service.consumePurchase(anyInt(), anyString(), anyString())).thenReturn(OK); final Bundle purchases = new Bundle(); purchases.putStringArrayList("INAPP_PURCHASE_DATA_LIST", new ArrayList<String>()); when(service.getPurchases(anyInt(), anyString(), anyString(), anyString())).thenReturn(purchases); when(service.getPurchaseHistory(anyInt(), anyString(), anyString(), anyString(), any(Bundle.class))).thenReturn(purchases); final Bundle skuDetails = new Bundle(); skuDetails.putStringArrayList("DETAILS_LIST", new ArrayList<String>()); when(service.getSkuDetails(anyInt(), anyString(), anyString(), any(Bundle.class))).thenReturn(skuDetails); final Bundle buyIntent = new Bundle(); buyIntent.putParcelable("BUY_INTENT", PendingIntent.getActivity(RuntimeEnvironment.application, 100, new Intent(), 0)); when(service.getBuyIntent(anyInt(), anyString(), anyString(), anyString(), anyString())).thenReturn(buyIntent); r.start(service, ""); verify(l).onSuccess(anyObject()); verify(l, never()).onError(anyInt(), any(Exception.class)); }
@Test public void testShouldHaveSameCacheKeys() throws Exception { final Request r1 = newRequest(); final Request r2 = newRequest(); assertEquals(r1.getCacheKey(), r2.getCacheKey()); }
private void onError(int response, @Nonnull Exception e) { Check.notEquals(OK, response); final RequestListener<R> l = getListener(); if (l != null) { if (checkListenerCalled()) return; l.onError(response, e); } }