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? :)
        }
});

当它被调用时,我需要做什么才能真正进入安卓商店的支付屏幕?

谢谢!

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. place the following code as mentioned with there places in your activity where purchase is being held.

    //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
        }
    

Note: To do a test purchase you need to put the public key in BillingSecurity.java as mentioned above secondly you need to upload the apk to the developer console(you can leave it uupublished and unactive) and thirdly you need a real android device(emulator wouldn't work) having updated play store app.

Note: the account needed for in app purchase and described in all above discussion is not just simple publisher account its publisher account embedded with google merchant wallet account. The details can be found in link below.

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

于 2012-06-26T08:45:34.593 回答
2

有2种方式

  • 在您的服务器端维护一个数据库,并为用户+购买的产品列表+到期日期创建一个表
  • 或客户端应用程序在共享首选项上保存加密代码(这样就不会轻易被黑客入侵)

Android API 不为您提供任何库存 API 来维护您的购买。

我使用了第二个选项。

于 2012-06-26T05:47:20.173 回答
2

-- single product purchase store.purchase( { "android.test.purchased" } )

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

in reference to Getting Started with Android In-app Billing

this code maybe the one you are looking for

于 2012-06-26T08:53:12.380 回答
2

1)download

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

2)add

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

3)add permission in your android manifest file

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

now your project should look like this...

enter image description here

4) place the public key (you can find it in developer console in the bottom section of edit profile) in the Security.java in line saying String base64EncodedPublicKey = "your public key here"

5) and finally your activity which have button should be look like this

public class YourActivity extends Activity implements 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

Here code i used for Simple InApp Billing / Payment and you can also use.

enter image description here

Also Refer this code May Helps.

于 2012-06-28T06:53:12.730 回答
2

The sample in-app billing code from Google is a good start. I have posted a link to a tutorial I gave which is three parts. This link is the first of three. I hope it helps.

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

于 2012-06-30T14:30:21.450 回答