Android In-app Purchase NullPointerException

У меня ошибка, и я схожу с ума, потому что случаюсь только в некоторых обстоятельствах, но я действительно не понимаю, когда, может быть, более опытный глаз может мне помочь:

Из учебников Google я взял код для совершения покупки в приложении, вкратце этот код :

  1. Initialize the In-App Service
  2. Retrieve the price объекта
  3. Start the in-purchase если пользователь нажмет кнопку «Купить».

Теперь, во всех тестах, которые я сделал, эта работа прекрасна (больше устройств и API), но у меня есть тонна отчетов, которые говорят: mHelper NullPointerException на mHelper .

Я думаю, что это происходит в 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) 

Вот какой-то задействованный метод класса Google IabHelper (возможно, вам не нужно это читать). Они просто упоминаются в журнале ошибок и написаны Google:

Утилизировать:

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

Вот полный класс IabHelper.

Резюме:

Скажите мне, если вы увидите, где / когда mHelper NullPointerException переменной mHelper . Я не мог из кода и тестирования с виртуальными и физическими устройствами, так как работал нормально.

Я почти уверен, что ошибка вызывается после того, как активность закрыта, но я не понимаю, зачем ее исправлять.

Напишите, если вам нужна дополнительная информация. Спасибо всем!

Вы должны стараться избегать использования getApplicationContext () как можно больше, так как это значительно увеличит вероятность получения Force Closes.

Используйте контекст действия. Если вы создаете объект IabHelper в Activity, тогда Pass ActivityName.this (означает контекст активности).

Если вы находитесь в Fragment, используйте getActivity ().

И в классе IabHelper используйте вот так:

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

Надеюсь, все будет хорошо.

Вы передаете new IabHelper.OnIabSetupFinishedListener() {...} в startSetup (), но mHelper.startSetup () не сохраняет ссылку, а функция onCreate () не сохраняет ее. Похоже, что у вас есть свойство ( mPurchaseListener ), чтобы удерживать прослушиватель, но не использует его – вместо этого вы создаете анонимный класс и передаете его в startSetup () … тогда ваш экземпляр получает сбор мусора, потому что нет Рекомендации.

Intereting Posts
Android Canvas OpenGL Renderer потерял память Закрыть PreferenceFragment Как я могу отправить приложение для Android, которое я разрабатываю для кого-то по электронной почте? Звук локального уведомления cordova не работает в ios и andorid Анализ файла манифеста Android для поиска тега uses-permission с использованием python Чтобы использовать JNI, или не использовать JNI (производительность Android) Как создавать всплывающие уведомления, такие как уведомление, используемое в whatsapp для Android? Предварительный просмотр Android Studio: этот JVM не поддерживает постоянный тег 15 Загружать изображение и аудио в один запрос в android CursorAdapter в Listview Лучший способ отформатировать дату относительно Android на Android Обнаружение лица Android MaxNumDetectedFaces Содержимое не разрешено в прологе в изображениях res Невозможно скомпилировать, Невозможно выполнить dex, не может объединиться, не-jumbo инструкция Получение SMS с помощью MonoDroid