我在本地设置了“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商店的付费界面?
谢谢!
答案 0 :(得分:4)
我建议你使用这段代码,因为这个例子安静简单,起初很容易处理..你要做的事情是
http://blog.blundell-apps.com/simple-inapp-billing-payment/
将以下实用程序文件放在任何包中,并相应地更正导入语句。
* BillingHelper.java
* BillingReceiver.java
* BillingSecurity.java
* BillingService.java
* C.java
在BillingSecurity.java中放置公钥(您可以在编辑个人资料底部的开发者控制台中找到它)String base64EncodedPublicKey = "your public key here"
在清单中声明以下权限(在应用程序标记之外),服务和接收者(在应用程序标记内),如下所示(也可以查看代码中的清单以供参考)
//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>
将上述代码放在您举行购买活动的地方。
//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中,如上所述,其次您需要将apk上传到开发者控制台(您可以将其保留为uupublished和unactive),其次您需要一个真实的更新了Play商店应用程序的Android设备(模拟器不起作用)。
注意:在应用内购买所需的帐户以及上述所有讨论中描述的帐户不仅仅是简单的发布商帐户,其发布商帐户嵌入了Google商家钱包帐户。详细信息可以在下面的链接中找到。
http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&answer=113468
答案 1 :(得分:2)
有两种方式
Android API不会为您提供任何库存API以维持您的购买。
我使用了第二个选项。
答案 2 :(得分:2)
- 购买单品 store.purchase({“android.test.purchased”})
-- multi-item purchase
store.purchase( { "android.test.purchased", "android.test.canceled" } )
参考Getting Started with Android In-app Billing
此代码可能是您正在寻找的代码
答案 3 :(得分: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)最后你的按钮活动应该是这样的
公共类YourActivity扩展Activity实现OnClickListener { String issueProductId =“您的产品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();
}
}
}
答案 4 :(得分:2)
答案 5 :(得分:2)
来自Google的示例应用内结算代码是一个良好的开端。我已经发布了一个指向我给出的教程的链接,这是一个三部分。这个链接是三个中的第一个。我希望它有所帮助。
http://www.mobileoped.com/2012/04/06/android-google-play-in-app-billing-part-1/