如何在Android应用程序中实现应用程序内结算? [英] How to implement In-App Billing in an Android application?

查看:156
本文介绍了如何在Android应用程序中实现应用程序内结算?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Android应用中实施应用内结算似乎相当复杂。我怎么能这样做? SDK中的示例应用程序只有一个Activity,对于像我这样有多个活动的应用程序来说,它过于简单了。

It seems that it is quite complicated to implement In-App Billing in an Android app. How could I do this? The sample app from the SDK only has one Activity, which kind of over-simplifies it for an application like mine that has multiple Activities.

推荐答案

好吧,我会试着解释一下我的经历。我不认为自己是这方面的专家,但我几天都弄坏了头。

Well, I'll try to explain what I experienced. I don't consider myself an expert on this but I broke my head several days.

对于初学者来说,我在尝试理解示例和应用程序的工作流程时非常糟糕。我认为从一个简单的例子开始应该会更好,但是很难将代码分成小块并且不知道你是否破坏了任何东西。我会告诉你我拥有什么以及我从示例中改变了什么以使其发挥作用。

For starters, I had a very bad time trying to understand the workflow of the example and the application. I thought it should be better to start with a simple example however its much difficult to separate the code in small pieces and not knowing if you are breaking anything. I'll tell you what I have and what I changed from the example to make it work.

我有一个活动,我的所有购买都来自。它被称为Pro。

I have a single Activity where all my purchases come from. It's called Pro.

首先,您应该使用公共市场开发人员密钥更新Security类中的变量base64EncodedPublicKey,否则您将看到一个不错的异常。

First, you should update the variable base64EncodedPublicKey in your Security class with your public Market developer key or you will see a nice Exception.

好吧,我将我的活动绑定到我的BillingService,如下所示:

Well, I bind my Activity to my BillingService like so:

      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请求进入市场。您可能认为购买是在同一时刻进行的,但没有。您发送请求,购买可能会在几分钟或几小时后发出。我认为这主要是服务器超载和信用卡审批。

That way, all the purchases talk to this service, that will then, send the JSON requests to the market. You might think that the purchases are made on the same instant but no. You send the request and the purchase might come minutes or hours later. I think this is mainly to server overload and approval of the credit cards.

然后我有一个带有我的物品的ListView,我在每个物品上打开一个AlertDialog,邀请他们购买物品。当他们点击某个项目时,我这样做:

Then I have a ListView with my items, and I open a AlertDialog on each one, inviting them to buy the item. When they click on an item, I do this:

  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();
                }

            }

        }

好的,您应该看到市场开启,用户完成或取消购买。

Alright, you should see that the Market opens and the user either finishes or cancels the buy.

重要的是我的PurChaseObserver,它处理市场发送的所有事件。这是它的剥离版本,但你应该明白这一点(通过代码查看我的评论):

Whats then important is my PurChaseObserver, which handles all the events that market sends. This is a stripped version of it but you should get the point (See my comments throught the code):

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

我相信您不需要编辑任何其他内容。其余代码有效。
您可以先尝试在自己的项目android.test.purchased中使用示例SKU。到目前为止,我已经对此进行了测试,但它仍然有效,但我仍然需要覆盖退款状态等所有内容。在这种情况下,我让用户保留这些功能,但我想确保它在完成之前完美无缺。

And I believe you shouldn't need to edit anything else. The rest of the code "works". You can try using the sample SKU at first in your own items "android.test.purchased". So far I have tested this and it works however I still need to cover everything like the refunded state. In this case, I am letting the user keep the features but I want to make sure it works perfect before modyfing it.

我希望它可以帮助你和其他人。

I hope it helps you and others.

这篇关于如何在Android应用程序中实现应用程序内结算?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆