AndroidアプリケーションにIn-App Billingを実装するには?
質問
Android アプリに In-App Billing を実装するのは、かなり複雑なようです。どうすればよいのでしょうか。SDK のサンプル アプリにはアクティビティが 1 つしかなく、複数のアクティビティを持つ私のようなアプリケーションにとっては単純化しすぎのような気がします。
どのように解決するのですか?
さて、私が経験したことを説明しようと思います。私は自分では専門家だとは思っていませんが、数日間、頭を壊しました。
手始めに、私は例とアプリケーションのワークフローを理解するために非常に悪い時間を過ごしました。簡単な例から始めた方が良いと思いましたが、コードを小片に分離するのは非常に難しく、何かを壊しているのかどうかわかりません。私が持っているもの、そしてそれを動作させるために例から変更したものをお話します。
私は、すべての購入が行われる1つのアクティビティを持っています。これはProと呼ばれています。
まず、Securityクラスのbase64EncodedPublicKeyという変数を、公開されているMarketの開発者キーで更新します。
さて、BillingServiceにActivityをバインドします。
public class Pro extends TrackedActivity implements OnItemClickListener {
private BillingService mBillingService;
private BillingPurchaseObserver mBillingPurchaseObserver;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pro);
//Do my stuff
mBillingService = new BillingService();
mBillingService.setContext(getApplicationContext());
mHandler = new Handler();
mBillingPurchaseObserver = new BillingPurchaseObserver(mHandler);
}
}
@Override
protected void onStart() {
//Register the observer to the service
super.onStart();
ResponseHandler.register(mBillingPurchaseObserver);
}
@Override
protected void onStop() {
//Unregister the observer since you dont need anymore
super.onStop();
ResponseHandler.unregister(mBillingPurchaseObserver);
}
@Override
protected void onDestroy() {
//Unbind the service
super.onDestroy();
mBillingService.unbind();
}
このように、すべての購入はこのサービスと話をし、そのサービスはマーケットにJSONリクエストを送信します。購入は同じ瞬間に行われると思うかもしれませんが、そうではありません。リクエストを送信してから、数分後、数時間後に購入が行われるかもしれません。これは主にサーバーの過負荷とクレジットカードの承認が原因だと思います。
次に、私はアイテムのListViewを持っていて、それぞれについてAlertDialogを開き、アイテムを購入するように誘います。アイテムをクリックすると、このようになります。
private class BuyButton implements DialogInterface.OnClickListener {
private BillingItem item = null;
private String developerPayload;
public BuyButton(BillingItem item, String developerPayload) {
this.item = item;
this.developerPayload = developerPayload;
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (GeneralHelper.isOnline(getApplicationContext())){
//I track the buy here with GA SDK.
mBillingService.requestPurchase(this.item.getSku(), this.developerPayload);
} else {
Toast.makeText(getApplicationContext(), R.string.msg_not_online, Toast.LENGTH_SHORT).show();
}
}
}
さて、マーケットが開き、ユーザーが購入を完了するか、キャンセルするのがわかるはずです。
次に重要なのは、私のPurChaseObserverで、マーケットが送信するすべてのイベントを処理します。これはその一部を切り取ったものですが、要点はご理解いただけると思います(コード中の私のコメントをご覧ください)。
private class BillingPurchaseObserver extends PurchaseObserver {
public BillingPurchaseObserver(Handler handler) {
super(Pro.this, handler);
}
@Override
public void onBillingSupported(boolean supported) {
if (supported) {
//Enable buy functions. Not required, but you can do stuff here. The market first checks if billing is supported. Maybe your country is not supported, for example.
} else {
Toast.makeText(getApplicationContext(), R.string.billing_not_supported, Toast.LENGTH_LONG).show();
}
}
@Override
public void onPurchaseStateChange(PurchaseState purchaseState, String itemId,
int quantity, long purchaseTime, String developerPayload) {
//This is the method that is called when the buy is completed or refunded I believe.
// Here you can do something with the developerPayload. Its basically a Tag you can use to follow your transactions. i dont use it.
BillingItem item = BillingItem.getBySku(getApplicationContext(), itemId);
if (purchaseState == PurchaseState.PURCHASED) {
if (item != null){
//This is my own implementation that sets the item purchased in my database. BillingHelper is a class with methods I use to check if the user bought an option and update the UI. You should also check for refunded. You can see the Consts class to find what you need to check for.
boolean resu = item.makePurchased(getApplicationContext());
if (resu){
Toast.makeText(getApplicationContext(), R.string.billing_item_purchased, Toast.LENGTH_LONG).show();
}
}
}
}
private void trackPurchase(BillingItem item, long purchaseTime) {
//My code to track the purchase in GA
}
@Override
public void onRequestPurchaseResponse(RequestPurchase request,
ResponseCode responseCode) {
//This is the callback that happens when you sent the request. It doesnt mean you bought something. Just that the Market received it.
if (responseCode == ResponseCode.RESULT_OK) {
Toast.makeText(getApplicationContext(), R.string.billing_item_request_sent, Toast.LENGTH_SHORT).show();
} else if (responseCode == ResponseCode.RESULT_USER_CANCELED) {
//The user canceled the item.
} else {
//If it got here, the Market had an unexpected problem.
}
}
@Override
public void onRestoreTransactionsResponse(RestoreTransactions request,
ResponseCode responseCode) {
if (responseCode == ResponseCode.RESULT_OK) {
//Restore transactions should only be run once in the lifecycle of your application unless you reinstalled the app or wipe the data.
SharedPreferences.Editor edit = PreferencesHelper.getInstance().getDefaultSettings(getApplicationContext()).edit();
edit.putBoolean(Consts.DB_INITIALIZED, true);
edit.commit();
} else {
//Something went wrong
}
}
}
で、あとは何も編集する必要はないはずです。残りのコードは"works"です。 まずはサンプルのSKUを自分のアイテムに使ってみてください "android.test.purchased". 今のところ、私はこれをテストし、それは動作しますが、私はまだ払い戻しの状態などすべてをカバーする必要があります。この場合、ユーザーには機能を残していますが、改造する前に完璧に動作することを確認したいのです。
これがあなたや他の人の役に立つことを願っています。
関連
-
Eclipse問題 アクセス制限。タイプ 'SunJCE' が API でないことを解決し、/jdk ディレクトリにある /jre と jre の違いについて理解を深める。
-
アクセス制限です。タイプ 'Application' は API ではない(必要なライブラリに制限がある)。
-
配列定数は初期化子でのみ使用可能です。
-
ApiModel と @ApiModelProperty の使用法
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] Androidアプリケーションのアクティビティ間でデータを受け渡すにはどうすればよいですか?
-
[解決済み] アプリケーションを終了することは嫌われますか?
-
[解決済み] グリッドレイアウトにおけるフリングジェスチャーの検出
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Eclipse の問題 アクセス制限。タイプ 'jfxrt' はAPI解決されていません。
-
java -jarコマンドでパッケージを実行すると、無効または破損したjarfile xxxx.jarが表示される。
-
SocketException java.netの4つの例外解決策。
-
Java基礎編 - オブジェクト指向
-
eclipse にリソースリーク:'in' が閉じない
-
ecplise プロンプトが表示されます。"選択したものは起動できません。" "最近の起動はありません。"
-
Java:未解決コンパイル問題の解決方法
-
Java基礎 - マッピングとQ/A
-
ApiModel と @ApiModelProperty の使用法
-
[解決済み] リクエストされた商品は購入できません。