diff --git a/astrid/src/main/AndroidManifest.xml b/astrid/src/main/AndroidManifest.xml
index 35c15456d..a819cbe8f 100644
--- a/astrid/src/main/AndroidManifest.xml
+++ b/astrid/src/main/AndroidManifest.xml
@@ -39,8 +39,6 @@
-
-
diff --git a/astrid/src/main/aidl/com/android/vending/billing/IMarketBillingService.aidl b/astrid/src/main/aidl/com/android/vending/billing/IMarketBillingService.aidl
deleted file mode 100644
index 6884b41f6..000000000
--- a/astrid/src/main/aidl/com/android/vending/billing/IMarketBillingService.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.vending.billing;
-
-import android.os.Bundle;
-
-interface IMarketBillingService {
- /** Given the arguments in bundle form, returns a bundle for results. */
- Bundle sendBillingRequest(in Bundle bundle);
-}
diff --git a/astrid/src/main/java/com/todoroo/astrid/activity/TaskListActivity.java b/astrid/src/main/java/com/todoroo/astrid/activity/TaskListActivity.java
index ccb9ebdcf..e845aef19 100644
--- a/astrid/src/main/java/com/todoroo/astrid/activity/TaskListActivity.java
+++ b/astrid/src/main/java/com/todoroo/astrid/activity/TaskListActivity.java
@@ -30,8 +30,6 @@ import com.todoroo.astrid.actfm.TagViewFragment;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
-import com.todoroo.astrid.billing.BillingConstants;
-import com.todoroo.astrid.billing.BillingService;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.core.CustomFilterActivity;
import com.todoroo.astrid.core.PluginServices;
@@ -75,7 +73,6 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
private int filterMode;
private FilterModeSpec filterModeSpec;
- private BillingService billingService;
/**
* @see android.app.Activity#onCreate(Bundle)
@@ -140,9 +137,6 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
if (getIntent().hasExtra(TOKEN_SOURCE)) {
trackActivitySource();
}
-
- billingService = new BillingService();
- billingService.setActivity(this);
}
@Override
@@ -319,7 +313,6 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menuDrawer.closeMenu();
- menu.findItem(R.id.menu_donate).setVisible(billingService.showDonateOption());
return super.onPrepareOptionsMenu(menu);
}
@@ -532,9 +525,6 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
rename.putExtra(TagViewFragment.EXTRA_TAG_UUID, renameTag.uuid);
startActivityForResult(rename, FilterListFragment.REQUEST_CUSTOM_INTENT);
return true;
- case R.id.menu_donate:
- billingService.requestPurchase(BillingConstants.TASKS_DONATION_ITEM_ID, BillingConstants.ITEM_TYPE_INAPP, null);
- return true;
default:
return super.onOptionsItemSelected(item);
}
@@ -569,28 +559,4 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
}
return super.onKeyDown(keyCode, event);
}
-
- @Override
- protected void onStart() {
- super.onStart();
- billingService.onStart();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- billingService.onStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- billingService.unbind();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- billingService.checkBillingSupported();
- }
}
diff --git a/astrid/src/main/java/com/todoroo/astrid/billing/BillingConstants.java b/astrid/src/main/java/com/todoroo/astrid/billing/BillingConstants.java
deleted file mode 100644
index d34515db6..000000000
--- a/astrid/src/main/java/com/todoroo/astrid/billing/BillingConstants.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.todoroo.astrid.billing;
-
-@SuppressWarnings("nls")
-public class BillingConstants {
-
- /** This is the action we use to bind to the MarketBillingService. */
- public static final String MARKET_BILLING_SERVICE_ACTION = "com.android.vending.billing.MarketBillingService.BIND";
-
- // Intent actions that we send from the BillingReceiver to the
- // BillingService. Defined by this application.
- public static final String ACTION_CONFIRM_NOTIFICATION = "com.timsu.astrid.subscriptions.CONFIRM_NOTIFICATION";
- public static final String ACTION_GET_PURCHASE_INFORMATION = "com.timsu.astrid.subscriptions.GET_PURCHASE_INFORMATION";
-
- // Intent actions that we receive in the BillingReceiver from Market.
- // These are defined by Market and cannot be changed.
- public static final String ACTION_NOTIFY = "com.android.vending.billing.IN_APP_NOTIFY";
- public static final String ACTION_RESPONSE_CODE = "com.android.vending.billing.RESPONSE_CODE";
- public static final String ACTION_PURCHASE_STATE_CHANGED = "com.android.vending.billing.PURCHASE_STATE_CHANGED";
-
- // These are the names of the extras that are passed in an intent from
- // Market to this application and cannot be changed.
- public static final String NOTIFICATION_ID = "notification_id";
- public static final String INAPP_SIGNED_DATA = "inapp_signed_data";
- public static final String INAPP_SIGNATURE = "inapp_signature";
- public static final String INAPP_REQUEST_ID = "request_id";
- public static final String INAPP_RESPONSE_CODE = "response_code";
-
- // These are the names of the fields in the request bundle.
- public static final String BILLING_REQUEST_METHOD = "BILLING_REQUEST";
- public static final String BILLING_REQUEST_API_VERSION = "API_VERSION";
- public static final String BILLING_REQUEST_PACKAGE_NAME = "PACKAGE_NAME";
- public static final String BILLING_REQUEST_ITEM_ID = "ITEM_ID";
- public static final String BILLING_REQUEST_ITEM_TYPE = "ITEM_TYPE";
- public static final String BILLING_REQUEST_DEVELOPER_PAYLOAD = "DEVELOPER_PAYLOAD";
- public static final String BILLING_REQUEST_NOTIFY_IDS = "NOTIFY_IDS";
- public static final String BILLING_REQUEST_NONCE = "NONCE";
-
- public static final String BILLING_RESPONSE_RESPONSE_CODE = "RESPONSE_CODE";
- public static final String BILLING_RESPONSE_PURCHASE_INTENT = "PURCHASE_INTENT";
- public static final String BILLING_RESPONSE_REQUEST_ID = "REQUEST_ID";
- public static final long BILLING_RESPONSE_INVALID_REQUEST_ID = -1;
-
- // These are the types supported in the IAB v2
- public static final String ITEM_TYPE_INAPP = "inapp";
- public static final String ITEM_TYPE_SUBSCRIPTION = "subs";
-
- public static final String TASKS_DONATION_ITEM_ID = "tasks_donation_4_6";
-
- public static final boolean DEBUG = true;
-
- // The response codes for a request, defined by Android Market.
- public enum ResponseCode {
- RESULT_OK,
- RESULT_USER_CANCELED,
- RESULT_SERVICE_UNAVAILABLE,
- RESULT_BILLING_UNAVAILABLE,
- RESULT_ITEM_UNAVAILABLE,
- RESULT_DEVELOPER_ERROR,
- RESULT_ERROR;
-
- // Converts from an ordinal value to the ResponseCode
- public static ResponseCode valueOf(int index) {
- ResponseCode[] values = ResponseCode.values();
- if (index < 0 || index >= values.length) {
- return RESULT_ERROR;
- }
- return values[index];
- }
- }
-
- // The possible states of an in-app purchase, as defined by Android Market.
- public enum PurchaseState {
- // Responses to requestPurchase or restoreTransactions.
- PURCHASED, // User was charged for the order.
- CANCELED, // The charge failed on the server. (NOT THE SAME AS CANCELING A SUBSCRIPTION)
- REFUNDED, // User received a refund for the order.
- EXPIRED; // Subscription expired due to non-payment or cancellation
-
- // Converts from an ordinal value to the PurchaseState
- public static PurchaseState valueOf(int index) {
- PurchaseState[] values = PurchaseState.values();
- if (index < 0 || index >= values.length) {
- return CANCELED;
- }
- return values[index];
- }
- }
-}
diff --git a/astrid/src/main/java/com/todoroo/astrid/billing/BillingReceiver.java b/astrid/src/main/java/com/todoroo/astrid/billing/BillingReceiver.java
deleted file mode 100644
index 7c502759d..000000000
--- a/astrid/src/main/java/com/todoroo/astrid/billing/BillingReceiver.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.todoroo.astrid.billing;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import com.todoroo.astrid.billing.BillingConstants.ResponseCode;
-
-public class BillingReceiver extends BroadcastReceiver {
- private static final String TAG = "BillingReceiver"; //$NON-NLS-1$
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- switch (action) {
- case BillingConstants.ACTION_PURCHASE_STATE_CHANGED:
- String signedData = intent.getStringExtra(BillingConstants.INAPP_SIGNED_DATA);
- String signature = intent.getStringExtra(BillingConstants.INAPP_SIGNATURE);
- purchaseStateChanged(context, signedData, signature);
- break;
- case BillingConstants.ACTION_NOTIFY:
- String notifyId = intent.getStringExtra(BillingConstants.NOTIFICATION_ID);
- Log.i(TAG, "notifyId: " + notifyId); //$NON-NLS-1$
- notify(context, notifyId);
- break;
- case BillingConstants.ACTION_RESPONSE_CODE:
- long requestId = intent.getLongExtra(BillingConstants.INAPP_REQUEST_ID, -1);
- int responseCodeIndex = intent.getIntExtra(BillingConstants.INAPP_RESPONSE_CODE,
- ResponseCode.RESULT_ERROR.ordinal());
- checkResponseCode(context, requestId, responseCodeIndex);
- break;
- default:
- Log.w(TAG, "unexpected action: " + action); //$NON-NLS-1$
- break;
- }
- }
-
- private void purchaseStateChanged(Context context, String signedData, String signature) {
- Intent intent = new Intent(BillingConstants.ACTION_PURCHASE_STATE_CHANGED);
- intent.setClass(context, BillingService.class);
- intent.putExtra(BillingConstants.INAPP_SIGNED_DATA, signedData);
- intent.putExtra(BillingConstants.INAPP_SIGNATURE, signature);
- context.startService(intent);
- }
-
- private void notify(Context context, String notifyId) {
- Intent intent = new Intent(BillingConstants.ACTION_GET_PURCHASE_INFORMATION);
- intent.setClass(context, BillingService.class);
- intent.putExtra(BillingConstants.NOTIFICATION_ID, notifyId);
- context.startService(intent);
- }
-
- private void checkResponseCode(Context context, long requestId, int responseCodeIndex) {
- Intent intent = new Intent(BillingConstants.ACTION_RESPONSE_CODE);
- intent.setClass(context, BillingService.class);
- intent.putExtra(BillingConstants.INAPP_REQUEST_ID, requestId);
- intent.putExtra(BillingConstants.INAPP_RESPONSE_CODE, responseCodeIndex);
- context.startService(intent);
- }
-}
diff --git a/astrid/src/main/java/com/todoroo/astrid/billing/BillingService.java b/astrid/src/main/java/com/todoroo/astrid/billing/BillingService.java
deleted file mode 100644
index 65c0b6aff..000000000
--- a/astrid/src/main/java/com/todoroo/astrid/billing/BillingService.java
+++ /dev/null
@@ -1,541 +0,0 @@
-package com.todoroo.astrid.billing;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.vending.billing.IMarketBillingService;
-import com.todoroo.astrid.billing.BillingConstants.ResponseCode;
-
-import org.tasks.billing.PurchaseHandler;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-
-import static com.todoroo.astrid.billing.Security.Purchase;
-
-@SuppressWarnings("nls")
-public class BillingService extends Service implements ServiceConnection {
- private static final String TAG = "BillingService";
-
- private static IMarketBillingService marketBillingService;
-
- private static LinkedList pendingRequests = new LinkedList<>();
-
- private static HashMap sentRequests = new HashMap<>();
-
- private PurchaseObserver purchaseObserver;
- private PurchaseHandler purchaseHandler;
-
- public boolean showDonateOption() {
- return purchaseHandler.isBillingSupported() && !purchaseHandler.userDonated();
- }
-
- abstract class BillingRequest {
- private final int mStartId;
- protected long mRequestId;
-
- public BillingRequest(int startId) {
- mStartId = startId;
- }
-
- public int getStartId() {
- return mStartId;
- }
-
- public boolean runRequest() {
- if (runIfConnected()) {
- return true;
- }
-
- if (bindToMarketBillingService()) {
- pendingRequests.add(this);
- return true;
- }
- return false;
- }
-
- /**
- * Try running the request directly if the service is already connected.
- *
- * @return true if the request ran successfully; false if the service
- * is not connected or there was an error when trying to use it
- */
- public boolean runIfConnected() {
- if (BillingConstants.DEBUG) {
- Log.d(TAG, getClass().getSimpleName());
- }
- if (marketBillingService != null) {
- try {
- mRequestId = run();
- if (BillingConstants.DEBUG) {
- Log.d(TAG, "request id: " + mRequestId);
- }
- if (mRequestId >= 0) {
- sentRequests.put(mRequestId, this);
- }
- return true;
- } catch (RemoteException e) {
- onRemoteException(e);
- }
- }
- return false;
- }
-
- /**
- * Called when a remote exception occurs while trying to execute the
- * {@link #run()} method. The derived class can override this to
- * execute exception-handling code.
- *
- * @param e the exception
- */
- protected void onRemoteException(RemoteException e) {
- Log.w(TAG, "remote billing service crashed");
- marketBillingService = null;
- }
-
- /**
- * The derived class must implement this method.
- *
- * @throws android.os.RemoteException
- */
- abstract protected long run() throws RemoteException;
-
- /**
- * This is called when Android Market sends a response code for this
- * request.
- *
- * @param responseCode the response code
- */
- protected void responseCodeReceived(ResponseCode responseCode) {
- //
- }
-
- protected Bundle makeRequestBundle(String method) {
- Bundle request = new Bundle();
- request.putString(BillingConstants.BILLING_REQUEST_METHOD, method);
- request.putInt(BillingConstants.BILLING_REQUEST_API_VERSION, 2);
- request.putString(BillingConstants.BILLING_REQUEST_PACKAGE_NAME, getPackageName());
- return request;
- }
-
- protected void logResponseCode(String method, Bundle response) {
- ResponseCode responseCode = ResponseCode.valueOf(
- response.getInt(BillingConstants.BILLING_RESPONSE_RESPONSE_CODE));
- if (BillingConstants.DEBUG) {
- Log.e(TAG, method + " received " + responseCode.toString());
- }
- }
- }
-
- class CheckBillingSupported extends BillingRequest {
- public String mProductType = null;
-
- /**
- * Constructor
- *
- * Note: Support for subscriptions implies support for one-time purchases. However, the
- * opposite is not true.
- *
- * Developers may want to perform two checks if both one-time and subscription products are
- * available.
- *
- * @param itemType Either BillingConstants.ITEM_TYPE_INAPP or BillingConstants.ITEM_TYPE_SUBSCRIPTION, indicating
- * the type of item support is being checked for.
- */
- public CheckBillingSupported(String itemType) {
- super(-1);
- mProductType = itemType;
- }
-
- @Override
- protected long run() throws RemoteException {
- Bundle request = makeRequestBundle("CHECK_BILLING_SUPPORTED");
- if (mProductType != null) {
- request.putString(BillingConstants.BILLING_REQUEST_ITEM_TYPE, mProductType);
- }
- Bundle response = marketBillingService.sendBillingRequest(request);
- int responseCode = response.getInt(BillingConstants.BILLING_RESPONSE_RESPONSE_CODE);
- if (BillingConstants.DEBUG) {
- Log.i(TAG, "CheckBillingSupported response code: " +
- ResponseCode.valueOf(responseCode));
- }
- boolean billingSupported = (responseCode == ResponseCode.RESULT_OK.ordinal());
- Log.d(TAG, "check billing support type: " + mProductType + ", response code: " + responseCode);
- ResponseHandler.checkBillingSupportedResponse(billingSupported, mProductType);
- return BillingConstants.BILLING_RESPONSE_INVALID_REQUEST_ID;
- }
- }
-
- class RequestPurchase extends BillingRequest {
- public final String mProductId;
- public final String mDeveloperPayload;
- public final String mProductType;
-
- /**
- * Constructor
- *
- * @param itemId The ID of the item to be purchased. Will be assumed to be a one-time
- * purchase.
- * @param itemType Either BillingConstants.ITEM_TYPE_INAPP or BillingConstants.ITEM_TYPE_SUBSCRIPTION,
- * indicating the type of item type support is being checked for.
- * @param developerPayload Optional data.
- */
- public RequestPurchase(String itemId, String itemType, String developerPayload) {
- // This object is never created as a side effect of starting this
- // service so we pass -1 as the startId to indicate that we should
- // not stop this service after executing this request.
- super(-1);
- mProductId = itemId;
- mDeveloperPayload = developerPayload;
- mProductType = itemType;
- }
-
- @Override
- protected long run() throws RemoteException {
- Bundle request = makeRequestBundle("REQUEST_PURCHASE");
- request.putString(BillingConstants.BILLING_REQUEST_ITEM_ID, mProductId);
- request.putString(BillingConstants.BILLING_REQUEST_ITEM_TYPE, mProductType);
- // Note that the developer payload is optional.
- if (mDeveloperPayload != null) {
- request.putString(BillingConstants.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
- }
- Bundle response = marketBillingService.sendBillingRequest(request);
- PendingIntent pendingIntent
- = response.getParcelable(BillingConstants.BILLING_RESPONSE_PURCHASE_INTENT);
- if (pendingIntent == null) {
- Log.e(TAG, "Error with requestPurchase");
- return BillingConstants.BILLING_RESPONSE_INVALID_REQUEST_ID;
- }
-
- Intent intent = new Intent();
- ResponseHandler.buyPageIntentResponse(pendingIntent, intent);
- return response.getLong(BillingConstants.BILLING_RESPONSE_REQUEST_ID,
- BillingConstants.BILLING_RESPONSE_INVALID_REQUEST_ID);
- }
-
- @Override
- protected void responseCodeReceived(ResponseCode responseCode) {
- Log.d(TAG, "received response code " + responseCode + " for request " + this);
- }
- }
-
- class ConfirmNotifications extends BillingRequest {
- final String[] mNotifyIds;
-
- public ConfirmNotifications(int startId, String[] notifyIds) {
- super(startId);
- mNotifyIds = notifyIds;
- }
-
- @Override
- protected long run() throws RemoteException {
- Bundle request = makeRequestBundle("CONFIRM_NOTIFICATIONS");
- request.putStringArray(BillingConstants.BILLING_REQUEST_NOTIFY_IDS, mNotifyIds);
- Bundle response = marketBillingService.sendBillingRequest(request);
- logResponseCode("confirmNotifications", response);
- return response.getLong(BillingConstants.BILLING_RESPONSE_REQUEST_ID,
- BillingConstants.BILLING_RESPONSE_INVALID_REQUEST_ID);
- }
- }
-
- class GetPurchaseInformation extends BillingRequest {
- long mNonce;
- final String[] mNotifyIds;
-
- public GetPurchaseInformation(int startId, String[] notifyIds) {
- super(startId);
- mNotifyIds = notifyIds;
- }
-
- @Override
- protected long run() throws RemoteException {
- mNonce = Security.generateNonce();
-
- Bundle request = makeRequestBundle("GET_PURCHASE_INFORMATION");
- request.putLong(BillingConstants.BILLING_REQUEST_NONCE, mNonce);
- request.putStringArray(BillingConstants.BILLING_REQUEST_NOTIFY_IDS, mNotifyIds);
- Bundle response = marketBillingService.sendBillingRequest(request);
- logResponseCode("getPurchaseInformation", response);
- return response.getLong(BillingConstants.BILLING_RESPONSE_REQUEST_ID,
- BillingConstants.BILLING_RESPONSE_INVALID_REQUEST_ID);
- }
- }
-
- class RestoreTransactions extends BillingRequest {
- long mNonce;
-
- public RestoreTransactions() {
- // This object is never created as a side effect of starting this
- // service so we pass -1 as the startId to indicate that we should
- // not stop this service after executing this request.
- super(-1);
- }
-
- @Override
- protected long run() throws RemoteException {
- mNonce = Security.generateNonce();
-
- Bundle request = makeRequestBundle("RESTORE_TRANSACTIONS");
- request.putLong(BillingConstants.BILLING_REQUEST_NONCE, mNonce);
- Bundle response = marketBillingService.sendBillingRequest(request);
- logResponseCode("restoreTransactions", response);
- return response.getLong(BillingConstants.BILLING_RESPONSE_REQUEST_ID,
- BillingConstants.BILLING_RESPONSE_INVALID_REQUEST_ID);
- }
-
- @Override
- protected void responseCodeReceived(ResponseCode responseCode) {
- Log.d(TAG, "received response code " + responseCode + " for request " + this);
- ResponseHandler.responseCodeReceived(responseCode);
- }
- }
-
- public void setActivity(Activity activity) {
- attachBaseContext(activity);
- purchaseHandler = new PurchaseHandler(this);
- purchaseObserver = new PurchaseObserver(activity, purchaseHandler);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null; // binding not supported for this service
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
- handleCommand(intent, startId);
- }
-
- /**
- * The {@link BillingReceiver} sends messages to this service using intents.
- * Each intent has an action and some extra arguments specific to that action.
- *
- * @param intent the intent containing one of the supported actions
- * @param startId an identifier for the invocation instance of this service
- */
- private void handleCommand(Intent intent, int startId) {
- if (intent == null) {
- return;
- }
- String action = intent.getAction();
- Log.d(TAG, "handleCommand(" + action + ")");
- switch (action) {
- case BillingConstants.ACTION_CONFIRM_NOTIFICATION:
- String[] notifyIds = intent.getStringArrayExtra(BillingConstants.NOTIFICATION_ID);
- confirmNotifications(startId, notifyIds);
- break;
- case BillingConstants.ACTION_GET_PURCHASE_INFORMATION:
- String notifyId = intent.getStringExtra(BillingConstants.NOTIFICATION_ID);
- getPurchaseInformation(startId, new String[]{notifyId});
- break;
- case BillingConstants.ACTION_PURCHASE_STATE_CHANGED:
- String signedData = intent.getStringExtra(BillingConstants.INAPP_SIGNED_DATA);
- purchaseStateChanged(startId, signedData);
- break;
- case BillingConstants.ACTION_RESPONSE_CODE:
- long requestId = intent.getLongExtra(BillingConstants.INAPP_REQUEST_ID, -1);
- int responseCodeIndex = intent.getIntExtra(BillingConstants.INAPP_RESPONSE_CODE,
- ResponseCode.RESULT_ERROR.ordinal());
- ResponseCode responseCode = ResponseCode.valueOf(responseCodeIndex);
- checkResponseCode(requestId, responseCode);
- break;
- }
- }
-
- private boolean bindToMarketBillingService() {
- Log.d(TAG, "bindToMarketBillingService()");
- try {
- boolean bindResult = bindService(
- new Intent(BillingConstants.MARKET_BILLING_SERVICE_ACTION),
- this,
- Context.BIND_AUTO_CREATE);
-
- if (bindResult) {
- return true;
- } else {
- Log.e(TAG, "Could not bind to service.");
- }
- } catch (SecurityException e) {
- Log.e(TAG, "Security exception: " + e);
- }
- return false;
- }
-
- public boolean checkBillingSupported() {
- return purchaseHandler.userDonated() || new CheckBillingSupported(BillingConstants.ITEM_TYPE_INAPP).runRequest();
- }
-
- /**
- * Requests that the given item be offered to the user for purchase. When
- * the purchase succeeds (or is canceled) the {@link BillingReceiver}
- * receives an intent with the action {@link BillingConstants#ACTION_NOTIFY}.
- * Returns false if there was an error trying to connect to Android Market.
- *
- * @param productId an identifier for the item being offered for purchase
- * @param itemType Either BillingConstants.ITEM_TYPE_INAPP or BillingConstants.ITEM_TYPE_SUBSCRIPTION, indicating
- * the type of item type support is being checked for.
- * @param developerPayload a payload that is associated with a given
- * purchase, if null, no payload is sent
- * @return false if there was an error connecting to Android Market
- */
- public boolean requestPurchase(String productId, String itemType, String developerPayload) {
- return new RequestPurchase(productId, itemType, developerPayload).runRequest();
- }
-
- /**
- * Requests transaction information for all managed items. Call this only when the
- * application is first installed or after a database wipe. Do NOT call this
- * every time the application starts up.
- *
- * @return false if there was an error connecting to Android Market
- */
- public boolean restoreTransactions() {
- return new RestoreTransactions().runRequest();
- }
-
- /**
- * Confirms receipt of a purchase state change. Each {@code notifyId} is
- * an opaque identifier that came from the server. This method sends those
- * identifiers back to the MarketBillingService, which ACKs them to the
- * server. Returns false if there was an error trying to connect to the
- * MarketBillingService.
- *
- * @param startId an identifier for the invocation instance of this service
- * @param notifyIds a list of opaque identifiers associated with purchase
- * state changes.
- * @return false if there was an error connecting to Market
- */
- private boolean confirmNotifications(int startId, String[] notifyIds) {
- return new ConfirmNotifications(startId, notifyIds).runRequest();
- }
-
- /**
- * Gets the purchase information. This message includes a list of
- * notification IDs sent to us by Android Market, which we include in
- * our request. The server responds with the purchase information,
- * encoded as a JSON string, and sends that to the {@link BillingReceiver}
- * in an intent with the action {@link BillingConstants#ACTION_PURCHASE_STATE_CHANGED}.
- * Returns false if there was an error trying to connect to the MarketBillingService.
- *
- * @param startId an identifier for the invocation instance of this service
- * @param notifyIds a list of opaque identifiers associated with purchase
- * state changes
- * @return false if there was an error connecting to Android Market
- */
- private boolean getPurchaseInformation(int startId, String[] notifyIds) {
- return new GetPurchaseInformation(startId, notifyIds).runRequest();
- }
-
- /**
- * Verifies that the data was signed with the given signature, and calls
- * ResponseHandler.purchaseResponse(android.content.Context, PurchaseState, String, String, long)
- * for each verified purchase.
- *
- * @param startId an identifier for the invocation instance of this service
- * @param signedData the signed JSON string (signed, not encrypted)
- */
- private void purchaseStateChanged(int startId, String signedData) {
- ArrayList purchases;
- purchases = Security.parse(signedData);
- ArrayList notifyList = new ArrayList<>();
- for (Purchase vp : purchases) {
- if (vp.notificationId != null) {
- notifyList.add(vp.notificationId);
- }
- Log.d(TAG, "purchase state changed productId: " + vp.productId + ", state: " + vp.purchaseState);
- ResponseHandler.purchaseResponse(vp.purchaseState, vp.productId);
- }
- if (!notifyList.isEmpty()) {
- String[] notifyIds = notifyList.toArray(new String[notifyList.size()]);
- confirmNotifications(startId, notifyIds);
- }
- }
-
- private void checkResponseCode(long requestId, ResponseCode responseCode) {
- BillingRequest request = sentRequests.get(requestId);
- if (request != null) {
- Log.d(TAG, request.getClass().getSimpleName() + ": " + responseCode);
- request.responseCodeReceived(responseCode);
- }
- sentRequests.remove(requestId);
- }
-
- /**
- * Runs any pending requests that are waiting for a connection to the
- * service to be established. This runs in the main UI thread.
- */
- private void runPendingRequests() {
- int maxStartId = -1;
- BillingRequest request;
- while ((request = pendingRequests.peek()) != null) {
- if (request.runIfConnected()) {
- // Remove the request
- pendingRequests.remove();
-
- // Remember the largest startId, which is the most recent
- // request to start this service.
- if (maxStartId < request.getStartId()) {
- maxStartId = request.getStartId();
- }
- } else {
- // The service crashed, so restart it. Note that this leaves
- // the current request on the queue.
- bindToMarketBillingService();
- return;
- }
- }
-
- // If we get here then all the requests ran successfully. If maxStartId
- // is not -1, then one of the requests started the service, so we can
- // stop it now.
- if (maxStartId >= 0) {
- if (BillingConstants.DEBUG) {
- Log.i(TAG, "stopping service, startId: " + maxStartId);
- }
- stopSelf(maxStartId);
- }
- }
-
- /**
- * This is called when we are connected to the MarketBillingService.
- * This runs in the main UI thread.
- */
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- Log.d(TAG, "Billing service connected");
- marketBillingService = IMarketBillingService.Stub.asInterface(service);
- runPendingRequests();
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- Log.w(TAG, "Billing service disconnected");
- marketBillingService = null;
- }
-
- public void unbind() {
- try {
- unbindService(this);
- } catch (IllegalArgumentException e) {
- // This might happen if the service was disconnected
- }
- }
-
- public void onStart() {
- ResponseHandler.register(purchaseObserver);
- }
-
- public void onStop() {
- ResponseHandler.unregister();
- }
-}
diff --git a/astrid/src/main/java/com/todoroo/astrid/billing/PurchaseObserver.java b/astrid/src/main/java/com/todoroo/astrid/billing/PurchaseObserver.java
deleted file mode 100644
index 910a20159..000000000
--- a/astrid/src/main/java/com/todoroo/astrid/billing/PurchaseObserver.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-
-package com.todoroo.astrid.billing;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.content.IntentSender;
-import android.os.Handler;
-import android.util.Log;
-
-import com.todoroo.astrid.billing.BillingConstants.PurchaseState;
-import com.todoroo.astrid.billing.BillingConstants.ResponseCode;
-
-import org.tasks.billing.PurchaseHandler;
-
-import java.lang.reflect.Method;
-
-public class PurchaseObserver {
- protected static final String TAG = "purchase-observer"; //$NON-NLS-1$
- protected final Activity mActivity;
- private PurchaseHandler purchaseHandler;
- private final Handler mHandler = new Handler();
- private Method mStartIntentSender;
- private final Object[] mStartIntentSenderArgs = new Object[5];
- private static final Class>[] START_INTENT_SENDER_SIG = new Class[] {
- IntentSender.class, Intent.class, int.class, int.class, int.class
- };
-
- public PurchaseObserver(Activity activity, PurchaseHandler purchaseHandler) {
- mActivity = activity;
- this.purchaseHandler = purchaseHandler;
- initCompatibilityLayer();
- }
-
- public void onBillingSupported(boolean supported, String type) {
- purchaseHandler.onBillingSupported(supported, type);
- }
-
- public void onRestoreTransactionsResponse(ResponseCode responseCode) {
- purchaseHandler.onRestoreTransactionsResponse(responseCode);
- }
-
- private void initCompatibilityLayer() {
- try {
- mStartIntentSender = mActivity.getClass().getMethod("startIntentSender", //$NON-NLS-1$
- START_INTENT_SENDER_SIG);
- } catch (SecurityException | NoSuchMethodException e) {
- mStartIntentSender = null;
- }
- }
-
- void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
- try {
- mStartIntentSenderArgs[0] = pendingIntent.getIntentSender();
- mStartIntentSenderArgs[1] = intent;
- mStartIntentSenderArgs[2] = 0;
- mStartIntentSenderArgs[3] = 0;
- mStartIntentSenderArgs[4] = 0;
- mStartIntentSender.invoke(mActivity, mStartIntentSenderArgs);
- } catch (Exception e) {
- Log.e(TAG, "error starting activity", e); //$NON-NLS-1$
- }
- }
-
- void postPurchaseStateChange(final PurchaseState purchaseState, final String itemId) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- purchaseHandler.onPurchaseStateChange(purchaseState, itemId);
- }
- });
- }
-}
diff --git a/astrid/src/main/java/com/todoroo/astrid/billing/ResponseHandler.java b/astrid/src/main/java/com/todoroo/astrid/billing/ResponseHandler.java
deleted file mode 100644
index 92b20a4f5..000000000
--- a/astrid/src/main/java/com/todoroo/astrid/billing/ResponseHandler.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.todoroo.astrid.billing;
-
-import android.app.PendingIntent;
-import android.content.Intent;
-
-import com.todoroo.astrid.billing.BillingConstants.PurchaseState;
-import com.todoroo.astrid.billing.BillingConstants.ResponseCode;
-
-public class ResponseHandler {
-
- private static PurchaseObserver sPurchaseObserver;
-
- public static synchronized void register(PurchaseObserver observer) {
- sPurchaseObserver = observer;
- }
-
- public static synchronized void unregister() {
- sPurchaseObserver = null;
- }
-
- public static void checkBillingSupportedResponse(boolean supported, String type) {
- if (sPurchaseObserver != null) {
- sPurchaseObserver.onBillingSupported(supported, type);
- }
- }
-
- public static void buyPageIntentResponse(PendingIntent pendingIntent, Intent intent) {
- if (sPurchaseObserver != null) {
- sPurchaseObserver.startBuyPageActivity(pendingIntent, intent);
- }
- }
-
- public static void purchaseResponse(final PurchaseState purchaseState, final String productId) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- // This needs to be synchronized because the UI thread can change the
- // value of sPurchaseObserver.
- synchronized (ResponseHandler.class) {
- if (sPurchaseObserver != null) {
- sPurchaseObserver.postPurchaseStateChange(purchaseState, productId);
- }
- }
- }
- }).start();
- }
-
- public static void responseCodeReceived(ResponseCode responseCode) {
- if (sPurchaseObserver != null) {
- sPurchaseObserver.onRestoreTransactionsResponse(responseCode);
- }
- }
-}
diff --git a/astrid/src/main/java/com/todoroo/astrid/billing/Security.java b/astrid/src/main/java/com/todoroo/astrid/billing/Security.java
deleted file mode 100644
index 4593243bc..000000000
--- a/astrid/src/main/java/com/todoroo/astrid/billing/Security.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.todoroo.astrid.billing;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.todoroo.astrid.billing.BillingConstants.PurchaseState;
-
-import java.security.SecureRandom;
-import java.util.ArrayList;
-
-public class Security {
- private static final SecureRandom RANDOM = new SecureRandom();
-
- public static class Purchase {
- public PurchaseState purchaseState;
- public String notificationId;
- public String productId;
-
- public Purchase(PurchaseState purchaseState, String notificationId, String productId) {
- this.purchaseState = purchaseState;
- this.notificationId = notificationId;
- this.productId = productId;
- }
- }
-
- public static long generateNonce() {
- return RANDOM.nextLong();
- }
-
- public static ArrayList parse(String signedData) {
- ArrayList purchases = new ArrayList<>();
- JsonElement jsonElement = new JsonParser().parse(signedData);
- JsonObject jsonObject = jsonElement.getAsJsonObject();
- JsonArray orders = jsonObject.getAsJsonArray("orders");
- for (JsonElement orderElement : orders) {
- JsonObject orderObject = orderElement.getAsJsonObject();
- purchases.add(new Purchase(
- PurchaseState.valueOf(orderObject.get("purchaseState").getAsInt()),
- orderObject.has("notificationId") ? orderObject.get("notificationId").getAsString() : null,
- orderObject.get("productId").getAsString()));
- }
- return purchases;
- }
-}
diff --git a/astrid/src/main/java/org/tasks/billing/PurchaseHandler.java b/astrid/src/main/java/org/tasks/billing/PurchaseHandler.java
deleted file mode 100644
index 01f9d6602..000000000
--- a/astrid/src/main/java/org/tasks/billing/PurchaseHandler.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.tasks.billing;
-
-import com.todoroo.andlib.utility.Preferences;
-import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
-import com.todoroo.astrid.billing.BillingConstants;
-import com.todoroo.astrid.billing.BillingConstants.PurchaseState;
-import com.todoroo.astrid.billing.BillingConstants.ResponseCode;
-import com.todoroo.astrid.billing.BillingService;
-
-import static com.todoroo.andlib.utility.Preferences.getBoolean;
-import static com.todoroo.andlib.utility.Preferences.getInt;
-import static com.todoroo.andlib.utility.Preferences.getStringValue;
-
-public class PurchaseHandler {
-
- private static final String PREF_PRODUCT_ID = ActFmPreferenceService.IDENTIFIER + "_inapp_product_id";
- private static final String PREF_PURCHASE_STATE = ActFmPreferenceService.IDENTIFIER + "_inapp_purchase_state";
- private static final String PREF_TRANSACTIONS_INITIALIZED = "premium_transactions_initialized"; //$NON-NLS-1$
-
- private boolean billingSupported;
- private boolean userDonated;
- private BillingService billingService;
-
- public PurchaseHandler(BillingService billingService) {
- this.billingService = billingService;
- updateDonationStatus();
- }
-
- public boolean isBillingSupported() {
- return billingSupported;
- }
-
- public boolean userDonated() {
- return userDonated;
- }
-
- private void updateDonationStatus() {
- userDonated = BillingConstants.TASKS_DONATION_ITEM_ID.equals(getStringValue(PREF_PRODUCT_ID)) &&
- getInt(PREF_PURCHASE_STATE, -1) == PurchaseState.PURCHASED.ordinal();
- }
-
- public void onBillingSupported(boolean supported, String type) {
- if (BillingConstants.ITEM_TYPE_INAPP.equals(type)) {
- billingSupported = supported;
- if (supported && !restoredTransactions()) {
- billingService.restoreTransactions();
- }
- }
- }
-
- public void onPurchaseStateChange(PurchaseState purchaseState, final String itemId) {
- if (BillingConstants.TASKS_DONATION_ITEM_ID.equals(itemId)) {
- Preferences.setString(PREF_PRODUCT_ID, itemId);
- Preferences.setInt(PREF_PURCHASE_STATE, purchaseState.ordinal());
- updateDonationStatus();
- }
- }
-
- public void onRestoreTransactionsResponse(ResponseCode responseCode) {
- if (responseCode == ResponseCode.RESULT_OK) {
- Preferences.setBoolean(PREF_TRANSACTIONS_INITIALIZED, true);
- }
- }
-
- boolean restoredTransactions() {
- return getBoolean(PREF_TRANSACTIONS_INITIALIZED, false);
- }
-}
diff --git a/astrid/src/main/res/menu/task_list_activity.xml b/astrid/src/main/res/menu/task_list_activity.xml
index ed0662fa3..4578ca028 100644
--- a/astrid/src/main/res/menu/task_list_activity.xml
+++ b/astrid/src/main/res/menu/task_list_activity.xml
@@ -39,11 +39,6 @@
android:id="@+id/menu_new_filter"
android:title="@string/FLA_new_filter"
tasks:showAsAction="never" />
-
- Dark theme
Dark widget theme
Delete task
- Donate
\ No newline at end of file
diff --git a/astrid/src/test/java/org/tasks/billing/PurchaseHandlerTest.java b/astrid/src/test/java/org/tasks/billing/PurchaseHandlerTest.java
deleted file mode 100644
index b11367518..000000000
--- a/astrid/src/test/java/org/tasks/billing/PurchaseHandlerTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.tasks.billing;
-
-import com.todoroo.astrid.billing.BillingConstants;
-import com.todoroo.astrid.billing.BillingService;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.tasks.TestUtilities.resetPreferences;
-
-@Ignore("Throws mockito exception on Travis for some reason")
-@RunWith(RobolectricTestRunner.class)
-public class PurchaseHandlerTest {
-
- BillingService billingService;
- PurchaseHandler purchaseHandler;
-
- @Before
- public void before() {
- resetPreferences();
- billingService = mock(BillingService.class);
- purchaseHandler = new PurchaseHandler(billingService);
- }
-
- @After
- public void after() {
- verifyNoMoreInteractions(billingService);
- }
-
- @Test
- public void userHasNotDonatedByDefault() {
- assertFalse(purchaseHandler.userDonated());
- }
-
- @Test
- public void billingNotSupportedByDefault() {
- assertFalse(purchaseHandler.isBillingSupported());
- }
-
- @Test
- public void haveNotRestoredTransactionsByDefault() {
- assertFalse(purchaseHandler.restoredTransactions());
- }
-
- @Test
- public void restoreTransactions() {
- purchaseHandler.onBillingSupported(true, BillingConstants.ITEM_TYPE_INAPP);
-
- verify(billingService).restoreTransactions();
- }
-
- @Test
- public void dontRestoreWhenBillingNotSupported() {
- purchaseHandler.onBillingSupported(false, BillingConstants.ITEM_TYPE_INAPP);
- }
-
- @Test
- public void dontRestoreWhenAlreadyRestored() {
- purchaseHandler.onRestoreTransactionsResponse(BillingConstants.ResponseCode.RESULT_OK);
- purchaseHandler.onBillingSupported(true, BillingConstants.ITEM_TYPE_INAPP);
- }
-
- @Test
- public void ignoreSubscriptions() {
- purchaseHandler.onBillingSupported(true, BillingConstants.ITEM_TYPE_SUBSCRIPTION);
- }
-
- @Test
- public void userDonated() {
- purchaseHandler.onPurchaseStateChange(BillingConstants.PurchaseState.PURCHASED, BillingConstants.TASKS_DONATION_ITEM_ID);
-
- assertTrue(purchaseHandler.userDonated());
- }
-
- @Test
- public void ignoreFailedTransaction() {
- purchaseHandler.onPurchaseStateChange(BillingConstants.PurchaseState.CANCELED, BillingConstants.TASKS_DONATION_ITEM_ID);
-
- assertFalse(purchaseHandler.userDonated());
- }
-
- @Test
- public void ignoreOldItems() {
- purchaseHandler.onPurchaseStateChange(BillingConstants.PurchaseState.PURCHASED, "some old purchase");
-
- assertFalse(purchaseHandler.userDonated());
- }
-
- @Test
- public void oldItemsDontReplaceLatest() {
- purchaseHandler.onPurchaseStateChange(BillingConstants.PurchaseState.PURCHASED, BillingConstants.TASKS_DONATION_ITEM_ID);
- purchaseHandler.onPurchaseStateChange(BillingConstants.PurchaseState.PURCHASED, "some old purchase");
-
- assertTrue(purchaseHandler.userDonated());
- }
-
- @Test
- public void restoredTransactions() {
- purchaseHandler.onRestoreTransactionsResponse(BillingConstants.ResponseCode.RESULT_OK);
-
- assertTrue(purchaseHandler.restoredTransactions());
- }
-
- @Test
- public void restoreTransactionsFailed() {
- purchaseHandler.onRestoreTransactionsResponse(BillingConstants.ResponseCode.RESULT_DEVELOPER_ERROR);
-
- assertFalse(purchaseHandler.restoredTransactions());
- }
-}