App Storeからのアプリケーションのデバッグに関するいくつかの言葉

マーマレードツール環境の一部として提供されているエミュレーターは非常に便利であり、考えられないあらゆる状況をデバッグできるという事実にもかかわらず、処理できないタスクがいくつかあります。 このようなタスクには、たとえば、開発されたアプリケーションからの製品の購入のデバッグ(App StoreまたはAndroidマーケット経由)が含まれます。 購入自体のテストは必ずデバイス上で実行する必要がありますが、アプリケーションロジックが購入に関連付けられていることがよくあります。これは、エミュレーターでデバッグすると便利です。 これを行う方法については、以下:





例として、Marmaladeのサンプルに同梱されているs3e / s3eIOSAppStoreBillingアプリケーションを検討してください。 実行すると、モーダルウィンドウが表示され、「この例は、アプリ内購入用に設定されたテストストアを持つiPhoneでのみ動作します」というエラーメッセージが表示されます。 これは確かに正しいことですが、iPhoneに投稿する前にアプリケーションをデバッグしたいと思います。 これを行うことはまったく難しくありません。 S3E iOS App Store Billingの動作を(デバッグビルドで)模倣するスタブを開発します。 ファイルをmkbファイルに追加することから始めましょう。



s3eIOSAppStoreBilling.mkb
#!/usr/bin/env mkb files { s3eIOSAppStoreBilling.cpp AppStoreStub.h AppStoreStub.cpp } ...
      
      







スタブコード自体はプリミティブです。 App Store Billingの各関数のhファイルで、接尾辞「Stub」を持つスタブを定義し、アセンブリがデバッグ中の場合、呼び出しを#defineディレクティブで置き換えます。



AppStoreStub.h
 #ifndef _APPSTORESTUB_H_ #define _APPSTORESTUB_H_ #include <string.h> #include "s3eTypes.h" #include "s3eIOSAppStoreBilling.h" #if defined IW_DEBUG #define s3eIOSAppStoreBillingAvailable \ s3eIOSAppStoreBillingAvailableStub #define s3eIOSAppStoreBillingGetInt \ s3eIOSAppStoreBillingGetIntStub #define s3eIOSAppStoreBillingInit \ s3eIOSAppStoreBillingInitStub #define s3eIOSAppStoreBillingStart \ s3eIOSAppStoreBillingInitStub #define s3eIOSAppStoreBillingTerminate \ s3eIOSAppStoreBillingTerminateStub #define s3eIOSAppStoreBillingStop \ s3eIOSAppStoreBillingTerminateStub #define s3eIOSAppStoreBillingRequestProductInformation \ s3eIOSAppStoreBillingRequestProductInformationStub #define s3eIOSAppStoreBillingCancelProductInformationRequests \ s3eIOSAppStoreBillingCancelProductInformationRequestsStub #define s3eIOSAppStoreBillingRequestPayment \ s3eIOSAppStoreBillingRequestPaymentStub #define s3eIOSAppStoreBillingCompleteTransaction \ s3eIOSAppStoreBillingCompleteTransactionStub #define s3eIOSAppStoreBillingRestoreCompletedTransactions \ s3eIOSAppStoreBillingRestoreCompletedTransactionsStub #endif s3eBool s3eIOSAppStoreBillingAvailableStub(); int32 s3eIOSAppStoreBillingGetIntStub(s3eIOSAppStoreBillingProperty property); s3eResult s3eIOSAppStoreBillingInitStub(s3eProductInformationCallbackFn infoCallback, s3ePaymentTransactionUpdateCallbackFn updateCallback, void* userData); void s3eIOSAppStoreBillingTerminateStub(); s3eResult s3eIOSAppStoreBillingRequestProductInformationStub(const char** productIdentifiers, uint32 numProductIdentifiers); void s3eIOSAppStoreBillingCancelProductInformationRequestsStub(); s3eResult s3eIOSAppStoreBillingRequestPaymentStub(s3ePaymentRequest* paymentRequest); s3eResult s3eIOSAppStoreBillingCompleteTransactionStub(s3ePaymentTransaction* transaction, s3eBool finalise); s3eResult s3eIOSAppStoreBillingRestoreCompletedTransactionsStub(); void appStoreStubUpdate(); #endif // _APPSTORESTUB_H_
      
      







これらの関数の実装には、超自然的なものも含まれていません。



AppStoreStub.cpp
 #include "AppStoreStub.h" #define PRODUCT_INFO_REQUESTED 0x0001 #define TRANSACTION_REQUESTED 0x0002 s3eProductInformationCallbackFn productInfoCallback = NULL; s3ePaymentTransactionUpdateCallbackFn transactionCallback = NULL; void* billingData = NULL; s3eProductInformation productInformation; s3ePaymentTransaction transaction; s3eTransactionReceipt receipt; int eventMask = 0; s3eBool s3eIOSAppStoreBillingAvailableStub() { return S3E_TRUE; } int32 s3eIOSAppStoreBillingGetIntStub(s3eIOSAppStoreBillingProperty property) { switch (property) { case S3E_IOSAPPSTOREBILLING_CAN_MAKE_PAYMENTS: return 1; default: return 0; } } s3eResult s3eIOSAppStoreBillingInitStub(s3eProductInformationCallbackFn infoCallback, s3ePaymentTransactionUpdateCallbackFn updateCallback, void* userData) { productInfoCallback = infoCallback; transactionCallback = updateCallback; billingData = userData; return S3E_RESULT_SUCCESS; } void s3eIOSAppStoreBillingTerminateStub() {} s3eResult s3eIOSAppStoreBillingRequestProductInformationStub(const char** productIdentifiers, uint32 numProductIdentifiers) { if (numProductIdentifiers != 1) return S3E_RESULT_ERROR; memset(&productInformation, 0, sizeof(productInformation)); strcpy(productInformation.m_ProductID, *productIdentifiers); strcpy(productInformation.m_LocalisedTitle, *productIdentifiers); strcpy(productInformation.m_LocalisedDescription, *productIdentifiers); strcpy(productInformation.m_FormattedPrice, "0.00"); strcpy(productInformation.m_PriceLocale, "0.00"); productInformation.m_Price = 0; productInformation.m_ProductStoreStatus = S3E_PRODUCT_STORE_STATUS_VALID; eventMask |= PRODUCT_INFO_REQUESTED; return S3E_RESULT_SUCCESS; } void s3eIOSAppStoreBillingCancelProductInformationRequestsStub() {} s3eResult s3eIOSAppStoreBillingRequestPaymentStub(s3ePaymentRequest* paymentRequest) { memset(&transaction, 0, sizeof(transaction)); transaction.m_TransactionStatus = S3E_PAYMENT_STATUS_PURCHASED; transaction.m_Request = paymentRequest; transaction.m_Retain = S3E_FALSE; transaction.m_TransactionReceipt = &receipt; strcpy(transaction.m_TransactionID, "1"); strcpy(transaction.m_OriginalTransactionID, "1"); memset(&receipt, 0, sizeof(receipt)); receipt.m_ReceiptSize = 0; eventMask |= TRANSACTION_REQUESTED; return S3E_RESULT_ERROR; // ??? } s3eResult s3eIOSAppStoreBillingCompleteTransactionStub(s3ePaymentTransaction* transaction, s3eBool finalise) { return S3E_RESULT_SUCCESS; } s3eResult s3eIOSAppStoreBillingRestoreCompletedTransactionsStub() { return S3E_RESULT_SUCCESS; } void appStoreStubUpdate() { #if defined IW_DEBUG if (eventMask != 0) { if (eventMask & PRODUCT_INFO_REQUESTED) { productInfoCallback(&productInformation, billingData); } if (eventMask & TRANSACTION_REQUESTED) { transactionCallback(&transaction, billingData); } eventMask = 0; } #endif }
      
      







ここでappStoreStubUpdate関数について言及する必要があります。 実際、App Store Billing APIは非同期呼び出しを使用してストアを操作します。 つまり、コールバック関数の呼び出しは、製品s3eIOSAppStoreBillingRequestProductInformationに関する情報を要求し、購入s3eIOSAppStoreBillingRequestPaymentを行う関数を呼び出すコンテキストの外側で行う必要があります。 appStoreStubUpdateでこれらの呼び出しを行い、Maramaladeアプリケーションの最後の更新関数を呼び出します。



また、戻りコードs3eIOSAppStoreBillingRequestPaymentStubによって質問が発生する場合があります。 正直なところ、私自身はこの瞬間を理解していません。 物事の論理によると、成功した場合はS3E_RESULT_SUCCESS(0に等しい)を返す必要がありますが、この例では要求の正確性の次の検証を使用しています。



s3eIOSAppStoreBilling.cpp
  if (s3eIOSAppStoreBillingRequestPayment(&g_PaymentRequest)) SetStatus("Purchasing %s...", g_ProductID2); else SetStatus("Purchasing %s FAILED", g_ProductID2);
      
      







つまり、ゼロ以外の値が予期されます。 どうやら、この例の開発者は間違いを犯したようですが、この時点で、iPhoneでアプリケーションをデバッグするときに注意を払う価値があります。



最後に言及するのはチェックです。 s3eIOSAppStoreBillingRequestPaymentStubで空のチェックを作成します。



AppStoreStub.cpp
  ... memset(&receipt, 0, sizeof(receipt)); receipt.m_ReceiptSize = 0; ...
      
      







しかし、アプリケーションが小切手を確認するか、それに含まれる情報(購入日など)を使用する必要がある場合、これはおそらく完全には正しくありません。 ここで 、正しいチェックがどのように構築されるかについて読むことができます 。 チェックを検証する方法について説明します。



残りはほとんどありません。 サンプルコードでは、非同期呼び出しをエミュレートするために、#include AppStoreStub.h(最後のものでなければなりません)とappStoreStubUpdateの呼び出しを追加します。



s3eIOSAppStoreBilling.cpp
 bool ExampleUpdate() { appStoreStubUpdate(); ...
      
      







サンプルをコンパイルしてデバッガーで実行すると、App Storeをまったく邪魔することなく、製品に関する情報を要求して購入できるようになります。




All Articles