0

我似乎对 Android 的应用内计费有问题

我遵循了这个指南Android Google Play In-App Billing这对设置很有帮助,但我不完全理解

我想知道的是

我可以通过用户单击某个按钮来启动服务吗?我如何启动服务,如果用户没有购买内容,我是否可以设置它,我可能会显示一个对话框并在用户使用时将其销毁有关于应用程序

任何建议或帮助将不胜感激

这是我的代码:

package com.IrishSign.app;

import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.IrishSign.app.BillingService.RequestPurchase;
import com.IrishSign.app.BillingService.RestoreTransactions;
import com.IrishSign.app.Consts.PurchaseState;
import com.IrishSign.app.Consts.ResponseCode;



public class IrishSignAppActivity extends Activity {
    /**
    * The SharedPreferences key for recording whether we initialized the
    * database.  If false, then we perform a RestoreTransactions request
    * to get all the purchases for this user.
    */

    private static final String DB_INITIALIZED = "db_initialized";
    private AppPurchaseObserver appPurchaseObserver;
    private Handler handler;
    private BillingService billingService;
    private PurchaseDatabase purchaseDatabase;

    private Set<String> ownedItems = new HashSet<String>();

    /**
    * The developer payload that is sent with subsequent
    * purchase requests.
    */

    private String payloadContents = null;

    /**
    * Each product in the catalog is either MANAGED or UNMANAGED.  MANAGED
    * means that the product can be purchased only once per user (such as a new
    * level in a game). The purchase is remembered by Android Market and
    * can be restored if this application is uninstalled and then
    * re-installed. UNMANAGED is used for products that can be used up and
    * purchased multiple times (such as poker chips). It is up to the
    * application to keep track of UNMANAGED products for the user.
    */

    private enum Managed { MANAGED, UNMANAGED }

    /**
    * A {@link PurchaseObserver} is used to get callbacks when Android Market sends
    * messages to this application so that we can update the UI.
    */

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

        public void onBillingSupported(boolean supported) {
            if (Consts.DEBUG) {
                Log.i(TAG, "supported: " + supported);
            }
            if (supported) {
                restoreDatabase();
                //ADD enabling methods or anything else you may need here...
            }
            //YOU can also put a dialog here
        }

        @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 (purchaseState == PurchaseState.PURCHASED) {
                ownedItems.add(itemId);
            }
            //YOU can also add other checks here
        }

        @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");
                }

               //Do something here if you want
            } 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 = getSharedPreferences("idroprbilling",Context.MODE_PRIVATE);//NOTE: Change the idroprbilling to something else
               SharedPreferences.Editor edit = prefs.edit();
               edit.putBoolean(DB_INITIALIZED, true);
               edit.commit();
            } else {
                if (Consts.DEBUG) {
                    Log.d(TAG, "RestoreTransactions error: " + responseCode);
                }
            }
        }

        @Override
        public void onBillingSupported(boolean supported, String type) {
            // TODO Auto-generated method stub

        }
    }

    //NOTE: This may not even apply to your app - copied here but may never be used if only purchasing an UPGRADE or PREMIUM service
    private static class CatalogEntry {
        public String sku;
        public int nameId;
        public Managed managed;

        public CatalogEntry(String sku, int nameId, Managed managed) {
            this.sku = sku;
            this.nameId = nameId;
            this.managed = managed;
        }
    }

    //NOTE: Same as above - An array of product list entries for the products that can be purchased.
    private static final CatalogEntry[] CATALOG = new CatalogEntry[] {
        new CatalogEntry("Upgrade", R.string.upgrade, Managed.MANAGED),
        new CatalogEntry("android.test.purchased", R.string.android_test_purchased, Managed.UNMANAGED),
        new CatalogEntry("android.test.canceled", R.string.android_test_canceled, Managed.UNMANAGED),
        new CatalogEntry("android.test.refunded", R.string.android_test_refunded, Managed.UNMANAGED),
        new CatalogEntry("android.test.item_unavailable", R.string.android_test_item_unavailable, Managed.UNMANAGED),
    };

    /**
    * If the database has not been initialized, we send a
    * RESTORE_TRANSACTIONS request to Android Market to get the list of purchased items
    * for this user. This happens if the application has just been installed
    * or the user wiped data. We do not want to do this on every startup, rather, we want to do
    * only when the database needs to be initialized.
    */
    private void restoreDatabase() {
        SharedPreferences prefs = getSharedPreferences("idroprbilling",MODE_PRIVATE);
        boolean initialized = prefs.getBoolean(DB_INITIALIZED, false);
        if (!initialized) {
            billingService.restoreTransactions();
            Toast.makeText(this, R.string.restoring_transactions, Toast.LENGTH_LONG).show();
        }
    }

    /**
    * 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
    */
    //NOTE: This method is here for convenience only
    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;


    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        //Now setup the in-app billing</pre>
        handler = new Handler();

        appPurchaseObserver = new AppPurchaseObserver(handler);

        billingService = new BillingService();

        billingService.setContext(this);
        purchaseDatabase = new PurchaseDatabase(this);

        ResponseHandler.register(appPurchaseObserver);
        /**
        * Creates a background thread that reads the database and initializes the
        * set of owned items.
        */



        //Check if billing is supported. (Optional)
        boolean check = billingService.checkBillingSupported();
        setContentView(R.layout.main);

        Button Language = (Button) findViewById(R.id.language);
        Button A = (Button) findViewById(R.id.alphabet);
        Button purchaseableItem = (Button) findViewById(R.id.topics);
        Button purchaseableItem2 = (Button) findViewById(R.id.intro);
        Button G = (Button) findViewById(R.id.about);


        G.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                AlertDialog alertDialog = new AlertDialog.Builder(
                        IrishSignAppActivity.this).setCancelable(false)
                        .create(); // Reads Update
                alertDialog.setTitle("Welcome ");
                alertDialog.setMessage("this is my first dialog box :)");// Change tommorow//

                alertDialog.setButton("Continue..",
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int arg1) {
                                Intent our3intent = new Intent(
                                        "com.IrishSign.app.MAIN"); // Change to
                                                                    // revert
                                                                    // back to
                                                                    // menu
                                startActivity(our3intent);

                            }
                        });

                alertDialog.show(); // <-- Shows dialog on screen.
            }

        });

        purchaseableItem2.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent our3intent = new Intent("com.IrishSign.app.Intro");
                startActivity(our3intent);
            }
        });

        purchaseableItem.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                //Now setup the in-app billing</pre>

                boolean val = billingService.requestPurchase("com.irishsign.app.topicvideos", payloadContents, null);

            }
        });

        A.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent ourintent = new Intent("com.IrishSign.app.alpha");
                startActivity(ourintent);

            }
        });

        Language.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                Intent language = new Intent("com.IrishSign.app.Language");
                startActivity(language);

            }
        });


    }


    }
4

1 回答 1

1

Google 的应用内计费示例实现过于复杂,并且在几个领域使用了非正统的方法。我无法解释他们为什么这样做,但这就是我解决它的方式。

首先,您可以假设该服务已“启动”并准备好在您在 onCreate 中对其进行初始化并为其提供上下文时使用。

您可以使用以下行加载 Google Market 购买屏幕:

this.billingService.requestPurchase(<String ID of the in-app product>, null);

如果用户成功购买了该商品,Market 将向 AppPurchaseObserver.onPurchaseStateChange() 广播一条消息,您已设置该消息来监听他们。在 onPurchaseStateChange() 中,您需要做两件事:

  1. 将此用户现在拥有此项目的事实存储在应用程序上您自己的数据存储中。

  2. 更新当前活动以显示新购买(即,您向用户显示他们不拥有该项目的对话框现在可以关闭。)。因为 AppPurchaseObserver 是活动中的嵌套类,所以 onPurchaseStateChange() 可以访问活动的视图对象。

要意识到的是,无法快速、持续地查询用户从 Market 购买的商品,因此 Google 实际上要求您在收到通知时将此信息存储在您自己的数据存储中(如上文 1. 所述)。当您加载自己的活动时,您只需查询您自己的用户购买的数据存储并相应地加载正确的视觉提示。

于 2012-07-11T01:28:08.957 回答