Edited at

Android 5.0 Lolipopでレガシー化するもの

More than 3 years have passed since last update.

「新しいもの」という観点はいっぱい見るけど、「なくなるもの」についてあまり見ないというか、調べてみたら結構あったので一部だけ。「This method was deprecated in API level 21.」で検索検索ゥ!


カメラ API 1.0

Lolipopでは新しいカメラAPIが搭載されることが大々的に報じられていますが、逆に言えば現在のAPIはレガシー化したということです。

しかし5.0に置き換わるまでは相当な時間が掛かるため、2~3年はレガシーAPIを使うことになると思います。今でも2.X系向け対応をしているような、明らかにコストとメリットが見合ってないようなことを続けているところは、下手したら永久に使う機会はないかもしれません。

getMaxNumFocusAreas()が0より大きいかどうかで、マニュアルフォーカスが使えるかどうか分岐させるような、API設計したやつを恨みたくなるようなコードを書かなくてもいい時代が来るのは喜ばしいことです。


PhoneNumberUtils#formatJapaneseNumber()

数字を渡すと日本の電話番号形式に変換してくれる便利なユーティリティクラスでした。

なくなるわけではなく、formatNumber(String phoneNumber, String defaultCountryIso)へ移行するとのことですが、このメソッドはLolipopでしか使えませんので、分岐書くのも面倒ですし、しばらくはformatJapaneseNumber()が使われることでしょう。

「日本の電話番号形式」を数値から復元する処理って、厳密に書くと大変そうなんですけど、どの程度正確なんでしょうね。

市外局番が6桁まであって市内局番がない電話番号が存在したころと比べれば、たぶんずっと楽だとは思うんですけど。業務系で電話番号を扱っている人はこの辺の闇を沢山見てるんでしょうね…。

UPDATE: JapanesePhoneNumberFormatterのコード読んでみたところ、


日本の電話番号の書式は少し複雑で、規則性がないため、処理するために巨大な配列が必要になる。


とのコメントと共に、理解不能な配列があったけどこれで力技で解決してるんでしょうか…。とりあえず特番とか在日米軍とかその辺には完全スルーっぽい。未使用の変数が放置されてるのが気になる。


ActionBarのTab

ActionBarTabについてはiOSのUINavigationControllerUITabBarControllerを模倣しようとして、両者の機能から合体事故を起こした残念なUIで迷走したまま終了した感があります。

ActionBarActivityがバックポートされるのも遅すぎましたし、Upボタンの判定がバージョンによって違ってユーザビリティのためのワークアラウンドが必要だったり、なんかいろいろ残念です。


ActivityManager.getRecentTasks()

セキュリティ上の理由で、ActivityManagerから「最近使ったアプリ」に相当するリストを取得できたgetRecentTasks()は、Lolipop以降では自身のアプリとホームアプリの情報しか見れなくなります。

タスクマネジメント系のスキルは全滅ですが、LolipopはOS標準のタスク管理がしっかりしていますのでそれほど問題にならないと思います。

根本的な問題として、バックグラウンドフェッチのパターンが確立されていないので、無駄に電源を食うアプリが世の中多すぎることですね。

Wifi、3G、4Gそれぞれに特性があり、電力消費を抑えられるポーリング期間は全く変わります。しかも自身のアプリだけがそこを完全に実装したところで、ほかのアプリが通信を始めたら無意味なわけで、本来であればOSに管理されるべき領域です。

AndroidにはSyncAdapterという素晴らしい機能があるのですが、ドキュメントが少なすぎるのと実装が面倒すぎました。そこをLolipopのJobSchedulerが補ってくれればいいと思うんですが、またドキュメントなさすぎて誰も使わないパターンじゃないですこれ?


自動解放のBitmap

一見素晴らしい機能に思えるこの地雷がついに除去されました。

BitmapFactory.Options.inPurgeableをtrueにした状態で読み込んだBitmap(ただしResourceおよびFileから読み込んだ場合を除く)は、不要になった時点で解放されるようになります。

というよりも、「Drawable Mutation(Drawableの変異)」という記事を読んだ方が分かりやすいのですけど、AndroidはBitmapの再デコードが発生したときに実際にはデコードを行わずに、キャッシュしたストリームから読み取る機能があるのですが、これをオフにする(ストリームへの強参照を持たない)という方が正しいような気がします?

inInputShareableというオプションと関連付いていて、これがmutate()相当なのかなーとか思ってるんですけど、BitmapFactory.Optionsもドキュメントだけだと正確な知識が手に入らないですね…。

BitmapNative Heapではなく、Dalvik Heapにアロケーションされるようになった3.0~4.Xでは、inPurgeableの使用はかえってパフォーマンスを悪くするため非推奨 となっていましたが、LolipopでinInputShareable共々無視されるようになりました。

ところで、ART RuntimeではBitmapがアロケーションされる領域ってどこになるんでしょう。


Canvasのいくつかのメソッド

Androidのカスタムビューを作ろう!となると、onDraw()メソッドでCanvasを扱うことになるのですけど、iOSのCore Graphics(HTML5のCanvas相当)を触った後だとガッカリすること請け合いです。

ハードウェアアクセラレーションを有効にすると正常に描画されないいくつかの機能があるのですが、今回ついにその手のメソッドが一掃されたのかと思いきや、別にそんなことはなかったです。あのトラップいつまで残るんでしょうね。


RemoteControlClient

ロック画面から音楽再生する機能。

Android4.0で追加されて、5.0でMediaSessionに統合されました。


Sticky Broadcast

悪名高いsendStickyBroadcast()がついに闇に葬られたようです。

Sticky Broadcastを使うと、ブロードキャスト送信後もメモリ上に残り続けるインテントを発行できます。これが利用される典型的な例として、バッテリー量の増減があります。

onResume()で登録して、onPause()で解除するようなブロードキャストレシーバでは、アプリがバックグラウンドにいる間に発行されたバッテリー減少の通知を受け取れません。しかしBatteryManagerSticky Broadcastとしてバッテリ増減の通知を発行するので、任意のタイミングでバッテリ状態を知ることができるのです。

一見とても便利に思えますが、アプリ内のデータの保持のために存在すると勘違いした人々によってセキュリティ上の懸念点となっていたほか、大量のSticky Broadcastを発行するだけでメモリを逼迫できるなど、問題がありすぎました。