Target SDK Version 26に上げる時につまづいたこと

Ac6f0faaab626a101cab97cab29f086f?s=47 katsuki-nakatani
September 19, 2017

Target SDK Version 26に上げる時につまづいたこと

Android Oreo Migration (Notification Channel,Background Limits) from GDG Kobe

Ac6f0faaab626a101cab97cab29f086f?s=128

katsuki-nakatani

September 19, 2017
Tweet

Transcript

  1. Target SDK Version 26に上げた時に躓いたこと 2017/9/18 Android Oreo with Kotlin&Android Studio

    3.0勉強会
  2. Speaker 中谷 克紀 仕事  Enterprise Server Engineer GDG 神戸スタッフ

  3. Theme 本日の勉強会のテーマは3つあります Android Oreo(8.0) Kotlin Android Studio

  4. OSバージョンのおさらい API Level Android バージョン 備考 4 1.6 Xperiaが登場 5 2.0

    6 2.0.1 7 2.1 8 2.2 JITコンパイラで高速化 9 2.3.0 ~ 2.3.2 10 2.3.3 ~ 2.3.7 14 4.0.1 ~ 4.0.2 HoloテーマやFragmentの追加。(Honeycombで追加されていた?知らない子ですねぇ) 15 4.0.3 ~ 4.0.4 16 4.1.0 ~ 4.1.2 Google NowやGCM(旧C2DM)が登場 17 4.2.0 ~ 4.2.2
  5. OSバージョンのおさらい API Level Android バージョン 備考 18 4.3.0 ~ 4.3.1 19

    4.4.0 ~ 4.4.4 Daydream? VRですか? 20 4.4w 初のAndroid Wear用バージョン 21 5.0.0 ~ 5.0.2 Material Designの登場 22 5.1 5.0のマイナーバージョンアップ 23 6.0.0 ~ 6.0.1 Runtime Permissionの登場 24 7.0.0 マルチタスク 25 7.1.0 ~ 7.1.2 7.0のマイナーバージョンアップ
  6. API Level 26 Android Oreoの登場

  7. Android Oreoでの新しい機能 ・Picture in Picture(P in P) ・Notification Channel ・Autofill

    Framework ・Background Limits ・Autosize Textview ・Download Fonts https://developers-jp.googleblog.com/2017/09/introducing-android-8-oreo.html ・Adaptive Icon more... https://developers-jp.googleblog.com/2017/09/introducing-android-8-oreo.html
  8. API Level上げてみました アプリの機能 ・ACやUSBプラグなどを接続・切断したのをトリガーに  通知バーに通知を行いLEDを充電量に合わせて光らせる

  9. API Level上げてみました compileSdkVersion 26 defaultConfig { applicationId "com.miruker.nexusbatteryled" minSdkVersion 23

    targetSdkVersion 26 versionCode 15 versionName "1.9.3" signingConfig signingConfigs.debugKey }
  10. 結果 通知が表示されなくなってしまった 端末起動時にアプリがクラッシュするようになった

  11. Notificationの仕組みが変わりました

  12. バッジがつくようになりました

  13. 通知の実装を変えないと、通知が 表示されなくなります

  14. 何が変わったの? Android 8.0より前  通知については、Notification単位で通知の重要度、LED、Vibe等を設定していた Android 8.0  通知チャンネルという概念が追加。通知チャンネルで通知の重要度、LED、Vibe等を設定する  Notificationを通知チャンネルへ発行することで、通知チャンネルの設定に従い端末に通知される

  15. Notification before Android 7.x var builder = NotificationCompat.Builder(this).apply{ setSmallIcon(R.drawable.notification_icon) setContentTitle("My

    notification") setLights(Color.BLUE,100,300) setContentText("Hello World!") } NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(mId, builder.build()); Notificationを作成 マネージャに渡して通知
  16. Notification after Android 8.0 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ var manager =

    getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager var channel = NotificationChannel("channel_1",getString(R.string.channel_1), NotificationManager.IMPORTANCE_HIGH) .apply { lightColor = Color.RED lockscreenVisibility = Notification.VISIBILITY_PUBLIC enableLights(true) } manager.createNotificationChannel(channel) Notification Channelを作成 var manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager var notification = NotificationCompat.Builder(this,"channel_1").apply { setSmallIcon(R.drawable.ic_stat_name) setContentText("チャンネル1通知です ") }.build() manager.notify(1,notification) Channelに通知を投稿
  17. 後方互換性 var manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager var notification =

    NotificationCompat.Builder(this,"channel_2").apply{ setSmallIcon(R.drawable.ic_stat_name) setLights(Color.BLUE,1000,10) setContentText("チャンネル2通知です") }.build() manager.notify(2,notification) NotificationCompatを利用して、通知を発行します 赤文字の箇所で、Oreo以降の投稿するチャンネルIDを記述します 青文字の箇所は、従来通りNougat以前の通知をサポートするために記述します 元からCompatを利用している場合は、Builderを生成する第二引数にChannelIDを追加するだけでOKです ※Oreoで通知を発行した場合、NotificationでLEDを指定してもChannel側で指定したLEDカラーが優先されます
  18. Channel設定はユーザーが変更できる

  19. どういうメリットが有るの? 開発者  通知の選択を行わせる設定画面を作らなくて良くなった 利用者  必要な通知だけを自分好みにカスタマイズできるように 通知がうざいので、アプリごと通知を削除される可能性が低減される

  20. ユーザのチャンネル設定を知りたい var manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager var channel =

    manager.getNotificationChannel("channel_1") NotificationManagerから取得することが出来ます 通知チャンネルの削除も、 NotificationManagerから行います
  21. Compatを使えないケースの場合は NotificationCompatに無いメソッドを利用している場合はバージョン分岐で書きましょう setSmallIcon(Icon icon)はBackportされていない。。。

  22. 次の対応 通知が表示されるようになりました 端末起動時にアプリがクラッシュするようになった

  23. Background Serviceの実行に 制限が入りました

  24. Background Limits https://developer.android.com/about/versions/oreo/background.html

  25. Backgroundの制限は大きく分けて2つ https://developer.android.com/about/versions/oreo/background.html Background Execution Limits  バックグラウンドの実行を制限するもの Background Location Limits  バックグラウンドので位置情報の取得を制限するもの

  26. Broadcastの制限 https://developer.android.com/guide/components/broadcast-exceptions.html ManifestでBroadcastReceiverを登録することができなくなりました ただし一部のレシーバは例外的にmanifestで利用が可能です 例えば、ACTION_BOOT_COMPLETEDは今まで通り利用可能なので、端末が起動した後にジョブを実行するなどは 従来通り可能です。 引き続きBroadcastを受け取る場合は「Context.registerService()」を使って、実行時にレシーバーを登録します

  27. BackgroundService実行時の制限

  28. BackgroundService実行時の制限

  29. 今回のクラッシュの原因 システム起動時(ACTION_BOOT_COMPLETED)時にサービスを実行して、パワープラグのON、OFF取得用レシーバ登録処理など を実行していた この時、画面も表示されない(可視アクティビティもない)し、フォアグラウンドサービスを使う等のその他の条件にも該当せず。 このようにBootCompletedでサービスを実行して何か処理をするというケースは真っ先に該当します

  30. Oreoでバックグラウンドサービスを動かす Start Service before Android 7.x context.startService(Intent(context, BatteryCheckerService::class.java)) Start Service

    after Android 8.0 context.startForegroundService(Intent(context, BatteryCheckerService::class.java))
  31. これだけではダメ Service Notification before Android 7.x 特にサービス側では明示的に何もする必要がありません Service after Android

    8.0(例:IntentServiceを使う場合) override fun onHandleIntent(intent: Intent?) { startForeground(R.string.app_name, NotificationCompat.Builder(applicationContext).build()) //サービス内の処理等 } サービスが起動後、直ちに(5秒以内)にNotificationを発行してください サービスが動作していることがユーザーに明示(通知)されます
  32. もちろんこれもダメ startForegroundService()を発行してから5秒以内にサービス(処理)が終了するから手当しない  →サービスが終了(stopService)でANRになります

  33. 罠 https://developer.android.com/about/versions/oreo/background.html DeveloperPreview初期の頃は、NotificationManagerにstartServiceInForeground()が生えていて、 これを使うようになっていたのですが、最終的にContext.startForegroundService()になっています

  34. Tips Context.startForegroundService()はAPILevel26からなので、バージョンを見て分岐してあげましょう

  35. Adaptive Icon Android Studioから生成できるので、 こちらを利用して作るのがオススメです

  36. まとめ Android Oreoへバージョンを上げることで、他にも影響が出る部分はありますが、 今回変更になった、「Notification Channel」「Background LImits」への対応を紹介しました 皆様のアプリも、いち早くTargetSDKVersionを26に出来るようにご参考になれば幸いです!

  37. おしまい Try TargetSDKVersion 26!!