Androidアプリでのアプリ内購入または内部支払い

それは何ですか?



Androidプラットフォームのアプリケーションの開発者向けのAndroidマーケットアプリケーション2.3.0のバージョンでは、アプリケーション自体の中でユーザーに支払いを提供する機会が開かれました。 組み込みのプラットフォームツールのみを使用して、レベルとアーティファクト、ビデオ、音楽、プラグインなどを販売できます。 これがどのように行われるかを見てみましょう。

何が必要ですか?



いつものように、私のお気に入りのIDE、Android SDK、およびサンプルアプリケーションです
Service、BroadcastReceiver、そしてもちろんActivityが何であるかを想像することも役立ちます。

また、マニフェストファイルで許可が必要です-

<uses-permission android:name="com.android.vending.BILLING"/> 、これなしでは何も機能しません。

これは原則としてどのように機能しますか?




すべてがAndroidマーケットアプリケーションのサービスを通じて機能します。 彼は、ユーザーが購入したい特定のものの詳細のリクエストを送信する方法、購入する方法、購入の成功または失敗に関する回答を受信する方法などを知っています。 販売する商品に関するすべての情報は、特定のアプリケーションの開発者コンソールを介して設定する必要があります。 購入の成功に関するシグナルを受け取ったらすぐに、サーバーからコンテンツのロードを開始できます。

どのように機能しますか?



画像

サーバー上で、市場は購入できるものに関する情報を保存します。 市場のクライアントアプリケーションはサーバーと対話します。 私たちのアプリケーションはそれと対話します。

アプリケーションは、少なくとも次のもので構成されます。
  1. BillingService。 これは、マーケットのアプリケーションに関連付けられたサービスであり、オペレーションに関するすべての情報を送信し、それらが同期的である場合、それらに対する回答を受け取ります。
  2. BillingReceiver マーケットアプリケーションから非同期応答を取得します。
  3. PurchaseObserver。 購入ステータスの変更をUIに通知するエンティティ。


どのようなメッセージを市場に送信しますか?



まず、MarketBillingServiceのsendBillingRequestメソッドを呼び出すために、BillingServiceをマーケットアプリケーションに接続する必要があります。 サービスインターフェイスはIMarketBillingService.aidlファイルに記述されており、ダウンロードできます。 画像 ここから、アプリケーションのパッケージをcom.android.vending.billingに入れます。 IDEはすぐにIMarketBillingService.javaファイルを生成する必要があります。このファイルを上記のメソッドを呼び出す必要があります。

メソッド自体は、すべての情報を保存するBundleパラメーターを取ります。 最も重要なのは、キー「BILLING_REQUEST」を持つパラメーターです。 要求のタイプを決定します。 それらは:

CHECK_BILLING_SUPPORTEDアプリ内課金の可用性を確認します。
REQUEST_PURCHASE購入リクエスト。
GET_PURCHASE_INFORMATION購入ステータスの変更に関する情報の受信。
CONFIRM_NOTIFICATIONSマーケットアプリケーションから通知を受信したという事実の確認。
RESTORE_TRANSACTIONSすでに購入したアイテムのトランザクションを復元します。

答えは何ですか?



このメソッドは、バンドルでもある応答を同期的に返します。 次のものが含まれます。

RESPONSE_CODE応答コード
PURCHASE_INTENT購入アクティビティを開始するためのPendingIntent
REQUEST_ID送信されたリクエストの識別子

非同期応答(BillingReceiverで取得)の場合、次のものが含まれます。

com.android.vending.billing.RESPONSE_CODE
応答コード。 市場は、リクエストの成功または失敗を確認します。

com.android.vending.billing.IN_APP_NOTIFY
購入ステータスが変更されたことを警告します。 このメッセージの後、情報を取得するためにタイプGET_PURCHASE_INFORMATIONリクエストを送信する必要があります。

com.android.vending.billing.PURCHASE_STATE_CHANGED
次に、購入に関する詳細情報が表示されます。 これには、ナンス、注文のリスト、製品識別子、それらの条件などが含まれます。

購入の順序は次のとおりです。

1. REQUEST_PURCHASEを送信しREQUEST_PURCHASE
2.同期応答を取得する
3.アクティビティ購入の起動(マーケットアプリにも組み込まれています)
4.非同期メッセージIN_APP_NOTIFYを受信します
5. GET_PURCHASE_INFORMATION
6.同期応答を取得します
7.非同期応答PURCHASE_STATE_CHANGEDを受信します
8. CONFIRM_NOTIFICATIONS送信
9.同期応答を取得します

それとも、コードをよりよく見るでしょうか?



したがって、コードの主なポイント:

1.マーケットに接続します。


BillingServiceのonCreate()で次のように記述します。
try {
boolean bindResult = getApplicationContext().bindService(
new Intent( "com.android.vending.billing.MarketBillingService.BIND" ),
this ,
Context.BIND_AUTO_CREATE);
if (bindResult) {
Log.i(TAG, "Service bind successful." );
} else {
Log.e(TAG, "Could not bind to the MarketBillingService." );
}
} catch (SecurityException e) {
Log.e(TAG, "Security exception: " + e);
}

// :
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i(TAG, "MarketBillingService connected." );
marketService = IMarketBillingService.Stub.asInterface(iBinder);
runPendingRequests();
}


* This source code was highlighted with Source Code Highlighter .

2.リクエストを送信します。


サンプルアプリケーションでは、クエリのクラス階層が作成されており、これは正しいです。 それらについて最も重要なことは、出荷の遅延です。 実際には、bindServiceは非同期に発生します。つまり、onCreate()が終了するよりもはるかに遅く、初めてリクエストを実行しようとするよりも後でMarketBillingServiceへのリンクを取得します。 したがって、これを行います。

/**
* Run the request, starting the connection if necessary.
*
* @return this request if the request was not executed in order to queue it.
*/
public final AbstractRequest runRequest() {
if (runIfConnected()) {
return null ;
}
return this ;
}

/**
* Try running the request directly if the service is already connected.
*
* @return true if the request ran successfully; false if the service
* is not connected or there was an error when trying to use it
*/
public boolean runIfConnected() {
if (service.isConnected()) {
try {
requestId = run();
if (requestId >= 0) {
service.addRequest(requestId, this );
}
return true ;
} catch (MyException e) {
onException(e);
}
}
return false ;
}


* This source code was highlighted with Source Code Highlighter .


サービス内の保留中のリクエストのリストにそれを記憶するには、リクエストの返却が必要です。 次に、onServiceConnected()でMarketBillingServiceへのリンクを取得すると、すべてのリクエストを再度送信しようとします。

3. UI通知


BillingServiceでは、UIからハンドラーを保存するエンティティへのリンクを保存します。 次に、回答を受け取った後、次のことを行うことができます。

private void notifyGui( int messageId, PurchasedItem item) {
if (observer != null ) {
observer.notifyGui(messageId, item);
} else {
// NotificationBar
}
}

* This source code was highlighted with Source Code Highlighter .


重要:終了するときにアクティビティからオブザーバーサービスをリセットし、このリンクを復元することを忘れないでください。 これは次のように行われます。

@Override
protected void onUserLeaveHint() {
if (billingService != null ) {
unbindService( this );
billingService.resetEventDispatcher();
billingService = null ;
}
super.onUserLeaveHint();
}

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//Connected to BillingService
if (componentName.getShortClassName().equals(serviceClassName)) {
billingService = ((BillingService.LocalBinder) iBinder).getService();
billingService.setObserver( new PurchaseObserver());
try {
billingService.checkBillingAvailability();
} catch (MyException e) {
Log.e(TAG, "Billing unavailable" , e);
Toast.makeText( this , "Billing unavailable" , Toast.LENGTH_LONG).show();
}
}
}


* This source code was highlighted with Source Code Highlighter .


4.アクティビティ購入を起動します。


PurchaseObserverサンプルクラスをご覧ください。 メソッドpublic void startBuyPageActivity(PendingIntent pendingIntent、Intent intent)があります。 PendingIntentは、市場から得たものです。 そして、Intentは新しいIntent()です。
このメソッドは何をしますか?
実際、アクティビティのインスタンスはこのクラスに渡されます。 さらに、リフレクションを通じて、startInstentSenderメソッドを取得しようとします。 このメソッドはAndroid 2.0でのみ登場しました。 そうである場合、メソッドが呼び出され、アクティビティがアプリケーションのアクティビティスタックで開始されます。 メソッドが見つからない場合、アクティビティは別のスタックで開始されます。

しかし、セキュリティはどうですか?



セキュリティの問題は別の記事のトピックであり、すでに多くの問題があります。 サンプルアプリケーションでは、Securityクラスがセキュリティを担当します。 私はあなたがアプリケーションではなく(例で行われたように)購入を検証する必要があると言うことができますが、潜在的なapk所有者の手に検証ロジックを与えないようにあなた自身のサーバーで。

PS developer.android.com/guide/market/billing/billing_overview.htmlに基づく

Source: https://habr.com/ru/post/J117944/


All Articles