0

私はこの例外があります:

java.lang.RuntimeException: Unable to start service com.problemio.BillingService@41342be8 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)

これは、次の2つの方法を示しています。

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

これはこのメソッドを呼び出し、nullインテントを送信します。

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

私が疑問に思っているのは、なぜインテントがかなり定期的に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);
    }

}

ありがとう!!

4

2 に答える 2

2

あなたが投稿したコードは、私が知る限り問題ないように見えます。BillingServiceクラスにnullチェックがあります。

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

私は少し前にそれをしました、そして正直に言うとそれがなぜそこにあるのか具体的に思い出せません。

于 2012-08-25T13:55:22.793 に答える
0

はるかに優れたソリューションがここに投稿されています: https ://stackoverflow.com/a/12488357/1291879

これにより、に関連するnullポインタの問題と非推奨の問題が修正されonStart()ます。

基本的に、修正は次onStartCommand()の代わりに使用することです。onStart()

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
   handleCommand(intent, startId);
   return START_NOT_STICKY;
}
于 2012-10-23T00:04:42.357 に答える