Skip to content

Commit 3a5e5f9

Browse files
author
Robot Media
committed
Closes robotmedia#17. Closes robotmedia#13. Closes robotmedia#6.
1 parent 43c874f commit 3a5e5f9

30 files changed

+767
-55
lines changed

AndroidBillingLibrary/src/net/robotmedia/billing/BillingController.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import net.robotmedia.billing.model.TransactionManager;
3030
import net.robotmedia.billing.request.BillingRequest;
3131
import net.robotmedia.billing.request.ResponseCode;
32+
import net.robotmedia.billing.request.RestoreTransactions;
3233
import net.robotmedia.billing.utils.Compatibility;
3334
import net.robotmedia.billing.utils.Security;
3435

@@ -427,6 +428,8 @@ protected static void onPurchaseStateChanged(Context context, String signedData,
427428
}
428429
}
429430

431+
private static HashMap<Long, BillingRequest> pendingRequests = new HashMap<Long, BillingRequest>();
432+
430433
/**
431434
* Called after a {@link net.robotmedia.billing.request.BillingRequest} is
432435
* sent.
@@ -440,14 +443,16 @@ protected static void onRequestSent(long requestId, BillingRequest request) {
440443
if (debug) {
441444
Log.d(BillingController.class.getSimpleName(), "Request " + requestId + " of type " + request.getRequestType() + " sent");
442445
}
443-
if (!request.isSuccess() && request.hasNonce()) {
446+
if (request.isSuccess()) {
447+
pendingRequests.put(requestId, request);
448+
} else if (request.hasNonce()) {
444449
Security.removeNonce(request.getNonce());
445450
}
446451
}
447452

448453
/**
449454
* Called after a {@link net.robotmedia.billing.request.BillingRequest} is
450-
* sent. Mostly used for debugging purposes.
455+
* sent.
451456
*
452457
* @param context
453458
* @param requestId
@@ -460,6 +465,11 @@ protected static void onResponseCode(Context context, long requestId, int respon
460465
if (debug) {
461466
Log.d(BillingController.class.getSimpleName(), "Request " + requestId + " received response " + ResponseCode.valueOf(responseCode));
462467
}
468+
final BillingRequest request = pendingRequests.get(requestId);
469+
if (request != null) {
470+
pendingRequests.remove(requestId);
471+
request.onResponseCode(responseCode);
472+
}
463473
}
464474

465475
/**
@@ -639,4 +649,14 @@ private static boolean verifyNonce(JSONObject data) {
639649
}
640650
}
641651

652+
/**
653+
*
654+
* @param restoreTransactions
655+
*/
656+
public static void onTransactionsRestored(RestoreTransactions restoreTransactions) {
657+
for (IBillingObserver o : observers) {
658+
o.onTransactionsRestored();
659+
}
660+
}
661+
642662
}

AndroidBillingLibrary/src/net/robotmedia/billing/BillingService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import net.robotmedia.billing.request.RequestPurchase;
2424
import net.robotmedia.billing.request.RestoreTransactions;
2525
import net.robotmedia.billing.request.BillingRequest;
26+
import net.robotmedia.billing.utils.Compatibility;
2627

2728
import com.android.vending.billing.IMarketBillingService;
2829

@@ -163,10 +164,10 @@ public void onStart(Intent intent, int startId) {
163164
handleCommand(intent);
164165
}
165166

166-
@Override
167+
// @Override // Avoid compile errors on pre-2.0
167168
public int onStartCommand(Intent intent, int flags, int startId) {
168169
handleCommand(intent);
169-
return START_NOT_STICKY;
170+
return Compatibility.START_NOT_STICKY;
170171
}
171172

172173
private void handleCommand(Intent intent) {

AndroidBillingLibrary/src/net/robotmedia/billing/IBillingObserver.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,9 @@ public interface IBillingObserver {
5555
*/
5656
public void onPurchaseRefunded(String itemId);
5757

58+
/**
59+
* Called after a restore transactions request has been successfully received by the server.
60+
*/
61+
public void onTransactionsRestored();
62+
5863
}

AndroidBillingLibrary/src/net/robotmedia/billing/model/Transaction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public class Transaction {
2222

2323
public enum PurchaseState {
2424
// Responses to requestPurchase or restoreTransactions.
25-
PURCHASED, // 0: The charge failed on the server.
26-
CANCELLED, // 1: User was charged for the order.
25+
PURCHASED, // 0: User was charged for the order.
26+
CANCELLED, // 1: The charge failed on the server.
2727
REFUNDED; // 2: User received a refund for the order.
2828

2929
// Converts from an ordinal value to the PurchaseState

AndroidBillingLibrary/src/net/robotmedia/billing/request/BillingRequest.java

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,53 @@ public abstract class BillingRequest {
2727
private static final String KEY_API_VERSION = "API_VERSION";
2828
private static final String KEY_PACKAGE_NAME = "PACKAGE_NAME";
2929
private static final String KEY_RESPONSE_CODE = "RESPONSE_CODE";
30-
private static final String KEY_REQUEST_ID = "REQUEST_ID";
30+
protected static final String KEY_REQUEST_ID = "REQUEST_ID";
3131
private static final String KEY_NONCE = "NONCE";
3232
public static final long IGNORE_REQUEST_ID = -1;
3333

34-
public abstract String getRequestType();
35-
protected abstract void addParams(Bundle request);
36-
protected abstract void processOkResponse(Bundle response);
34+
private String packageName;
35+
private boolean success;
36+
private long nonce;
3737

38-
public boolean hasNonce() {
39-
return false;
38+
public BillingRequest(String packageName) {
39+
this.packageName = packageName;
4040
}
4141

42-
private String packageName;
43-
private boolean success;
44-
private long nonce;
42+
protected void addParams(Bundle request) {
43+
// Do nothing by default
44+
}
4545

4646
public long getNonce() {
4747
return nonce;
4848
}
49-
public void setNonce(long nonce) {
50-
this.nonce = nonce;
51-
}
52-
public BillingRequest(String packageName) {
53-
this.packageName = packageName;
49+
public abstract String getRequestType();
50+
51+
public boolean hasNonce() {
52+
return false;
53+
}
54+
public boolean isSuccess() {
55+
return success;
56+
}
57+
protected Bundle makeRequestBundle() {
58+
final Bundle request = new Bundle();
59+
request.putString(KEY_BILLING_REQUEST, getRequestType());
60+
request.putInt(KEY_API_VERSION, 1);
61+
request.putString(KEY_PACKAGE_NAME, packageName);
62+
if (hasNonce()) {
63+
request.putLong(KEY_NONCE, nonce);
64+
}
65+
return request;
5466
}
5567

56-
public long run(IMarketBillingService mService) throws RemoteException {
68+
public void onResponseCode(int responseCode) {
69+
// Do nothing by default
70+
}
71+
72+
protected void processOkResponse(Bundle response) {
73+
// Do nothing by default
74+
}
75+
76+
public long run(IMarketBillingService mService) throws RemoteException {
5777
final Bundle request = makeRequestBundle();
5878
addParams(request);
5979
final Bundle response = mService.sendBillingRequest(request);
@@ -64,18 +84,11 @@ public long run(IMarketBillingService mService) throws RemoteException {
6484
return IGNORE_REQUEST_ID;
6585
}
6686
}
67-
68-
protected Bundle makeRequestBundle() {
69-
final Bundle request = new Bundle();
70-
request.putString(KEY_BILLING_REQUEST, getRequestType());
71-
request.putInt(KEY_API_VERSION, 1);
72-
request.putString(KEY_PACKAGE_NAME, packageName);
73-
if (hasNonce()) {
74-
request.putLong(KEY_NONCE, nonce);
75-
}
76-
return request;
77-
}
78-
87+
88+
public void setNonce(long nonce) {
89+
this.nonce = nonce;
90+
}
91+
7992
protected boolean validateResponse(Bundle response) {
8093
final int responseCode = response.getInt(KEY_RESPONSE_CODE);
8194
success = ResponseCode.isResponseOk(responseCode);
@@ -85,8 +98,4 @@ protected boolean validateResponse(Bundle response) {
8598
return success;
8699
}
87100

88-
public boolean isSuccess() {
89-
return success;
90-
}
91-
92101
}

AndroidBillingLibrary/src/net/robotmedia/billing/request/CheckBillingSupported.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ public String getRequestType() {
2929
return "CHECK_BILLING_SUPPORTED";
3030
}
3131

32-
@Override
33-
protected void addParams(Bundle request) {}
34-
3532
@Override
3633
protected void processOkResponse(Bundle response) {
3734
final boolean supported = this.isSuccess();

AndroidBillingLibrary/src/net/robotmedia/billing/request/ConfirmNotifications.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,5 @@ public String getRequestType() {
3737
protected void addParams(Bundle request) {
3838
request.putStringArray(KEY_NOTIFY_IDS, notifyIds);
3939
}
40-
41-
@Override
42-
protected void processOkResponse(Bundle response) {}
4340

4441
}

AndroidBillingLibrary/src/net/robotmedia/billing/request/GetPurchaseInformation.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,5 @@ public String getRequestType() {
3939
protected void addParams(Bundle request) {
4040
request.putStringArray(KEY_NOTIFY_IDS, notifyIds);
4141
}
42-
43-
@Override
44-
protected void processOkResponse(Bundle response) {
45-
}
4642

4743
}

AndroidBillingLibrary/src/net/robotmedia/billing/request/RestoreTransactions.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
package net.robotmedia.billing.request;
1717

18-
import android.os.Bundle;
18+
import net.robotmedia.billing.BillingController;
1919

2020
public class RestoreTransactions extends BillingRequest {
2121

@@ -29,11 +29,13 @@ public RestoreTransactions(String packageName) {
2929
public String getRequestType() {
3030
return "RESTORE_TRANSACTIONS";
3131
}
32-
33-
@Override
34-
protected void addParams(Bundle request) {}
35-
32+
3633
@Override
37-
protected void processOkResponse(Bundle response) {}
34+
public void onResponseCode(int responseCode) {
35+
super.onResponseCode(responseCode);
36+
if (ResponseCode.isResponseOk(responseCode)) {
37+
BillingController.onTransactionsRestored(this);
38+
}
39+
}
3840

3941
}

AndroidBillingLibrary/src/net/robotmedia/billing/utils/Compatibility.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@
1515

1616
package net.robotmedia.billing.utils;
1717

18+
import java.lang.reflect.Field;
1819
import java.lang.reflect.Method;
1920

2021
import android.app.Activity;
22+
import android.app.Service;
2123
import android.content.Intent;
2224
import android.content.IntentSender;
2325
import android.util.Log;
2426

2527
public class Compatibility {
2628
private static Method startIntentSender;
29+
public static int START_NOT_STICKY;
2730
@SuppressWarnings("rawtypes")
2831
private static final Class[] START_INTENT_SENDER_SIG = new Class[] {
2932
IntentSender.class, Intent.class, int.class, int.class, int.class
@@ -34,7 +37,13 @@ public class Compatibility {
3437
};
3538

3639
private static void initCompatibility() {
37-
try {
40+
try {
41+
final Field field = Service.class.getField("START_NOT_STICKY");
42+
START_NOT_STICKY = field.getInt(null);
43+
} catch (Exception e) {
44+
START_NOT_STICKY = 2;
45+
}
46+
try {
3847
startIntentSender = Activity.class.getMethod("startIntentSender",
3948
START_INTENT_SENDER_SIG);
4049
} catch (SecurityException e) {

AndroidBillingLibraryTest/src/net/robotmedia/billing/BillingControllerTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,19 @@
1515

1616
package net.robotmedia.billing;
1717

18+
import java.util.HashSet;
1819
import java.util.List;
20+
import java.util.Set;
1921

2022
import net.robotmedia.billing.model.BillingDB;
2123
import net.robotmedia.billing.model.BillingDBTest;
2224
import net.robotmedia.billing.model.Transaction;
2325
import net.robotmedia.billing.model.TransactionTest;
26+
import net.robotmedia.billing.request.RestoreTransactions;
27+
import android.app.PendingIntent;
2428
import android.test.AndroidTestCase;
2529
import android.test.suitebuilder.annotation.MediumTest;
30+
import android.test.suitebuilder.annotation.SmallTest;
2631

2732
public class BillingControllerTest extends AndroidTestCase {
2833

@@ -99,4 +104,27 @@ public void testGetTransactionsString() throws Exception {
99104
final List<Transaction> transactions2 = BillingController.getTransactions(getContext(), TransactionTest.TRANSACTION_1.productId);
100105
assertEquals(transactions2.size(), 1);
101106
}
107+
108+
@SmallTest
109+
public void testOnTransactionRestored() throws Exception {
110+
final Set<Boolean> flags = new HashSet<Boolean>();
111+
final IBillingObserver observer = new IBillingObserver() {
112+
113+
@Override
114+
public void onTransactionsRestored() {
115+
flags.add(true);
116+
}
117+
118+
public void onPurchaseRefunded(String itemId) {}
119+
public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {}
120+
public void onPurchaseExecuted(String itemId) {}
121+
public void onPurchaseCancelled(String itemId) {}
122+
public void onBillingChecked(boolean supported) {}
123+
};
124+
BillingController.registerObserver(observer);
125+
final RestoreTransactions request = new RestoreTransactions(getContext().getPackageName());
126+
BillingController.onTransactionsRestored(request);
127+
assertEquals(flags.size(), 1);
128+
BillingController.unregisterObserver(observer);
129+
}
102130
}

AndroidBillingLibraryTest/src/net/robotmedia/billing/MockBillingActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,9 @@ public String getPublicKey() {
5353
return null;
5454
}
5555

56+
@Override
57+
public void onTransactionsRestored() {
58+
// TODO Auto-generated method stub
59+
}
60+
5661
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package net.robotmedia.billing.utils;
2+
3+
import android.app.Service;
4+
import android.test.AndroidTestCase;
5+
import android.test.suitebuilder.annotation.SmallTest;
6+
7+
public class CompatibilityTest extends AndroidTestCase {
8+
9+
@SmallTest
10+
public void testStartNotSticky() throws Exception {
11+
assertEquals(Compatibility.START_NOT_STICKY, Service.START_NOT_STICKY);
12+
}
13+
14+
}

DungeonsRedux/.classpath

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<classpath>
3+
<classpathentry kind="src" path="src"/>
4+
<classpathentry kind="src" path="gen"/>
5+
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
6+
<classpathentry kind="src" path="AndroidBillingLibrary_src"/>
7+
<classpathentry kind="output" path="bin"/>
8+
</classpath>

DungeonsRedux/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
bin
2+
gen

0 commit comments

Comments
 (0)