1

My App uses LocationServices to request location updates. It sends the results via a PendingIntent to a Receiver. In onReceive() a LocationResult is extracted from the intent, which yields a Location that is then expressed in terms of Lat and Lng, to be used further. Sounds OK, right?

Well, the App started to crash with NullPointerException.

I investigated using Debugger and found that the three lines of code which I described above executed fine, but then, instead of proceeding to the following lines of code, execution was somehow directed back again to the first of the three lines, which extracts a LocationResult from an intent. This now turned out to be null, and crashed on the following line with NullPointerException, as LocationResult was assumed not to be null.

I have no idea why this is happening. Any pointers, please? (Sorry for the pun)

Here is my code:

public class MyLocationUpdateReceiver extends BroadcastReceiver {

    private static final String TAG = "MyLocationUpdateRcvr";

 // empty constructor
    public MyLocationUpdateReceiver(){}

    @Override
    public void onReceive(Context context, Intent intent) {

        Log.i(TAG,"onReceive update");

        // extract locationResult from intent received from Update Request
        LocationResult locationResult = LocationResult.extractResult(intent);
        double locationLat = locationResult.getLastLocation().getLatitude();
        double locationLng = locationResult.getLastLocation().getLongitude();

        // send the Lat and Lng of new location to MapActivity via intent
        Intent mIntent = new Intent(context.getApplicationContext(), 
        MapActivity.class);
        mIntent.putExtra("New_Lat", locationLat);
        mIntent.putExtra("New_Lng", locationLng);
        mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(mIntent);

    }
}

And here is the screenshot of the first time through.Note the LocationResult is not null.

enter image description here

Still on the first time round...

enter image description here

and on the second time round...

enter image description here

Jo Mo
  • 317
  • 1
  • 3
  • 14

3 Answers3

1

Are there scenarios where you are putting extras into the PendingIntent? After some testing, I've found that this causes the location information to not be stored in the intent when it's passed to the receiver. It seems like they should be able to put the locations alongside the extras in your intent, but it's not implemented that way.

Jeff Schmitz
  • 1,087
  • 1
  • 13
  • 28
  • Yes I am passing extras to my intent. And as a result LocationResult.extractResult(intent); is null. If I don't pass extra then LocationResult.extractResult(intent); is not null. What should i do? – Pravinsingh Waghela Dec 25 '19 at 09:45
0

I am assuming you are using your receiver while registering in manifest. You need to use broadcast receivers with java coding i mean dynamic binding. For details how to bind you may refer below link.

Dynamically registering a broadcast receiver

And secondly you can you can also try instead of passing intent as you passing LocationResult.extractResult(intent); evaluate intent in onReceive() method

Community
  • 1
  • 1
Abdul Waheed
  • 4,540
  • 6
  • 35
  • 58
  • i have registered the receiver in the Manifest and also dynamically in my code. Your second point was not clear to me what you meant. – Jo Mo Feb 20 '17 at 14:16
  • I am trying to say you should try using intent locally.(locally means in the scope of onReceive).In short don't pass intent to other method to extract data use the intent in onReceive method boundary – Abdul Waheed Feb 20 '17 at 14:20
  • how do I extract a LocationResult from the intent if not by using extractResult()? – Jo Mo Feb 20 '17 at 14:31
  • ..also, it works fine the first time round. My question is why it suddenly goes back on itself. – Jo Mo Feb 20 '17 at 14:35
0

If you look into the source of LocationResult.extractResult you'll see that it can return null regardless of the @NonNull annotation:

@NonNull
public static LocationResult extractResult(@NonNull Intent var0) {
   return !hasResult(var0) ? null : (LocationResult)var0.getParcelableExtra("com.google.android.gms.location.EXTRA_LOCATION_RESULT");
}

So you should be fine if you handle the return value as optional.

In my investigation a null value is returned if the user revokes "all-time" location access and returns to the app. The receiver will be invoked but the Intent is missing the com.google.android.gms.location.EXTRA_LOCATION_RESULT extra, hence the null value.

public static boolean hasResult(@NonNull Intent var0) {
   return var0 == null ? false : var0.hasExtra("com.google.android.gms.location.EXTRA_LOCATION_RESULT");
}

What you can find in the extras in this case is com.google.android.gms.location.EXTRA_LOCATION_AVAILABILITY, based on which you can decide how to handle the Intent.

bearlysophisticated
  • 543
  • 1
  • 8
  • 19