1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FusedLocationProviderClientがclassからinterfaceになった。ライブラリとのバージョン不一致に気をつけろ

Last updated at Posted at 2022-11-12

com.google.android.gms:play-services-location:21.0.0にて、FusedLocationProviderClient, ActivityRecognitionClient, GeofencingClient, SettingsClientがclassからinterfaceに変わったらしいです。

FusedLocationProviderClient, ActivityRecognitionClient, GeofencingClient and SettingsClient are now interfaces instead of classes, which helps enforce correct usage and improves testability.

20.0.0 までのFusedLocationProviderClientの使い方は以下のような形かと思います。

LocationServices.getFusedLocationProviderClient(this)
    .requestLocationUpdates(
        LocationRequest.create().setInterval(5000L),
        object : LocationCallback() {
            override fun onLocationResult(result: LocationResult) {
                // handle result
            }
        },
        Looper.getMainLooper()
    )

21.0.0 では、LocationRequest.Builderが追加されたことで、LocationRequest.create()がDeprecatedになっており、abstruct classであるLocationCallbackの代わりに、interfaceであるLocationListenerも使えるようになったことで、以下のようによりシンプルにかけるように変わっています。

LocationServices.getFusedLocationProviderClient(context)
    .requestLocationUpdates(
        LocationRequest.Builder(5000L).build(), {
            // handle result
        },
        Looper.getMainLooper()
    )

とはいえ、旧来の記述のままでも、implementationのバージョンを書き換えるだけで特に問題無く動作します。

ただし、これをライブラリで使っている場合に問題が発生するということを経験しました。

java.lang.IncompatibleClassChangeError

java.lang.IncompatibleClassChangeErrorが発生しました。メッセージによるとFusedLocationProviderClientはクラスだと思ってたのにインターフェースだったってことです。

FATAL EXCEPTION: main
Process: net.mm2d.myapplication, PID: 4946
java.lang.IncompatibleClassChangeError: Found interface com.google.android.gms.location.FusedLocationProviderClient, but class was expected (declaration of 'com.google.android.gms.location.FusedLocationProviderClient' appears in /data/app/~~6HpKRmhmmxafqGImwiJmvg==/net.mm2d.myapplication-szASdrDCRTpbZKYoLEPVbw==/base.apk)
	at net.mm2d.mylibrary.Locations.get(Locations.kt:28)
	at net.mm2d.myapplication.MainActivity.onCreate$lambda$1(MainActivity.kt:46)
	at net.mm2d.myapplication.MainActivity.$r8$lambda$YO0xJVQBy7fTOQisoSQWMfyKSqw(Unknown Source:0)
	at net.mm2d.myapplication.MainActivity$$ExternalSyntheticLambda1.onClick(Unknown Source:2)
	at android.view.View.performClick(View.java:7506)
	at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1219)
	at android.view.View.performClickInternal(View.java:7483)
	at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
	at android.view.View$PerformClick.run(View.java:29335)
	at android.os.Handler.handleCallback(Handler.java:942)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7898)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

原因は、ライブラリが20.0.0を使っており、アプリの方で21.0.1を組み込んだからです。ライブラリはFusedLocationProviderClientがclassである環境でコンパイルされているが、アプリの方で21.0.1を指定したので、依存関係からより新しい、21.0.1 が組み込まれます。 21.0.1 ではFusedLocationProviderClientがinterfaceになっているため、違うじゃん、ってエラーになってしまったわけです。

マルチモジュール環境では以下のような状況ですね。

app/build.gradle.kts
dependencies {
    implementation(project(":mylibrary"))
    implementation("com.google.android.gms:play-services-location:21.0.1")
}
mylibrary/build.gradle.kts
dependencies {
    implementation("com.google.android.gms:play-services-location:20.0.0")
}

これはどうしようもないので、アプリの方はライブラリが対応するまで、20.0.0 を利用し、ライブラリの方で対応ができたら、それに併せて 21.0.1 に上げられるようになります。
ライブラリの方からplay-services-locationの依存関係をアプリの方にも伝搬させるようにしておけば、アプリ側でplay-services-locationのバージョン更新を忘れていても自動的に高い方にあわせることができます。

app/build.gradle.kts
dependencies {
    implementation(project(":mylibrary"))
    implementation("com.google.android.gms:play-services-location:20.0.0")
}
mylibrary/build.gradle.kts
dependencies {
    implementation("com.google.android.gms:play-services-location:21.0.1")
}

ということで、play-services-location を内部で使っているライブラリをアプリに組み込むときは、バージョンの不一致に注意しようって話でした。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?