2012-08-25 33 views
0

時異常與BillingService有我有這樣的例外:Android的賬單 - 購買一個應用程式內項目

java.lang.RuntimeException: Unable to start service [email protected] with null: java.lang.NullPointerException 
     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2376) 
     at android.app.ActivityThread.access$1900(ActivityThread.java:123) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 
     at android.os.Handler.dispatchMessage(Handler.java:99) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:4424) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:511) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
     at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.NullPointerException 
     at com.problemio.BillingService.handleCommand(BillingService.java:452) 
     at com.problemio.BillingService.onStart(BillingService.java:442) 
     at android.app.Service.onStartCommand(Service.java:438) 
     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2359) 
     ... 10 more 
java.lang.NullPointerException 
     at com.problemio.BillingService.handleCommand(BillingService.java:452) 
     at com.problemio.BillingService.onStart(BillingService.java:442) 
     at android.app.Service.onStartCommand(Service.java:438) 
     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2359) 
     at android.app.ActivityThread.access$1900(ActivityThread.java:123) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 
     at android.os.Handler.dispatchMessage(Handler.java:99) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:4424) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:511) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
     at dalvik.system.NativeStart.main(Native Method) 

它指出,這兩種方法:

@Override 
public void onStart(Intent intent, int startId) { 
    handleCommand(intent, startId); //TODO intent is null. 
} 

調用該方法,併發送一個空的意圖:

public void handleCommand(Intent intent, int startId) { 
    String action = intent.getAction(); //Exception happens right here when intent is null. 
    ... 

我想知道的是,爲什麼這個意圖是定期發送爲空。這一定是我在代碼中做得不對的事情,問題的根源可能在其他地方。

這是整個BillingReciever代碼:

package com.problemio; 

import utils.Consts; 
import utils.Consts.ResponseCode; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.util.Log; 

public class BillingReceiver extends BroadcastReceiver 
{ 
    private static final String TAG = "BillingReceiver"; 

    /** 
    * This is the entry point for all asynchronous messages sent from Android Market to 
    * the application. This method forwards the messages on to the 
    * {@link BillingService}, which handles the communication back to Android Market. 
    * The {@link BillingService} also reports state changes back to the application through 
    * the {@link ResponseHandler}. 
    */ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     String action = intent.getAction(); 
     if (Consts.ACTION_PURCHASE_STATE_CHANGED.equals(action)) { 
      String signedData = intent.getStringExtra(Consts.INAPP_SIGNED_DATA); 
      String signature = intent.getStringExtra(Consts.INAPP_SIGNATURE); 
      purchaseStateChanged(context, signedData, signature); 
     } else if (Consts.ACTION_NOTIFY.equals(action)) { 
      String notifyId = intent.getStringExtra(Consts.NOTIFICATION_ID); 
      if (Consts.DEBUG) { 
       Log.i(TAG, "notifyId: " + notifyId); 
      } 
      notify(context, notifyId); 
     } else if (Consts.ACTION_RESPONSE_CODE.equals(action)) { 
      long requestId = intent.getLongExtra(Consts.INAPP_REQUEST_ID, -1); 
      int responseCodeIndex = intent.getIntExtra(Consts.INAPP_RESPONSE_CODE, 
        ResponseCode.RESULT_ERROR.ordinal()); 
      checkResponseCode(context, requestId, responseCodeIndex); 
     } else { 
      Log.w(TAG, "unexpected action: " + action); 
     } 
    } 

    /** 
    * This is called when Android Market sends information about a purchase state 
    * change. The signedData parameter is a plaintext JSON string that is 
    * signed by the server with the developer's private key. The signature 
    * for the signed data is passed in the signature parameter. 
    * @param context the context 
    * @param signedData the (unencrypted) JSON string 
    * @param signature the signature for the signedData 
    */ 
    private void purchaseStateChanged(Context context, String signedData, String signature) { 
     Intent intent = new Intent(Consts.ACTION_PURCHASE_STATE_CHANGED); 
     intent.setClass(context, BillingService.class); 
     intent.putExtra(Consts.INAPP_SIGNED_DATA, signedData); 
     intent.putExtra(Consts.INAPP_SIGNATURE, signature); 
     context.startService(intent); 
    } 

    /** 
    * This is called when Android Market sends a "notify" message indicating that transaction 
    * information is available. The request includes a nonce (random number used once) that 
    * we generate and Android Market signs and sends back to us with the purchase state and 
    * other transaction details. This BroadcastReceiver cannot bind to the 
    * MarketBillingService directly so it starts the {@link BillingService}, which does the 
    * actual work of sending the message. 
    * 
    * @param context the context 
    * @param notifyId the notification ID 
    */ 
    private void notify(Context context, String notifyId) 
    { 
     Intent intent = new Intent(Consts.ACTION_GET_PURCHASE_INFORMATION); 
     intent.setClass(context, BillingService.class); 
     intent.putExtra(Consts.NOTIFICATION_ID, notifyId); 
     context.startService(intent); 
    } 

    /** 
    * This is called when Android Market sends a server response code. The BillingService can 
    * then report the status of the response if desired. 
    * 
    * @param context the context 
    * @param requestId the request ID that corresponds to a previous request 
    * @param responseCodeIndex the ResponseCode ordinal value for the request 
    */ 
    private void checkResponseCode(Context context, long requestId, int responseCodeIndex) { 
     Intent intent = new Intent(Consts.ACTION_RESPONSE_CODE); 
     intent.setClass(context, BillingService.class); 
     intent.putExtra(Consts.INAPP_REQUEST_ID, requestId); 
     intent.putExtra(Consts.INAPP_RESPONSE_CODE, responseCodeIndex); 
     context.startService(intent); 
    } 

} 

謝謝!

+0

你能告訴我們你的BillingReceiver代碼?這是BillingService應該開始的地方(通常有意向,我不認爲有另一種方式去做...) –

+0

@Orabîg是的,只是發佈了整個BillingReciever類 – Genadinik

回答

2

你發佈的代碼看起來好像據我​​所知。我在BillingService類中有一個空檢查:

public void handleCommand(Intent intent, int startId) 
{ 
    if (intent != null) 
    { 
     String action = intent.getAction(); 
      ..... 
    } 
} 

我以前做過,說實話不記得具體爲什麼在那裏。

+0

是啊我正在考慮添加一個空檢查以及我會這樣做,但我只是想知道爲什麼會發生這種情況,爲什麼有時它是空的。在我的情況下,null是常見的。 – Genadinik

0

一個更好的解決方案張貼在這裏: https://stackoverflow.com/a/12488357/1291879

來解決這些空指針的問題,涉及到onStart()棄用的問題。

基本上,解決辦法是使用onStartCommand(),而不是onStart()如下:

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    handleCommand(intent, startId); 
    return START_NOT_STICKY; 
}