abusuioc / hms-gms-wrapper-location

Location wrapper on top of HMS and GMS.
MIT License
11 stars 4 forks source link

NullPointerException when removing non-null LocationCallback #4

Closed munnitz closed 4 years ago

munnitz commented 4 years ago

When both Huawei and Google services are not available a NullPointerException is thrown when removing the non-null LocationCallback from the FusedLocationProviderClient. Because both the Huawei and Google LocationCallback that are wrapped within the LocationCallback-Wrapper are null.

2020-10-06 13:50:10.665 14066-14066/xx.xx.xx E/ExceptionHandlerDelegate: uncaught exception
    java.lang.NullPointerException: Listener must not be null
        at com.google.android.gms.common.internal.Preconditions.checkNotNull(com.google.android.gms:play-services-basement@@17.3.0:11)
        at com.google.android.gms.common.api.internal.ListenerHolders.createListenerKey(com.google.android.gms:play-services-base@@17.3.0:17)
        at com.google.android.gms.location.FusedLocationProviderClient.removeLocationUpdates(Unknown Source:6)
        at mobileservices.location.FusedLocationProviderClientGMS.removeLocationUpdates(FusedLocationProviderClientGMS.java:57)
        at xx.xx.xx.fragments.XxxFragment.onDestroy(XxxFragment.java:329)
        at androidx.fragment.app.Fragment.performDestroy(Fragment.java:2927)
        at androidx.fragment.app.FragmentStateManager.destroy(FragmentStateManager.java:492)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1296)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:442)
        at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
abusuioc commented 4 years ago

Hi @munnitz , thx for your contribution.

I'm trying to understand how you were able to land in this scenario. If no GMS or HMS is available, then:

  1. the next method returns true https://github.com/abusuioc/hms-gms-wrapper-location/blob/f4be4f80132d1a99a812967e4a658ac4313b2bd4/lib/src/main/java/mobileservices/location/LocationServices.java#L15-L18
  2. then LocationServices will instantiate a instantiates a FusedLocationProviderClientGMS https://github.com/abusuioc/hms-gms-wrapper-location/blob/f4be4f80132d1a99a812967e4a658ac4313b2bd4/lib/src/main/java/mobileservices/location/LocationServices.java#L24-L27
  3. when registering a location callback, I assume you call the next method (executing this code): https://github.com/abusuioc/hms-gms-wrapper-location/blob/f4be4f80132d1a99a812967e4a658ac4313b2bd4/lib/src/main/java/mobileservices/location/FusedLocationProviderClientGMS.java#L65-L87
  4. a link is created inside the wrapped location callback to the gms location callback: https://github.com/abusuioc/hms-gms-wrapper-location/blob/f4be4f80132d1a99a812967e4a658ac4313b2bd4/lib/src/main/java/mobileservices/location/FusedLocationProviderClientGMS.java#L78
  5. when removing the callback then I assume you will call this method (executing this code): https://github.com/abusuioc/hms-gms-wrapper-location/blob/f4be4f80132d1a99a812967e4a658ac4313b2bd4/lib/src/main/java/mobileservices/location/FusedLocationProviderClientGMS.java#L55-L59

At this point (because of 4) the gms location callback should not be null, right?

Could you detail which calls you do to the location wrapper?

munnitz commented 4 years ago

I think the problem is that the callback's gmsLocationCallback is initialised by the FusedLocationProviderClient's requestLocationUpdates. So when calling removeLocationUpdates without invoking requestLocationUpdates first, a NullPointerException is thrown and there is no way to prevent that since the gmsLocationCallback is private and it's impossible to check where or not it is null.

abusuioc commented 4 years ago

You're absolutely right about this scenario. I will patch it asap.

abusuioc commented 4 years ago

Interesting that only the FusedLocationProvider of GMS checks for nulls; the one from HMS is happy to receive nulls. Please use https://github.com/abusuioc/hms-gms-wrapper-location/releases/tag/1.0-beta-3 to take advantage of the fix.

munnitz commented 4 years ago

Ok it works now. Thank you for the quick fix!