fkm blog

software開発に関することを書いていきます

Google I/O 2019: What's New in Android Development Tools

youtu.be

Android Studio 3.2

去年のI/Oでは、Android Studio 3.2が発表された。App bundleやナビゲーションエディタなど。

Android Studio 3.3

今年(2019年)1月にAndroid Studio 3.3がリリースされた。プロジェクト作成ウィザードの刷新や、単一variantのsyncなど。

Android Studio 3.4

今年(2019年)4月にAndroid Studio 3.4がリリースされた。リソースマネージャーの登場や、R8(Proguardの新しい版)がデフォルトになるなど。

Android Studio 3.5

Project Marble。IDEの体験を向上させよう。そのために大量のIssueを - System health - Feature Polish - Bug Backlog に分類したよ。

System health

Android Studio起動時に「統計情報をGoogleに送っていい?」と聞かれるが、その情報が使われてるのがここらしい。

有効にしていて、Android Studioがクラッシュすると、クラッシュレポートがGoogleに送信される。

UIのフリーズは注意しておきたい分野。UIスレッドが数秒とまった場合、すべてのスレッドダンプをとってGoogleに送信している。ダッシュボードによると、平均14秒止まり、発生回数が5万件というのがあったりする。

この統計をもとにバグを直したところ、例としてデータバインディングを使っているXMLの編集がとてもはやくなった。

もちろんスポットで直してるだけではない。ちゃんとリグレッションテストもやってる。例えばUIスレッドがネットワークリクエスト投げていたりしたらテストがFailするようにしてる(Javadoc出したりするときに発生しそう)。

次はメモリに関して。IDEがOOMに遭遇したとき、ヒープの統計とかを収集してGoogleに送信している。このような統計から見えてきたことは、多くのユーザーはAndroid Studioをヒープ1.2GBで動かしていたという事実。

なぜ1.2GBをデフォルトにしたか?デフォルトを大きくすると、ローエンドのマシンで起動すらできなくなってしまうから。だからといって小さくしすぎると、通常のプロジェクトを開くときに開けなくなってしまう。

もしマシンのメモリがたっぷりあるのなら、Android Studioが使用するヒープサイズは大きくしよう。

Android Studio 3.5では、「もうちょいAndroid Studioが使用するヒープサイズ大きくする?」のダイアログが出るように。その場で設定を変更して再起動もできる。

Android Studioメモリリークを調べるには、ヒープダンプを取るのが手っ取り早い。でもでかいし、個人情報が含まれるからそれは無理。そのため、OOMが近くと一旦ヒープダンプをとってローカルに保存し、次回起動時にメモリリークを解析してその結果だけを送信するようにしてある。送信後、保存したダンプファイルは消している。送信前にはどんな情報を送るか、プレーンテキストになっているものが確認できる。

このメモリリークの情報から、有名なサードパーティプラグインメモリリークを突き止めた(すげー)。プラグイン開発者にバグレポートしたところ、「数年前からなんかリークしてたっぽいんだけど、わかんなかったんだよねー」とともに、24時間以内に直してくれた。

だいぶ改善されたとはいえ、メモリリークのあるプロダクトを出荷しているという事実にかわりはない。なので特殊なテストランナーを用意し、テストでメモリリークを発見できるようにした。

次にスピードに関して。1つの手は余計なプラグインをいれないこと。でもパフォーマンスのためにプラグイン使うのやめるのはおすすめしない。

高速化のために、アノテーションプロセッシングのインクリメンタル化をしたよ(別セッションにて)

Android Studioのマジョリティは(Macではなく)Windows。ファイルのセパレータが違うといった、Windows特有の問題もあるけど、パフォーマンスに影響があったのがウィルスチェッカー。SDKやプロジェクトのフォルダを除外すると、速度が4倍になった。そのため、SDKやプロジェクトフォルダがウィルスチェッカーに除外されていない場合、ダイアログを出すようにしたよ。盲目的に除外するのではなく、セキュリティとのトレードオフを考えてね。

エミュレーターもまたCPUをよく使う分野。Google Play入りのものだと、アップデートの確認やアプリの最適化などが走って結構CPU使っている。これをなんとかするために、エミュレーターのデフォルトを「バッテリー使用中」に変更したよ。

もう1つの改善は、マイクでずっと待ち受けするのをやめたよ(ホームとかで「お〜け〜ぐ〜ぐる」と呼ぶと下からにょきっとでてくるあの機能)。マイクが必要な場合はその都度ONにして使ってね。

Feature polish

Instant runの代わりにApply changesを作ったよ。機能的にはInstant runとほぼ同じだけど、Android O以降に限定して変なhack使うのをやめてるよ。Instant runの時はホットスワッピングのためのコードを差し込んでたりしたので、逆にクリーンビルドが遅くなってた。Apply changesはOS側のホットスワップの機能を使ってるので、より安定してるよ。

次はGradle。今までGradleはjarとか、ライブラリで使ってるのをどんどんホームディレクトリにキャッシュとして放り込んでたけど、それを自動で削除してくれる機能が入ったよ。でもAndroid Studio的にはキャッシュから読んだほうが早いので、この機能には困った。けどなんとか直した(It's been fixed)。

飛行機の中とか、ネットワークの使用がめっちゃ制限されている環境で開発する人のために、maven.google.com のリポジトリをダウンロードしてオフラインでも使えるようにしたよ。zipを展開して、READMEに書かれているように設定してみてね。

Android Studioをアップデートして、プロジェクトを開いた時に「いろいろアップデートしてね」のメッセージがこれまでは出ていたが、今後は出なくなる。

データバインディングを使ってる人は、いろいろ改善したのでAndroid Studio 3.5を使ってみてね。

Bug backlog

数週間が400以上のバグを直したよ

Gradle plugin

今までは、Android StudioのバージョンをあげるとGradleプラグインのバージョンもあわせてあげる必要があった。今後はその必要はなくなる(あげたほうがいいが)。そのため、プラグインさえあわせていればAndroid Studioのstable版を使おうが、betaを使おうが、かまわない。

デモは動画みてね。他のセッションで紹介されたものがほとんど。

Chrome OS

Chrome 75以上でx86Chrome OSで、Android Studio 3.5が正式サポート。

Google I/O 2019: Overview of Privacy Changes in Android Q

youtu.be

Android Qでのプライバシーに関して。あれAmphitheatreなのに18分しかないぞ?

Android Qでは50以上のプライバシー/セキュリティに関する機能が追加。

Permission

Android 6.0でRuntime Permissionが追加された。

ところで、ユーザーがpermissionに対して拒否した理由トップ3

  1. そのpermissionを必要とすべきではない
  2. そのpermission許可しなくても動くはずだ
  3. あとで許可すればいいや

これらは、permissionを聞いた時点でユーザーにそのpermissionをとる価値を与えられていないのが原因。

ベストな方法

Step 1. 代替のAPIがあるなら、それを使い、permissionを取らないようにする。例えばSMSでのverificationをやる場合、SMSのパーミッションをとるのではなく、Play SMS Retriever APIを使うなど。別の例として、アプリユーザーが電話中かを調べる際、 READ_PHONE_STATE を取るのではなく、Audio Focus APIを使う(hackな感じだ。。。)。

Step 2. パーミッションのスコープを決め、どのようにとるかを決める。すべてのpermissionに許可を出すのは18%のユーザーだけ。

例えばユーザーがカメラのアイコンをタップしたとき、permissionを取るようにする。この場合、ユーザーにとってカメラの使用許可を聞かれるのは自然である。

また、ユーザーにより情報を与えるために、いきなりOSのAPIを呼ぶのではなく、ダイアログでこのpermissionに許可すると何がおきるかを説明するといった配慮も有効。

Android Qでは位置情報のpermissionの場合、ダイアログが異なる。locationのセッション参照。

Step 3. ユーザーを驚かせない。

  • 必要なデータだけを取る。
  • ユーザーの許可をとった上で情報を共有する。
  • 情報を端末の外に持ち出す場合、暗号化しセキュアにする。
  • とった情報は必要な期間だけ保持する(ずっと保持しつづけない)

端末ID

Android Qでは不変となる端末IDは READ_PHONE_STATE をとっても取得できなくなる。代わりにユーザーがリセット可能なIDを使おう。

MACアドレスのランダム化は、Android Pでは開発者オプションだったが、Andoird Qで正式採用される。

アプリの起動と通知

Android Qではバックグラウンドからのアプリ起動はブロックされる。

フォアグラウンドサービス

Android Qでは、フォアグラウンドサービスに種類が追加された。

  • sync
  • media playback
  • media projection
  • phone call
  • location
  • connected device

種類によって、使用できるpermissionに違いがある。

わ、ほんとに18分で終わった。。。

Google I/O 2019: Best Practices in Using the Android Emulator

youtu.be

Androidエミュレーターに関するセッション

今年は折りたたみ機能が追加された。

エミュレーターの開発に関し、大事にしていること。 - 早いこと - 忠実であること(fidelity) - 多様であること(versatility)

今のエミュレーターはPCが早いと、実機より早い。動画では2015年のPCとPixel 2との比較が紹介されてた。

通常、エミュレーターはホストとゲストでCPUのアーキテクチャが違うので、翻訳が必要。最近のAndroidエミュレーターx86版で動作しているので、ほぼ翻訳なしにホストで実行できる。これらのテクノロジーはハイパーバイザー(hypervisor)と呼ばれ、WindowsだとHAXMかWindows Hypervisor Platform、MacだとMacOS Hypervisor FrameworkとKVM

ハードウェアGPUはデフォルトに。なのでVulkanやOpenGL ES 3.1をエミュレーターでサポート。

次はADBの話。実機に繋いでファイルを送信した場合、USBケーブルあたりでの制約を受けるが、エミュレーターだと仮想TCPで繋がるので早い。

AR Macro

ARCoreを使ったアプリをエミュレーターデバッグできる。またマクロ機能が追加された。

バッテリーモードがデフォルトに

今まで、エミュレーターは常に充電中モードだった。そのため、Playストアアプリがアップデートの有無にかかわらず更新を探しに行ってた。それだとホストのCPUとか食っちゃうので、バッテリー使用中のモードをデフォルトにした。もちろん設定を変更して充電中モードに戻すことも可能。

より実機に近づける

エミュレーターに対しては90万以上のコンパチビリティテストが実施されている。これらのテストは実際に実機に対しても行われているもの。

Playストア入り版の場合、アプリ内課金やSNSへのログインとかもちゃんとできる。さらにアプリのシェア機能もエミュレーターで行うことができる。

スナップショット

例えばアプリのテストを再度実施したい場合、今までだとアプリを一度アンインストールして、再度インストールしてからテストを実施するといった作業が必要だった。スナップショット機能を使えば、テスト前の状態でスナップショットをとることで簡単にテストを再度実施できる。

複数インスタンス

先ほどのスナップショットを用いて、同じエミュレーターを複数起動することができる。テストを同時に実行可能に。

エミュレーター起動時、 -read-only をつけることで、同じAVD でいくつもエミュレーターが起動できる。同時に起動した場合、書き込みが行われるまでRAMは共有されるので省メモリで動作する。

Headless mode

起動するには emulator ではなく emulator-headless コマンドを使う。

Google I/O 2019: Build Apps for Foldable, Multi-Display, and Large-Screen Devices

折りたたみスマホや、複数ディスプレイに関するセッション

youtu.be

Foldable Device

折りたたみデバイスには2種類ある

fold in: 谷折り。ディスプレイ名が重なるように折りたたむ。Galaxy Foldがこちら fold out: 山折り。ディスプレイが外側になるように折りたたむ。Huaway Mate Xがこちら(出るのかなこれ。。。

fold inはディスプレイが3枚分あるの??

Androidはこの折りたたみをサポートする。

UXに関して

広げたときは、大画面になるので動画再生やゲームに最適

折りたたんでいるときは、通常の電話と同じような体験に。

また、広げたときはウィンドウを2つ並べてマルチタスクとしても使える。

アスペクト比

minAspectRatiomaxAspectRatio で、サポートするスクリーンのアスペクト比を制限することができる。

最小幅

最低でも2インチあることが保証されるように。下ナビゲーションにアイコン5つギリ入る幅。Jelly Proみたいな端末は出せなくなる?

アプリの連続性

折りたたんだり、元に戻したりしたとき、ユーザーの状態をロストしないようにしよう。折りたたんだら動画再生が先頭から みたいなのは悪い体験。configurationの変更として扱われるので、画面回転と同じようなものとして捉えればOK。

android:resizableActivity="false" にしても、configurationの変更でサイズを変更しなければならない場面がある点に注意。このフラグはアクティビティがマルチウィンドウやマルチディスプレイ環境に対応してるかだけを表すフラグ。

Android Qでは、マルチウィンドウと画面回転の両方に対応しないアプリのためにCompat modeが用意されている。この場合、折りたたみ環境で広げた状態ではiPadのように真ん中に縦長のアクティビティが表示される。

マルチウィンドウ

Android Qではマルチレジュームという機能が導入される。これはマルチウィンドウの状態で、複数のアプリがRESUMED状態(=ユーザーからの操作を受け付ける状態)になること。

アクティビティがPAUSED状態になるのは、 - 上に透明なアクティビティが重なった - フォーカスがあたらない状態(例えばPicture in Picture modeとか)になった

マルチレジュームで考えないといけないのは、排他的に使うべきリソースにアクセスする場合。例えばカメラやマイクとか。当然複数のアプリ間で同時に使うことはできないので、ちゃんとdisconnectのイベントを処理し、使えるようになったら再接続するような実装が必要。動画ではカメラアプリを同時に3つ起動する例が示されている。

resizableActivity="false" としても、カメラへのアクセスが保証されるわけではないので注意。

「使えるようになったら」のためのコールバックとして、 onTopResumedActivityChanged(topResumed: bool) が追加されている。 true が渡されたらカメラとかへのアクセス権がもらえている。

ドラッグ&ドロップも考える必要がある。機能自体はNぐらいから導入されてるのと同じ(Nだったかは要調査)。

1Passwordの例。リサイズに対応し、ドラッグ&ドロップ(持ち出す方)に対応。アプリから離れるとロックする機能をいれていたが、リサイズするたびにロックされてしまうという問題に直面した。アクティビティのライフサイクルに対する理解を改め、なんとかしたっぽい。

続いてGameloftの例。Device unknownというのをつくり、あらゆる仮定(スクリーンサイズやピクセル密度など)を排除して考えてみた。エディタは画面の要素をアンカーベースで配置してもらい、いつ画面のサイズが変わっても大丈夫なようにしてもらった。

マルチディスプレイ

アクティビティを別のディスプレイに持っていったとき、コンテキストも変わってしまう。アクティビティコンテキストは、今表示されているディスプレイの情報がとれる。逆にアプリケーションコンテキストでディスプレイの情報と取ってしまうと、意図しない情報がとれたりする。

トーストの表示も、アクティビティコンテキストの影響を受ける。引数で渡したアクティビティが表示されている側にトーストが表示されるようになっている。

configurationの変更イベントの中には、「タッチ可能の有無が変更された」などもある。例えばスマホの画面にいたアクティビティが、外付けのディスプレイに移動したときなど。

マルチディスプレイを扱うには、 DisplayManager 経由で各ディスプレイの情報がとれる。 startActivity() のオプションに、どのディスプレイで起動するかを渡すことができる。またディスプレイによってはアクティビティの起動が禁止されているものもある。その場合は SecurityException が投げられる。Android Qでは、そのディスプレイで起動可能かをチェックするためのAPIが追加されている。

セカンドディスプレイにソフトキーボードを表示することもできる。その場合、キーボードもディスプレイ間を移動することになる。

壁紙もディスプレイ毎に用意できる。

テストについて

こんな変態的な環境を用意するのはたいへん。なのでエミュレーターで折りたたみがサポート。7.3インチと8インチを現時点で用意している。将来的にはもっと増えるみたい。

マルチディスプレイは、開発者オプションで「強制デスクトップモード」がAndroid Qに追加されている。もし端末にHDMI出力があれば、マルチディスプレイで動作させることもできる。

デベロッパーガイドは https://developer.android.com/preview/features/foldables にある。

Google I/O 2019: Updating Your Apps for Location Permission Changes in Android Q

現地で聞いてないセッション。「位置情報に関する更新はだいじ!」と何名から言われたので早めに確認します。

youtu.be

Android Qでは、ユーザーにとって - シンプルで(simple) - 発見しやすく(discoverable) - 理解しやすい(easy to understand) 位置情報データに対するアクセスコントロールを提供。

Qより前は、ユーザーは位置情報に関して「許可」「禁止」の2つしか選べなかった。許可した場合、アプリ使用中/バックグラウンドに関わらず、位置情報が取得できた。そのため、Qでは「このアプリ使用中にのみ位置情報の取得を許可する」が追加された。

「使用中」とは? - アクティビティがフォアグラウンド - フォアグラウンドサービス

targetSdkVersionがQの場合、 バックグラウンドで位置情報を取得するには AndroidManifest.xmlACCESS_BACKGROUND_LOCATIONパーミッション追加が必要。 今までの ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION はフォアグラウンドでしか取得できない。

また、Q以前にしていた場合は自動で ACCESS_BACKGROUND_LOCATION にマップされる。これをオプトアウトする術はない。

targetSdkVersionをQにした場合、位置情報取得の許可を得る際、「このアプリ使用中のみ取得」「拒否」の2択ダイアログが出せる(「常に取得」を非表示にできる)。また、インクリメンタルに許可をとることもできる。

例えば鉄道のアプリで、ユーザーがアプリを起動中に近くの駅の情報を出すといった機能があった場合、「アプリ使用中のみ位置情報を取得する」のダイアログを表示することができる。そしてユーザーがバックグラウンドにいるときも運行情報を取得したいとしたときにはじめて「常に位置情報を使用」まで含めたダイアログを表示。その際、「アプリは現在、使用中のみ位置情報にアクセスできます」と表示される。

ユーザーが許可したかは、 checkSelfPermission() で確認できる。またユーザーは設定でいつでも「常に許可」「アプリ使用中のみ許可」の変更ができる。アプリ開発者はQでのテストを早めに行ってほしい。

ユーザーがPからQにアップグレードした場合は?Pで許可していた場合、Qでは「常に許可」としてアップグレードされる。つまりバックグラウンドでの位置情報もとれる。

フォアグラウンドサービス

ユーザーが、ユーザーの意思で位置情報を取得し続けてほしい(ホームボタンでアプリが中断されても)場合、それはフォアグラウンドサービスとして実装されるべき。

Qでは、フォアグラウンドサービスを作る場合、 AndroidManifest.xmlandoird:foregroundServiceType="location" をつける必要がある。この権限をつけ忘れ、ユーザーが「アプリ使用中」の設定にした場合、位置情報は取得できない。

通知について

位置情報の使用を許可したアプリで、ユーザーが長期間使用していない場合、システムが通知欄に「このアプリは位置情報を取得しつづけてるよ」の通知を出す。ユーザーはこの通知をタップすると、位置情報の許可レベル設定画面が表示される。

Wifi API

Q以前は、WifiのスキャンAPIと接続APIがあった。スキャンできるということは、そこからだいたいの位置が特定できてしまう。なので位置情報のパーミッションが必要だった。ユーザーにとって、「なんでWifiに繋ぐだけなのに位置情報を取得するの?」と混乱の元となっていた。

この問題を解決するため、Qでは次の2つのAPIが追加された。

  • Wifi NetworkSuggestion
  • Wifi NetworkSpecify

これらを使うと、アプリは近くのWifi情報にアクセスできなくなるので位置情報のパーミッションが不要になる。

Wifiが位置情報を出していた場合、それらを取得するには ACCESS_FINE_LOCATIONパーミッションが必要になる。

Wifi Network Suggestion

WifiNetworkSuggestion.Builder() を使って組み立てる。SSIDやパスワードの指定も可能。組み立てたら WifiManageraddaddNetworkSuggestion() に渡す。

あとはユーザーが指定したWifiの領域内に入ったら、システムが通知で「このネットワークに繋ぐ?」と出してくれる。その際、「このアプリが提案してるよ」と出してくれる。

setIsAppInteractionRequired()WifiNetworkSuggestion につけると、接続後にアプリにブロードキャストが投げられる。インテントフィルタは ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION (長いなぁ)。この機能はユーザーの位置がある程度わかっちゃうので ACCESS_FINE_LOCATION が必要。

Wifi Network Specier API

例えばIoT機器を買ってきて、セットアップが必要な場合、電源をいれてスマホからWifi経由で繋ぐというケースがある。こんなときに使えるのがWifi Network Specier APIWifi Network Suggestionと似ているが、このケースの場合、機器ごとにSSIDが違う(もちろんパターンはある)のでWifi Network Suggestionは使えない。

WifiNetworkSpecifier.Builder() を使って組み立てる。SSIDのパターンや、BSSID(MACアドレス)のパターンを登録する。

次に NetworkRequest オブジェクトを組み立てる。「インターネット接続はいらない」といった設定を付与できる。

これができたら、URL Connectivity Manager APIを使って確認するだけ(ソースなし。。)

ベストプラクティス

  • 必要ないときは位置情報をとらない
  • 必要になったときに許可をとる
  • 位置情報取得の理由をユーザーに伝えよう
  • アプリ起動直後に「位置情報使うよ」のダイアログを出さないようにしよう
  • インクリメンタルに聞こう(バックグラウンドで取得する必要がでたら、そのときに聞こう)
  • 位置情報がとれないときの処理をちゃんと書こう。ユーザーはいつでも設定を変更できる。

Google I/O 2019: Android Studio: Tips and Tricks

Android Studioを使い倒すためのセッション。何度も巻き戻しながら操作を確認したほうがよいです。

youtu.be

全編デモというなかなかにクレイジーなセッション。

プロファイラ

Command+Shift+up でウィンドウの大きさが変更できる。

メモリプロファイラ

  • Command + GでGC実行。
  • Command + マイナスでズームアウト
  • Command + 0(ゼロ)でデフォルトの大きさに

電力(energy)プロファイラ

システムイベントがとれる。

IDEのtips

ツールウィンドウ(上下左右にくっついてるやつ)は、Command+書かれてる数値 でOpen/Closeできる。Windowsの場合はAlt+書かれてる数値

Switcher(Ctrl+tab)を使うと、数値の書いてないツールウィンドウ(例えばGradle)もぱっと選べる。

Shift+Escapeで最近開いたウィンドウを閉じれる。

F12で直近のウィンドウに戻れる。

Command+Shift+F12(Ctrl+Shift+F12 on Windows)で、すべてのウィンドウを隠す。もう一度押すと元に戻る。

Projectウィンドウとかで探したい文字列を直で入力すると、フィルタされる。これは結構使ってる人多そう。

エディタで、隣のタブに行きたいときはalt+左右。これもすでに使ってる人多そう。なおレイアウトエディタのように、下にもタブがある場合はalt+shift+左右で切り替わる。

エディタは上下左右に分割できる。タブの部分をドラッグすれば分割した別のとこに持っていくことも可能。

分割を元に戻したいときは、Shiftx2(Search everywhere)でunsplitを選べば戻せる。

Command+O(Ctrl+Shift+N on Windows)でファイルを探す。

Ctrl+1でブックマーク1に飛ぶ。

Ctrl+左右でカーソルを単語単位で移動。Shiftをつければ当然選択される。

CamelHumps wordを使うモードがある。

メソッドでCtrl+上下(Alt+上下 on Windows)で、次のメソッド/前のメソッドに飛べる。

Command+Shift+Backspace(Ctrl+Shift+Backspace on Windows)で、最後に編集したところに飛べる。

インテリジェンス系

F1(Ctrl+Q on Windows)でtooltipを表示。メソッドの説明が欲しいときに。

引数の中でCommand+P(Ctrl + p on Windows)で、引数の説明を読んだりするモードになる。tabで次の引数に移動したりとかもできるようになる。

Ctrl+spaceで基本的なコード補完。この時、引数名から推測して「この変数?」というのを提案してくれる。引数を書き換える時はEnterではなくtabを押そう。

() まで書かれた状態で、引数をいい感じにうめたい時はCtrl+Shift+Spaceでいい感じに候補を絞り込める(スマートタイプというらしい)。引数が2つかある場合、まとめて設定とかもできちゃう。

編集に関するtips

Command+Shift+a(Ctrl+Shift+a on Windows)でアクションを探せる。

Ctrl+Shift+jで行を連結。

Option+w(Ctrl+w on Windows)で選択範囲を広げる。

Command+D(Ctrl+D on Windows)で選択してるのを複製。

Command+/(Ctrl+/ on Winddows)でコメント化

行を選択した状態でCommand+Shift+上下で持ち運べる。ちゃんとブロックの中とか意識してくれる。

Command+Backspace(Ctrl+Y on Windows)で1行削除

Command+F(Ctrl+F on Windows)で検索。

Ctrl+G(Alt+J on Windows)で、選択してるのと同じものを選択範囲に追加。

Command+Shift+v(Ctrl+Shift+v on Windows)で、履歴からペースト。

Option+Command+M(Ctrl+alt+m on Windows)で、選択してたのを関数化。このとき似たようなのがあったら同時に関数を呼ぶスタイルに変更してくれる。

Option+Command+v(Ctrl+alt+v on Windows)で、選択してたのを変数化

Option+Command+n(Ctrl+alt+n on Windows)で、変数のインライン化

範囲選択してOption+Command+t(Ctrl+alt+t on Windows)で、ifで囲んだりtry-catchにしたり。

Command+Shift+Enter(Ctrl+Shift+Enter on Windows)で、現在のステートメントを完成させる。

Option+Command+p(Ctrl+alt+p in Windows)で、指定したものをメソッドの引数に移動させる。ちゃんと呼び出し側も変更される。

Command+b(Ctrl+b on Windows)で、定義に移動。

例えば戻り値のないメソッドで return true と書いた場合、alt+enterで戻り値のあるメソッドに変更してくれる。

もしメソッドがbooleanを返す場合、呼び出し側で .if のように追加してあげると、if文に変更してくれる。

alt+enterを使えば、if文の条件をひっくり返すことも可能。

デザインツール

ナビゲーションエディタ

auto arrangeボタンを使うと、いい感じに整形してくれる。

複数選択して、右クリックで別のナビゲーショングラフに移動させることができる。

レイアウトエディタ

Command+クリックでサンプルデータにも飛べる。

Viewが重なってる時は、左側のツリーでドラッグで移動させるのも手。

リソースマネージャー

画像をレイアウトに放り込むと、ImageViewとして追加してくれる。

レイアウトファイルをレイアウトに放り込むと、includeとして追加してくれる。

なお、上記2つの操作はXMLに対しても行える。すでに配置されているImageViewに対し、別の画像を放り込んだ場合はsrcを書き換えてくれる。

ImageViewで、選択後右側のAttributeのところでマージンの中央の左上(図でないとわからないな。。。)をクリックすると、アスペクト比を保持する設定が追加できる。

ビルドと実行

例えば core プロジェクトを libraries/core に移動させたい場合、何もしないと :libraries:core になっちゃう。しかし settings.gradle で、次のように書けば :core のまま使うことができる。また、名前も好き勝手に変更できる。

include ':app'
include ':core-lib' // フォルダ名はcoreだが、core-libとして使おう

project(":core-lib").projectDir = new File(rootDir, "libraries/core")

アプリやライブラリの build.gradle で、 buildDir = new File(適当なパス) とすると、ビルド時のフォルダ指定ができる。例えば高速なディスクを使いたい時とかに有効(かなりマニアックな気がする)。

マルチモジュールで、ライブラリの依存関係をハードコードした場合、アップデートする時に全部手作業で直す必要があるので危険。その場合は library_versions.gradle ファイルをトップに作り、次のように記述する。

def androidx = [:]
androidx.appcompat = 'androidx.appcompat:appcompat:1.0.2'

ext.libs = [:]
ext.libs.androidx = androidx

そしてルートにある build.gradle で、次のようにapplyする

buildscript {
    apply from: 'library_versions.gradle'
    repositories {
        google()
    }
    // 以下はそのまま
}

こうすると、アプリ側とかのdependenciesが次のように書ける。

dependencies {
    implementation libs.androidx.appcompat
}

どのライブラリがどの依存関係なのかを調べるには、File→Project StructureのDependenciesで確認できる。

ビルド速度を高めよう。理想は修正なしでリビルドした場合、全タスクがUP-TO-DATEになること。例えば buildConfigField()で、値に日付を使っちゃったりすると、毎回ビルド時に変更しないといけなくなっちゃう。

Apply Changesを使おう。Instant runとは違うアプローチになっている。

ブレークポイントでとめて、バグに気づいて修正。Apply codeで変更を適用したあと、Drop frameしてメソッド呼ぶ前に戻すと、なんとそこから再開できる。

Google I/O 2019: What's New in Android Studio UI Design and Debugging Tools

Android Studio使いこなそうシリーズを先に解説。講演やるので。

youtu.be

このセッションは、UIデザインのためのAndroid Studioの使い方編。

レイアウトエディタ

BlueprintModeを使ってみよう。コンテキストメニュー(右クリック)を使うと、例えば「中央に配置」といった制約の追加が簡単にできるよ。

RecyclerViewは、中身を動的に作るのでレイアウトエディタではデフォルトではショボイ表示しか確認できない。そこで登場するのがdesign tool attribute。 tools: で始まる属性。

まずはRecyclerViewの上で右クリック。するとサンプルデータの表示が簡単にできる。

Viewが重なっているとき、レイアウトエディタでドラッグで制約を追加するのは超困難。なのでコンテキストメニューで制約が追加できるように。またドラッグした対象が重なっている場合、「どのViewに対して」制約を追加するかメニューがでるようになった。

また、コンポーネントツリーでも右クリックで制約を追加できるようになった。ドリルダウンでどんどん選んでいく感じ。

Viewを選択したとき、右に表示されるAttribute panelもデザイン一新。属性の追加が割と簡単にできるようになった。操作感はChromeのDev toolsでCSSのプロパティを追加していくのに近い感じ(伝わるかな。。)

マージンを設定する場面で、 @dimen/xxxx によるカスタムディメンションが設定できるようになった。今までは8/16/24といった数値のみだった。

ImageView用のサンプルデータにcitiesが追加。

ナビゲーションエディタ

レイアウトにNavHostFragmentを貼り付けたあと、エディタ上でダブルクリックでナビゲーションエディタに飛ぶように。

遷移先の画面のFragmentはナビゲーションエディタからぱぱっと作れる。

遷移先のFragmentが引数を要求する場合、 Arguments のところで引数を追加できる。これはType-safeになる。

呼ぶときはこんな感じ(動画より)

holder.item.setOnClickListener {
    val action = WelcomeFragmentDirections.actionTripToDetails(tripId)
    Navigation.findNavController(holder.item).navigate(action)
}

リソースマネージャー

Androidのリソースフォルダは、ユーザー(開発者)のためではなく、どちらかというとOSのための構成になってる。さらにAndroid Studio上では単なるファイルなので、中身をいちいち開いて確認しないといけない。

これをなんとかしたいので、Android Studio 3.4でリソースマネージャーが追加された。

リソースのインポート

デザイナーから素材をもらうと

  • フォルダの先頭にdrawable- がついていない
  • ピクセル密度の指定が、ファイル名に @2x などをつけるスタイル(Web formatと呼んでた)

だったりする。ファイルやフォルダ名をAndroidスタイルに変更するのは苦痛なので、これらをリソースマネージャにドラッグ&ドロップするだけで、空気を読んでインポートしてくれるようになった。

インポート時はダイアログが表示され、より細かくインポート時の指定ができる。例えば言語を指定したりとか。

また、今まではSVGのインポートは1つずつしかできなかったが、これもまとめてドラッグ&ドロップでインポートできるようになった。

画像リソースをダブルクリックすると、ピクセル密度や言語毎にどれが使われるかが表示される。

レイアウトファイル

レイアウトXMLもリソースマネージャーで扱ってくれる。レイアウトエディタとの連携もあり、リソースマネージャーからレイアウトXMLをドラッグ&ドロップすると、そのレイアウトに <include> で追加してくれる。

同様に、drawableをレイアウトに対してドラッグ&ドロップすると、ImageViewとして追加してくれる。

レイアウトインスペクタ

レイアウトインスペクタ自体はちょっと前に追加されたもので、実行中のレイアウトを見ることができる。Android Qではインスペクタのための機能が追加されており、いい感じに確認できるように。例えば android:id@+id/xxxx スタイルで表示されたりとか。

今までは属性が全部まとめて表示されていたが、新しいインスペクタでは開発者が設定したものがグループわけされて表示されるようになる。「どれを設定して、どれがデフォルトのままか」が一目瞭然に。

今までのレイアウトエディタはスナップショットをとっている感じだったが、新しいインスペクタは「ライブの」データになった。なので端末側のリストをスクロールすると、インスペクタ側もあわせてスクロールする。

新機能として、ビューの階層を3D表示。たしかXcodeにも同様の機能があったはず。例えば背景色をどのViewが設定してるのかを確認するのにとても役立つ。

Android Qに関して

どちらかというとAndroid Studioのために追加されたAPI群。

  • Skia Picture
  • Fast Property Reading
  • Style Resolution Stack