From 709312f90eb894cfa3dbb91f5f90be48a9807fe3 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:39:05 +0200
Subject: [PATCH 01/28] Fix Android project properties
---
AndroidBillingLibrary/.settings/org.eclipse.jdt.core.prefs | 4 ++++
.../.settings/org.eclipse.jdt.core.prefs | 4 ++++
DungeonsRedux/.settings/org.eclipse.jdt.core.prefs | 4 ++++
3 files changed, 12 insertions(+)
create mode 100644 AndroidBillingLibrary/.settings/org.eclipse.jdt.core.prefs
create mode 100644 AndroidBillingLibraryTest/.settings/org.eclipse.jdt.core.prefs
create mode 100644 DungeonsRedux/.settings/org.eclipse.jdt.core.prefs
diff --git a/AndroidBillingLibrary/.settings/org.eclipse.jdt.core.prefs b/AndroidBillingLibrary/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f77b31c
--- /dev/null
+++ b/AndroidBillingLibrary/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/AndroidBillingLibraryTest/.settings/org.eclipse.jdt.core.prefs b/AndroidBillingLibraryTest/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f77b31c
--- /dev/null
+++ b/AndroidBillingLibraryTest/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/DungeonsRedux/.settings/org.eclipse.jdt.core.prefs b/DungeonsRedux/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f77b31c
--- /dev/null
+++ b/DungeonsRedux/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.source=1.5
From 17a48458e8d1b1bb1b82cdb79b28a607160211c4 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:39:25 +0200
Subject: [PATCH 02/28] Remove interface @Override
---
.../src/net/robotmedia/billing/BillingService.java | 2 --
.../net/robotmedia/billing/helper/AbstractBillingActivity.java | 3 ---
.../net/robotmedia/billing/helper/AbstractBillingObserver.java | 2 --
.../robotmedia/billing/security/DefaultSignatureValidator.java | 1 -
4 files changed, 8 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
index 348e429..3c56c62 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
@@ -141,13 +141,11 @@ public IBinder onBind(Intent intent) {
return null;
}
- @Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IMarketBillingService.Stub.asInterface(service);
runPendingRequests();
}
- @Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
index c8e978c..1115b2e 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
@@ -46,17 +46,14 @@ protected void onCreate(android.os.Bundle savedInstanceState) {
mBillingObserver = new AbstractBillingObserver(this) {
- @Override
public void onBillingChecked(boolean supported) {
AbstractBillingActivity.this.onBillingChecked(supported);
}
- @Override
public void onPurchaseStateChanged(String itemId, PurchaseState state) {
AbstractBillingActivity.this.onPurchaseStateChanged(itemId, state);
}
- @Override
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
AbstractBillingActivity.this.onRequestPurchaseResponse(itemId, response);
}
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingObserver.java b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingObserver.java
index fdea04d..f982d43 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingObserver.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingObserver.java
@@ -53,12 +53,10 @@ public boolean isTransactionsRestored() {
* @param purchaseIntent
* a purchase pending intent for the specified item.
*/
- @Override
public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {
BillingController.startPurchaseIntent(activity, purchaseIntent, null);
}
- @Override
public void onTransactionsRestored() {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
final Editor editor = preferences.edit();
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/security/DefaultSignatureValidator.java b/AndroidBillingLibrary/src/net/robotmedia/billing/security/DefaultSignatureValidator.java
index 207b44f..fb9e5db 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/security/DefaultSignatureValidator.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/security/DefaultSignatureValidator.java
@@ -89,7 +89,6 @@ protected boolean validate(PublicKey publicKey, String signedData, String signat
return false;
}
- @Override
public boolean validate(String signedData, String signature) {
final String publicKey;
if (configuration == null || TextUtils.isEmpty(publicKey = configuration.getPublicKey())) {
From 7b84efadc020ba0ec6885e77c8e36ea8dbbd6c42 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:39:37 +0200
Subject: [PATCH 03/28] Ignore .metadata
---
.gitignore | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 496ee2c..a6c8a51 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-.DS_Store
\ No newline at end of file
+.DS_Store
+.metadata
\ No newline at end of file
From 6714c0d52508a869c543097bf9f640cad8d5896c Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:43:00 +0200
Subject: [PATCH 04/28] Increase minSdkVersion to avoid Lint error
---
AndroidBillingLibraryTest/AndroidManifest.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/AndroidBillingLibraryTest/AndroidManifest.xml b/AndroidBillingLibraryTest/AndroidManifest.xml
index 3ced93f..76cda86 100644
--- a/AndroidBillingLibraryTest/AndroidManifest.xml
+++ b/AndroidBillingLibraryTest/AndroidManifest.xml
@@ -3,7 +3,7 @@
package="net.robotmedia.billing.test"
android:versionCode="1"
android:versionName="1.0">
-
+
From 2d47ca5f4c9c5c263d28aa3dc4717e025c6549c1 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:44:57 +0200
Subject: [PATCH 05/28] Put uses-sdk before application and add
targetSdkVersion
---
DungeonsRedux/AndroidManifest.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/DungeonsRedux/AndroidManifest.xml b/DungeonsRedux/AndroidManifest.xml
index fc86a0d..84a1291 100644
--- a/DungeonsRedux/AndroidManifest.xml
+++ b/DungeonsRedux/AndroidManifest.xml
@@ -2,10 +2,11 @@
-
+
+
-
+
@@ -25,6 +26,5 @@
-
From 7df20c81cf699a5db54709d7bfe17c95117ea5fe Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:46:37 +0200
Subject: [PATCH 06/28] Use keepclasseswithmembers in proguard.cfg
---
AndroidBillingLibraryTest/proguard.cfg | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/AndroidBillingLibraryTest/proguard.cfg b/AndroidBillingLibraryTest/proguard.cfg
index 12dd039..4dc32b1 100644
--- a/AndroidBillingLibraryTest/proguard.cfg
+++ b/AndroidBillingLibraryTest/proguard.cfg
@@ -14,15 +14,15 @@
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
--keepclasseswithmembernames class * {
+-keepclasseswithmembers class * {
native ;
}
--keepclasseswithmembernames class * {
+-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet);
}
--keepclasseswithmembernames class * {
+-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet, int);
}
From 91f597a85ef151f461110b3afdce5e5b298a9bff Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 11:52:20 +0200
Subject: [PATCH 07/28] Remove unused strings
---
AndroidBillingLibrary/res/values/strings.xml | 1 -
AndroidBillingLibraryTest/res/values/strings.xml | 1 -
DungeonsRedux/res/values/strings.xml | 2 --
3 files changed, 4 deletions(-)
diff --git a/AndroidBillingLibrary/res/values/strings.xml b/AndroidBillingLibrary/res/values/strings.xml
index e1ab33c..75c75a3 100644
--- a/AndroidBillingLibrary/res/values/strings.xml
+++ b/AndroidBillingLibrary/res/values/strings.xml
@@ -1,5 +1,4 @@
- Hello World!
AndroidBillingLibraryTest
diff --git a/AndroidBillingLibraryTest/res/values/strings.xml b/AndroidBillingLibraryTest/res/values/strings.xml
index e1ab33c..75c75a3 100644
--- a/AndroidBillingLibraryTest/res/values/strings.xml
+++ b/AndroidBillingLibraryTest/res/values/strings.xml
@@ -1,5 +1,4 @@
- Hello World!
AndroidBillingLibraryTest
diff --git a/DungeonsRedux/res/values/strings.xml b/DungeonsRedux/res/values/strings.xml
index f158e0d..bb69610 100644
--- a/DungeonsRedux/res/values/strings.xml
+++ b/DungeonsRedux/res/values/strings.xml
@@ -18,7 +18,6 @@
-->
- Welcome to the Sample store!
Dungeons Redux
Can\'t make purchases
The Market billing
@@ -29,7 +28,6 @@
Select an item
Items for sale
Items you own
- Recent activity
Two-handed sword
Potions
From 22086ddde121c0f2c076abffa891e19eb8966da2 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 12:08:22 +0200
Subject: [PATCH 08/28] Remove interface @Override
---
.../src/net/robotmedia/billing/BillingControllerTest.java | 1 -
.../net/robotmedia/billing/helper/MockBillingActivity.java | 2 --
.../src/net/robotmedia/billing/example/Application.java | 2 --
.../src/net/robotmedia/billing/example/Dungeons.java | 4 ----
4 files changed, 9 deletions(-)
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
index 8f7c2a6..fc82563 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
@@ -128,7 +128,6 @@ public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
assertEquals(testItemId, itemId);
assertEquals(testResponse, response);
}
- @Override
public void onPurchaseStateChanged(String itemId, PurchaseState state) {}
};
BillingController.registerObserver(observer);
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java
index 5e87764..b32820f 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java
@@ -26,13 +26,11 @@ public void onBillingChecked(boolean supported) {
}
- @Override
public byte[] getObfuscationSalt() {
// TODO Auto-generated method stub
return null;
}
- @Override
public String getPublicKey() {
// TODO Auto-generated method stub
return null;
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/Application.java b/DungeonsRedux/src/net/robotmedia/billing/example/Application.java
index a0b46c6..e0cc47b 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/Application.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/Application.java
@@ -10,12 +10,10 @@ public void onCreate() {
BillingController.setDebug(true);
BillingController.setConfiguration(new BillingController.IConfiguration() {
- @Override
public byte[] getObfuscationSalt() {
return new byte[] {41, -90, -116, -41, 66, -53, 122, -110, -127, -96, -88, 77, 127, 115, 1, 73, 57, 110, 48, -116};
}
- @Override
public String getPublicKey() {
return "your public key here";
}
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
index 9413c42..640650e 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
@@ -68,17 +68,14 @@ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBillingObserver = new AbstractBillingObserver(this) {
- @Override
public void onBillingChecked(boolean supported) {
Dungeons.this.onBillingChecked(supported);
}
- @Override
public void onPurchaseStateChanged(String itemId, PurchaseState state) {
Dungeons.this.onPurchaseStateChanged(itemId, state);
}
- @Override
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
Dungeons.this.onRequestPurchaseResponse(itemId, response);
}
@@ -134,7 +131,6 @@ private void setupWidgets() {
mBuyButton.setEnabled(false);
mBuyButton.setOnClickListener(new OnClickListener() {
- @Override
public void onClick(View v) {
BillingController.requestPurchase(Dungeons.this, mSku, true /* confirm */);
}
From 48f4135d4dde781dadcd9ad70ec3c13b6ba72435 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 13:53:15 +0200
Subject: [PATCH 09/28] checkSubscriptionSupported
---
.../robotmedia/billing/BillingController.java | 75 +++++++++++++++++--
.../robotmedia/billing/BillingRequest.java | 34 ++++++++-
.../robotmedia/billing/BillingService.java | 16 +++-
.../robotmedia/billing/IBillingObserver.java | 16 +++-
.../helper/AbstractBillingActivity.java | 49 ++++++++++--
.../billing/BillingControllerTest.java | 7 ++
.../billing/BillingServiceTest.java | 5 ++
.../helper/AbstractBillingActivityTest.java | 5 ++
.../billing/helper/MockBillingActivity.java | 6 +-
.../robotmedia/billing/example/Dungeons.java | 10 +++
10 files changed, 205 insertions(+), 18 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index 5bb18ff..c2c3ff5 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -67,7 +67,8 @@ public interface IConfiguration {
public String getPublicKey();
}
- private static BillingStatus status = BillingStatus.UNKNOWN;
+ private static BillingStatus billingStatus = BillingStatus.UNKNOWN;
+ private static BillingStatus subscriptionStatus = BillingStatus.UNKNOWN;
private static Set automaticConfirmations = new HashSet();
private static IConfiguration configuration = null;
@@ -103,23 +104,61 @@ private static final void addManualConfirmation(String itemId, String notificati
}
/**
- * Returns the billing status. If it is currently unknown, checks the
- * billing status asynchronously. Observers will receive a
+ * Returns the in-app product billing support status, and checks it
+ * asynchronously if it is currently unknown. Observers will receive a
* {@link IBillingObserver#onBillingChecked(boolean)} notification in either
* case.
+ *
+ * In-app product support does not imply subscription support. To check if
+ * subscriptions are supported, use
+ * {@link BillingController#checkSubscriptionSupported(Context)}.
+ *
*
* @param context
- * @return the current billing status (unknown, supported or unsupported).
+ * @return the current in-app product billing support status (unknown,
+ * supported or unsupported). If it is unsupported, subscriptions
+ * are also unsupported.
* @see IBillingObserver#onBillingChecked(boolean)
+ * @see BillingController#checkSubscriptionSupported(Context)
*/
public static BillingStatus checkBillingSupported(Context context) {
- if (status == BillingStatus.UNKNOWN) {
+ if (billingStatus == BillingStatus.UNKNOWN) {
BillingService.checkBillingSupported(context);
} else {
- boolean supported = status == BillingStatus.SUPPORTED;
+ boolean supported = billingStatus == BillingStatus.SUPPORTED;
onBillingChecked(supported);
}
- return status;
+ return billingStatus;
+ }
+
+ /**
+ *
+ * Returns the subscription billing support status, and checks it
+ * asynchronously if it is currently unknown. Observers will receive a
+ * {@link IBillingObserver#onSubscriptionChecked(boolean)} notification in
+ * either case.
+ *
+ *
+ * No support for subscriptions does not imply that in-app products are also
+ * unsupported. To check if in-app products are supported, use
+ * {@link BillingController#checkBillingSupported(Context)}.
+ *
+ *
+ * @param context
+ * @return the current subscription billing status (unknown, supported or
+ * unsupported). If it is supported, in-app products are also
+ * supported.
+ * @see IBillingObserver#onSubscriptionChecked(boolean)
+ * @see BillingController#checkBillingSupported(Context)
+ */
+ public static BillingStatus checkSubscriptionSupported(Context context) {
+ if (subscriptionStatus == BillingStatus.UNKNOWN) {
+ BillingService.checkSubscriptionSupported(context);
+ } else {
+ boolean supported = billingStatus == BillingStatus.SUPPORTED;
+ onSubscriptionChecked(supported);
+ }
+ return billingStatus;
}
/**
@@ -291,7 +330,10 @@ static void obfuscate(Context context, Transaction purchase) {
* @param supported
*/
protected static void onBillingChecked(boolean supported) {
- status = supported ? BillingStatus.SUPPORTED : BillingStatus.UNSUPPORTED;
+ billingStatus = supported ? BillingStatus.SUPPORTED : BillingStatus.UNSUPPORTED;
+ if (billingStatus == BillingStatus.UNSUPPORTED) { // Save us the subscription check
+ subscriptionStatus = BillingStatus.UNSUPPORTED;
+ }
for (IBillingObserver o : observers) {
o.onBillingChecked(supported);
}
@@ -430,6 +472,23 @@ protected static void onResponseCode(Context context, long requestId, int respon
request.onResponseCode(response);
}
}
+
+ /**
+ * Called after the response to a
+ * {@link net.robotmedia.billing.request.CheckSubscriptionSupported} request is
+ * received.
+ *
+ * @param supported
+ */
+ protected static void onSubscriptionChecked(boolean supported) {
+ subscriptionStatus = supported ? BillingStatus.SUPPORTED : BillingStatus.UNSUPPORTED;
+ if (subscriptionStatus == BillingStatus.SUPPORTED) { // Save us the billing check
+ billingStatus = BillingStatus.SUPPORTED;
+ }
+ for (IBillingObserver o : observers) {
+ o.onSubscriptionChecked(supported);
+ }
+ }
protected static void onTransactionsRestored() {
for (IBillingObserver o : observers) {
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
index de69c2d..ee0f9ab 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
@@ -24,6 +24,9 @@
public abstract class BillingRequest {
+ private static final String ITEM_TYPE_SUBSCRIPTION = "subs";
+ private static final String REQUEST_TYPE_CHECK_BILLING_SUPPORTED = "CHECK_BILLING_SUPPORTED";
+
public static class CheckBillingSupported extends BillingRequest {
public CheckBillingSupported(String packageName, int startId) {
@@ -32,7 +35,7 @@ public CheckBillingSupported(String packageName, int startId) {
@Override
public String getRequestType() {
- return "CHECK_BILLING_SUPPORTED";
+ return REQUEST_TYPE_CHECK_BILLING_SUPPORTED;
}
@Override
@@ -42,6 +45,35 @@ protected void processOkResponse(Bundle response) {
}
}
+
+ public static class CheckSubscriptionSupported extends BillingRequest {
+
+ private static final String KEY_API_VERSION = "API_VERSION";
+ private static final String KEY_ITEM_TYPE = "ITEM_TYPE";
+
+ public CheckSubscriptionSupported(String packageName, int startId) {
+ super(packageName, startId);
+ }
+
+ @Override
+ public String getRequestType() {
+ return REQUEST_TYPE_CHECK_BILLING_SUPPORTED;
+ }
+
+ @Override
+ protected void processOkResponse(Bundle response) {
+ final boolean supported = this.isSuccess();
+ BillingController.onSubscriptionChecked(supported);
+ }
+
+ @Override
+ protected void addParams(Bundle request) {
+ request.putInt(KEY_API_VERSION, 2);
+ request.putString(KEY_ITEM_TYPE, ITEM_TYPE_SUBSCRIPTION);
+ }
+
+ }
+
public static class ConfirmNotifications extends BillingRequest {
private String[] notifyIds;
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
index 3c56c62..dbacb05 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
@@ -35,7 +35,7 @@
public class BillingService extends Service implements ServiceConnection {
private static enum Action {
- CHECK_BILLING_SUPPORTED, CONFIRM_NOTIFICATIONS, GET_PURCHASE_INFORMATION, REQUEST_PURCHASE, RESTORE_TRANSACTIONS,
+ CHECK_BILLING_SUPPORTED, CHECK_SUBSCRIPTION_SUPPORTED, CONFIRM_NOTIFICATIONS, GET_PURCHASE_INFORMATION, REQUEST_PURCHASE, RESTORE_TRANSACTIONS
}
private static final String ACTION_MARKET_BILLING_SERVICE = "com.android.vending.billing.MarketBillingService.BIND";
@@ -53,6 +53,11 @@ public static void checkBillingSupported(Context context) {
context.startService(intent);
}
+ public static void checkSubscriptionSupported(Context context) {
+ final Intent intent = createIntent(context, Action.CHECK_SUBSCRIPTION_SUPPORTED);
+ context.startService(intent);
+ }
+
public static void confirmNotifications(Context context, String[] notifyIds) {
final Intent intent = createIntent(context, Action.CONFIRM_NOTIFICATIONS);
intent.putExtra(EXTRA_NOTIFY_IDS, notifyIds);
@@ -107,6 +112,12 @@ private void checkBillingSupported(int startId) {
final CheckBillingSupported request = new CheckBillingSupported(packageName, startId);
runRequestOrQueue(request);
}
+
+ private void checkSubscriptionSupported(int startId) {
+ final String packageName = getPackageName();
+ final CheckSubscriptionSupported request = new CheckSubscriptionSupported(packageName, startId);
+ runRequestOrQueue(request);
+ }
private void confirmNotifications(Intent intent, int startId) {
final String packageName = getPackageName();
@@ -173,6 +184,9 @@ private void handleCommand(Intent intent, int startId) {
case CHECK_BILLING_SUPPORTED:
checkBillingSupported(startId);
break;
+ case CHECK_SUBSCRIPTION_SUPPORTED:
+ checkSubscriptionSupported(startId);
+ break;
case REQUEST_PURCHASE:
requestPurchase(intent, startId);
break;
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/IBillingObserver.java b/AndroidBillingLibrary/src/net/robotmedia/billing/IBillingObserver.java
index c1c3ae9..59f3ab4 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/IBillingObserver.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/IBillingObserver.java
@@ -22,14 +22,26 @@
public interface IBillingObserver {
/**
- * Called only once after determining if in-app billing is supported or not.
+ * Called after checking if in-app product billing is supported or not.
*
* @param supported
- * if true, in-app billing is supported. Otherwise, it isn't.
+ * if true, in-app product billing is supported. If false, in-app
+ * product billing is not supported, and neither is subscription
+ * billing.
* @see BillingController#checkBillingSupported(android.content.Context)
*/
public void onBillingChecked(boolean supported);
+ /**
+ * Called after checking if subscription billing is supported or not.
+ *
+ * @param supported
+ * if true, subscription billing is supported, and also is in-app
+ * product billing. Otherwise, subscription billing is not
+ * supported.
+ */
+ public void onSubscriptionChecked(boolean supported);
+
/**
* Called after requesting the purchase of the specified item.
*
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
index 1115b2e..17bac58 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
@@ -26,19 +26,54 @@ public abstract class AbstractBillingActivity extends Activity implements Billin
protected AbstractBillingObserver mBillingObserver;
/**
- * Returns the billing status. If it's currently unknown, requests to check
- * if billing is supported and
- * {@link AbstractBillingActivity#onBillingChecked(boolean)} should be
- * called later with the result.
+ *
+ * Returns the in-app product billing support status, and checks it
+ * asynchronously if it is currently unknown.
+ * {@link AbstractBillingActivity#onBillingChecked(boolean)} will be called
+ * eventually with the result.
+ *
+ *
+ * In-app product support does not imply subscription support. To check if
+ * subscriptions are supported, use
+ * {@link AbstractBillingActivity#checkSubscriptionSupported()}.
+ *
*
- * @return the current billing status (unknown, supported or unsupported).
+ * @return the current in-app product billing support status (unknown,
+ * supported or unsupported). If it is unsupported, subscriptions
+ * are also unsupported.
* @see AbstractBillingActivity#onBillingChecked(boolean)
+ * @see AbstractBillingActivity#checkSubscriptionSupported()
*/
public BillingStatus checkBillingSupported() {
return BillingController.checkBillingSupported(this);
}
+ /**
+ *
+ * Returns the subscription billing support status, and checks it
+ * asynchronously if it is currently unknown.
+ * {@link AbstractBillingActivity#onSubscriptionChecked(boolean)} will be
+ * called eventually with the result.
+ *
+ *
+ * No support for subscriptions does not imply that in-app products are also
+ * unsupported. To check if subscriptions are supported, use
+ * {@link AbstractBillingActivity#checkSubscriptionSupported()}.
+ *
+ *
+ * @return the current in-app product billing support status (unknown,
+ * supported or unsupported). If it is unsupported, subscriptions
+ * are also unsupported.
+ * @see AbstractBillingActivity#onBillingChecked(boolean)
+ * @see AbstractBillingActivity#checkSubscriptionSupported()
+ */
+ public BillingStatus checkSubscriptionSupported() {
+ return BillingController.checkSubscriptionSupported(this);
+ }
+
public abstract void onBillingChecked(boolean supported);
+
+ public abstract void onSubscriptionChecked(boolean supported);
@Override
protected void onCreate(android.os.Bundle savedInstanceState) {
@@ -49,6 +84,10 @@ protected void onCreate(android.os.Bundle savedInstanceState) {
public void onBillingChecked(boolean supported) {
AbstractBillingActivity.this.onBillingChecked(supported);
}
+
+ public void onSubscriptionChecked(boolean supported) {
+ AbstractBillingActivity.this.onSubscriptionChecked(supported);
+ }
public void onPurchaseStateChanged(String itemId, PurchaseState state) {
AbstractBillingActivity.this.onPurchaseStateChanged(itemId, state);
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
index fc82563..55c606d 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
@@ -51,6 +51,11 @@ public void testCheckBillingSupported() throws Exception {
BillingController.checkBillingSupported(getContext());
}
+ @SmallTest
+ public void testCheckSubscriptionSupported() throws Exception {
+ BillingController.checkSubscriptionSupported(getContext());
+ }
+
@MediumTest
public void testIsPurchased() throws Exception {
assertFalse(BillingController.isPurchased(getContext(), TransactionTest.TRANSACTION_1.productId));
@@ -106,6 +111,7 @@ public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {}
public void onBillingChecked(boolean supported) {}
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {}
public void onPurchaseStateChanged(String itemId, PurchaseState state) {}
+ public void onSubscriptionChecked(boolean supported) {};
};
BillingController.registerObserver(observer);
BillingController.onTransactionsRestored();
@@ -129,6 +135,7 @@ public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
assertEquals(testResponse, response);
}
public void onPurchaseStateChanged(String itemId, PurchaseState state) {}
+ public void onSubscriptionChecked(boolean supported) {};
};
BillingController.registerObserver(observer);
BillingController.onRequestPurchaseResponse(testItemId, testResponse);
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java
index fe0e672..3fb9197 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java
@@ -41,6 +41,11 @@ public void testStart() throws Exception {
public void testCheckBillingSupported() throws Exception {
BillingService.checkBillingSupported(getContext());
}
+
+ @SmallTest
+ public void testCheckSubscriptionSupported() throws Exception {
+ BillingService.checkSubscriptionSupported(getContext());
+ }
@SmallTest
public void testConfirmNotifications() throws Exception {
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/AbstractBillingActivityTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/AbstractBillingActivityTest.java
index 6f984ca..7e01e8d 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/AbstractBillingActivityTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/AbstractBillingActivityTest.java
@@ -38,6 +38,11 @@ protected void setUp() throws Exception {
public void testCheckBillingSupported() throws Exception {
mActivity.checkBillingSupported();
}
+
+ @MediumTest
+ public void testCheckSubscriptionSupported() throws Exception {
+ mActivity.checkSubscriptionSupported();
+ }
// TODO: Find a way to test the following without hanging the test suite
// @SmallTest
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java
index b32820f..4b9599a 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingActivity.java
@@ -23,7 +23,11 @@ public class MockBillingActivity extends AbstractBillingActivity {
@Override
public void onBillingChecked(boolean supported) {
// TODO Auto-generated method stub
-
+ }
+
+ @Override
+ public void onSubscriptionChecked(boolean supported) {
+ // TODO Auto-generated method stub
}
public byte[] getObfuscationSalt() {
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
index 640650e..50e0496 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
@@ -79,6 +79,11 @@ public void onPurchaseStateChanged(String itemId, PurchaseState state) {
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
Dungeons.this.onRequestPurchaseResponse(itemId, response);
}
+
+ public void onSubscriptionChecked(boolean supported) {
+ Dungeons.this.onSubscriptionChecked(supported);
+ }
+
};
setContentView(R.layout.main);
@@ -86,6 +91,7 @@ public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
setupWidgets();
BillingController.registerObserver(mBillingObserver);
BillingController.checkBillingSupported(this);
+ BillingController.checkSubscriptionSupported(this);
updateOwnedItems();
}
@@ -112,6 +118,10 @@ public void onPurchaseStateChanged(String itemId, PurchaseState state) {
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
}
+
+ public void onSubscriptionChecked(boolean supported) {
+
+ }
/**
* Restores previous transactions, if any. This happens if the application
From 874d30ced7a29802f44ba71f8c8faa5cf5d5901c Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 18:22:18 +0200
Subject: [PATCH 10/28] onBillingChecked and onSubscriptionChecked unit tests +
bug fix
---
.../robotmedia/billing/BillingController.java | 4 +-
.../billing/BillingControllerTest.java | 87 +++++++++++++++----
.../billing/helper/MockBillingObserver.java | 28 ++++++
3 files changed, 102 insertions(+), 17 deletions(-)
create mode 100644 AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingObserver.java
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index c2c3ff5..e376141 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -155,10 +155,10 @@ public static BillingStatus checkSubscriptionSupported(Context context) {
if (subscriptionStatus == BillingStatus.UNKNOWN) {
BillingService.checkSubscriptionSupported(context);
} else {
- boolean supported = billingStatus == BillingStatus.SUPPORTED;
+ boolean supported = subscriptionStatus == BillingStatus.SUPPORTED;
onSubscriptionChecked(supported);
}
- return billingStatus;
+ return subscriptionStatus;
}
/**
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
index 55c606d..4cf7f3c 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java
@@ -19,13 +19,13 @@
import java.util.List;
import java.util.Set;
+import net.robotmedia.billing.BillingController.BillingStatus;
import net.robotmedia.billing.BillingRequest.ResponseCode;
+import net.robotmedia.billing.helper.MockBillingObserver;
import net.robotmedia.billing.model.BillingDB;
import net.robotmedia.billing.model.BillingDBTest;
import net.robotmedia.billing.model.Transaction;
import net.robotmedia.billing.model.TransactionTest;
-import net.robotmedia.billing.model.Transaction.PurchaseState;
-import android.app.PendingIntent;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
@@ -103,15 +103,11 @@ public void testGetTransactionsString() throws Exception {
@SmallTest
public void testOnTransactionRestored() throws Exception {
final Set flags = new HashSet();
- final IBillingObserver observer = new IBillingObserver() {
+ final IBillingObserver observer = new MockBillingObserver() {
+ @Override
public void onTransactionsRestored() {
flags.add(true);
}
- public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {}
- public void onBillingChecked(boolean supported) {}
- public void onRequestPurchaseResponse(String itemId, ResponseCode response) {}
- public void onPurchaseStateChanged(String itemId, PurchaseState state) {}
- public void onSubscriptionChecked(boolean supported) {};
};
BillingController.registerObserver(observer);
BillingController.onTransactionsRestored();
@@ -124,22 +120,83 @@ public void testOnRequestPurchaseResponse() throws Exception {
final String testItemId = TransactionTest.TRANSACTION_1.productId;
final ResponseCode testResponse = ResponseCode.RESULT_OK;
final Set flags = new HashSet();
- final IBillingObserver observer = new IBillingObserver() {
-
- public void onTransactionsRestored() {}
- public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {}
- public void onBillingChecked(boolean supported) {}
+ final IBillingObserver observer = new MockBillingObserver() {
+ @Override
public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
flags.add(true);
assertEquals(testItemId, itemId);
assertEquals(testResponse, response);
}
- public void onPurchaseStateChanged(String itemId, PurchaseState state) {}
- public void onSubscriptionChecked(boolean supported) {};
};
BillingController.registerObserver(observer);
BillingController.onRequestPurchaseResponse(testItemId, testResponse);
assertEquals(flags.size(), 1);
BillingController.unregisterObserver(observer);
}
+
+ public void testOnBillingCheckedSupportedTrue() throws Exception {
+ final Set flags = new HashSet();
+ final IBillingObserver observer = new MockBillingObserver() {
+ @Override
+ public void onBillingChecked(boolean supported) {
+ flags.add(true);
+ assertTrue(supported);
+ }
+ };
+ BillingController.registerObserver(observer);
+ BillingController.onBillingChecked(true);
+ assertEquals(flags.size(), 1);
+ assertEquals(BillingController.checkBillingSupported(getContext()), BillingStatus.SUPPORTED);
+ BillingController.unregisterObserver(observer);
+ }
+
+ public void testOnBillingCheckedSupportedFalse() throws Exception {
+ final Set flags = new HashSet();
+ final IBillingObserver observer = new MockBillingObserver() {
+ @Override
+ public void onBillingChecked(boolean supported) {
+ flags.add(true);
+ assertFalse(supported);
+ }
+ };
+ BillingController.registerObserver(observer);
+ BillingController.onBillingChecked(false);
+ assertEquals(flags.size(), 1);
+ assertEquals(BillingController.checkBillingSupported(getContext()), BillingStatus.UNSUPPORTED);
+ assertEquals(BillingController.checkSubscriptionSupported(getContext()), BillingStatus.UNSUPPORTED);
+ BillingController.unregisterObserver(observer);
+ }
+
+ public void testOnSubscriptionCheckedSupportedTrue() throws Exception {
+ final Set flags = new HashSet();
+ final IBillingObserver observer = new MockBillingObserver() {
+ @Override
+ public void onSubscriptionChecked(boolean supported) {
+ flags.add(true);
+ assertTrue(supported);
+ }
+ };
+ BillingController.registerObserver(observer);
+ BillingController.onSubscriptionChecked(true);
+ assertEquals(flags.size(), 1);
+ assertEquals(BillingController.checkBillingSupported(getContext()), BillingStatus.SUPPORTED);
+ assertEquals(BillingController.checkSubscriptionSupported(getContext()), BillingStatus.SUPPORTED);
+ BillingController.unregisterObserver(observer);
+ }
+
+ public void testOnSubscriptionCheckedSupportedFalse() throws Exception {
+ final Set flags = new HashSet();
+ final IBillingObserver observer = new MockBillingObserver() {
+ @Override
+ public void onSubscriptionChecked(boolean supported) {
+ flags.add(true);
+ assertFalse(supported);
+ }
+ };
+ BillingController.registerObserver(observer);
+ BillingController.onSubscriptionChecked(false);
+ assertEquals(flags.size(), 1);
+ assertEquals(BillingController.checkSubscriptionSupported(getContext()), BillingStatus.UNSUPPORTED);
+ BillingController.unregisterObserver(observer);
+ }
}
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingObserver.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingObserver.java
new file mode 100644
index 0000000..f9bb54b
--- /dev/null
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/helper/MockBillingObserver.java
@@ -0,0 +1,28 @@
+package net.robotmedia.billing.helper;
+
+import android.app.PendingIntent;
+import net.robotmedia.billing.BillingRequest.ResponseCode;
+import net.robotmedia.billing.IBillingObserver;
+import net.robotmedia.billing.model.Transaction.PurchaseState;
+
+public class MockBillingObserver implements IBillingObserver {
+
+ public void onBillingChecked(boolean supported) {
+ }
+
+ public void onSubscriptionChecked(boolean supported) {
+ }
+
+ public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {
+ }
+
+ public void onPurchaseStateChanged(String itemId, PurchaseState state) {
+ }
+
+ public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
+ }
+
+ public void onTransactionsRestored() {
+ }
+
+}
From 65d08e9babb5b8df3dc11d894f30971b468f7ec8 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 18:46:30 +0200
Subject: [PATCH 11/28] requestSubscription
---
.../robotmedia/billing/BillingController.java | 47 ++++++++++++++++++-
.../robotmedia/billing/BillingRequest.java | 12 +++--
.../robotmedia/billing/BillingService.java | 14 +++++-
.../helper/AbstractBillingActivity.java | 15 ++++++
.../billing/BillingServiceTest.java | 5 ++
5 files changed, 86 insertions(+), 7 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index e376141..b1c0533 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -537,6 +537,10 @@ public static boolean registerObserver(IBillingObserver observer) {
/**
* Requests the purchase of the specified item. The transaction will not be
* confirmed automatically.
+ *
+ * For subscriptions, use {@link #requestSubscription(Context, String)}
+ * instead.
+ *
*
* @param context
* @param itemId
@@ -548,8 +552,14 @@ public static void requestPurchase(Context context, String itemId) {
}
/**
+ *
* Requests the purchase of the specified item with optional automatic
* confirmation.
+ *
+ *
+ * For subscriptions, use
+ * {@link #requestSubscription(Context, String, boolean)} instead.
+ *
*
* @param context
* @param itemId
@@ -560,13 +570,48 @@ public static void requestPurchase(Context context, String itemId) {
* to {@link #confirmNotifications(Context, String)}.
* @see IBillingObserver#onPurchaseIntent(String, PendingIntent)
*/
- public static void requestPurchase(Context context, String itemId, boolean confirm) {
+ public static void requestPurchase(Context context, String itemId,
+ boolean confirm) {
if (confirm) {
automaticConfirmations.add(itemId);
}
BillingService.requestPurchase(context, itemId, null);
}
+ /**
+ * Requests the purchase of the specified subscription item. The transaction
+ * will not be confirmed automatically.
+ *
+ * @param context
+ * @param itemId
+ * id of the item to be purchased.
+ * @see #requestSubscription(Context, String, boolean)
+ */
+ public static void requestSubscription(Context context, String itemId) {
+ requestSubscription(context, itemId, false);
+ }
+
+ /**
+ * Requests the purchase of the specified subscription item with optional
+ * automatic confirmation.
+ *
+ * @param context
+ * @param itemId
+ * id of the item to be purchased.
+ * @param confirm
+ * if true, the transaction will be confirmed automatically. If
+ * false, the transaction will have to be confirmed with a call
+ * to {@link #confirmNotifications(Context, String)}.
+ * @see IBillingObserver#onPurchaseIntent(String, PendingIntent)
+ */
+ public static void requestSubscription(Context context, String itemId,
+ boolean confirm) {
+ if (confirm) {
+ automaticConfirmations.add(itemId);
+ }
+ BillingService.requestSubscription(context, itemId, null);
+ }
+
/**
* Requests to restore all transactions.
*
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
index ee0f9ab..d9feda9 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
@@ -24,8 +24,10 @@
public abstract class BillingRequest {
- private static final String ITEM_TYPE_SUBSCRIPTION = "subs";
- private static final String REQUEST_TYPE_CHECK_BILLING_SUPPORTED = "CHECK_BILLING_SUPPORTED";
+ public static final String ITEM_TYPE_INAPP = "inapp";
+ public static final String ITEM_TYPE_SUBSCRIPTION = "subs";
+ private static final String KEY_ITEM_TYPE = "ITEM_TYPE";
+ private static final String REQUEST_TYPE_CHECK_BILLING_SUPPORTED = "CHECK_BILLING_SUPPORTED";
public static class CheckBillingSupported extends BillingRequest {
@@ -49,7 +51,6 @@ protected void processOkResponse(Bundle response) {
public static class CheckSubscriptionSupported extends BillingRequest {
private static final String KEY_API_VERSION = "API_VERSION";
- private static final String KEY_ITEM_TYPE = "ITEM_TYPE";
public CheckSubscriptionSupported(String packageName, int startId) {
super(packageName, startId);
@@ -123,21 +124,24 @@ public String getRequestType() {
public static class RequestPurchase extends BillingRequest {
private String itemId;
+ private String itemType;
private String developerPayload;
private static final String KEY_ITEM_ID = "ITEM_ID";
private static final String KEY_DEVELOPER_PAYLOAD = "DEVELOPER_PAYLOAD";
private static final String KEY_PURCHASE_INTENT = "PURCHASE_INTENT";
- public RequestPurchase(String packageName, int startId, String itemId, String developerPayload) {
+ public RequestPurchase(String packageName, int startId, String itemId, String itemType, String developerPayload) {
super(packageName, startId);
this.itemId = itemId;
+ this.itemType = itemType;
this.developerPayload = developerPayload;
}
@Override
protected void addParams(Bundle request) {
request.putString(KEY_ITEM_ID, itemId);
+ request.putString(KEY_ITEM_TYPE, itemType);
if (developerPayload != null) {
request.putString(KEY_DEVELOPER_PAYLOAD, developerPayload);
}
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
index dbacb05..81cf230 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
@@ -40,8 +40,8 @@ private static enum Action {
private static final String ACTION_MARKET_BILLING_SERVICE = "com.android.vending.billing.MarketBillingService.BIND";
private static final String EXTRA_DEVELOPER_PAYLOAD = "DEVELOPER_PAYLOAD";
-
private static final String EXTRA_ITEM_ID = "ITEM_ID";
+ private static final String EXTRA_ITEM_TYPE = "ITEM_TYPE";
private static final String EXTRA_NONCE = "EXTRA_NONCE";
private static final String EXTRA_NOTIFY_IDS = "NOTIFY_IDS";
private static LinkedList mPendingRequests = new LinkedList();
@@ -85,6 +85,15 @@ public static void getPurchaseInformation(Context context, String[] notifyIds, l
public static void requestPurchase(Context context, String itemId, String developerPayload) {
final Intent intent = createIntent(context, Action.REQUEST_PURCHASE);
intent.putExtra(EXTRA_ITEM_ID, itemId);
+ intent.putExtra(EXTRA_ITEM_TYPE, BillingRequest.ITEM_TYPE_INAPP);
+ intent.putExtra(EXTRA_DEVELOPER_PAYLOAD, developerPayload);
+ context.startService(intent);
+ }
+
+ public static void requestSubscription(Context context, String itemId, String developerPayload) {
+ final Intent intent = createIntent(context, Action.REQUEST_PURCHASE);
+ intent.putExtra(EXTRA_ITEM_ID, itemId);
+ intent.putExtra(EXTRA_ITEM_TYPE, BillingRequest.ITEM_TYPE_SUBSCRIPTION);
intent.putExtra(EXTRA_DEVELOPER_PAYLOAD, developerPayload);
context.startService(intent);
}
@@ -204,8 +213,9 @@ private void handleCommand(Intent intent, int startId) {
private void requestPurchase(Intent intent, int startId) {
final String packageName = getPackageName();
final String itemId = intent.getStringExtra(EXTRA_ITEM_ID);
+ final String itemType = intent.getStringExtra(EXTRA_ITEM_TYPE);
final String developerPayload = intent.getStringExtra(EXTRA_DEVELOPER_PAYLOAD);
- final RequestPurchase request = new RequestPurchase(packageName, startId, itemId, developerPayload);
+ final RequestPurchase request = new RequestPurchase(packageName, startId, itemId, itemType, developerPayload);
runRequestOrQueue(request);
}
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
index 17bac58..4415c05 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
@@ -135,6 +135,21 @@ public void requestPurchase(String itemId) {
BillingController.requestPurchase(this, itemId);
}
+ /**
+ * Requests the purchase of the specified subscription item. The transaction
+ * will not be confirmed automatically; such confirmation could be handled
+ * in {@link AbstractBillingActivity#onPurchaseExecuted(String)}. If
+ * automatic confirmation is preferred use
+ * {@link BillingController#requestPurchase(android.content.Context, String, boolean)}
+ * instead.
+ *
+ * @param itemId
+ * id of the item to be purchased.
+ */
+ public void requestSubscription(String itemId) {
+ BillingController.requestSubscription(this, itemId);
+ }
+
/**
* Requests to restore all transactions.
*/
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java
index 3fb9197..375bd4d 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingServiceTest.java
@@ -62,6 +62,11 @@ public void testRequestPurchase() throws Exception {
BillingService.requestPurchase(getContext(), ITEM_ID, null);
}
+ @SmallTest
+ public void testRequestSubscription() throws Exception {
+ BillingService.requestSubscription(getContext(), ITEM_ID, null);
+ }
+
@SmallTest
public void testRestoreTransactions() throws Exception {
BillingService.restoreTransations(getContext(), NONCE);
From 4e5e6057d01720e04e0bd6172937c15244ba69ab Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 18:52:08 +0200
Subject: [PATCH 12/28] PurchaseState.EXPIRED
---
.../net/robotmedia/billing/model/Transaction.java | 12 ++++++++----
.../robotmedia/billing/model/TransactionTest.java | 1 +
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/model/Transaction.java b/AndroidBillingLibrary/src/net/robotmedia/billing/model/Transaction.java
index 297baf8..b3b01e8 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/model/Transaction.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/model/Transaction.java
@@ -21,10 +21,14 @@
public class Transaction {
public enum PurchaseState {
- // Responses to requestPurchase or restoreTransactions.
- PURCHASED, // 0: User was charged for the order.
- CANCELLED, // 1: The charge failed on the server.
- REFUNDED; // 2: User received a refund for the order.
+ // Responses to requestPurchase or restoreTransactions.
+ PURCHASED, // 0: User was charged for the order.
+ CANCELLED, // 1: The charge failed on the server.
+ REFUNDED, // 2: User received a refund for the order.
+ EXPIRED; // 3: Sent at the end of a billing cycle to indicate that the
+ // subscription expired without renewal because of
+ // non-payment or user-cancellation. Your app does not need
+ // to grant continued access to the subscription content.
// Converts from an ordinal value to the PurchaseState
public static PurchaseState valueOf(int index) {
diff --git a/AndroidBillingLibraryTest/src/net/robotmedia/billing/model/TransactionTest.java b/AndroidBillingLibraryTest/src/net/robotmedia/billing/model/TransactionTest.java
index 71b2789..4275333 100644
--- a/AndroidBillingLibraryTest/src/net/robotmedia/billing/model/TransactionTest.java
+++ b/AndroidBillingLibraryTest/src/net/robotmedia/billing/model/TransactionTest.java
@@ -69,6 +69,7 @@ public void testPurchaseStateOrdinal() throws Exception {
assertEquals(Transaction.PurchaseState.PURCHASED.ordinal(), 0);
assertEquals(Transaction.PurchaseState.CANCELLED.ordinal(), 1);
assertEquals(Transaction.PurchaseState.REFUNDED.ordinal(), 2);
+ assertEquals(Transaction.PurchaseState.EXPIRED.ordinal(), 3);
}
@SmallTest
From 1f9a196619feb066b038585dab5d16012cbf69da Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 19:03:02 +0200
Subject: [PATCH 13/28] Add subscription items
---
DungeonsRedux/res/values/strings.xml | 2 ++
.../example/auxiliary/CatalogEntry.java | 20 +++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/DungeonsRedux/res/values/strings.xml b/DungeonsRedux/res/values/strings.xml
index bb69610..901e105 100644
--- a/DungeonsRedux/res/values/strings.xml
+++ b/DungeonsRedux/res/values/strings.xml
@@ -31,6 +31,8 @@
Two-handed sword
Potions
+ Subscription monthly
+ Subscription yearly
android.test.canceled
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java b/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
index 66c04b2..32600bb 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
@@ -5,16 +5,18 @@
public class CatalogEntry {
/**
- * Each product in the catalog is either MANAGED or UNMANAGED. MANAGED means
- * that the product can be purchased only once per user (such as a new level
- * in a game). The purchase is remembered by Android Market and can be
- * restored if this application is uninstalled and then re-installed.
- * UNMANAGED is used for products that can be used up and purchased multiple
- * times (such as poker chips). It is up to the application to keep track of
- * UNMANAGED products for the user.
+ * Each product in the catalog can be MANAGED, UNMANAGED, or SUBSCRIPTION.
+ * MANAGED means that the product can be purchased only once per user (such
+ * as a new level in a game). The purchase is remembered by Android Market
+ * and can be restored if this application is uninstalled and then
+ * re-installed. UNMANAGED is used for products that can be used up and
+ * purchased multiple times (such as poker chips). It is up to the
+ * application to keep track of UNMANAGED products for the user.
+ * SUBSCRIPTION is just like MANAGED except that the user gets charged
+ * monthly or yearly.
*/
public enum Managed {
- MANAGED, UNMANAGED
+ MANAGED, UNMANAGED, SUBSCRIPTION
}
public String sku;
@@ -31,6 +33,8 @@ public CatalogEntry(String sku, int nameId, Managed managed) {
public static final CatalogEntry[] CATALOG = new CatalogEntry[] {
new CatalogEntry("sword_001", R.string.two_handed_sword, Managed.MANAGED),
new CatalogEntry("potion_001", R.string.potions, Managed.UNMANAGED),
+ new CatalogEntry("subscription_monthly", R.string.subscription_monthly, Managed.UNMANAGED),
+ new CatalogEntry("subscription_yearly", R.string.subscription_yearly, Managed.UNMANAGED),
new CatalogEntry("android.test.purchased", R.string.android_test_purchased, Managed.UNMANAGED),
new CatalogEntry("android.test.canceled", R.string.android_test_canceled, Managed.UNMANAGED),
new CatalogEntry("android.test.refunded", R.string.android_test_refunded, Managed.UNMANAGED),
From b21fd2322b50747294ab9b5bcae9c1da8a6de081 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sun, 29 Jul 2012 19:03:20 +0200
Subject: [PATCH 14/28] Update to new Dungeons look
---
DungeonsRedux/res/layout/item_row.xml | 6 ++----
DungeonsRedux/res/layout/main.xml | 5 +----
DungeonsRedux/res/values/colors.xml | 1 -
3 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/DungeonsRedux/res/layout/item_row.xml b/DungeonsRedux/res/layout/item_row.xml
index 9accc5f..313262b 100644
--- a/DungeonsRedux/res/layout/item_row.xml
+++ b/DungeonsRedux/res/layout/item_row.xml
@@ -19,14 +19,12 @@
+ android:layout_height="wrap_content">
+ android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/DungeonsRedux/res/layout/main.xml b/DungeonsRedux/res/layout/main.xml
index 40a2b9a..fbf49f6 100644
--- a/DungeonsRedux/res/layout/main.xml
+++ b/DungeonsRedux/res/layout/main.xml
@@ -22,8 +22,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:background="@color/screen_background">
+ android:paddingRight="4dip">
@@ -60,7 +58,6 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="10dip"
- android:textColor="@android:color/black"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:text="@string/items_you_own" />
diff --git a/DungeonsRedux/res/values/colors.xml b/DungeonsRedux/res/values/colors.xml
index 1b08c48..35ddbf4 100644
--- a/DungeonsRedux/res/values/colors.xml
+++ b/DungeonsRedux/res/values/colors.xml
@@ -18,6 +18,5 @@
-->
- #ffc0f0c0
#ffc00000
From f1a4105352cf20c37026fd9752f3b5e19a6e3662 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 09:31:01 +0200
Subject: [PATCH 15/28] Use requestSubscription for subscriptions
---
.../src/net/robotmedia/billing/example/Dungeons.java | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
index 50e0496..1e9746a 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
@@ -23,6 +23,7 @@
import net.robotmedia.billing.example.R;
import net.robotmedia.billing.example.auxiliary.CatalogAdapter;
import net.robotmedia.billing.example.auxiliary.CatalogEntry;
+import net.robotmedia.billing.example.auxiliary.CatalogEntry.Managed;
import net.robotmedia.billing.helper.AbstractBillingObserver;
import net.robotmedia.billing.model.Transaction;
import net.robotmedia.billing.model.Transaction.PurchaseState;
@@ -41,7 +42,7 @@ public class Dungeons extends Activity {
private static final int DIALOG_BILLING_NOT_SUPPORTED_ID = 2;
- private String mSku;
+ private CatalogEntry mSelectedItem;
private CatalogAdapter mCatalogAdapter;
@@ -142,7 +143,11 @@ private void setupWidgets() {
mBuyButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- BillingController.requestPurchase(Dungeons.this, mSku, true /* confirm */);
+ if (mSelectedItem.managed != Managed.SUBSCRIPTION) {
+ BillingController.requestPurchase(Dungeons.this, mSelectedItem.sku, true /* confirm */);
+ } else {
+ BillingController.requestSubscription(Dungeons.this, mSelectedItem.sku, true /* confirm */);
+ }
}
});
@@ -152,7 +157,7 @@ public void onClick(View v) {
mSelectItemSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- mSku = CatalogEntry.CATALOG[position].sku;
+ mSelectedItem = CatalogEntry.CATALOG[position];
}
public void onNothingSelected(AdapterView> arg0) {
From 681f020b45fdd943b4c185cdd7d4a00465deeec1 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 11:14:14 +0200
Subject: [PATCH 16/28] Fixed isPurchased javadoc. Closes #68.
---
.../src/net/robotmedia/billing/BillingController.java | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index b1c0533..39441e6 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -274,9 +274,8 @@ public static List getTransactions(Context context, String itemId)
/**
* Returns true if the specified item has been registered as purchased in
- * local memory. Note that if the item was later canceled or refunded this
- * will still return true. Also note that the item might have been purchased
- * in another installation, but not yet registered in this one.
+ * local memory, false otherwise. Also note that the item might have been
+ * purchased in another installation, but not yet registered in this one.
*
* @param context
* @param itemId
From 40269a1b7a12a15ae77dfa0c343b68c87153465c Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 11:44:39 +0200
Subject: [PATCH 17/28] Add developerPayload to requestPurchase and
requestSubscription. Closes #59.
---
.../robotmedia/billing/BillingController.java | 45 ++++++++++---------
.../robotmedia/billing/example/Dungeons.java | 4 +-
2 files changed, 27 insertions(+), 22 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index 39441e6..bce19e1 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -206,7 +206,7 @@ public static int countPurchases(Context context, String itemId) {
itemId = salt != null ? Security.obfuscate(context, salt, itemId) : itemId;
return TransactionManager.countPurchases(context, itemId);
}
-
+
protected static void debug(String message) {
if (debug) {
Log.d(LOG_TAG, message);
@@ -330,7 +330,9 @@ static void obfuscate(Context context, Transaction purchase) {
*/
protected static void onBillingChecked(boolean supported) {
billingStatus = supported ? BillingStatus.SUPPORTED : BillingStatus.UNSUPPORTED;
- if (billingStatus == BillingStatus.UNSUPPORTED) { // Save us the subscription check
+ if (billingStatus == BillingStatus.UNSUPPORTED) { // Save us the
+ // subscription
+ // check
subscriptionStatus = BillingStatus.UNSUPPORTED;
}
for (IBillingObserver o : observers) {
@@ -432,8 +434,7 @@ protected static void onPurchaseStateChanged(Context context, String signedData,
}
/**
- * Called after a {@link net.robotmedia.billing.BillingRequest} is
- * sent.
+ * Called after a {@link net.robotmedia.billing.BillingRequest} is sent.
*
* @param requestId
* the id the request.
@@ -451,8 +452,7 @@ protected static void onRequestSent(long requestId, BillingRequest request) {
}
/**
- * Called after a {@link net.robotmedia.billing.BillingRequest} is
- * sent.
+ * Called after a {@link net.robotmedia.billing.BillingRequest} is sent.
*
* @param context
* @param requestId
@@ -471,17 +471,18 @@ protected static void onResponseCode(Context context, long requestId, int respon
request.onResponseCode(response);
}
}
-
+
/**
* Called after the response to a
- * {@link net.robotmedia.billing.request.CheckSubscriptionSupported} request is
- * received.
+ * {@link net.robotmedia.billing.request.CheckSubscriptionSupported} request
+ * is received.
*
* @param supported
*/
protected static void onSubscriptionChecked(boolean supported) {
subscriptionStatus = supported ? BillingStatus.SUPPORTED : BillingStatus.UNSUPPORTED;
- if (subscriptionStatus == BillingStatus.SUPPORTED) { // Save us the billing check
+ if (subscriptionStatus == BillingStatus.SUPPORTED) { // Save us the
+ // billing check
billingStatus = BillingStatus.SUPPORTED;
}
for (IBillingObserver o : observers) {
@@ -547,7 +548,7 @@ public static boolean registerObserver(IBillingObserver observer) {
* @see #requestPurchase(Context, String, boolean)
*/
public static void requestPurchase(Context context, String itemId) {
- requestPurchase(context, itemId, false);
+ requestPurchase(context, itemId, false, null);
}
/**
@@ -557,7 +558,7 @@ public static void requestPurchase(Context context, String itemId) {
*
*
* For subscriptions, use
- * {@link #requestSubscription(Context, String, boolean)} instead.
+ * {@link #requestSubscription(Context, String, boolean, String)} instead.
*
*
* @param context
@@ -567,14 +568,16 @@ public static void requestPurchase(Context context, String itemId) {
* if true, the transaction will be confirmed automatically. If
* false, the transaction will have to be confirmed with a call
* to {@link #confirmNotifications(Context, String)}.
+ * @param developerPayload
+ * a developer-specified string that contains supplemental
+ * information about the order.
* @see IBillingObserver#onPurchaseIntent(String, PendingIntent)
*/
- public static void requestPurchase(Context context, String itemId,
- boolean confirm) {
+ public static void requestPurchase(Context context, String itemId, boolean confirm, String developerPayload) {
if (confirm) {
automaticConfirmations.add(itemId);
}
- BillingService.requestPurchase(context, itemId, null);
+ BillingService.requestPurchase(context, itemId, developerPayload);
}
/**
@@ -584,10 +587,10 @@ public static void requestPurchase(Context context, String itemId,
* @param context
* @param itemId
* id of the item to be purchased.
- * @see #requestSubscription(Context, String, boolean)
+ * @see #requestSubscription(Context, String, boolean, String)
*/
public static void requestSubscription(Context context, String itemId) {
- requestSubscription(context, itemId, false);
+ requestSubscription(context, itemId, false, null);
}
/**
@@ -601,14 +604,16 @@ public static void requestSubscription(Context context, String itemId) {
* if true, the transaction will be confirmed automatically. If
* false, the transaction will have to be confirmed with a call
* to {@link #confirmNotifications(Context, String)}.
+ * @param developerPayload
+ * a developer-specified string that contains supplemental
+ * information about the order.
* @see IBillingObserver#onPurchaseIntent(String, PendingIntent)
*/
- public static void requestSubscription(Context context, String itemId,
- boolean confirm) {
+ public static void requestSubscription(Context context, String itemId, boolean confirm, String developerPayload) {
if (confirm) {
automaticConfirmations.add(itemId);
}
- BillingService.requestSubscription(context, itemId, null);
+ BillingService.requestSubscription(context, itemId, developerPayload);
}
/**
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
index 1e9746a..82720a0 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
@@ -144,9 +144,9 @@ private void setupWidgets() {
public void onClick(View v) {
if (mSelectedItem.managed != Managed.SUBSCRIPTION) {
- BillingController.requestPurchase(Dungeons.this, mSelectedItem.sku, true /* confirm */);
+ BillingController.requestPurchase(Dungeons.this, mSelectedItem.sku, true /* confirm */, null);
} else {
- BillingController.requestSubscription(Dungeons.this, mSelectedItem.sku, true /* confirm */);
+ BillingController.requestSubscription(Dungeons.this, mSelectedItem.sku, true /* confirm */, null);
}
}
});
From 3ca95844c560a4711bdf140050d631f9fd99c739 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 11:51:04 +0200
Subject: [PATCH 18/28] Log signed data on debug mode. Closes #47.
---
.../src/net/robotmedia/billing/BillingController.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index bce19e1..5b9d107 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -383,10 +383,12 @@ protected static void onPurchaseIntent(String itemId, PendingIntent purchaseInte
*/
protected static void onPurchaseStateChanged(Context context, String signedData, String signature) {
debug("Purchase state changed");
-
+
if (TextUtils.isEmpty(signedData)) {
Log.w(LOG_TAG, "Signed data is empty");
return;
+ } else {
+ debug(signedData);
}
if (!debug) {
From 3f09a6c5c7b58f02754a69dcc060d3d72c991d98 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 12:07:11 +0200
Subject: [PATCH 19/28] AbstractBillingFragment
---
.../helper/AbstractBillingFragment.java | 147 ++++++++++++++++++
README.mdown | 4 +-
2 files changed, 149 insertions(+), 2 deletions(-)
create mode 100644 AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingFragment.java
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingFragment.java b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingFragment.java
new file mode 100644
index 0000000..01644d2
--- /dev/null
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingFragment.java
@@ -0,0 +1,147 @@
+package net.robotmedia.billing.helper;
+
+import net.robotmedia.billing.BillingController;
+import net.robotmedia.billing.BillingController.BillingStatus;
+import net.robotmedia.billing.BillingRequest.ResponseCode;
+import net.robotmedia.billing.model.Transaction.PurchaseState;
+import android.annotation.TargetApi;
+import android.app.Fragment;
+
+@TargetApi(11)
+public abstract class AbstractBillingFragment extends Fragment implements BillingController.IConfiguration {
+
+ protected AbstractBillingObserver mBillingObserver;
+
+ /**
+ *
+ * Returns the in-app product billing support status, and checks it
+ * asynchronously if it is currently unknown.
+ * {@link AbstractBillingActivity#onBillingChecked(boolean)} will be called
+ * eventually with the result.
+ *
+ *
+ * In-app product support does not imply subscription support. To check if
+ * subscriptions are supported, use
+ * {@link AbstractBillingActivity#checkSubscriptionSupported()}.
+ *
+ *
+ * @return the current in-app product billing support status (unknown,
+ * supported or unsupported). If it is unsupported, subscriptions
+ * are also unsupported.
+ * @see AbstractBillingActivity#onBillingChecked(boolean)
+ * @see AbstractBillingActivity#checkSubscriptionSupported()
+ */
+ public BillingStatus checkBillingSupported() {
+ return BillingController.checkBillingSupported(getActivity());
+ }
+
+ /**
+ *
+ * Returns the subscription billing support status, and checks it
+ * asynchronously if it is currently unknown.
+ * {@link AbstractBillingActivity#onSubscriptionChecked(boolean)} will be
+ * called eventually with the result.
+ *
+ *
+ * No support for subscriptions does not imply that in-app products are also
+ * unsupported. To check if subscriptions are supported, use
+ * {@link AbstractBillingActivity#checkSubscriptionSupported()}.
+ *
+ *
+ * @return the current in-app product billing support status (unknown,
+ * supported or unsupported). If it is unsupported, subscriptions
+ * are also unsupported.
+ * @see AbstractBillingActivity#onBillingChecked(boolean)
+ * @see AbstractBillingActivity#checkSubscriptionSupported()
+ */
+ public BillingStatus checkSubscriptionSupported() {
+ return BillingController.checkSubscriptionSupported(getActivity());
+ }
+
+ public abstract void onBillingChecked(boolean supported);
+
+ public abstract void onSubscriptionChecked(boolean supported);
+
+ @Override
+ public void onCreate(android.os.Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mBillingObserver = new AbstractBillingObserver(getActivity()) {
+
+ public void onBillingChecked(boolean supported) {
+ AbstractBillingFragment.this.onBillingChecked(supported);
+ }
+
+ public void onSubscriptionChecked(boolean supported) {
+ AbstractBillingFragment.this.onSubscriptionChecked(supported);
+ }
+
+ public void onPurchaseStateChanged(String itemId, PurchaseState state) {
+ AbstractBillingFragment.this.onPurchaseStateChanged(itemId, state);
+ }
+
+ public void onRequestPurchaseResponse(String itemId, ResponseCode response) {
+ AbstractBillingFragment.this.onRequestPurchaseResponse(itemId, response);
+ }
+ };
+ BillingController.registerObserver(mBillingObserver);
+ BillingController.setConfiguration(this); // This fragment will provide
+ // the public key and salt
+ this.checkBillingSupported();
+ if (!mBillingObserver.isTransactionsRestored()) {
+ BillingController.restoreTransactions(getActivity());
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ BillingController.unregisterObserver(mBillingObserver); // Avoid
+ // receiving
+ // notifications
+ // after destroy
+ BillingController.setConfiguration(null);
+ }
+
+ public abstract void onPurchaseStateChanged(String itemId, PurchaseState state);;
+
+ public abstract void onRequestPurchaseResponse(String itemId, ResponseCode response);
+
+ /**
+ * Requests the purchase of the specified item. The transaction will not be
+ * confirmed automatically; such confirmation could be handled in
+ * {@link AbstractBillingActivity#onPurchaseExecuted(String)}. If automatic
+ * confirmation is preferred use
+ * {@link BillingController#requestPurchase(android.content.Context, String, boolean)}
+ * instead.
+ *
+ * @param itemId
+ * id of the item to be purchased.
+ */
+ public void requestPurchase(String itemId) {
+ BillingController.requestPurchase(getActivity(), itemId);
+ }
+
+ /**
+ * Requests the purchase of the specified subscription item. The transaction
+ * will not be confirmed automatically; such confirmation could be handled
+ * in {@link AbstractBillingActivity#onPurchaseExecuted(String)}. If
+ * automatic confirmation is preferred use
+ * {@link BillingController#requestPurchase(android.content.Context, String, boolean)}
+ * instead.
+ *
+ * @param itemId
+ * id of the item to be purchased.
+ */
+ public void requestSubscription(String itemId) {
+ BillingController.requestSubscription(getActivity(), itemId);
+ }
+
+ /**
+ * Requests to restore all transactions.
+ */
+ public void restoreTransactions() {
+ BillingController.restoreTransactions(getActivity());
+ }
+
+}
diff --git a/README.mdown b/README.mdown
index b2fde13..34b7bbd 100644
--- a/README.mdown
+++ b/README.mdown
@@ -41,7 +41,7 @@ Usage
Subclassing AbstractBillingActivity
-----------------------------------
-[AbstractBillingActivity][2] is an abstract activity that provides default integration with in-app billing. It is useful to get acquainted with the library, or for very simple applications that require in-app billing integration in only one activity. For more flexibility use [BillingController][3] directly instead.
+[AbstractBillingActivity][2] is an abstract activity that provides default integration with in-app billing (an analogous class for fragments is also provided). It is useful to get acquainted with the library, or for very simple applications that require in-app billing integration in only one activity. For more flexibility use [BillingController][3] directly.
When created your [AbstractBillingActivity][2] instance will check if in-app billing is supported, followed by a call to `onBillingChecked(boolean)`, which has to be implemented by the subclass.
@@ -63,7 +63,7 @@ Additionally, [BillingController][3] requires a `BillingController.IConfiguratio
Dungeons Redux
==============
-[Dungeons Redux][5] is a sample app that shows how to use *Android Billing Library* through [BillingController][3]. It is a simplified version of the Dungeons in-app billing example provided by Google.
+[Dungeons Redux][5] is a sample app that shows how to use *Android Billing Library* via [BillingController][3]. It is a simplified version of the Dungeons in-app billing example provided by Google.
It should be noted that Dungeons Redux does not intend to be an example of how to use in-app billing in general.
From 192f429b1d81e14cfbc791ab5d8fd0aa2c142272 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 12:26:20 +0200
Subject: [PATCH 20/28] Tag subscription_monthly and subscription_yearly as
subscriptions
---
.../robotmedia/billing/example/auxiliary/CatalogEntry.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java b/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
index 32600bb..733c905 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
@@ -33,8 +33,8 @@ public CatalogEntry(String sku, int nameId, Managed managed) {
public static final CatalogEntry[] CATALOG = new CatalogEntry[] {
new CatalogEntry("sword_001", R.string.two_handed_sword, Managed.MANAGED),
new CatalogEntry("potion_001", R.string.potions, Managed.UNMANAGED),
- new CatalogEntry("subscription_monthly", R.string.subscription_monthly, Managed.UNMANAGED),
- new CatalogEntry("subscription_yearly", R.string.subscription_yearly, Managed.UNMANAGED),
+ new CatalogEntry("subscription_monthly", R.string.subscription_monthly, Managed.SUBSCRIPTION),
+ new CatalogEntry("subscription_yearly", R.string.subscription_yearly, Managed.SUBSCRIPTION),
new CatalogEntry("android.test.purchased", R.string.android_test_purchased, Managed.UNMANAGED),
new CatalogEntry("android.test.canceled", R.string.android_test_canceled, Managed.UNMANAGED),
new CatalogEntry("android.test.refunded", R.string.android_test_refunded, Managed.UNMANAGED),
From ae7253061a8ef46e1287ca1ecfac90e127f4a38f Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 14:11:37 +0200
Subject: [PATCH 21/28] Fully qualify activity and application to simplify APK
generation
---
DungeonsRedux/AndroidManifest.xml | 6 +++---
.../src/net/robotmedia/billing/example/Dungeons.java | 2 +-
.../robotmedia/billing/example/auxiliary/CatalogEntry.java | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/DungeonsRedux/AndroidManifest.xml b/DungeonsRedux/AndroidManifest.xml
index 84a1291..c9488c2 100644
--- a/DungeonsRedux/AndroidManifest.xml
+++ b/DungeonsRedux/AndroidManifest.xml
@@ -1,14 +1,14 @@
+ package="net.robotmedia.billing.dungeons.redux">
-
-
+
+
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
index 82720a0..99e0bf6 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/Dungeons.java
@@ -20,7 +20,7 @@
import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.BillingRequest.ResponseCode;
-import net.robotmedia.billing.example.R;
+import net.robotmedia.billing.dungeons.redux.R;
import net.robotmedia.billing.example.auxiliary.CatalogAdapter;
import net.robotmedia.billing.example.auxiliary.CatalogEntry;
import net.robotmedia.billing.example.auxiliary.CatalogEntry.Managed;
diff --git a/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java b/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
index 733c905..08c2a14 100644
--- a/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
+++ b/DungeonsRedux/src/net/robotmedia/billing/example/auxiliary/CatalogEntry.java
@@ -1,6 +1,6 @@
package net.robotmedia.billing.example.auxiliary;
-import net.robotmedia.billing.example.R;
+import net.robotmedia.billing.dungeons.redux.R;
public class CatalogEntry {
From 957253a7142b4996195b7b5338d68cf35dbd03bf Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 14:12:27 +0200
Subject: [PATCH 22/28] getAPIVersion and RequestSubscription
---
.../robotmedia/billing/BillingRequest.java | 58 ++++++++++++-------
1 file changed, 38 insertions(+), 20 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
index d9feda9..8362559 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingRequest.java
@@ -23,11 +23,6 @@
import com.android.vending.billing.IMarketBillingService;
public abstract class BillingRequest {
-
- public static final String ITEM_TYPE_INAPP = "inapp";
- public static final String ITEM_TYPE_SUBSCRIPTION = "subs";
- private static final String KEY_ITEM_TYPE = "ITEM_TYPE";
- private static final String REQUEST_TYPE_CHECK_BILLING_SUPPORTED = "CHECK_BILLING_SUPPORTED";
public static class CheckBillingSupported extends BillingRequest {
@@ -49,13 +44,16 @@ protected void processOkResponse(Bundle response) {
}
public static class CheckSubscriptionSupported extends BillingRequest {
-
- private static final String KEY_API_VERSION = "API_VERSION";
public CheckSubscriptionSupported(String packageName, int startId) {
super(packageName, startId);
}
+ @Override
+ protected int getAPIVersion() {
+ return 2;
+ };
+
@Override
public String getRequestType() {
return REQUEST_TYPE_CHECK_BILLING_SUPPORTED;
@@ -69,7 +67,6 @@ protected void processOkResponse(Bundle response) {
@Override
protected void addParams(Bundle request) {
- request.putInt(KEY_API_VERSION, 2);
request.putString(KEY_ITEM_TYPE, ITEM_TYPE_SUBSCRIPTION);
}
@@ -121,27 +118,25 @@ public String getRequestType() {
@Override public boolean hasNonce() { return true; }
}
+
public static class RequestPurchase extends BillingRequest {
private String itemId;
- private String itemType;
private String developerPayload;
private static final String KEY_ITEM_ID = "ITEM_ID";
private static final String KEY_DEVELOPER_PAYLOAD = "DEVELOPER_PAYLOAD";
private static final String KEY_PURCHASE_INTENT = "PURCHASE_INTENT";
- public RequestPurchase(String packageName, int startId, String itemId, String itemType, String developerPayload) {
+ public RequestPurchase(String packageName, int startId, String itemId, String developerPayload) {
super(packageName, startId);
this.itemId = itemId;
- this.itemType = itemType;
this.developerPayload = developerPayload;
}
@Override
protected void addParams(Bundle request) {
request.putString(KEY_ITEM_ID, itemId);
- request.putString(KEY_ITEM_TYPE, itemType);
if (developerPayload != null) {
request.putString(KEY_DEVELOPER_PAYLOAD, developerPayload);
}
@@ -163,9 +158,27 @@ protected void processOkResponse(Bundle response) {
final PendingIntent purchaseIntent = response.getParcelable(KEY_PURCHASE_INTENT);
BillingController.onPurchaseIntent(itemId, purchaseIntent);
}
+
+ }
+
+ public static class RequestSubscription extends RequestPurchase {
+
+ public RequestSubscription(String packageName, int startId, String itemId, String developerPayload) {
+ super(packageName, startId, itemId, developerPayload);
+ }
+ @Override
+ protected void addParams(Bundle request) {
+ super.addParams(request);
+ request.putString(KEY_ITEM_TYPE, ITEM_TYPE_SUBSCRIPTION);
+ }
+ @Override
+ protected int getAPIVersion() {
+ return 2;
+ }
}
+
public static enum ResponseCode {
RESULT_OK, // 0
RESULT_USER_CANCELED, // 1
@@ -210,15 +223,16 @@ public void onResponseCode(ResponseCode response) {
}
}
+
+ public static final String ITEM_TYPE_SUBSCRIPTION = "subs";
+ private static final String KEY_API_VERSION = "API_VERSION";
private static final String KEY_BILLING_REQUEST = "BILLING_REQUEST";
-
- private static final String KEY_API_VERSION = "API_VERSION";
- private static final String KEY_PACKAGE_NAME = "PACKAGE_NAME";
- private static final String KEY_RESPONSE_CODE = "RESPONSE_CODE";
-
- protected static final String KEY_REQUEST_ID = "REQUEST_ID";
-
+ private static final String KEY_ITEM_TYPE = "ITEM_TYPE";
private static final String KEY_NONCE = "NONCE";
+ private static final String KEY_PACKAGE_NAME = "PACKAGE_NAME";
+ protected static final String KEY_REQUEST_ID = "REQUEST_ID";
+ private static final String KEY_RESPONSE_CODE = "RESPONSE_CODE";
+ private static final String REQUEST_TYPE_CHECK_BILLING_SUPPORTED = "CHECK_BILLING_SUPPORTED";
public static final long IGNORE_REQUEST_ID = -1;
private String packageName;
@@ -234,6 +248,10 @@ public BillingRequest(String packageName,int startId) {
protected void addParams(Bundle request) {
// Do nothing by default
}
+
+ protected int getAPIVersion() {
+ return 1;
+ }
public long getNonce() {
return nonce;
@@ -252,7 +270,7 @@ public boolean isSuccess() {
protected Bundle makeRequestBundle() {
final Bundle request = new Bundle();
request.putString(KEY_BILLING_REQUEST, getRequestType());
- request.putInt(KEY_API_VERSION, 1);
+ request.putInt(KEY_API_VERSION, getAPIVersion());
request.putString(KEY_PACKAGE_NAME, packageName);
if (hasNonce()) {
request.putLong(KEY_NONCE, nonce);
From d0345d13e549ac367e46d3331e151dc04b2d4ba5 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 14:12:47 +0200
Subject: [PATCH 23/28] Use RequestSubscription
---
.../robotmedia/billing/BillingService.java | 20 ++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
index 81cf230..eaa48cf 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
@@ -35,13 +35,12 @@
public class BillingService extends Service implements ServiceConnection {
private static enum Action {
- CHECK_BILLING_SUPPORTED, CHECK_SUBSCRIPTION_SUPPORTED, CONFIRM_NOTIFICATIONS, GET_PURCHASE_INFORMATION, REQUEST_PURCHASE, RESTORE_TRANSACTIONS
+ CHECK_BILLING_SUPPORTED, CHECK_SUBSCRIPTION_SUPPORTED, CONFIRM_NOTIFICATIONS, GET_PURCHASE_INFORMATION, REQUEST_PURCHASE, REQUEST_SUBSCRIPTION, RESTORE_TRANSACTIONS
}
private static final String ACTION_MARKET_BILLING_SERVICE = "com.android.vending.billing.MarketBillingService.BIND";
private static final String EXTRA_DEVELOPER_PAYLOAD = "DEVELOPER_PAYLOAD";
private static final String EXTRA_ITEM_ID = "ITEM_ID";
- private static final String EXTRA_ITEM_TYPE = "ITEM_TYPE";
private static final String EXTRA_NONCE = "EXTRA_NONCE";
private static final String EXTRA_NOTIFY_IDS = "NOTIFY_IDS";
private static LinkedList mPendingRequests = new LinkedList();
@@ -85,15 +84,13 @@ public static void getPurchaseInformation(Context context, String[] notifyIds, l
public static void requestPurchase(Context context, String itemId, String developerPayload) {
final Intent intent = createIntent(context, Action.REQUEST_PURCHASE);
intent.putExtra(EXTRA_ITEM_ID, itemId);
- intent.putExtra(EXTRA_ITEM_TYPE, BillingRequest.ITEM_TYPE_INAPP);
intent.putExtra(EXTRA_DEVELOPER_PAYLOAD, developerPayload);
context.startService(intent);
}
public static void requestSubscription(Context context, String itemId, String developerPayload) {
- final Intent intent = createIntent(context, Action.REQUEST_PURCHASE);
+ final Intent intent = createIntent(context, Action.REQUEST_SUBSCRIPTION);
intent.putExtra(EXTRA_ITEM_ID, itemId);
- intent.putExtra(EXTRA_ITEM_TYPE, BillingRequest.ITEM_TYPE_SUBSCRIPTION);
intent.putExtra(EXTRA_DEVELOPER_PAYLOAD, developerPayload);
context.startService(intent);
}
@@ -198,6 +195,8 @@ private void handleCommand(Intent intent, int startId) {
break;
case REQUEST_PURCHASE:
requestPurchase(intent, startId);
+ case REQUEST_SUBSCRIPTION:
+ requestSubscription(intent, startId);
break;
case GET_PURCHASE_INFORMATION:
getPurchaseInformation(intent, startId);
@@ -213,9 +212,16 @@ private void handleCommand(Intent intent, int startId) {
private void requestPurchase(Intent intent, int startId) {
final String packageName = getPackageName();
final String itemId = intent.getStringExtra(EXTRA_ITEM_ID);
- final String itemType = intent.getStringExtra(EXTRA_ITEM_TYPE);
final String developerPayload = intent.getStringExtra(EXTRA_DEVELOPER_PAYLOAD);
- final RequestPurchase request = new RequestPurchase(packageName, startId, itemId, itemType, developerPayload);
+ final RequestPurchase request = new RequestPurchase(packageName, startId, itemId, developerPayload);
+ runRequestOrQueue(request);
+ }
+
+ private void requestSubscription(Intent intent, int startId) {
+ final String packageName = getPackageName();
+ final String itemId = intent.getStringExtra(EXTRA_ITEM_ID);
+ final String developerPayload = intent.getStringExtra(EXTRA_DEVELOPER_PAYLOAD);
+ final RequestPurchase request = new RequestSubscription(packageName, startId, itemId, developerPayload);
runRequestOrQueue(request);
}
From 8e0b9436f6f48e7580b40423b83127e5368d3d19 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 30 Jul 2012 15:26:34 +0200
Subject: [PATCH 24/28] Missing break!
---
.../src/net/robotmedia/billing/BillingService.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
index eaa48cf..a37a1ae 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java
@@ -195,6 +195,7 @@ private void handleCommand(Intent intent, int startId) {
break;
case REQUEST_PURCHASE:
requestPurchase(intent, startId);
+ break;
case REQUEST_SUBSCRIPTION:
requestSubscription(intent, startId);
break;
From 3ecc7cad9cb6ca55d0de607e03b717876212178d Mon Sep 17 00:00:00 2001
From: hpique
Date: Tue, 11 Dec 2012 16:39:28 +0100
Subject: [PATCH 25/28] Update README.mdown
---
README.mdown | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/README.mdown b/README.mdown
index 34b7bbd..a33d241 100644
--- a/README.mdown
+++ b/README.mdown
@@ -1,3 +1,9 @@
+Update
+======
+
+The In-app Billing API has been recently updated to [version 3](https://developer.android.com/google/play/billing/api.html). This library is currently for version 2 only, and will be updated in early 2013.
+
+
Android Billing Library
=======================
From 799aff4078973c06ce903be5f39176cdcbbca8ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Brais=20Gab=C3=ADn?=
Date: Tue, 2 Apr 2013 19:56:35 +0300
Subject: [PATCH 26/28] Fixed a minor error in javadoc
---
.../src/net/robotmedia/billing/BillingController.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
index 5b9d107..cbf179e 100644
--- a/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
+++ b/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
@@ -547,7 +547,7 @@ public static boolean registerObserver(IBillingObserver observer) {
* @param context
* @param itemId
* id of the item to be purchased.
- * @see #requestPurchase(Context, String, boolean)
+ * @see #requestPurchase(Context, String, boolean, String)
*/
public static void requestPurchase(Context context, String itemId) {
requestPurchase(context, itemId, false, null);
From 4bbe429d7811d531ca6d478745b4eeebb17f1783 Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Mon, 12 Aug 2013 15:13:22 +0200
Subject: [PATCH 27/28] Update README.mdown
---
README.mdown | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.mdown b/README.mdown
index a33d241..ed03c3a 100644
--- a/README.mdown
+++ b/README.mdown
@@ -1,8 +1,9 @@
Update
======
-The In-app Billing API has been recently updated to [version 3](https://developer.android.com/google/play/billing/api.html). This library is currently for version 2 only, and will be updated in early 2013.
+The In-app Billing API was updated to [version 3](https://developer.android.com/google/play/billing/api.html) in early 2013. This library is currently for version 2 and version 1 only.
+If you're interested in helping to update it to version 3, please fork and send a pull request.
Android Billing Library
=======================
@@ -99,4 +100,4 @@ limitations under the License.
[2]: https://github.com/robotmedia/AndroidBillingLibrary/blob/master/AndroidBillingLibrary/src/net/robotmedia/billing/helper/AbstractBillingActivity.java
[3]: https://github.com/robotmedia/AndroidBillingLibrary/blob/master/AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java
[4]: https://github.com/robotmedia/AndroidBillingLibrary/blob/master/AndroidBillingLibrary/src/net/robotmedia/billing/IBillingObserver.java
-[5]: https://github.com/robotmedia/AndroidBillingLibrary/tree/master/DungeonsRedux
\ No newline at end of file
+[5]: https://github.com/robotmedia/AndroidBillingLibrary/tree/master/DungeonsRedux
From fc637bb2ed9d0c864e1b918f9b604fb140104f6d Mon Sep 17 00:00:00 2001
From: Hermes Pique
Date: Sat, 18 Oct 2014 06:13:00 +0100
Subject: [PATCH 28/28] Mention v2 shut down
---
README.mdown | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.mdown b/README.mdown
index ed03c3a..c0db052 100644
--- a/README.mdown
+++ b/README.mdown
@@ -1,9 +1,10 @@
Update
======
-The In-app Billing API was updated to [version 3](https://developer.android.com/google/play/billing/api.html) in early 2013. This library is currently for version 2 and version 1 only.
+In-app Billing v2 API is deprecated and will be shut down in January 2015. This library was developed for v2 a long time ago. If your app is still using this library, please migrate to the [v3 API](https://developer.android.com/google/play/billing/api.html) as soon as possible.
+
+The project [Android Checkout Library](https://github.com/serso/android-checkout) by @serso supports v3 and attemps to provide [data compatibility](https://github.com/serso/android-checkout#billing-version-2) with AndroidBillingLibrary. We haven't verified this so please use it at your own discretion.
-If you're interested in helping to update it to version 3, please fork and send a pull request.
Android Billing Library
=======================