2017/10/09

DevFest2017

Android1.5~8.0 Walkthrough のセッションに登壇した際のスライドとスピーカーノートメモ、あと喋った内容の文字起こし.

はじまり。

2017年8月に最新のOS Android8.0 コードネーム Oreoがリリースされました.

アプリを Oreo に最適化するには TargetSdkVersion を 26 に上げる必要があります。
TargetSdkVersion を上げることで、Oreoの新機能を十分に活かすことができます。

ここ数年のアップデートでは システムリソースの消費を抑える DozeやAppStandby、バックグラウンド動作制限などがリリースされています。

これによって、ユーザは端末やアプリを使っていないときの バッテリー消費 を抑えることができます。
その一方で, 開発者は OSの仕様変更に対応する必要があります。

バックグラウンド活動のデザイン原則というものがあります。

  • バックグラウンドの活動を減らすことができないのか?
  • デバイスが充電中の状態になるまで活動を遅らせることができないのか?
  • 他の活動とまとめることができないのか?

といったことを考える必要があります。

8.0で バックグラウンド活動が厳格化されたことで 開発者はこれらと “まじめに” 向き合っていく必要があります。

これらの機能を搭載したOSが市場にどれぐらい流通しているのかをグラフにしました。
一番左のグラフは、下から青がAndroid ヌガー, 緑がマシュマロ, 黄色がロリポップ, 赤がキットカット のシェア率を積み上げたものです。

Dozeは マシュマロ以降のOSに搭載されていますので 市場端末の およそ50% がこれを搭載しています。
Android ヌガーでリリースされた, 一部のBroadcastを無効にするProjectSvelteは 18% です。

この割合は DevelopersサイトのDashboardで公開されている 10月時点でのWorldWideなOSバージョンシェアの数字になります。国内に限定したり、ターゲットユーザ層やminSdkでそもそもサポートしていないOSがあると思いますので、みなさんのサービスと同じ数字にはならない点にご注意ください。

本日は、こういった仕様変更や動作制限の移り変わりを Android 1.5~8.0まで 振り返ります。
時間の都合上、厳選してピックアップしている点はご了承ください。

まず初めは2009年4月リリースのOS1.5 CUPCAKEです.

2009年といえば バラク・オバマ氏が アメリカ合衆国大統領に就任した年 になりますね。
その頃Androidは スクリーンキーボードのサポートやアプリウィジェットプロバイダーをリリースしていました。

リリース:2009年4月 Android1.5 - Api Lv.3

3rd party keyboards… サードパーティ製のキーボードはこの頃からサポート.
Bluetooth A2DP… BluetoothプロファイルのA2DPがサポートされました. 当然まだBLEはサポートされていません.
AppWidgetProvider… アプリウィジェット機能のAPIがリリースされ, 開発者はアプリウィジェットを作成することができるようになりました.

次にリリースされたのが 2009年9月 OS1.6 DONUT です。
Cupcakeでは 320ピクセル x 480ピクセル の解像度のみをサポートしていましたが、Donutからは複数の解像度を扱えるようになりました。
また、バッテリー問題が今よりも はるかに深刻だった時代で, アプリ毎のバッテリー使用量をユーザが確認できる機能などが追加されました。

リリース:2009年9月 Android1.6 - Api Lv.4

Battery usage indicator… アプリごとの消費電力がわかる画面を搭載
当時は電力消費問題が深刻で朝満充電にしても夕方前にはバッテリー切れという状態.

New Android Market UI… 現Google PlayのUIが大幅刷新.
当時のAndroidアプリは簡素なものが多かっただけに, Android Marketの多彩な表現は開発者の目をひくものだった

Text-to-speech engine… 多言語の音声合成エンジンでテキスト読み上げをサポート. ただし日本語は含まれていなかった.

2009年10月 Donutリリースから わずか1ヶ月後には OS2.0 Eclair がリリースされました。
この頃はOSバージョンアップが 今よりも頻繁にあった時代です。
ここでサービス周りのアップデートがありましたので詳しくみてみます。

リリース:2009年10月 Android2.0~2.1 - Api Lv.5~7

Service.setForeground deprecated… Service.setForegroundが非推奨に.
代わりにService.startForegroundを使う必要がある. さらにフォアグラウンドで動作していることをユーザに伝えるためにOngoing Notificationの登録が必須化された.

Key events executed on Key-up… Android2.0はHOMEやBackといったバーチャルキーをサポートするため, ユーザが誤ってキーダウンしてもドラッグすることでキーイベントをキャンセルすることができるように, キーアップでイベント発火されるように変更された.

Multi-touch… マルチタッチがサポートされて, キーボードで素早く文字入力しても抜けることが少なくなりました

その他… Live WallpaperのAPIリリースもこの時.

まず、2.0のタイミングでService.setForegroundメソッドが非推奨になりました。
2.0未満のOSでは フォアグラウンドサービスを開始するのに 通知アイコン が不要でした。

通知アイコンが必須になったのは2.0からで、これによって、ユーザがバックグラウンドで活動しているアプリの存在に気づき、
無用なアプリを停止させることができるようになりました。

また、当時はバックグラウンドの活動に対する制限が緩かったので、バックグラウンドにいるアプリプロセスを片っ端からKillしていくタスクキラー系アプリが バッテリー寿命に効くということで流行りました。
アプリ開発者はそうしたキラー系アプリとも戦っていた時代です。

8.0ではサービスの在り方が大きく変わりました。原則、バックグラウンド状態から新しくサービスを起動できなくなったり、startForegroundServiceで起動する場合には5秒以内にフォアグラウンドへ昇格させないとANRが発生するなど厳格化されました。

バックグラウンド活動まわりで使えるAPIに、ロリポップでリリースされたJobScheduler APIがあります。
これの互換性ライブラリとして FirebaseJobDispatcherが API Lv.9から利用可能です。カバー率はほぼ100%です。
JobSchedulerは ロリポップ から使えるAPIなので 78% の端末で使うことができます。

2010年5月にはOS2.2 Froyoがリリースされました。
音声操作機能や、テザリング機能、GCMの前身にあたる C2DM がリリースされたのもこの時です。

リリース:2010年5月 Android2.2 - Api Lv.8

Install on external storage… アプリのインストール領域に外部ストレージを指定可能になった.

Backup Manager, C2DM… 新しい端末に乗換えした時に便利なアプリデータをクラウドへバックアップ/リストアを実現するAPI Backup Managerがリリース.
アプリはBackup agentを実装することでこれを実現することができる. 現在のバックアップの仕組みとは少し異なる. またGCMやFCMの前身にあたるC2DMもこのOSからサポートされています. C2DMはGCMにリプレースされた時点で非推奨になっています.

JIT compiler… JITコンパイラサポートにより2~5倍高速化. マニフェストに vmSafeMode=false を指定することでJITコンパイラによる最適化を無効化することができます. このオプションは後々AOTコンパイラを無効化するオプションに置きかわります.

その他… PlayServiceはこれ以前のバージョンでは対応していない.

2010年12月には OS2.3 Gingerbreadがリリースされました。
電池が何に使われたかを計測するバッテリー管理機能などが強化されています。

Androidのイースターエッグが搭載されたのもGingerbreadからです。
Gingerbreadでは ゾンビ ジンジャーブレッドマン の絵がイースターエッグで表示されます。
実際、ジンジャーブレッドは ゾンビ な状態になります。

スマホ向けOSの最新版としての期間が長かったことと、スマホブームが重なったこともあって 一時期は全体の60%を超えるシェアにまでGingerbreadは普及しました。
その後は、2015年にマシュマロがリリースされて、ようやくGingerbreadのシェアが10%を切ったぐらいに ”ゾンビ” な状態でした。

リリース:2010年12月 Android2.3 - Api Lv.9/10

2010年… 東北新幹線全線開業した年.

1touch word selection & copy/paste… テキストのロングプレスで単語が選択されフリー選択モードに移行するようになった.

Improved Power management… アプリがバックグラウンドで消費したCPUタイムをユーザが見られるようになるなどバッテリー管理機能が強化された.

その他… StrictMode搭載. Apache Harmony 6.0ベース化. システムアプリやシステムUIの刷新. Google PlayServiceのサポートはここから.

ここで、パフォーマンスに関する仕様変更についてみてみます。
OS5.0から実行環境がARTに置き換わりましたが、それまではDalvikでした。

OS2.2でJITコンパイラが搭載されたことで CPU使用率の高いコードのパフォーマンスが 最大で5倍改善されました。
OS2.3ではコンカレントGCが採用され、いわゆる”Stop the world”が改善されています。
OS5.0でランタイムがARTに置き換わり、OS7.0ではARTにJITコンパイラが採用されています。

JITコンパイラの採用によってDEXを ジャストインタイム方式で 実行形式にコンバートすればよくなるので、
アプリのインストールやアップデート、OSバージョンアップの時間が大幅に短縮されています。

ランタイムやコンパイラやGCアルゴリズムの違いによってパフォーマンスに差がでる場合もありますので、
ランタイムの違いぐらいは覚えておいて損はないと思います。

ARTはキットカットでも利用できますが オプショナルです。
標準搭載されたのはロリポップ以降ですので 78% の端末に搭載されています。

2011年 2月には OS3.0 Honeycomb がリリースされました。
なかには 黒歴史 という人もいるハニカムですが、重要なアップデートが多くあった OS です。

ActionBar, Fragment, Loader, ハードウェアアクセラレーション, ホログラフィックUIがリリースされています。
ホログラフィックUIはこのスライドデザインのように 黒背景に水色のアクセントカラーをもつテーマで、白背景もバリエーションとしてありましたが、
黒背景が印象的なUIでした。ハニカムは大画面向けのOSで、スマホ向けには配信されていません。

リリース:2011年2月 Android3.0 - Api Lv.11/12/13

New UI design for tablets… Android3.0はタブレットデバイスのような大画面向けのアップデートですが, その内容は後々スマホ向けにも展開され非常に重要なアップデート内容が多く含まれている.

ActionBar, Fragment, Loader… アプリのUI要素にActionBarが導入されました. ActionBarにはMenuキーをエミュレートするオーバーフローメニューが導入されました. また, ActivityをFragmentというサブコンポーネントに分割してMaster-Detail Flowのような柔軟な画面デザインを提供することができる. 開発者は画面の大きさが異なるスマートフォンとタブレット両方で動作するアプリケーションを効率よく作成できるようになります. またActivityやFragmentからの非同期ロードをサポートするLoaderも追加.

Holographic UI… システム全体に新しいUIテーマが適用され, デザインが一新されました. アプリはTheme.Holoを指定することでこれを適用できるようになります. Notificationの表現がリッチになり始めたのもこの頃です.

その他… クリップボードへのコピー&ペースト対応. ハードウェアアクセラレーションサポート.

2011年10月には OS4.0 IceCreamSandwichがリリースされました。
ハニカムの大画面向けUI Frameworkがスマホ向けにも移植され、統一UIフレームワークとなりました。
また、ハードウェアにMenuキーを搭載することが必須でなくなったのもこのタイミングからです。

リリース:2011年10月 Android4.0 - Api Lv.14/15

Unified UI framework… Honeycombで追加されたタブレット向け要素がスマートフォン向けにも引き継がれた. スマホでは画面が小さいことからアクションアイテムがActionBarに収まらない場合, 上下に分割するSplit ActionBarの実装もここから始まります.
ただし, SplitActionBarは現在では非推奨となっています.

MENUボタンがハードウェアに搭載されることは必須ではなくなり, オプションメニューを提供する場合はActionBarにオーバーフローメニューを配置する必要が出てきたのもこのバージョンからです.

2012年 6月には OS4.1 JellyBean がリリースされました。
16ms毎のvsyncやトリプルバッファリングによって、アニメーションやスクロールがより滑らかになりました。
Unicode6対応によって Unicode絵文字にも対応し、また, Google Play Service v1がリリースされたのもこの年です。

リリース:2012年6月 Android4.1~4.3 - Api Lv.16/17/18

Project Butter… 16ms毎のvsyncやグラフィクスのトリプルバッファリングにより, より早く, よりスムーズなユーザ体験を得られるようになりアニメーションやスクロール操作がより滑らかになりました. デバッグツールのsystraceがリリースされたのもこのタイミングです.

Unicode6.0… Unicode6.0絵文字がサポートされたのがこのOSからです. それまでの絵文字はキャリア絵文字でそれぞれ独自の文字コードが割り当てられていましたが, Unicode6.0絵文字がサポートされたことでキャリアを問わず絵文字が使えるようになりました.

Notification styles, GCM … NotificationにBigStyle/InBoxStyle/PictureStyleのスタイルが加わったのがこのバージョン. まだC2DMはGCMにリプレースされた.

その他… 2012年はAndroidMarketがGooglePlayに改名され, Androidアプリ以外のビデオや音楽も扱うストアサービスとして登場した.
GooglePlayServiceライブラリもこの頃にリリースされた. API.18でBluetooth GATTプロファイルに対応も対応した.

Unicode6対応で うれしいことは Unicode絵文字が使えるようになったことですね。
プッシュ文言にUnicode絵文字を使うサービスも増えてきましたが、Unicode絵文字が使えるのはOS4.3からで、それ以前のOSでは文字化けするものがあります。
また, 絵文字に色がついてカラフルになったのはOS4.4からです。

OS5.0では、人間に関わる絵文字はスライドにあるような黄色いキャラクターのグリフに差し替えられました。
OS6.0でUnicode 7と8をサポートし、また「お父さんの絵文字+お母さんの絵文字+子供の絵文字」を
Zero Width Joiner の文字コードで連結すると「家族」の絵文字、1文字に置き換わる仕様にも対応しています。

OS7.0ではUnicode9に対応し、5.0で対応されたnonhuman shapeのキャラクターが”人間”の見た目に戻りました。
絵文字には国や宗教、人種、思想に配慮した仕様になっていて複雑ですが、「human shape」な絵文字と Skin toneの文字コードを繋げることで
絵文字の肌の色を変えることができるようになり、絵文字のバリエーションがグッと増えました。

一応、国内キャリア端末は標準絵文字グリフをキャリア絵文字のグリフで上書きしているので、
OSが同じでもキャリアによって絵文字の見た目に違いがでる問題があることも, ここに付け加えておきます。

それぞれのUnicodeバージョンを搭載している端末の割合はこちらの通りで、
Unicode6が 94%、Unicode 7&8が 50%、Unicode 9が 18%です。

2013年 10月にはOS4.4 Kitkatがリリースされました。
エントリーレベルのデバイスでも動作できるように設計されたOSでストレージアクセスフレームワークが搭載されたのもここからです。
WebViewのアップデートもありましたが そちらは後ほどお話しします。

リリース:2013年10月 Android4.4 - Api Lv.19

Support 512MB RAM device… エントリーレベルのデバイスであっても動作するように設計されたOSで, アプリもActivityManager.isLowRamDevice() APIを使うことで低スペックデバイス向けのコンフィグレーションが可能になりました.

Storage Access Framework… これまで端末内のファイルをユーザに選択させたり, 保存場所を指定させる場合に使われるファイルエクスプローラはOSから提供されていませんでした. ストレージアクセスフレームワークを使うことでユーザに一貫したファイルシステムへの参照方法を提供できるようになりました.

Chromium WebView… WebKitがChromiumベースに差し代わりました. これよりChrome Dev Toolsによるリモートデバッグもサポートされるようになった.

その他… RTLサポートが強化されました. それまではテキストの対応しかなく, リソースを重複して持つ必要がありました.

Android4.4からは, バッテリー消費を抑えるためにアラームの発火タイミングが不正確になります。
4.4以降、どうしても正確なアラームが欲しい場合は AlarmManager の setWindow() か setExact() を使うことになります。

Android6.0は Dozeによるデバイスアイドル状態では アラームの発火が保留されます。
アイドル状態でもアラームを正確に発火させたい場合は setAndAllowWhileIdle() か setExactAndAllowWhileIdle() を使うことになります。

ちなみに、アラームはアプリごとに9分間に1回以上発火はされない仕様です。

2014年10月にはOS5.0 Lollipop がリリースされました。
マテリアルデザインによってUI/UXが大きく変更され、ベクタードロワブル や マルチユーザのサポート、
ARTの標準搭載、CPUの64bitアーキテクチャサポートなど、幅広いアップデート内容になっています。

リリース:2014年10月 Android5.0 - Api Lv.21/22

Material Design, Project Volta… マテリアルデザインの導入でUI/UXが大きく刷新された. RecyclerViewやZ軸, シャドウの概念もここから.
また, バッテリー消費を抑えて電池持ちを改善するプロジェクトProject Voltaが明らかにされました. ジョブスケジューラの機能が提供されたことにより, アプリの動作が最適化されバッテリー消費を抑えることに貢献しています.

Overview, Notification, Multi-user… OverviewはこれまでRecentsと呼ばれていた”最近使ったアプリーケション一覧”の機能に相当するものです.
従来は使ったアプリケーションのリストが並ぶだけでしたが, ここに複数のActivityをドキュメントとして追加することができるようになり, マルチタスクにも使えるようになりました. また, Notificationにはプライオリティやカテゴリの概念が追加され, 重要な通知がヘッドアップ表示されるようになったのもこの頃です.

64bit, ART… また, パフォーマンス改善も行われ, ARTランタイム対応や64bit対応もここから始まりました.

その他… Chromium WebViewがPlayStoreからアップデートできるようになった. AndroidHttpClientのメンテナンスが終了・廃止されURLConnectionの使用が必須に. API Lv20はAndroid Wear向けのAPI Lvとして割り当てられた. またディベロッパープレビュー版という提供方法が始まったのもここから.

WebView周りの変更についてみてみると、4.3までのWebViewは WebKit上で動作していましたが, 4.4以降はChromium上で動作します。
5.0では Google Play経由で アップデート可能になり、WebViewのセキュリティパッチが素早くユーザに届けられるようになりました。
WebViewに依存したアプリの開発者は WebViewのアップデート頻度が高くなったので注意する必要があります。

7.0 以降は Chrome APKから WebViewを提供する機能が搭載されています。これによって、メモリ消費が改善されました。
8.0では アプリのWebView がマルチプロセスモードで実行されます。ウェブコンテンツはアプリのプロセスとは別の独立したプロセスで処理されるので、
セキュリティが強化されています。

また、ここに記載していませんが Chrome custom Tab の機能がOS4.1以降で利用できるようになっています。

Chromium版は 93%の端末 に搭載されていて, WebViewを個別にアップデート可能な端末は 78% です。

2015年 10月にはOS6.0 マシュマロがリリースされました。
このあたりからアプリの挙動を変えるアップデートが目立つようになりました。
RuntimePermission, Doze, AppStandbyなどです。

リリース:2015年10月 Android6.0 - Api Lv.23

RuntimePermission… パーミッションモデルに大きな変更が入りました. ユーザはアプリのパーミッションを管理できるようになり, 好きなタイミングで権限を付与/剥奪できるようになります. また, アプリインストール時にパーミッション許可を求めることはせず, アプリの任意のタイミングでユーザにパーミッション付与を求めるようになります.

Doze, App Standby… 電源に接続していない状態で, 一定時間端末を画面オフで放置していた場合にスリープ状態を維持するDozeや, アプリが長時間アイドル状態であった場合にアプリのネットワークアクセスが無効になり, 同期とジョブが保留されるようになりました.

AutoBackup, Do not disturb… アプリデータが自動でGoogle Driveへバックアップできるようになりました. 追加のコードは必要ありません. バックアップを無効にする場合はマニフェストに1行無効にするフラグを定義します. また, Do not disturbモードもこのバージョンからです.

その他… Apache HTTP clientが削除. OpenSSLからBoringSSLに移行. TextSelectionもそれまでの編集モードからpopup windowでアクションを選択するUIに変更されました.

6.0のDoze機能は, 画面OFF かつ 充電中ではない場合 かつ 端末をほとんど動かさない静止状態 にし続けると、
CPU と ネットワーク通信 を一時保留して バッテリーの寿命を延ばす 省電力機能が働きます。

7.0ではDoze状態になる条件が緩和されて、端末が静止していなくてもDoze状態に入ります。
これによって、ポケットにスマホを入れて持ち歩いているような状況でも バッテリー消費を抑えることができるようになりました。

Dozeがリリースされたのは Android マシュマロ以降なので 50%の端末 がこれを搭載しています。

2016年8月には OS7.0 Nougat がリリースされました。
マルチウィンドウやRAMの使用量を削減するProject Svelteによって一部のブロードキャストが廃止されました。
また、ランチャーアイコンにまつわる変更もあります。

リリース:2016年8月 Android7.0/71 - Api Lv.24/25

Multi-window, Screen zoom… スマートフォンやタブレットで画面を分割して2つのアプリを並べて利用できるようになり, AndroidTVではピクチャーインピクチャーがサポートがサポートされました. また視力が低いユーザ向けの補助機能としてスクリーンズームが搭載され, 端末の画面密度設定が変更可能になりました.

Doze2, File security… 従来はDozeモードに突入するためには端末が静止状態である必要がありましたが, Doze2ではこの制限がなくなりました.
また, プライベートディレクトリのアクセス権限が厳格化され, 他アプリにファイルを直接読み書きさせることができなくなりました. これに伴いfileスキームのURIを含むIntentを共有しようとするとセキュリティ例外が投げられるようになっています.

Project Svelte… アプリのバックグラウンド実行を最適化することでRAMの使用量を削減する取り組み. CONNECTIVITY_ACTION、ACTION_NEW_PICTURE、ACTION_NEW_VIDEOの暗黙的なブロードキャストが削除されました. これらのブロードキャストは複数のアプリが同時に起動するため, メモリが逼迫しシステムのパフォーマンスを低下させる要因になるためです.

その他… 3DレンダリングAPIのvulkanがプラットフォームに統合, データセーバ機能の搭載, WebViewがChrome APKから提供される, VRサポート, App Shortcutなど. またこのタイミングでApache HarmonyベースからOpenJDKベースに移行された.

OS4.3 では 一般的なサイズよりも大きく アプリアイコンを表示するランチャーアプリに対応するため,
端末の抽象解像度ではなく、リクエストされたサイズに応じてリソースを返す mipmapリソースがサポートされました。

OS7.1では アプリアイコンを丸く表示するランチャーアプリが増えたため, アプリから丸いアイコンを提供するRound Iconリソースが追加されています。
OS8.0では さらに元のデザインを崩すことなく、自由にアプリアイコンの形を変えることができるAdaptive Iconがサポートされています。

そして 2017年8月の Android8.0 現在に至ります。

リリース:2017年8月 Android8.0 - Api Lv.26

Background execution limits… バックグランドによる動作が大きく制限されました。サービスを開始してもアプリがバックグラウンドに遷移するとサービスは自動で停止されます。
バックグランドからサービス開始したい場合はContext.startForegroundServiceメソッドをコールし, 5秒以内にフォアグラウンドサービスに昇格させる必要があります。
また、暗黙的なブロードキャストも制限されはじめ、JobShcedulerへの移行が推奨されています。

Notification dots, XML font… アプリの通知がランチャーアイコンにドットで表現されるようになったり, フォントをリソースとして扱えるXMLフォントの機能が導入されました。

Alert windows… システムウィンドウより上にアラートウィンドウを表示できなくなりました。アプリはTYPE_APPLICATION_OVERLAYウィンドウを使うことができます。

その他… HttpsURLConnectionが古いTSLバージョンへフォールバックする動作をやめる, WebViewのマルチプロセスモード実行, ANDROID-IDの処理方法変更, クリッカブルなViewがデフォルトでフォーカス可能に変更, スマホ/タブレットでのピクチャーインピクチャーモード対応, AppShortcutの改善, アダプティブアイコン, 最大アスペクト比, マルティディスプレイ, JobScheduler改善など

Android8.0 ではバックグラウンドで実行する動作を制限していますが、多くの場合 ジョブスケジューラに置き換えることができます。

これは ディベロッパーサイトの Intelligent Job-Scheduling というページからの引用で、
 ジョブを賢くスケジューリングすることで、バッテリ寿命といったシステム状態とともに、アプリのパフォーマンスも向上できます。
と書かれています。

バッテリー寿命というのは、モバイルユーザ体験の重要なポイントです。

Android を よりスマートで、より早く、よりパワフルなプラットフォームに仕上げるには、OSのバージョンアップだけではなく、
アプリの最適化によるバージョンアップも必要不可欠です。

OSに最適化する作業は大変ですが、プラットフォームにも デバイスにも また, ユーザにも優しいアプリ開発を心がけたいものです。

発表は以上ですが、本日紹介した内容は時間の都合上、細かな内容は省いています。
みなさんのサービスに関わる部分で気になるものがありましたら、これらのページを参考にしてみてください。