@Composable Scaffold で This material API is experimental and is likely to change or to be removed in the future.

Jetpack Compose で Material3 を使うと、


This material API is experimental and is likely to change or to be removed in the future.

で、ビルド通らず。

AndroidStudio が提案してくる対応としては以下。

@Composable Scaffold で This material API is experimental and is likely to change or to be removed in the future.

アノテーションを付けるのもアレですね。

gradle 側から一括無視しておきましょう。


kotlinOptions {
  allWarningsAsErrors = false
  freeCompilerArgs += [
      "-Xopt-in=kotlin.RequiresOptIn",
      "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
      "-Xopt-in=kotlinx.coroutines.FlowPreview",
      "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi",
      "-Xopt-in=kotlin.Experimental"
  ]
}

👉 Opt-in requirement marker annotation on override requires the same marker on base declaration hatena-bookmark

少し将来に向けて修正。


'-Xopt-in' → '-opt-in'

👉 '-Xopt-in' is deprecated and will be removed in a future release, please use -opt-in instead hatena-bookmark

よって、今回のビルドエラーについてのみで言えば、以下で避けるのが良さげです。


freeCompilerArgs += '-opt-in=androidx.compose.material3.ExperimentalMaterial3Api'

この記述をどこに書くか。

対象が複数になるのを考慮して


freeCompilerArgs += [
    '-opt-in=androidx.compose.material3.ExperimentalMaterial3Api',
]

としておきます。

 

build.gradle (app) allprojects/subprojects {} 内


allprojects { // subproject {
  tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {

    kotlinOptions {
      allWarningsAsErrors = false
      freeCompilerArgs += [
          '-opt-in=androidx.compose.material3.ExperimentalMaterial3Api',
      ]
    }

  }
}

 

build.gradle (module) android {} 内


android {

  kotlinOptions {
    jvmTarget = JavaVersion.VERSION_11.toString()

    allWarningsAsErrors = false
    freeCompilerArgs += [
        '-opt-in=androidx.compose.material3.ExperimentalMaterial3Api',
    ]

  }

 

build.gradle (module) の最後


dependencies {
  // ...
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {

  kotlinOptions {
    allWarningsAsErrors = false
    freeCompilerArgs += [
        '-opt-in=androidx.compose.material3.ExperimentalMaterial3Api',
    ]
  }

}

 

まとめ

プロジェクトの構成に合わせて、多少の拡張性を考慮しながら設定する必要があるでしょう。

👉 Opt-in requirements | Kotlin hatena-bookmark
👉 tachiyomi/build.gradle.kts at master · tachiyomiorg/tachiyomi hatena-bookmark


'-Xopt-in' is deprecated and will be removed in a future release, please use -opt-in instead

'-Xopt-in' is deprecated and will be removed in a future release, please use -opt-in instead
👉 Issues with Gradle Kotlin DSL and `-Xopt-in` deprecation : KT-51708 hatena-bookmark


tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
   kotlinOptions {
     allWarningsAsErrors = false
     freeCompilerArgs += [
         "-Xopt-in=kotlin.RequiresOptIn",
         "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
         "-Xopt-in=kotlinx.coroutines.FlowPreview",
         "-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi",
         "-Xopt-in=kotlin.Experimental",
     ]
   }
 }


'-Xopt-in' → '-opt-in'


tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
   kotlinOptions {
     allWarningsAsErrors = false
     freeCompilerArgs += [
         "-opt-in=kotlin.RequiresOptIn",
         "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
         "-opt-in=kotlinx.coroutines.FlowPreview",
         "-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
         "-opt-in=kotlin.Experimental",
     ]
   }
 }

単純に gradle ファイル内、文字列の置換で完。

コード内アノテーションで利用の人はそのままでいいんかな。

👉 Opt-in requirement marker annotation on override requires the same marker on base declaration  hatena-bookmark
👉 AGP Upgrade Assistant で 7.2 移行時にCause: manifestData.`package` must not be null hatena-bookmark
👉 @Composable Scaffold で This material API is experimental and is likely to change or to be removed in the future. hatena-bookmark


AGP Upgrade Assistant で 7.2 移行時にCause: manifestData.`package` must not be null

初回は、自動認識でダイアログから進むことになると思うが、

手動でやるなら以下から。


[Tools]

  ↓

[AGP Upgrade Assistant]

このステップでコケる。

Move package from Android manifest to build files

Declaration of a project's namespace using the package attribute of the Android manifest is deprecated in favour of a namespace declaration in build files.

なんすかねこれ。

 

Gradle sync failed: Cause: manifestData.`package` must not be null

Issue Tracker にありました。

AGP namespace property and app id suffix and Safe Args plugin don't work together

Using the new namespace property in build.gradle instead of the package attribute in AndroidManifest.xml while also using a custom applicationIdSuffix breaks androidx.navigation.safeargs plugin.

👉 Gradle sync failed: Cause: manifestData.`package` must not be null - Issue Tracker
👉 AGP namespace property and app id suffix and Safe Args plugin don't work together [232107688] - Visible to Public - Issue Tracker hatena-bookmark

どうやら、namespace の新記述は、

androidx.navigation.safeargs と同時に使えないようです。

使っているか、コード内を探してみました。


[Edit]

  ↓

[Find]

  ↓

[Find in Files ...]

androidx.navigation.safeargs

...

どうやら、ツールの書き換え内容は以下の様子。

👉 AndroidManifest の package 属性による名前空間宣言が廃止される - BattleProgrammerShibata hatena-bookmark

2行だけなので直接書き換えて namespace 記述は以前の形に戻す。と。

暫定的な対応なので、以下のようにFix版リリース時に注意が必要です。

👉 java.lang.IncompatibleClassChangeError: The method 'java.lang.Class java.lang.Object.getClass()' was expected to be of type interface but instead was found to be of type virtual hatena-bookmark


IncompatibleClassChangeError: The method 'java.lang.Class java.lang.Object.getClass()' was expected to be of type interface but instead was found to be of type virtual

ちとハマったので書く。

API-26 (Oreo/8) でのみ落ちてる。


java.lang.IncompatibleClassChangeError: The method 'java.lang.Class java.lang.Object.getClass()' was expected to be of type interface but instead was found to be of type virtual (declaration of 'com.google.android.gms.dynamic.ObjectWrapper' appears in /data/app/com.benigumo.sample)
  at com.google.android.gms.dynamic.ObjectWrapper.unwrap(com.google.android.gms:play-services-basement@@18.0.2:4)
  at com.google.android.gms.internal.ads.zzbji.zzl(com.google.android.gms:play-services-ads-lite@@20.6.0:20)
  at com.google.android.gms.ads.BaseAdView.loadAd(com.google.android.gms:play-services-ads-lite@@20.6.0:1)
...

Firebase 周りの、API-26 新規当時の不具合。

👉 java.lang.IllegalArgumentException: Service not registered: com.google.android.gms.measurement.internal.zzji@dbed45a · Issue #1662 · firebase/firebase-android-sdk hatena-bookmark

fixedバージョンを半年待つか、

または、以下の半年先までの暫定対応記述追加で回避できた。


dependencies {
  implementation 'com.google.android.gms:play-services-basement:17.5.0'
}

👉 Why does I'm getting "Service not registered" exception, even though I not used any service in Android - Java/Kotlin? - Stack Overflow hatena-bookmark

その暫定的であるべきはずの implementation 記述が残ったまま、

dependencies の更新を繰り返してきました。


//implementation 'com.google.android.gms:play-services-basement:18.0.2'

今回のエラーの時点で

firebase-ads と折り合いがつかず、

コメントアウト→削除となりました。

ありがとうございました。

👉 R8 で 難読化 された スタックトレース を元に戻す hatena-bookmark


利用している Google Mobile Ads SDK (play-services-ads) のバージョンを確認する

👉 Google Play と Android の変更点に対応するためのアプリの準備 - Google AdMob ヘルプ hatena-bookmark


implementation com.google.android.gms:play-services-ads:x.y.z

20.4.0 (バージョン)
→ 広告IDの使用を継続するために自動的に権限が宣言されます。

20.5.0
→ オプトアウト済みユーザーのデータ収集と不正防止に対応するため、新しいアプリアセットIDに対応します。

20.6.0
→ tagForChildDirected(TFCD)または tagForUnderAgeOfConsent(TFUA)を通して子供向け取り扱いタグが付与された広告リクエストにおいては、広告IDが送信されないようにすることができます。

👉 Googleモバイル広告SDK  |  Android  |  Google Developers hatena-bookmark

現在、アプリで利用中のバージョンを build.gradle で確認してみたら、


com.google.android.gms:play-services-ads

がありません!

 

依存性を確認していく


./gradlew -q :app:androidDependencies  

...
release
releaseCompileClasspath - Dependencies for compilation
...
+--- com.google.android.play:core:1.10.3@aar
+--- com.google.android.gms:play-services-analytics:18.0.1@aar
+--- com.google.android.gms:play-services-oss-licenses:17.0.0@aar
+--- com.google.android.gms:play-services-tagmanager-v4-impl:18.0.1@aar
+--- com.google.android.gms:play-services-analytics-impl:18.0.1@aar
+--- com.google.firebase:firebase-messaging-ktx:23.0.4@aar
+--- com.google.firebase:firebase-messaging:23.0.4@aar
+--- com.firebaseui:firebase-ui-auth:8.0.1@aar
+--- com.google.android.gms:play-services-auth:19.0.0@aar
+--- com.google.firebase:firebase-ads:20.6.0@aar
+--- com.google.android.gms:play-services-ads:20.6.0@aar 👈
+--- com.google.android.gms:play-services-appset:16.0.0@aar
+--- com.google.firebase:firebase-auth-ktx:21.0.3@aar
+--- com.google.firebase:firebase-auth:21.0.3@aar
+--- com.google.android.gms:play-services-auth-api-phone:17.4.0@aar
+--- com.google.android.gms:play-services-safetynet:17.0.0@aar
+--- com.google.android.gms:play-services-auth-base:17.0.0@aar
+--- com.google.android.gms:play-services-base:18.0.1@aar
...

play-services-ads は、20.6.0 が、なぜか、見えますが。

さらに詳細を確認していきます。


./gradlew -q :app:dependencies --configuration releaseCompileClasspath

...
|         |         +--- com.google.android.gms:play-services-basement:17.0.0 -> 18.0.2 (*)
|         |         \--- com.google.firebase:firebase-annotations:16.0.0
|         \--- com.google.android.gms:play-services-measurement-sdk:21.0.0
|              +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|              +--- com.google.android.gms:play-services-basement:18.0.0 -> 18.0.2 (*)
|              +--- com.google.android.gms:play-services-measurement-base:21.0.0 (*)
|              \--- com.google.android.gms:play-services-measurement-impl:21.0.0 (*)
+--- com.google.firebase:firebase-ads:20.6.0 👈
|    +--- com.google.android.gms:play-services-ads:20.6.0 👈
|    |    +--- androidx.browser:browser:1.0.0 -> 1.3.0
|    |    |    +--- androidx.core:core:1.1.0 -> 1.7.0 (*)
|    |    |    +--- androidx.annotation:annotation:1.1.0 -> 1.3.0
|    |    |    \--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava
|    |    +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|    |    +--- androidx.core:core:1.0.0 -> 1.7.0 (*)
|    |    +--- com.google.android.gms:play-services-ads-base:20.6.0
...
(c) - dependency constraint
(*) - dependencies omitted (listed previously)
(n) - Not resolved (configuration is not meant to be resolved)

dependencies の記述の親子依存の調べ方

firebase-ads に依存されていますね。

もう一度、build.gradle を見てみます。


dependencies {
  ...
  implementation 'com.google.firebase:firebase-core:21.0.0'
  implementation 'com.google.firebase:firebase-ads:20.6.0' 👈
  implementation 'com.google.firebase:firebase-analytics-ktx:21.0.0'
  ...

つまりは、

play-services-ads の implementation 記述がなくても

firebase-ads から依存を追って解決されていってたのですね!!