LollipopでMapboxのLocationLayerPluginが動作しない


なぜかLollipopでは自分の現在位置の表示ができませんでした。

試しにこんなコードを書いてみたところ、onConnectedは呼ばれるがやはりonLocationChangedは呼ばれない。

```kotlin
    var locationEngine: LocationEngine? = null

    fun startLocationEngine() {
        locationEngine = LocationEngineProvider(mapView?.context).obtainBestLocationEngineAvailable()
        info { "locationEngineType:${locationEngine?.javaClass?.simpleName}" }
        locationEngine?.setPriority(LocationEnginePriority.LOW_POWER)
        locationEngine?.setFastestInterval(1000)
        locationEngine?.addLocationEngineListener(this)
        locationEngine?.activate()
    }

    override fun onConnected() {
        info { "onConnected" }
    }
   
    override fun onLocationChanged(location: Location?) {
        info { "onLocationChanged:${location.toString()}" }
    }
```

`locationEngineType:AndroidLocationEngine` というLocationEngineが使われているようだ。

使用されるEngineは以下のように2種類あるらしい。

```java:LocationEngineProvider.java
  private Map<LocationEngine.Type, LocationEngineSupplier> obtainDefaultLocationEnginesDictionary() {
    ClasspathChecker classpathChecker = new ClasspathChecker();
    Map<LocationEngine.Type, LocationEngineSupplier> locationSources = new HashMap<>();
    locationSources.put(LocationEngine.Type.GOOGLE_PLAY_SERVICES, new GoogleLocationEngineFactory(classpathChecker));
    locationSources.put(LocationEngine.Type.ANDROID, new AndroidLocationEngineFactory());

    return locationSources;
  }
```

というわけでもう一つの方を試してみようと、タイプ指定でLocationEngineの取得を試みるも、なぜかnullになる。

```kotlin
locationEngine = LocationEngineProvider(mapView?.context).obtainLocationEngineBy(LocationEngine.Type.GOOGLE_PLAY_SERVICES)
```

どうやら、`locationEngineSupplier.hasDependencyOnClasspath` の分岐で除外されているようだ。


```java:LocationEngineProvider.java
  private void initAvailableLocationEngines(Context context) {
    locationEngineDictionary = new HashMap<>();
    Map<LocationEngine.Type, LocationEngineSupplier> locationEnginesDictionary =
      obtainDefaultLocationEnginesDictionary();
    for (Map.Entry<LocationEngine.Type, LocationEngineSupplier> entry : locationEnginesDictionary.entrySet()) {
      LocationEngineSupplier locationEngineSupplier = entry.getValue();
      if (locationEngineSupplier.hasDependencyOnClasspath()) {
        LocationEngine available = locationEngineSupplier.supply(context);
        locationEngineDictionary.put(entry.getKey(), available);
      }
    }
  }
```

実装はこんな感じになっていて、クラスの名前解決ができないと使用されないらしい。

```
class GoogleLocationEngineFactory implements LocationEngineSupplier {

  private static final String GOOGLE_LOCATION_SERVICES = "com.google.android.gms.location.LocationServices";
  private final ClasspathChecker classpathChecker;

  GoogleLocationEngineFactory(ClasspathChecker classpathChecker) {
    this.classpathChecker = classpathChecker;
  }

  @Override
  public LocationEngine supply(Context context) {
    return GoogleLocationEngine.getLocationEngine(context);
  }

  @Override
  public boolean hasDependencyOnClasspath() {
    return classpathChecker.hasDependencyOnClasspath(GOOGLE_LOCATION_SERVICES);
  }
}
```

build.gradleにおなじみのimplementationを追記してビルドすることで、GoogleLocationEngineが使用されるようになり、無事に現在地が表示されるようになりました。

```build.gradle
implementation "com.google.android.gms:play-services-location:16.0.0"
```

ちなみに AndroidLocationEngine で動かない理由は調べてません。