5

「Dungeons」の InAppBilling の例をローカルでセットアップし、試してみる準備ができましたが、少し混乱しています。次のようなボタンがあります。

Button donate = (Button)findViewById(R.id.donate);     
donate.setOnClickListener(new Button.OnClickListener() {  
        public void onClick(View v) {     
        // But what do I do here? :)
        }
});

そして、それが呼び出されたときに、実際にAndroidストアの有料画面に移動するにはどうすればよいですか?

ありがとう!

4

6 に答える 6

4

この例は静かでシンプルで、最初は扱いやすいので、このコードを使用することをお勧めします..あなたがしなければならないことは

http://blog.blundell-apps.com/simple-inapp-billing-payment/

  1. 上記のリンクからサンプル プロジェクト コードをダウンロードします (下部にコードの説明とダウンロード リンクがあります)。
  2. アプリ課金に実装する Android プロジェクトで、パッケージ com.android.vending.billing を作成し、IMarketBillingService.aidl を配置します (これとすべてのファイルは、手順 1 でダウンロードしたプロジェクトで見つけることができます)。
  3. 次のユーティリティ ファイルを任意のパッケージに配置し、それに応じてインポート ステートメントを修正します。

          * BillingHelper.java
          * BillingReceiver.java
          * BillingSecurity.java
          * BillingService.java
          * C.java
    
  4. BillingSecurity.java の行に公開鍵を配置します (編集プロファイルの下部セクションにある開発者コンソールで見つけることができます)。String base64EncodedPublicKey = "your public key here"

  5. 以下に示すように、マニフェストで次のアクセス許可 (アプリケーション タグの外側)、サービス、および受信者 (アプリケーション タグの内側) を宣言します (参照用のコードに沿ったマニフェストも参照できます)。

     //outside the application tag 
     <uses-permission android:name="com.android.vending.BILLING" />
    
     // Inside the application tag
     <service android:name=".BillingService" />
    
    <receiver android:name=".BillingReceiver">
        <intent-filter>
            <action android:name="com.android.vending.billing.IN_APP_NOTIFY" />
            <action android:name="com.android.vending.billing.RESPONSE_CODE" />
            <action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" />            
        </intent-filter>
    </receiver> 
    
  6. 前述のように、購入が行われているアクティビティの場所に次のコードを配置します。

    //at the starting of your onCreate()
    startService(new Intent(mContext, BillingService.class));
    BillingHelper.setCompletedHandler(mTransactionHandler);
    
    //outside onCreate() Within class
     public Handler mTransactionHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            Log.i(TAG, "Transaction complete");
            Log.i(TAG, "Transaction status: "+BillingHelper.latestPurchase.purchaseState);
            Log.i(TAG, "Item purchased is: "+BillingHelper.latestPurchase.productId);
    
            if(BillingHelper.latestPurchase.isPurchased()){
                //code here which is to be performed after successful purchase
            }
        };
    
     };
    
     //code to initiate a purchase... can be placed in onClickListener etc
      if(BillingHelper.isBillingSupported()){
            BillingHelper.requestPurchase(mContext, "android.test.purchased"); 
            // where android.test.purchased is test id for fake purchase, when you create products through developer console you can set a code to pass the id(which is given on developer console while creating a product) of the item which is selected for purchase to intiate purchase of that item.
        } else {
            Log.i(TAG,"Can't purchase on this device");
             // Do Anything Heer to show user that purchase not possible on this device
        }
    

注: テスト購入を行うには、上記のように BillingSecurity.java に公開キーを配置する必要があります。2 番目に開発者コンソールに apk をアップロードする必要があります (uupublished および非アクティブのままにしておくことができます)。3 番目に、実際の Android デバイスが必要です (エミュレーターは動作しません) Play ストア アプリを更新しました。

注: アプリ内購入に必要で、上記のすべての説明で説明されているアカウントは、Google マーチャント ウォレット アカウントに埋め込まれた単なる発行者アカウントではありません。詳細は下記リンクよりご覧いただけます。

http://support.google.com/googleplay/android-developer/bin/answer.py?hl=ja&answer=113468

于 2012-06-26T08:45:34.593 に答える
2

1)ダウンロード

http://developer.android.com/guide/google/play/billing/billing_integrate.html#billing-download

2)追加

http://developer.android.com/guide/google/play/billing/billing_integrate.html#billing-add-aidl

3)Androidマニフェストファイルに権限を追加する

http://developer.android.com/guide/google/play/billing/billing_integrate.html#billing-permission

これで、プロジェクトは次のようになります...

ここに画像の説明を入力してください

4)公開鍵(開発者コンソールの編集プロファイルの下部セクションにあります)をSecurity.javaのString base64EncodedPublicKey="ここに公開鍵"という行に配置します。

5)そして最後にボタンのあるあなたの活動はこのようになるはずです

public class YourActivity extends Activityimplements OnClickListener {String issueProductId = "Your Product ID";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.updates);
    SetInAppBilling();
    Button donate = (Button) findViewById(R.id.donate);
    donate.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {
            if (mBillingService.requestPurchase(issueProductId, null)) {

            } else {
                showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID);
                Log.i("tag", "Can't purchase on this device");

            }

        }
    });
}


public void register() {
    ResponseHandler.register(mDungeonsPurchaseObserver);
}

public void unregister() {
    ResponseHandler.unregister(mDungeonsPurchaseObserver);
}

public void close_unbind() {
    if (mPurchaseDatabase != null)
        // mPurchaseDatabase.close();
        if (mBillingService != null)
            mBillingService.unbind();
    // stopService(new Intent(this, BillingService.class));
}

/**
 * Called when this activity becomes visible.
 */
@Override
protected void onStart() {
    super.onStart();

    register();
}

/**
 * Called when this activity is no longer visible.
 */
@Override
protected void onStop() {
    unregister();
    super.onStop();

}

@Override
protected void onDestroy() {
    close_unbind();
    super.onDestroy();

}

private static final String TAG = "YourActivity";

private static final String DB_INITIALIZED = "db_initialized";

// private static final String Dir_Check = "Dir_Check";

private DungeonsPurchaseObserver mDungeonsPurchaseObserver;
private Handler mHandler;

private BillingService mBillingService;
private PurchaseDatabase mPurchaseDatabase;
private static final int DIALOG_CANNOT_CONNECT_ID = 1;
private static final int DIALOG_BILLING_NOT_SUPPORTED_ID = 2;
private Cursor mOwnedItemsCursor;

public void SetInAppBilling() {
    mHandler = new Handler();
    mDungeonsPurchaseObserver = new DungeonsPurchaseObserver(mHandler);
    mBillingService = new BillingService();
    mBillingService.setContext(this);

    mPurchaseDatabase = new PurchaseDatabase(this);

    mOwnedItemsCursor = mPurchaseDatabase
            .queryAllPurchasedHistroyTabelItems();
    startManagingCursor(mOwnedItemsCursor);

    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    boolean initialized = prefs.getBoolean(DB_INITIALIZED, false);
    // Check if billing is supported.
    ResponseHandler.register(mDungeonsPurchaseObserver);
    if (!mBillingService.checkBillingSupported()) {
        showDialog(DIALOG_CANNOT_CONNECT_ID);
    }
}

private class DungeonsPurchaseObserver extends PurchaseObserver {
    public DungeonsPurchaseObserver(Handler handler) {
        super(YourActiviy.this, handler);
    }

    @Override
    public void onBillingSupported(boolean supported) {

        Log.i(TAG, "supportedCheck: " + supported);
        if (Consts.DEBUG) {
            Log.i(TAG, "supported: " + supported);
        }
        if (supported) {
            restoreDatabase();
        } else {
            showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID);
        }
    }

    @Override
    public void onPurchaseStateChange(PurchaseState purchaseState,
            String itemId, int quantity, long purchaseTime,
            String developerPayload) {
        if (Consts.DEBUG) {
            Log.i(TAG, "onPurchaseStateChange() itemId: " + itemId + " "
                    + purchaseState);
        }

        if (developerPayload == null) {

        } else {

        }

        Log.e(TAG, "onPurchaseStateChangeCheck: " + "onPurchaseStateChange");
        if (purchaseState == PurchaseState.PURCHASED) {

            /** TODO: */
            Toast.makeText(
                    mContext,
                    "You successfully upgraded to the entire Volume One. Enjoy!",
                    Toast.LENGTH_SHORT).show();
            finish();
        }

    }

    @Override
    public void onRequestPurchaseResponse(RequestPurchase request,
            ResponseCode responseCode) {
        if (Consts.DEBUG) {
            Log.d(TAG, request.mProductId + ": " + responseCode);
        }
        if (responseCode == ResponseCode.RESULT_OK) {
            if (Consts.DEBUG) {
                Log.i(TAG, "purchase was successfully sent to server");
            }

        } else if (responseCode == ResponseCode.RESULT_USER_CANCELED) {
            if (Consts.DEBUG) {
                Log.i(TAG, "user canceled purchase");
            }

        } else {
            if (Consts.DEBUG) {
                Log.i(TAG, "purchase failed");
            }

        }
    }

    @Override
    public void onRestoreTransactionsResponse(RestoreTransactions request,
            ResponseCode responseCode) {
        if (responseCode == ResponseCode.RESULT_OK) {
            if (Consts.DEBUG) {
                Log.d(TAG, "completed RestoreTransactions request");
            }
            // Update the shared preferences so that we don't perform
            // a RestoreTransactions again.

            SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
            SharedPreferences.Editor edit = prefs.edit();
            edit.putBoolean(DB_INITIALIZED, true);
            edit.commit();

            mOwnedItemsCursor = mPurchaseDatabase
                    .queryAllPurchasedHistroyTabelItems();
            Log.d(TAG, String.valueOf(mOwnedItemsCursor.getCount()));
            startManagingCursor(mOwnedItemsCursor);

            if (mOwnedItemsCursor.getCount() > 0) {
                Log.d(TAG, "Updating the DB");
                Toast.makeText(
                        mContext,
                        "You successfully upgraded to the entire Volume One. Enjoy!",
                        Toast.LENGTH_SHORT).show();
                finish();
            }

        } else {
            if (Consts.DEBUG) {
                Log.d(TAG, "RestoreTransactions error: " + responseCode);
            }
        }
    }
}

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case DIALOG_CANNOT_CONNECT_ID:
        return createDialog(R.string.cannot_connect_title,
                R.string.cannot_connect_message);
    case DIALOG_BILLING_NOT_SUPPORTED_ID:
        return createDialog(R.string.billing_not_supported_title,
                R.string.billing_not_supported_message);
    default:
        return null;
    }
}

private Dialog createDialog(int titleId, int messageId) {
    String helpUrl = replaceLanguageAndRegion(getString(R.string.help_url));
    if (Consts.DEBUG) {
        Log.i(TAG, helpUrl);
    }
    final Uri helpUri = Uri.parse(helpUrl);

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(titleId)
            .setIcon(android.R.drawable.stat_sys_warning)
            .setMessage(messageId)
            .setCancelable(false)
            .setPositiveButton(android.R.string.ok, null)
            .setNegativeButton(R.string.learn_more,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog,
                                int which) {
                            Intent intent = new Intent(Intent.ACTION_VIEW,
                                    helpUri);
                            startActivity(intent);
                        }
                    });
    return builder.create();
}

/**
 * Replaces the language and/or country of the device into the given string.
 * The pattern "%lang%" will be replaced by the device's language code and
 * the pattern "%region%" will be replaced with the device's country code.
 * 
 * @param str
 *            the string to replace the language/country within
 * @return a string containing the local language and region codes
 */
private String replaceLanguageAndRegion(String str) {
    // Substitute language and or region if present in string
    if (str.contains("%lang%") || str.contains("%region%")) {
        Locale locale = Locale.getDefault();
        str = str.replace("%lang%", locale.getLanguage().toLowerCase());
        str = str.replace("%region%", locale.getCountry().toLowerCase());
    }
    return str;
}

private void restoreDatabase() {
    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    boolean initialized = prefs.getBoolean(DB_INITIALIZED, false);
    if (!initialized) {
        mBillingService.restoreTransactions();
        // Toast.makeText(this, "restoring...", Toast.LENGTH_LONG).show();

    }
}

}

于 2012-06-27T17:37:56.410 に答える
2

Googleのサンプルのアプリ内課金コードは良いスタートです。私が提供したチュートリアルへのリンクを投稿しました。これは3つの部分です。このリンクは3つのうちの最初のものです。お役に立てば幸いです。

http://www.mobileoped.com/2012/04/06/android-google-play-in-app-billing-part-1/

于 2012-06-30T14:30:21.450 に答える
2

2つの方法があります

  • サーバー側でデータベースを維持し、ユーザー+購入した製品リスト+有効期限のテーブルを作成します
  • または、暗号化されたコードを共有設定に保存するクライアントアプリ(簡単にハッキングされないようにするため)

Android APIは、購入を維持するためのインベントリAPIを提供しません。

2番目のオプションを使用しました。

于 2012-06-26T05:47:20.173 に答える
2

-- 単品購入 store.purchase( { "android.test.purchased" } )

-- multi-item purchase
store.purchase( { "android.test.purchased", "android.test.canceled" } )

Android のアプリ内課金の開始方法について

このコードはおそらくあなたが探しているものです

于 2012-06-26T08:53:12.380 に答える
2

ここで、シンプルなアプリ内課金/支払いに使用したコードを使用できます。

ここに画像の説明を入力

また、このコードを参照してください。

于 2012-06-28T06:53:12.730 に答える