2017-01-24 62 views
5

我得到了一個錯誤,我要瘋了,因爲只有在某些情況下發生,但我真的不明白的時候,也許更專家的眼睛可以幫助我:的Android應用內購買的NullPointerException

從谷歌教程我把代碼做一個應用程序內購買,簡單的代碼做

  1. Initialize the In-App Service
  2. 對象Retrieve the price
  3. Start the in-purchase如果用戶點擊按鈕「購買」。現在

,在我做這項工作很好(更多的器件和API)所有的測試我得到噸的報告,說:扔在mHelper一個NullPointerException

我認爲這發生在OnDestroy()服務處置時,但我不知道,我無法修復它(完成錯誤日誌結束)。

這裏是我的清洗和評論儘可能代碼:

IabHelper mHelper; 
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener; 
Activity c; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_show_room); 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
    c=this; 

    //Initialize the In-App Service 
    mHelper = new IabHelper(this, "my_key"); 
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { 
      public void onIabSetupFinished(IabResult result) { 
       if (!result.isSuccess()) { 
         //Problem setting up In-app Billing 
        return; 
       } 
       if (mHelper == null) return; 

       //Ask for the price 
       List additionalSkuList = new ArrayList(); 
       additionalSkuList.add("SKU_ID"); 
       try { 
        mHelper.queryInventoryAsync(true, additionalSkuList, mQueryFinishedListener); 
       }catch (Exception e){ 
        //Fail while asking the price 
       } 
      } 
     }); 

    //Buy Button Listener 
    b_buy.setOnClickListener(new View.OnClickListener() 
    { 
     public void onClick(View V) 
     { 
      try { 
      String payload= "my_payload" 
      mHelper.launchPurchaseFlow(c, "SKU_ID",1111,mPurchaseFinishedListener, payload); 
      } catch (Exception e) { 
       //Error launching purchase flow. Another async operation in progress 
      } 
     } 
    }); 

    // Callback for when a purchase is finished 
    mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { 
     public void onIabPurchaseFinished(IabResult result, Purchase purchase) { 
      // if we were disposed of in the meantime, quit. 
      if (mHelper == null) return; 

      if (result.isFailure()) { 
       //Error while buying 
       return; 
      } 

      if (purchase.getSku().equals("SKU_ID")) { 
       // bought the premium upgrade! 
      } 
      } 
     }; 
} 

//For retrieve the price: 
IabHelper.QueryInventoryFinishedListener mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() { 
    public void onQueryInventoryFinished(IabResult result, Inventory inventory) { 
     if (result.isFailure()) { 
      return; 
     } 
     String z = inventory.getSkuDetails("SKU_ID").getPrice(); 
     //The price of the object is + z !!! 
    } 

}; 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (mHelper == null) return; 

    // Pass on the activity result to the helper for handling 
    if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { 
     super.onActivityResult(requestCode, resultCode, data); 
    } 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
     if (mHelper != null) mHelper.dispose(); 
     mHelper = null; 
} 

@Override 
public void onBackPressed() { 
    super.onBackPressed(); 
    finish(); 
} 
} 

這是錯誤:

Exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference 
com.myproj.util.IabHelper.startSetup (IabHelper.java) 
__null__.dispose (IabHelper.java) 
__null__.launchPurchaseFlow (IabHelper.java) 
__null__.handleActivityResult (IabHelper.java) 
__null__.queryInventory (IabHelper.java) 
__null__.queryInventoryAsync (IabHelper.java) 
__null__.getResponseDesc (IabHelper.java) 
__null__.checkSetupDone (IabHelper.java) 
__null__.getResponseCodeFromBundle (IabHelper.java) 
__null__.getResponseCodeFromIntent (IabHelper.java) 
__null__.queryPurchases (IabHelper.java) 
__null__.querySkuDetails (IabHelper.java) 
com.myproj.util.IabHelper.startSetup (IabHelper.java) 
__null__.dispose (IabHelper.java) 
__null__.launchPurchaseFlow (IabHelper.java) 
__null__.handleActivityResult (IabHelper.java) 
__null__.queryInventory (IabHelper.java) 
__null__.queryInventoryAsync (IabHelper.java) 
__null__.getResponseDesc (IabHelper.java) 
__null__.checkSetupDone (IabHelper.java) 
__null__.getResponseCodeFromBundle (IabHelper.java) 
__null__.getResponseCodeFromIntent (IabHelper.java) 
__null__.queryPurchases (IabHelper.java) 
__null__.querySkuDetails (IabHelper.java) 
com.myproj.util.IabHelper.startSetup (IabHelper.java) 
__null__.dispose (IabHelper.java) 
__null__.launchPurchaseFlow (IabHelper.java) 
__null__.handleActivityResult (IabHelper.java) 
__null__.queryInventory (IabHelper.java) 
__null__.queryInventoryAsync (IabHelper.java) 
__null__.getResponseDesc (IabHelper.java) 
__null__.checkSetupDone (IabHelper.java) 
__null__.getResponseCodeFromBundle (IabHelper.java) 
__null__.getResponseCodeFromIntent (IabHelper.java) 
__null__.queryPurchases (IabHelper.java) 
__null__.querySkuDetails (IabHelper.java) 
com.myproj.util.IabHelper$2.run (IabHelper.java) 
java.lang.Thread.run (Thread.java:818) 

這裏的一些參與方法谷歌IabHelper類(可能你不需要閱讀)它們在錯誤日誌剛纔提到的和谷歌都寫:

配置:

public void dispose() { 
    logDebug("Disposing."); 
    mSetupDone = false; 
    if (mServiceConn != null) { 
     logDebug("Unbinding from service."); 
     if (mContext != null) mContext.unbindService(mServiceConn); 
    } 
    mDisposed = true; 
    mContext = null; 
    mServiceConn = null; 
    mService = null; 
    mPurchaseListener = null; 
} 

StartSetup:

public void startSetup(final OnIabSetupFinishedListener listener) { 
    // If already set up, can't do it again. 
    checkNotDisposed(); 
    if (mSetupDone) throw new IllegalStateException("IAB helper is already set up."); 

    // Connection to IAB service 
    logDebug("Starting in-app billing setup."); 
    mServiceConn = new ServiceConnection() { 
     @Override 
     public void onServiceDisconnected(ComponentName name) { 
      logDebug("Billing service disconnected."); 
      mService = null; 
     } 

     @Override 
     public void onServiceConnected(ComponentName name, IBinder service) { 
      if (mDisposed) return; 
      logDebug("Billing service connected."); 
      mService = IInAppBillingService.Stub.asInterface(service); 
      String packageName = mContext.getPackageName(); 
      try { 
       logDebug("Checking for in-app billing 3 support."); 

       // check for in-app billing v3 support 
       int response = mService.isBillingSupported(3, packageName, ITEM_TYPE_INAPP); 
       if (response != BILLING_RESPONSE_RESULT_OK) { 
        if (listener != null) listener.onIabSetupFinished(new IabResult(response, 
          "Error checking for billing v3 support.")); 

        // if in-app purchases aren't supported, neither are subscriptions. 
        mSubscriptionsSupported = false; 
        return; 
       } 
       logDebug("In-app billing version 3 supported for " + packageName); 

       // check for v3 subscriptions support 
       response = mService.isBillingSupported(3, packageName, ITEM_TYPE_SUBS); 
       if (response == BILLING_RESPONSE_RESULT_OK) { 
        logDebug("Subscriptions AVAILABLE."); 
        mSubscriptionsSupported = true; 
       } 
       else { 
        logDebug("Subscriptions NOT AVAILABLE. Response: " + response); 
       } 

       mSetupDone = true; 
      } 
      catch (RemoteException e) { 
       if (listener != null) { 
        listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, 
               "RemoteException while setting up in-app billing.")); 
       } 
       e.printStackTrace(); 
       return; 
      } 

      if (listener != null) { 
       listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Setup successful.")); 
      } 
     } 
    }; 

    Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND"); 
    serviceIntent.setPackage("com.android.vending"); 
    if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) { 
     // service available to handle that Intent 
     mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); 
    } 
    else { 
     // no service available to handle that Intent 
     if (listener != null) { 
      listener.onIabSetupFinished(
        new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE, 
        "Billing service unavailable on device.")); 
     } 
    } 
} 

和IabHelper的構造:

public IabHelper(Context ctx, String base64PublicKey) { 
     mContext = ctx.getApplicationContext(); 
     mSignatureBase64 = base64PublicKey; 
     logDebug("IAB helper created."); 
    } 

Here是完整的IabHelper類。

回顧:

告訴我,如果你能看到其中/當變量mHelperNullPointerException被拋出。因爲工作正常,我無法從代碼和虛擬和物理設備進行測試。

我很確定在關閉Activity之後拋出錯誤,但我不明白爲什麼要修復它。

如果您需要更多信息,請填寫。謝謝大家!

+1

你可以用完整的堆棧跟蹤更新你的問題 –

+0

當然,問題更新 – GMX

+0

你能調試看到mContext返回爲null嗎? –

回答

2

您應該儘量避免使用getApplicationContext(),因爲這會極大地增加獲得強制關閉的機率。

使用活動上下文。如果您是在Activity中創建IabHelper的對象,則傳遞ActivityName.this(意味着Activity上下文)。

如果您在分片中使用getActivity()。

而且在IabHelper類使用這樣的:

public IabHelper(Context ctx, String base64PublicKey) { 
    mContext = ctx; 
    mSignatureBase64 = base64PublicKey; 
    logDebug("IAB helper created."); 
} 

我希望它工作正常。

+0

我會盡快測試 – GMX

0

您將new IabHelper.OnIabSetupFinishedListener() {...}傳入startSetup(),但mHelper.startSetup()不保留引用,並且onCreate()也不保留一個。看起來像你有一個屬性(mPurchaseListener)來容納一個監聽器,但沒有使用它 - 而是你創建一個匿名類並將其傳遞給startSetup()...然後你的實例被垃圾收集,因爲沒有引用。