mirror of
https://github.com/defold/extension-iap
synced 2025-06-27 10:27:46 +02:00
commit
e79b5cfb36
@ -161,6 +161,13 @@
|
|||||||
desc: value is `true` if current store supports handling
|
desc: value is `true` if current store supports handling
|
||||||
restored transactions, otherwise `false`.
|
restored transactions, otherwise `false`.
|
||||||
|
|
||||||
|
#*****************************************************************************************************
|
||||||
|
|
||||||
|
- name: process_pending_transactions
|
||||||
|
type: function
|
||||||
|
desc: Process transactions still unprocessed from previous session if any. Transactions will be
|
||||||
|
processed with callback function set with `set_listener` function
|
||||||
|
|
||||||
#*****************************************************************************************************
|
#*****************************************************************************************************
|
||||||
|
|
||||||
- name: set_listener
|
- name: set_listener
|
||||||
|
@ -34,7 +34,6 @@ struct IAP
|
|||||||
bool m_autoFinishTransactions;
|
bool m_autoFinishTransactions;
|
||||||
int m_ProviderId;
|
int m_ProviderId;
|
||||||
|
|
||||||
dmScript::LuaCallbackInfo* m_ProductCallback;
|
|
||||||
dmScript::LuaCallbackInfo* m_Listener;
|
dmScript::LuaCallbackInfo* m_Listener;
|
||||||
|
|
||||||
jobject m_IAP;
|
jobject m_IAP;
|
||||||
@ -51,6 +50,12 @@ struct IAP
|
|||||||
|
|
||||||
static IAP g_IAP;
|
static IAP g_IAP;
|
||||||
|
|
||||||
|
static int IAP_ProcessPendingTransactions(lua_State* L)
|
||||||
|
{
|
||||||
|
//todo handle pending transactions if there is such thing on Android
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int IAP_List(lua_State* L)
|
static int IAP_List(lua_State* L)
|
||||||
{
|
{
|
||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
@ -61,14 +66,13 @@ static int IAP_List(lua_State* L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_IAP.m_ProductCallback)
|
|
||||||
dmScript::DestroyCallback(g_IAP.m_ProductCallback);
|
|
||||||
|
|
||||||
g_IAP.m_ProductCallback = dmScript::CreateCallback(L, 2);
|
|
||||||
|
|
||||||
JNIEnv* env = Attach();
|
JNIEnv* env = Attach();
|
||||||
|
IAPCommand* cmd = new IAPCommand;
|
||||||
|
cmd->m_Callback = dmScript::CreateCallback(L, 2);
|
||||||
|
cmd->m_Command = IAP_PRODUCT_RESULT;
|
||||||
|
|
||||||
jstring products = env->NewStringUTF(buf);
|
jstring products = env->NewStringUTF(buf);
|
||||||
env->CallVoidMethod(g_IAP.m_IAP, g_IAP.m_List, products, g_IAP.m_IAPJNI);
|
env->CallVoidMethod(g_IAP.m_IAP, g_IAP.m_List, products, g_IAP.m_IAPJNI, (jlong)cmd);
|
||||||
env->DeleteLocalRef(products);
|
env->DeleteLocalRef(products);
|
||||||
Detach();
|
Detach();
|
||||||
|
|
||||||
@ -189,6 +193,7 @@ static const luaL_reg IAP_methods[] =
|
|||||||
{"restore", IAP_Restore},
|
{"restore", IAP_Restore},
|
||||||
{"set_listener", IAP_SetListener},
|
{"set_listener", IAP_SetListener},
|
||||||
{"get_provider_id", IAP_GetProviderId},
|
{"get_provider_id", IAP_GetProviderId},
|
||||||
|
{"process_pending_transactions", IAP_ProcessPendingTransactions},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -198,7 +203,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_com_defold_iap_IapJNI_onProductsResult__ILjava_lang_String_2(JNIEnv* env, jobject, jint responseCode, jstring productList)
|
JNIEXPORT void JNICALL Java_com_defold_iap_IapJNI_onProductsResult(JNIEnv* env, jobject, jint responseCode, jstring productList, jlong cmdHandle)
|
||||||
{
|
{
|
||||||
const char* pl = 0;
|
const char* pl = 0;
|
||||||
if (productList)
|
if (productList)
|
||||||
@ -206,16 +211,14 @@ JNIEXPORT void JNICALL Java_com_defold_iap_IapJNI_onProductsResult__ILjava_lang_
|
|||||||
pl = env->GetStringUTFChars(productList, 0);
|
pl = env->GetStringUTFChars(productList, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IAPCommand cmd;
|
IAPCommand* cmd = (IAPCommand*)cmdHandle;
|
||||||
cmd.m_Callback = g_IAP.m_ProductCallback;
|
cmd->m_ResponseCode = responseCode;
|
||||||
cmd.m_Command = IAP_PRODUCT_RESULT;
|
|
||||||
cmd.m_ResponseCode = responseCode;
|
|
||||||
if (pl)
|
if (pl)
|
||||||
{
|
{
|
||||||
cmd.m_Data = strdup(pl);
|
cmd->m_Data = strdup(pl);
|
||||||
env->ReleaseStringUTFChars(productList, pl);
|
env->ReleaseStringUTFChars(productList, pl);
|
||||||
}
|
}
|
||||||
IAP_Queue_Push(&g_IAP.m_CommandQueue, &cmd);
|
IAP_Queue_Push(&g_IAP.m_CommandQueue, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_com_defold_iap_IapJNI_onPurchaseResult__ILjava_lang_String_2(JNIEnv* env, jobject, jint responseCode, jstring purchaseData)
|
JNIEXPORT void JNICALL Java_com_defold_iap_IapJNI_onPurchaseResult__ILjava_lang_String_2(JNIEnv* env, jobject, jint responseCode, jstring purchaseData)
|
||||||
@ -287,8 +290,6 @@ static void HandleProductResult(const IAPCommand* cmd)
|
|||||||
|
|
||||||
dmScript::TeardownCallback(cmd->m_Callback);
|
dmScript::TeardownCallback(cmd->m_Callback);
|
||||||
dmScript::DestroyCallback(cmd->m_Callback);
|
dmScript::DestroyCallback(cmd->m_Callback);
|
||||||
assert(g_IAP.m_ProductCallback == cmd->m_Callback);
|
|
||||||
g_IAP.m_ProductCallback = 0;
|
|
||||||
|
|
||||||
assert(top == lua_gettop(L));
|
assert(top == lua_gettop(L));
|
||||||
}
|
}
|
||||||
@ -388,7 +389,7 @@ static dmExtension::Result InitializeIAP(dmExtension::Params* params)
|
|||||||
jclass iap_jni_class = (jclass)env->CallObjectMethod(cls, find_class, str_class_name);
|
jclass iap_jni_class = (jclass)env->CallObjectMethod(cls, find_class, str_class_name);
|
||||||
env->DeleteLocalRef(str_class_name);
|
env->DeleteLocalRef(str_class_name);
|
||||||
|
|
||||||
g_IAP.m_List = env->GetMethodID(iap_class, "listItems", "(Ljava/lang/String;Lcom/defold/iap/IListProductsListener;)V");
|
g_IAP.m_List = env->GetMethodID(iap_class, "listItems", "(Ljava/lang/String;Lcom/defold/iap/IListProductsListener;J)V");
|
||||||
g_IAP.m_Buy = env->GetMethodID(iap_class, "buy", "(Ljava/lang/String;Lcom/defold/iap/IPurchaseListener;)V");
|
g_IAP.m_Buy = env->GetMethodID(iap_class, "buy", "(Ljava/lang/String;Lcom/defold/iap/IPurchaseListener;)V");
|
||||||
g_IAP.m_Restore = env->GetMethodID(iap_class, "restore", "(Lcom/defold/iap/IPurchaseListener;)V");
|
g_IAP.m_Restore = env->GetMethodID(iap_class, "restore", "(Lcom/defold/iap/IPurchaseListener;)V");
|
||||||
g_IAP.m_Stop = env->GetMethodID(iap_class, "stop", "()V");
|
g_IAP.m_Stop = env->GetMethodID(iap_class, "stop", "()V");
|
||||||
|
@ -77,6 +77,11 @@ static void IAPList_Callback(void* luacallback, const char* result_json)
|
|||||||
dmScript::TeardownCallback(callback);
|
dmScript::TeardownCallback(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int IAP_ProcessPendingTransactions(lua_State* L)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int IAP_List(lua_State* L)
|
static int IAP_List(lua_State* L)
|
||||||
{
|
{
|
||||||
DM_LUA_STACK_CHECK(L, 0);
|
DM_LUA_STACK_CHECK(L, 0);
|
||||||
@ -210,6 +215,7 @@ static const luaL_reg IAP_methods[] =
|
|||||||
{"restore", IAP_Restore},
|
{"restore", IAP_Restore},
|
||||||
{"set_listener", IAP_SetListener},
|
{"set_listener", IAP_SetListener},
|
||||||
{"get_provider_id", IAP_GetProviderId},
|
{"get_provider_id", IAP_GetProviderId},
|
||||||
|
{"process_pending_transactions", IAP_ProcessPendingTransactions},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ struct IAP
|
|||||||
NSMutableDictionary* m_PendingTransactions;
|
NSMutableDictionary* m_PendingTransactions;
|
||||||
dmScript::LuaCallbackInfo* m_Listener;
|
dmScript::LuaCallbackInfo* m_Listener;
|
||||||
IAPCommandQueue m_CommandQueue;
|
IAPCommandQueue m_CommandQueue;
|
||||||
|
IAPCommandQueue m_ObservableQueue;
|
||||||
SKPaymentTransactionObserver* m_Observer;
|
SKPaymentTransactionObserver* m_Observer;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -337,28 +338,25 @@ static void HandlePurchaseResult(IAPCommand* cmd)
|
|||||||
assert(top == lua_gettop(L));
|
assert(top == lua_gettop(L));
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation SKPaymentTransactionObserver
|
static void processTransactions(IAP* iap, NSArray* transactions) {
|
||||||
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
|
|
||||||
{
|
|
||||||
for (SKPaymentTransaction* transaction in transactions) {
|
for (SKPaymentTransaction* transaction in transactions) {
|
||||||
|
if ((!iap->m_AutoFinishTransactions) && (transaction.transactionState == SKPaymentTransactionStatePurchased)) {
|
||||||
if ((!self.m_IAP->m_AutoFinishTransactions) && (transaction.transactionState == SKPaymentTransactionStatePurchased)) {
|
|
||||||
NSData *data = [transaction.transactionIdentifier dataUsingEncoding:NSUTF8StringEncoding];
|
NSData *data = [transaction.transactionIdentifier dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
uint64_t trans_id_hash = dmHashBuffer64((const char*) [data bytes], [data length]);
|
uint64_t trans_id_hash = dmHashBuffer64((const char*) [data bytes], [data length]);
|
||||||
[self.m_IAP->m_PendingTransactions setObject:transaction forKey:[NSNumber numberWithInteger:trans_id_hash] ];
|
[iap->m_PendingTransactions setObject:transaction forKey:[NSNumber numberWithInteger:trans_id_hash] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.m_IAP->m_Listener)
|
if (!iap->m_Listener)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
IAPTransaction* iap_transaction = new IAPTransaction;
|
IAPTransaction* iap_transaction = new IAPTransaction;
|
||||||
CopyTransaction(transaction, iap_transaction);
|
CopyTransaction(transaction, iap_transaction);
|
||||||
|
|
||||||
IAPCommand cmd;
|
IAPCommand cmd;
|
||||||
cmd.m_Callback = self.m_IAP->m_Listener;
|
cmd.m_Callback = iap->m_Listener;
|
||||||
cmd.m_Command = IAP_PURCHASE_RESULT;
|
cmd.m_Command = IAP_PURCHASE_RESULT;
|
||||||
cmd.m_Data = iap_transaction;
|
cmd.m_Data = iap_transaction;
|
||||||
IAP_Queue_Push(&self.m_IAP->m_CommandQueue, &cmd);
|
IAP_Queue_Push(&iap->m_ObservableQueue, &cmd);
|
||||||
|
|
||||||
switch (transaction.transactionState)
|
switch (transaction.transactionState)
|
||||||
{
|
{
|
||||||
@ -378,6 +376,18 @@ static void HandlePurchaseResult(IAPCommand* cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int IAP_ProcessPendingTransactions(lua_State* L)
|
||||||
|
{
|
||||||
|
processTransactions(&g_IAP, [SKPaymentQueue defaultQueue].transactions);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation SKPaymentTransactionObserver
|
||||||
|
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
|
||||||
|
{
|
||||||
|
processTransactions(self.m_IAP, transactions);
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static int IAP_List(lua_State* L)
|
static int IAP_List(lua_State* L)
|
||||||
@ -490,18 +500,6 @@ static int IAP_SetListener(lua_State* L)
|
|||||||
dmScript::DestroyCallback(iap->m_Listener);
|
dmScript::DestroyCallback(iap->m_Listener);
|
||||||
|
|
||||||
iap->m_Listener = dmScript::CreateCallback(L, 1);
|
iap->m_Listener = dmScript::CreateCallback(L, 1);
|
||||||
|
|
||||||
if (g_IAP.m_Observer == 0) {
|
|
||||||
SKPaymentTransactionObserver* observer = [[SKPaymentTransactionObserver alloc] init];
|
|
||||||
observer.m_IAP = &g_IAP;
|
|
||||||
// NOTE: We add the listener *after* a lua listener is set
|
|
||||||
// The payment queue is persistent and "old" transaction might be processed
|
|
||||||
// from previous session. We call "finishTransaction" when appropriate
|
|
||||||
// for all transaction and we must ensure that the result is delivered to lua.
|
|
||||||
[[SKPaymentQueue defaultQueue] addTransactionObserver: observer];
|
|
||||||
g_IAP.m_Observer = observer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,6 +517,7 @@ static const luaL_reg IAP_methods[] =
|
|||||||
{"restore", IAP_Restore},
|
{"restore", IAP_Restore},
|
||||||
{"set_listener", IAP_SetListener},
|
{"set_listener", IAP_SetListener},
|
||||||
{"get_provider_id", IAP_GetProviderId},
|
{"get_provider_id", IAP_GetProviderId},
|
||||||
|
{"process_pending_transactions", IAP_ProcessPendingTransactions},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -533,6 +532,7 @@ static dmExtension::Result InitializeIAP(dmExtension::Params* params)
|
|||||||
g_IAP.m_InitCount++;
|
g_IAP.m_InitCount++;
|
||||||
|
|
||||||
IAP_Queue_Create(&g_IAP.m_CommandQueue);
|
IAP_Queue_Create(&g_IAP.m_CommandQueue);
|
||||||
|
IAP_Queue_Create(&g_IAP.m_ObservableQueue);
|
||||||
|
|
||||||
lua_State*L = params->m_L;
|
lua_State*L = params->m_L;
|
||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
@ -548,6 +548,12 @@ static dmExtension::Result InitializeIAP(dmExtension::Params* params)
|
|||||||
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
assert(top == lua_gettop(L));
|
assert(top == lua_gettop(L));
|
||||||
|
|
||||||
|
SKPaymentTransactionObserver* observer = [[SKPaymentTransactionObserver alloc] init];
|
||||||
|
observer.m_IAP = &g_IAP;
|
||||||
|
[[SKPaymentQueue defaultQueue] addTransactionObserver: observer];
|
||||||
|
g_IAP.m_Observer = observer;
|
||||||
|
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,6 +576,9 @@ static void IAP_OnCommand(IAPCommand* cmd, void*)
|
|||||||
static dmExtension::Result UpdateIAP(dmExtension::Params* params)
|
static dmExtension::Result UpdateIAP(dmExtension::Params* params)
|
||||||
{
|
{
|
||||||
IAP_Queue_Flush(&g_IAP.m_CommandQueue, IAP_OnCommand, 0);
|
IAP_Queue_Flush(&g_IAP.m_CommandQueue, IAP_OnCommand, 0);
|
||||||
|
if (g_IAP.m_Observer) {
|
||||||
|
IAP_Queue_Flush(&g_IAP.m_ObservableQueue, IAP_OnCommand, 0);
|
||||||
|
}
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,6 +607,7 @@ static dmExtension::Result FinalizeIAP(dmExtension::Params* params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IAP_Queue_Destroy(&g_IAP.m_CommandQueue);
|
IAP_Queue_Destroy(&g_IAP.m_CommandQueue);
|
||||||
|
IAP_Queue_Destroy(&g_IAP.m_ObservableQueue);
|
||||||
|
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package com.defold.iap;
|
package com.defold.iap;
|
||||||
|
|
||||||
public interface IListProductsListener {
|
public interface IListProductsListener {
|
||||||
public void onProductsResult(int resultCode, String productList);
|
public void onProductsResult(int resultCode, String productList, long cmdHandle);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ public class IapAmazon implements PurchasingListener {
|
|||||||
public static final String TAG = "iap";
|
public static final String TAG = "iap";
|
||||||
|
|
||||||
private HashMap<RequestId, IListProductsListener> listProductsListeners;
|
private HashMap<RequestId, IListProductsListener> listProductsListeners;
|
||||||
|
private HashMap<RequestId, Long> listProductsCommandPtrs;
|
||||||
private HashMap<RequestId, IPurchaseListener> purchaseListeners;
|
private HashMap<RequestId, IPurchaseListener> purchaseListeners;
|
||||||
|
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
@ -54,7 +55,7 @@ public class IapAmazon implements PurchasingListener {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void listItems(final String skus, final IListProductsListener listener) {
|
public void listItems(final String skus, final IListProductsListener listener, final long commandPtr) {
|
||||||
final Set<String> skuSet = new HashSet<String>();
|
final Set<String> skuSet = new HashSet<String>();
|
||||||
for (String x : skus.split(",")) {
|
for (String x : skus.split(",")) {
|
||||||
if (x.trim().length() > 0) {
|
if (x.trim().length() > 0) {
|
||||||
@ -71,6 +72,7 @@ public class IapAmazon implements PurchasingListener {
|
|||||||
RequestId req = PurchasingService.getProductData(skuSet);
|
RequestId req = PurchasingService.getProductData(skuSet);
|
||||||
if (req != null) {
|
if (req != null) {
|
||||||
listProductsListeners.put(req, listener);
|
listProductsListeners.put(req, listener);
|
||||||
|
listProductsCommandPtrs.put(req, commandPtr);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Did not expect a null requestId");
|
Log.e(TAG, "Did not expect a null requestId");
|
||||||
}
|
}
|
||||||
@ -150,17 +152,21 @@ public class IapAmazon implements PurchasingListener {
|
|||||||
public void onProductDataResponse(ProductDataResponse productDataResponse) {
|
public void onProductDataResponse(ProductDataResponse productDataResponse) {
|
||||||
RequestId reqId = productDataResponse.getRequestId();
|
RequestId reqId = productDataResponse.getRequestId();
|
||||||
IListProductsListener listener;
|
IListProductsListener listener;
|
||||||
|
long commadPtr = 0;
|
||||||
synchronized (this.listProductsListeners) {
|
synchronized (this.listProductsListeners) {
|
||||||
listener = this.listProductsListeners.get(reqId);
|
listener = this.listProductsListeners.get(reqId);
|
||||||
|
commadPtr = this.listProductsCommandPtrs.get(reqId);
|
||||||
|
|
||||||
|
this.listProductsListeners.remove(reqId);
|
||||||
|
this.listProductsCommandPtrs.remove(reqId);
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
Log.e(TAG, "No listener found for request " + reqId.toString());
|
Log.e(TAG, "No listener found for request " + reqId.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.listProductsListeners.remove(reqId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (productDataResponse.getRequestStatus() != ProductDataResponse.RequestStatus.SUCCESSFUL) {
|
if (productDataResponse.getRequestStatus() != ProductDataResponse.RequestStatus.SUCCESSFUL) {
|
||||||
listener.onProductsResult(IapJNI.BILLING_RESPONSE_RESULT_ERROR, null);
|
listener.onProductsResult(IapJNI.BILLING_RESPONSE_RESULT_ERROR, null, commadPtr);
|
||||||
} else {
|
} else {
|
||||||
Map<String, Product> products = productDataResponse.getProductData();
|
Map<String, Product> products = productDataResponse.getProductData();
|
||||||
try {
|
try {
|
||||||
@ -180,9 +186,9 @@ public class IapAmazon implements PurchasingListener {
|
|||||||
}
|
}
|
||||||
data.put(key, item);
|
data.put(key, item);
|
||||||
}
|
}
|
||||||
listener.onProductsResult(IapJNI.BILLING_RESPONSE_RESULT_OK, data.toString());
|
listener.onProductsResult(IapJNI.BILLING_RESPONSE_RESULT_OK, data.toString(), commadPtr);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
listener.onProductsResult(IapJNI.BILLING_RESPONSE_RESULT_ERROR, null);
|
listener.onProductsResult(IapJNI.BILLING_RESPONSE_RESULT_ERROR, null, commadPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ public class IapGooglePlay implements Handler.Callback {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void listItems(final String skus, final IListProductsListener listener) {
|
public void listItems(final String skus, final IListProductsListener listener, final long commandPtr) {
|
||||||
ArrayList<String> skuList = new ArrayList<String>();
|
ArrayList<String> skuList = new ArrayList<String>();
|
||||||
for (String x : skus.split(",")) {
|
for (String x : skus.split(",")) {
|
||||||
if (x.trim().length() > 0) {
|
if (x.trim().length() > 0) {
|
||||||
@ -276,15 +276,15 @@ public class IapGooglePlay implements Handler.Callback {
|
|||||||
products.put(key, convertProduct(product));
|
products.put(key, convertProduct(product));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listener.onProductsResult(resultCode, products.toString());
|
listener.onProductsResult(resultCode, products.toString(), commandPtr);
|
||||||
}
|
}
|
||||||
catch(JSONException e) {
|
catch(JSONException e) {
|
||||||
Log.wtf(TAG, "Failed to convert products", e);
|
Log.wtf(TAG, "Failed to convert products", e);
|
||||||
listener.onProductsResult(resultCode, null);
|
listener.onProductsResult(resultCode, null, commandPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
listener.onProductsResult(resultCode, null);
|
listener.onProductsResult(resultCode, null, commandPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -23,7 +23,7 @@ public class IapJNI implements IListProductsListener, IPurchaseListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native void onProductsResult(int responseCode, String productList);
|
public native void onProductsResult(int responseCode, String productList, long cmdHandle);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native void onPurchaseResult(int responseCode, String purchaseData);
|
public native void onPurchaseResult(int responseCode, String purchaseData);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user