はじめに
- 簡単なAndroidアプリを作りたく、クイック設定タイル(以下,タイル)を使おうとしました。
- 基礎練習として、デフォルトのタイルの並びに自作タイルを追加し、自作タイルの適当なライフサイクルでログを出力するだけのアプリを製作しました。
- クイック設定タイル開発については、その筋の人々にとってあまりにも簡単すぎるのか、それともクイック設定タイルを作ろうなんて奴はいないのか、ググっても情報が少なく、はまったポイントがあったため、備忘録と情報共有を兼ねて記事にします。
- ド初心者向けのタイルのHello Worldのつもりです。
クイック設定タイルとは
Androidスマホを上からスワイプしたときに降りてくる、通知の上に並んでいるボタンたちのことです。
設定アプリを開かずに、素早くWi-Fiの接続先を選択したり、BluetoothをON/OFFしたりできるあれです。
製作手順
- TileServiceを継承したクラスを作ります。
- AndroidManifest.xmlにて、1で作ったクラスをTileの仲間に入れてくれるようにお願いします。
以上、たった2ステップでとりあえず動くものができます。
TileServiceを継承したクラス
class BrightnessSwitchTileService: TileService() {
override fun onClick() {
super.onClick()
Log.d("BSTS","onClick")
}
override fun onStartListening() {
super.onStartListening()
Log.d("BSTS","onStartListening")
val qsTile = getQsTile()
qsTile.state = Tile.STATE_ACTIVE
qsTile.updateTile()
}
override fun onStopListening() {
super.onStopListening()
Log.d("BSTS","onStopListening")
}
}
簡単な説明
- クラス名 BrightnessSwitchTileServise
最終的に、画面輝度を変更するタイルを作りたいのでこの名前にしましたが任意です。
-
onClick
タップ時に呼ばれます。
-
onStartListening
上からスワイプして、タイルが降りてきたときに呼ばれます。
-
onStopListening
タイルが画面から消えた時に呼ばれます。
-
qsTile
名前は任意です。 getQsTile() でタイルそのものを取得し、プロパティを読み書きして、タイルの状態を変更できます。
プロパティは、state(タップできる、かつ、設定ON・タップできる、かつ、設定OFF・タップできない、の3通り)の他にも、label(表示される文字)やicon(そのままアイコン)などが変更可能です。
プロパティを変更しただけでは、タイルそのものは変わらず、 updateTile() を呼ぶことで反映されます。
実装時のおおまかな流れ
Bluetoothのタイルを例に説明します。
- onStartListening 内で、タイルの初期設定を行う。(このアプリにBluetoothのON/OFFを切り替える権限があるかチェック。権限があればさらに現在ONかOFFかチェック。結果に合わせてstateをset。)
- onStartListening 内で、タイルタップによって変更される状態(BluetoothがONかOFFか)を監視して、変わったときにタイルのstateを変更するやつ(ContentObserverで調べてください)を起動する。
- onClick で、タップした時の動作を指定する。(BluetoothのON/OFF切り替え処理)
- stopListening 内で、状態が変わったときにタイルのstateを変更するやつを停止する。
以上
AndroidManifest.xmlの修正
AndroidManifest.xml に作ったTileServiceを追加します。
<service
android:name=".BrightnessSwitchTileService"
android:exported="true"
android:label="@string/default_tile_label"
android:icon="@drawable/baseline_light_mode_24"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
nameは作ったTileServiceのクラス名です。
私はここでしばらくはまりました。
ポイントは exported です。
Android Developersにタイルを作る場合の大まかな手順があり、このブロックもほぼ丸コピですが、コピー元には exported がないのです。
Andoroid 12より、この場合 exported が必須となっており、明記しない場合はコンパイル不能、falseではコンパイルは通るが実行すると java.lang.SecurityException: Not allowed to bind to service Intent を吐いて落ちるという挙動となります。明記が必須となったことは知っていましたが、 exported で指定するところの「他のアプリから起動できる/できない」とはどういうことか、を理解していなかったため、falseにしていました。
タイルは、「タイルを管理する他のアプリ」がこの自作サービスを起動する形のため、 exported が true でなくてはならないというオチでした。
動作確認
ここまで来たらとりあえず動くと思います。
タイルを追加、タップしてログが出ることを確認しましょう。