Android无法绑定服务(在AP​​P-计费) [英] Android cannot bind to service (In App-Billing)

查看:171
本文介绍了Android无法绑定服务(在AP​​P-计费)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在app计费,以实现我的应用程序,但我有一个小问题吧。我使用的是来自Android开发者的网站,每次的例子,我开始将连接到计费服务的活动它显示了我,我不能连接到服务器对话框,当我preSS了解它要的web页面在解释我更新Android Market的应用程序,但它已经是最新的一个。而其他的事情,实现我的应用程序中的code之前,我创建了一个测试应用程序,我可以用相同的code连接,我不明白的问题。但是,在我的应用程序,我不能这样做。是否与开发者API密钥,你只能在一个应用程序或类似的东西使用的任何连接。因为我使用的是相同的测试和实际应用。

I'm trying to implement in app-billing in my application, but I have a little problem with it. I'm using the example from android developer's site and everytime I start the activity which will connect to the billing service it's showing me a dialog that I cannot connect to server and when I press learn more it's going to a web page which is explaining me to update my android market app, but it's already the latest one. And the other thing, before implementing the code on my application I create a test application where I can connect with the same code and I don't get problems. But in my application I can't do that. Is there any connection with the developer api key, which you can use only in one application or something like that. Because I'm using the same for test and real app.

和这里是我的code,如果你能看到一些东西,是不是真的像它应该是:

And here is my code if you can see something which is not really like it should be :

public class StampiiStore extends Activity {
    String servername;
    int userId;
    int storageID;
    RPCCommunicator rpc;
    String path;
    Button envelope1, envelope2, envelope3;
    private static final String TAG = "STAMPII";
    /**
     * 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 mStampiiPurchaseObserver mStampiiPurchaseObserver;
    private Handler mHandler;
    private BillingService mBillingService;
    private TextView mLogTextView;
    private Cursor mOwnedItemsCursor;
    private PurchaseDatabase mPurchaseDatabase;
    private Set<String> mOwnedItems = new HashSet<String>();
    /**
     * The developer payload that is sent with subsequent
     * purchase requests.
     */
    private static final int DIALOG_CANNOT_CONNECT_ID = 1;
    private static final int DIALOG_BILLING_NOT_SUPPORTED_ID = 2;

    @SuppressWarnings("static-access")
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.store);


        SystemDatabaseHelper sysDbHelper = new SystemDatabaseHelper(this, null, 1);
        sysDbHelper.initialize(this);

        ImageView icon = (ImageView) findViewById (R.id.store_img);

        final int collId = getIntent().getIntExtra("collection_id",0);
        Log.e("collId","collId : "+collId);

        // Getting all variables from SharedPreferences to build the right path to images
        servername = rpc.getCurrentServerName(this);
        Log.d("","Current Server Name : "+servername);
        userId = rpc.getUserId(this);
        Log.d("","User Id : "+userId);
        storageID = rpc.getCurrentStoragePath(this);
        Log.d("","storage ID : "+storageID);
        //

        TextView colltitle = (TextView) findViewById(R.id.collection_title);
        TextView sTitle = (TextView) findViewById(R.id.store_collId);
        TextView collInfo = (TextView) findViewById(R.id.store_coll_info);

        envelope1 = (Button) findViewById(R.id.buyone);
        envelope1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                mBillingService.requestPurchase("android.test.purchased", "");
            }
        });

        envelope2 = (Button) findViewById(R.id.buytwo);
        envelope2.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                mBillingService.requestPurchase("android.test.canceled", "");
            }
        });

        envelope3 = (Button) findViewById(R.id.buythree);
        envelope3.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                mBillingService.requestPurchase("com.stampii.stampii.envelopesthree", "");
            }
        });

        mHandler = new Handler();
        mStampiiPurchaseObserver = new mStampiiPurchaseObserver(mHandler);
        mBillingService = new BillingService();
        mBillingService.setContext(this);

        mPurchaseDatabase = new PurchaseDatabase(this);
        setupWidgets();

        // Check if billing is supported.
        ResponseHandler.register(mStampiiPurchaseObserver);
        if (!mBillingService.checkBillingSupported()) {
            showDialog(DIALOG_CANNOT_CONNECT_ID);
        }



        Button back = (Button) findViewById(R.id.store_back_button);
        back.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                finish();
            }
        });
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);

        boolean isLoggedIn = settings.getBoolean("isLoggedIn", false);

        ImageButton sync = (ImageButton) findViewById(R.id.sync_store);
        if(isLoggedIn){
            sync.setVisibility(View.VISIBLE);
        } else if(!isLoggedIn){
            sync.setVisibility(View.GONE);
        }
        sync.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(StampiiStore.this, Synchronization.class);
                intent.putExtra("process", 2);
                startActivity(intent);              
            }
        });

        String titleSql = "SELECT title FROM collection_lang WHERE collection_id= " + collId + " AND lang_code='en_US'";
        Cursor title = sysDbHelper.executeSQLQuery(titleSql);
        if(title.getCount()==0){
            title.close();
        } else if(title.getCount()>0){
            for(title.move(0); title.moveToNext(); title.isAfterLast()){
                String collectionTitle = title.getString(title.getColumnIndex("title"));
                sTitle.setText(collectionTitle);
                if (collectionTitle.length() > 20){
                       String newTitle = collectionTitle.substring(0, 20);
                       colltitle.setText(newTitle + "...");
                } else {
                    colltitle.setText(collectionTitle);
                }
            }
        }
        title.close();

        String infoSql =  "SELECT DISTINCT  c.total_cards AS cardsCount, " +
                            " c.cards_per_envelope AS cardsPerEnvelope " +
                            "FROM collections AS c, collection_lang AS cl " +
                            "WHERE c.collection_id = cl.collection_id AND c.collection_id=" + collId;
        Cursor info = sysDbHelper.executeSQLQuery(infoSql);
        if(info.getCount()==0){
            info.close();
        } else if (info.getCount()>0){
            info.moveToFirst();
                int cardsCount = info.getInt(info.getColumnIndex("cardsCount"));
                int cardsPerEnvelope = info.getInt(info.getColumnIndex("cardsPerEnvelope"));
                collInfo.setText(cardsCount+" Stampii\n"+cardsPerEnvelope+" cards per envelope");
        }

        String sqlite2 = "SELECT media_id FROM collection_media WHERE collection_id="+collId+" AND media_type_id="+3018;
        Cursor bg = sysDbHelper.executeSQLQuery(sqlite2);
        if (bg.getCount() == 0) {
            bg.close();
        } else if (bg.getCount() > 0) {
            for (bg.move(0); bg.moveToNext(); bg.isAfterLast()) {
                int objectId = Integer.parseInt(bg.getString(bg.getColumnIndex("media_id")));
                String filename = "mediacollection-"+objectId+".png";
                //if(storageID==1){
                    path = rpc.getPublicPathsInternal(servername, 3018, filename, StampiiStore.this);
            /*} else if(storageID==2){
                path = rpc.getPublicPathsExternal(servername, 3007, objectId);
            }*/
            }
        }
        bg.close();

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inTempStorage = new byte[3*1024];

        Bitmap ops = BitmapFactory.decodeFile(path, options);
        BitmapDrawable bitmapDrawable = new BitmapDrawable(ops);
        icon.setBackgroundDrawable(bitmapDrawable);

        Button promoCode = (Button) findViewById(R.id.promo_code_btn);
        promoCode.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                SharedPreferences isSelectedCode = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                String isSelected = isSelectedCode.getString("isSelected", "");
                Log.i("isSelected", "isSelected" + isSelected);
                EditText input = new EditText(StampiiStore.this);
                input.setText(isSelected);

                final int loggedOut = getIntent().getIntExtra("statement", 0);
                if(loggedOut==0){
                    new AlertDialog.Builder(getParent())
                    .setTitle("Promotional Code")
                    .setView(input)
                    .setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.d("AlertDialog", "Positive");
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.d("AlertDialog","Negative");
                            dialog.cancel();
                        }
                    }).show();
                } else if (loggedOut==1){
                    new AlertDialog.Builder(Collections.parentActivity)
                    .setTitle("Promotional Code")
                    .setView(input)
                    .setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.d("AlertDialog", "Positive");
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.d("AlertDialog","Negative");
                            dialog.cancel();
                        }
                    }).show();
                }
            }
        });

        Button savedCodes = (Button) findViewById(R.id.saved_codes_btn);
        savedCodes.setOnClickListener(new OnClickListener(){
            public void onClick(View v){
                Intent previewMessage = new Intent(getParent(), SavedCodes.class);
                TabGroupActivity parentActivity = (TabGroupActivity)getParent();
                parentActivity.startChildActivity("Saved Codes", previewMessage);
            }
        });
    }


    /**
     * Sets up the UI.
     */
    private void setupWidgets() {
        //TODO: If need any changes in the UI!
    }


    /**
     * 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 = getPreferences(MODE_PRIVATE);
        boolean initialized = prefs.getBoolean(DB_INITIALIZED, false);
        if (!initialized) {
            mBillingService.restoreTransactions();
            Toast.makeText(this, "Restoring Transactions", Toast.LENGTH_LONG).show();
        }
    }

    private void prependLogEntry(CharSequence cs) {
        SpannableStringBuilder contents = new SpannableStringBuilder(cs);
        contents.append('\n');
        contents.append(mLogTextView.getText());
        mLogTextView.setText(contents);
    }

    private void logProductActivity(String product, String activity) {
        SpannableStringBuilder contents = new SpannableStringBuilder();
        contents.append(Html.fromHtml("<b>" + product + "</b>: "));
        contents.append(activity);
        prependLogEntry(contents);
    }


    //PurchaseObserver
    private class mStampiiPurchaseObserver extends PurchaseObserver {
        public mStampiiPurchaseObserver(Handler handler) {
            super(StampiiStore.this, handler);
        }

        @Override
        public void onBillingSupported(boolean supported) {
            if (Consts.DEBUG) {
                Log.i(TAG, "supported: " + supported);
            }
            if (supported) {
                restoreDatabase();
                envelope1.setEnabled(true);
                envelope2.setEnabled(true);
                envelope3.setEnabled(true);
            } 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) {
                logProductActivity(itemId, purchaseState.toString());
            } else {
                logProductActivity(itemId, purchaseState + "\n\t" + developerPayload);
            }

            if (purchaseState == PurchaseState.PURCHASED) {
                mOwnedItems.add(itemId);
            }
            mOwnedItemsCursor.requery();
        }

        @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");
                }
                logProductActivity(request.mProductId, "sending purchase request");
            } else if (responseCode == ResponseCode.RESULT_USER_CANCELED) {
                if (Consts.DEBUG) {
                    Log.i(TAG, "user canceled purchase");
                }
                logProductActivity(request.mProductId, "dismissed purchase dialog");
            } else {
                if (Consts.DEBUG) {
                    Log.i(TAG, "purchase failed");
                }
                logProductActivity(request.mProductId, "request purchase returned " + responseCode);
            }
        }

        @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();
            } else {
                if (Consts.DEBUG) {
                    Log.d(TAG, "RestoreTransactions error: " + responseCode);
                }
            }
        }
    }


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

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPurchaseDatabase.close();
        mBillingService.unbind();
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case DIALOG_CANNOT_CONNECT_ID:
            return createDialog("Server cannot Connect",
                    "Server cannot connect");
        case DIALOG_BILLING_NOT_SUPPORTED_ID:
            return createDialog("Billing not supported",
                    "Billing not supported");
        default:
            return null;
        }
    }

    /**
     * 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 Dialog createDialog(String titleId, String 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 = null;
        final int loggedOut = getIntent().getIntExtra("statement", 0);
        if(loggedOut==0){
            builder = new AlertDialog.Builder(getParent());
            builder.setTitle(titleId)
                .setIcon(android.R.drawable.stat_sys_warning)
                .setMessage(messageId)
                .setCancelable(false)
                .setPositiveButton(android.R.string.ok, null)
                .setNegativeButton("Learn More", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(Intent.ACTION_VIEW, helpUri);
                        startActivity(intent);
                    }
                });
        } else if(loggedOut==1){
            builder = new AlertDialog.Builder(Collections.parentActivity);
            builder.setTitle(titleId)
                .setIcon(android.R.drawable.stat_sys_warning)
                .setMessage(messageId)
                .setCancelable(false)
                .setPositiveButton(android.R.string.ok, null)
                .setNegativeButton("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();

    }


    @Override
    public void onRestart(){
        super.onRestart();
        Intent previewMessage = new Intent(StampiiStore.this, StampiiStore.class);
        TabGroupActivity parentActivity = (TabGroupActivity)getParent();
        parentActivity.startChildActivity("StampiiStore", previewMessage);
        this.finish();
    }

}

这里是我如何申报清单文件服务:

And here is how I'm declaring the service in manifest file :

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

任何建议如何连接到市场上?

Any suggestions how to connect to the market?

推荐答案

我有同样的问题,可能是你的错误是我的一样。我使用的是TabHost在我的活动,我发现,则tabspec无法绑定到服务。因此,检查这一点:

I had the same issue and probably your mistake is the same as mine. I was using a TabHost in my activities and I find out that TabSpec cannot bind to services. So check this :

使用getApplicationContext()。bindService而不只是bindService   上的活动解决,因为它是使用更高层的问题   应用程序上下文。

Using getApplicationContext().bindService instead of just bindService on your activity solves the problem as it is using the higher level application context.

这篇关于Android无法绑定服务(在AP​​P-计费)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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