我试图使用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;
}