2011-12-02 66 views
1

我試圖在我的應用程序的應用程序結算中實現,但我遇到了一些問題。我使用的是Android開發者網站的例子,每次我開始連接到計費服務的活動時,它會顯示一個對話框,我無法連接到服務器,當我按下了解更多信息時,它會轉到一個解釋我的網頁更新我的Android Market應用程序,但它已經是最新的了。另一件事,在我的應用程序上實現代碼之前,我創建了一個測試應用程序,我可以使用相同的代碼進行連接,但是我沒有遇到問題。但在我的申請中,我無法做到這一點。是否與開發人員api密鑰有任何關聯,您只能在一個應用程序或類似的應用程序中使用它。因爲我使用相同的測試和真實應用程序。Android無法綁定到服務(在應用程序計費)

這裏是我的代碼,如果你能看到的東西是不是真的喜歡它應該是:

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

} 

這裏是我如何申報清單文件服務:

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

任何建議如何連接到市場?

+0

您是否檢查過這個http://developer.android.com/guide/market/billing/billing_integrate.html – Ramakrishna

+0

是的,我運行它正在運行的示例應用程序。我創建了我的測試應用程序,它仍然在運行(使用相同的代碼),但是在我的應用程序活動中實現它之後,我得到了應用程序內帳單檢查對話框。我在同一臺設備上運行測試應用程序和真正的應用程序,測試應用程序正在工作,真正的不是。 –

+0

你上傳你的應用程序在市場上,並簽署你的應用程序,然後通過apk安裝應用程序在你的設備上 – Ramakrishna

回答

6

我有同樣的問題,可能你的錯誤與我的一樣。我在我的活動中使用了TabHost,我發現TabSpec無法綁定到服務。所以檢查:。

使用getApplicationContext()bindService,而不是你的活動只是bindService 解決,因爲它是使用更高級別的 應用程序上下文的問題。

+0

偉大的答案..你拯救了我的日子..謝謝了很多.. – hacker

0

你不能通過該代碼進行調試嗎?可能mBillingService.checkBillingSupported()返回false,由於失敗BillingService.bindToMarketBillingService()而導致。

+0

問題在於代碼在測試應用程序中運行,但不在處於開發過程中的實際應用程序中工作。 –

+0

通過調試,您至少可以發現問題出在哪裏。 – devisnik

+0

如果包裝結構需要這個,還要嘗試在清單中完全限定您的接收器/服務。 – devisnik

0

我對我的索愛面臨這樣的問題,W8,我所做的2.1的Android設備 有以下幾種: 1)getApplicationContext()bindService(如Android的機器人說) 2)重置我的手機和下載APK市場2.3.4版本並安裝它 3)然後打開手機的市場應用,並點擊接受,當應用程序,我辭去 4)rerunned應用它工作正常

注:這樣做之前,我測試我的應用程序在其他設備上使用市場版本3.x,它工作,所以我做了所有這些事情...