AndroidManifest.xml に Admob application ID の記述が必須になったとさ

こんなエラーメッセージ。


E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ru.balumates.balu, PID: 4409
    java.lang.RuntimeException: Unable to get provider com.google.android.gms.ads.MobileAdsInitProvider: java.lang.IllegalStateException:

    ******************************************************************************
    * The Google Mobile Ads SDK was initialized incorrectly. AdMob publishers    *
    * should follow the instructions here: https://goo.gl/fQ2neu to add a valid  *
    * App ID inside the AndroidManifest. Google Ad Manager publishers should     *
    * follow instructions here: https://goo.gl/h17b6x.                           *
    ******************************************************************************


        at android.app.ActivityThread.installProvider(ActivityThread.java:6242)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:5805)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5722)
        at android.app.ActivityThread.-wrap1(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.IllegalStateException:

    ******************************************************************************
    * The Google Mobile Ads SDK was initialized incorrectly. AdMob publishers    *
    * should follow the instructions here: https://goo.gl/fQ2neu to add a valid  *
    * App ID inside the AndroidManifest. Google Ad Manager publishers should     *
    * follow instructions here: https://goo.gl/h17b6x.                           *
    ******************************************************************************


        at com.google.android.gms.internal.ads.zzmn.attachInfo(Unknown Source:17)
        at com.google.android.gms.ads.MobileAdsInitProvider.attachInfo(Unknown Source:3)
        at android.app.ActivityThread.installProvider(ActivityThread.java:6239)
        	... 10 more
Disconnected from the target VM, address: 'localhost:8600', transport: 'socket'

Google Mobile Ads SDK v17.0.0 以降で必須だと。

Google Ads Developer Blog: Announcing v17.0.0 of the Android Google Mobile Ads SDK

このことは、


implementation "com.google.firebase:firebase-ads:17.0.0"

も同じ。

以下、AndroidManifest.xml の必須記述。


<manifest>
  <application>
    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-################~##########"/>

  </application>
</manifest>

Ad Manager や NativeAppInstallAd / NativeContentAd も注意が必要な模様。


11月1日に迫った「targetSdkVersion は 26以上」に向けての対応の目処

メール来てますよね。

Hello Google Play Developer,

This is a reminder that starting November 1, 2018, updates to apps and games on Google Play will be required to target Android Oreo (API level 26) or higher. After this date, the Play Console will prevent you from submitting new APKs with a targetSdkVersion less than 26.

Configuring your app to target a recent API level ensures that users benefit from significant security and performance improvements, while still allowing your app to run on older Android versions (down to the minSdkVersion).

Action required

Please ensure that your apps are configured to target at least Android 8.0 (API level 26) by November 1, 2018. For technical advice on how to change your app's target API level to meet these requirements, refer to the migration guide.

Affected apps

The apps included below have one or more APKs—in production or testing tracks—that aren't currently targeting API level 26 or higher. Apps are listed with the maximum version code and corresponding targetSdkVersion. If you have more than 20 apps that could be affected in your account, please check the Play Console for a full list.

動くとはいうものの、GoogleサービスAPIの仕様や各サービス/プラットフォームのポリシーの変更が頻繁なことを考えると、放置しているアプリは一掃されていくと思われます。

メールには、以下が「マイグレーションガイド」として案内されています。

Meet Google Play's target API level requirement  |  Android Developers

おおまかに、影響しそうなキーワードを拾っておきます。

API 23 (6.0) 未満

「Runtime Permission」
実行時のパーミッション リクエスト  |  Android Developers

API 24 (7.0) 未満

「Doze」
Doze と App Standby 用に最適化する  |  Android Developers

「Firebase Cloud Messaging (FCM)」
Firebase Cloud Messaging  |  Firebase

「file://」
Setting up file sharing  |  Android Developers

API 26 (8.0) 未満

「startService()」
「startForeground()」
「startForegroundService()」
「Firebase Cloud Messaging (FCM)」
「Google Play services SDK」
「JobScheduler」

バックグラウンド実行制限  |  Android Developers

「Notification」
Create and Manage Notification Channels  |  Android Developers

「ANDROID_ID」
Settings.Secure  |  Android Developers

「multiple window/display」
マルチ ウィンドウのサポート  |  Android Developers
Android 8.0 の機能と API  |  Android Developers

「Camera API」
android.hardware.camera2  |  Android Developers

まとめ

Gradle周りやライブラリ同士の依存関係などもあって簡単には終われないですよね。

保守的に古いSDKにスティックしていた開発陣はモヤモヤ一掃のチャンスと思うべし。

あと、オプトインしといたほうがいいよ、と以下リンクがありました。

http://g.co/play/monthlynews


Admob firebase-ads:15.0.1 でメモリーリークする

なんか以前からよくリークしてましたよね、Admob。

今回は, 以下バージョン。


implementation "com.google.firebase:firebase-core:15.0.2"
implementation "com.google.firebase:firebase-ads:15.0.1"

Activity#finish()後、

百発百中でLeakCanaryが鳴く。

情報はないか、と探すが古いものばかり。

最新の公式サンプルを見る。

BannerExamples

advanced-APIDemo

BannerRecyclerViewExample

AndroidManifest.xmlの「INTERNET」関連の2行はもう不要だったり。

サンプル通りライフサイクル周り記述しても消えやしない。

百発百中でアウトでござる。


// Called when leaving the activity
public override fun onPause() {
    ad_view.pause()
    super.onPause()
}

// Called when returning to the activity
public override fun onResume() {
    super.onResume()
    ad_view.resume()
}

// Called before the activity is destroyed
public override fun onDestroy() {
    ad_view.destroy()
    super.onDestroy()
}

公式サンプルの中に以下を見つけた。


if (adView.getParent() != null) {
  ((ViewGroup) adView.getParent()).removeView(adView);
}

RecyclerViewAdapter.java#L146-L148

ぶら下がったままだった模様。

以下で完。


inline fun AdView.remove() {
  if (parent != null) {
    (parent as ViewGroup).removeView(this)
  }
}

最初のライフサイクル周りは、

公式マニュアル通り不要だったりしたが。