Error in Intent Service in Android



我试图使用IntentService获取一些位置地址,但最终导致应用程序崩溃的错误。请帮帮我。

下面是Stacktrace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.ResultReceiver.send(int, android.os.Bundle)' on a null object reference
        at com.example.ajender.sample2.FetchAddressIntentService.deliverResultToReceiver(FetchAddressIntentService.java:91)
        at com.example.ajender.sample2.FetchAddressIntentService.onHandleIntent(FetchAddressIntentService.java:81)
        at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.os.HandlerThread.run(HandlerThread.java:61)

FetchAddressIntentService:

public class FetchAddressIntentService extends IntentService {
private static String TAG="Fetch-address-Service";
protected ResultReceiver mReceiver;
/**
 * Creates an IntentService.  Invoked by your subclass's constructor.
 *
 * @param name Used to name the worker thread, important only for debugging.
 */
public FetchAddressIntentService(String name) {
    super(name);
}
public FetchAddressIntentService(){
    super("FetchAddressIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
    String errorMessage = "";
    Geocoder geocoder = new Geocoder(this, Locale.getDefault());
    Location location = intent.getParcelableExtra(
            Constants.LOCATION_DATA_EXTRA);
    mReceiver=intent.getParcelableExtra(Constants.RECEIVER);
    Log.e(TAG,"1-----");
    List<Address> addresses = null;
    try {
        addresses = geocoder.getFromLocation(
                location.getLatitude(),
                location.getLongitude(),
                // In this sample, get just a single address.
                1);
    } catch (IOException ioException) {
        // Catch network or other I/O problems.
        errorMessage = "service_not_available";
        Log.e(TAG, errorMessage, ioException);
    } catch (IllegalArgumentException illegalArgumentException) {
        // Catch invalid latitude or longitude values.
        errorMessage = "invalid_lat_long_used";
        Log.e(TAG, errorMessage + ". " +
                "Latitude = " + location.getLatitude() +
                ", Longitude = " +
                location.getLongitude(), illegalArgumentException);
    }
    // Handle case where no address was found.
    if (addresses == null || addresses.size()  == 0) {
        if (errorMessage.isEmpty()) {
            errorMessage = "no_address_found";
            Log.e(TAG, errorMessage);
        }
        deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
    } else {
        Address address = addresses.get(0);
        ArrayList<String> addressFragments = new ArrayList<String>();
        // Fetch the address lines using getAddressLine,
        // join them, and send them to the thread.
        for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
            addressFragments.add(address.getAddressLine(i));
        }
        Log.i(TAG, "address_found");
        deliverResultToReceiver(Constants.SUCCESS_RESULT,
                TextUtils.join(System.getProperty("line.separator"),
                        addressFragments));
    }
}
private void deliverResultToReceiver(int resultCode, String message) {
    Bundle bundle = new Bundle();
    bundle.putString(Constants.RESULT_DATA_KEY, message);
    Log.e(TAG, "2-----");
    mReceiver.send(resultCode, bundle);
    Log.e(TAG, "3-----");
}

此服务应该发送回带有结果接收器和结果代码的bundle,但没有发生....

可以按照以下步骤解决错误

  • 在MainActivity

    • 增加公共AddressResultReceiver mResultReceiver;
    • mResultReceiver = new AddressResultReceiver(null)-这将自动为主活动类分配id。
  • 在FetchAddressIntentService
    • 添加mReceiver = intent.getParcelableExtra(Constants.RECEIVER);
    • 记录mReceiver是否为空
    • 使用当前代码发送数据。这应该行得通。我就是这样绕过它的。如有任何问题请留言。

可能你还没有从你的活动正确地初始化mResultReceiver,你应该传递给FetchAddressIntentService意图:

mResultReceiver = new AddressResultReceiver(new android.os.Handler());
..
Intent intent = new Intent(this, FetchAddressIntentService.class);
intent.putExtra(Constants.RECEIVER, mResultReceiver);
..
startService(intent);

IntentService的情况下发生的事情是,你有三个组件正在发挥作用:MainActivity(将调用意图服务),IntentService(负责处理意图)和最后的ResultReceiver在意图被处理(或操作)后接收结果。

Log可以看出,你没有初始化或赋值给ResultReceiver mReceiver你应该通过声明一个类来初始化mResultReceiver,让我们把它叫做AddressResultReceiver,它扩展了ResultReceiver,并有一个参数化的构造函数,它接受单个参数作为Handler对象,并覆盖onReceiveResult()方法,如下所示:

    AddressResultReceiver(Handler handler) {
        super(handler);
    }
    //Result from intent service
    @Override
    public void onReceiveResult(int resultCode, Bundle bundle) {
       ...
    }

现在你已经成功地获得了三个组件中的两个:MainActivity用于启动意图请求和ResultReceiver用于接收结果。现在让我们通过在项目层次结构中定义一个类并使用IntentService扩展它并覆盖其方法onHandleIntent(Intent intent)():

来制作IntentService
public class FetchAddressIntentService extends IntentService {
     public FetchAddressIntentService() {
        super("FetchAddressIntentService");
     }
     @Override
     protected void onHandleIntent(Intent intent) {...}
}

所以我们现在可以把东西启动并工作了。现在在MainActivity中编写以下代码:

  //Initializing the reference with AddressResultReceiver object
  mResultReceiver = new AddressResultReceiver(new Handler());
  ...
  //Setting the IntentService to FetchAddressIntentService
  Intent intent = new Intent(this, FetchAddressIntentService.class);
  /*passing the receiver object to the service so as to let it know where to 
    publish results*/
  intent.putExtra(Constants.RECEIVER, mResultReceiver);
  ...
  //starting the service
  startService(intent);

现在你的deliverResult(int, String)不再抛出NullPointerException。更多信息请访问IntentService和ResultReceiver。希望能有所帮助!:)

在Geocoder之前将以下代码添加到受保护的void onHandleIntent (@Nullable Intent){}中

    if (intent != null){
        String errorMessage ="";
        resultReceiver = intent.getParcelableExtra(Constants.RECEIVER);
        Location location = intent.getParcelableExtra(Constants.LOCATION_DATA_EXTRA);
        if (location == null) {
            return;
        }