ホーム画面でワイヤレスイヤホンやキーボードのバッテリー残量をパッと確認したくてウィジェット作りに挑戦したけれど、権限や省電力制限でつまずいてしまった経験はありませんか。
この記事では実際に動くAndroidウィジェットをステップごとに作りながら、Bluetooth機器のバッテリー情報を定期取得して表示する方法をわかりやすく紹介します。権限周りの扱い方やBLEとクラシックの違い、省電力への配慮といった現場で役立つコツも丁寧に解説します。
| 項目 | 内容 |
|---|---|
| 独自コンテンツ1 | 実践的な手順で必要なコードと設定がそのまま使える形で手に入ります。 |
| 独自コンテンツ2 | 実際に遭遇したトラブル例と具体的な直し方で迷わず先に進めます。 |
| 独自コンテンツ3 | テストやデバッグの工夫を紹介するので安定して動くウィジェットを作れます。 |
まずはサンプルを動かして少しずつ自分の機器に合わせて調整していきましょう。途中で立ち止まっても読み返せば復習できるように書いてあります。
Android博士分からないところがあっても大丈夫です。落ち着いて一つずつ進めれば必ず動かせますから気楽に試してみてください。
AndroidウィジェットでBluetooth機器のバッテリー残量を定期取得して表示する方法


ウィジェットでBluetooth機器のバッテリー残量を定期取得して表示するには、実用的なパターンがいくつかあります。端末の種類やOSバージョンで使える手法が変わるため、目的に合わせて柔軟に選ぶと失敗が少ないです。
ここでは代表的な3つの流れをわかりやすく紹介します。BLEのBattery Serviceを直接読む方法、システム通知を拾う方法、ウィジェットごとに表示デバイスを選べる設定画面を作る方法です。



まずは小さなハードで試してみると理解が早いです。失敗してもリトライ方法を一緒に用意すれば安心して進められますよ。
BLEのBattery Serviceからバッテリーを読み取ってウィジェットに反映するパターン


BLEのBattery Serviceは標準化された手段でバッテリー値を提供します。対応機器ならGATTでBattery Serviceを見つけてCharacteristicを読むだけで済むので実装が素直になります。
注意点はスキャンとGATT接続の電力消費と接続数制限です。WorkManagerで実行間隔を控えめにし、接続後は速やかに切断する運用にすると実用的になります。
AppWidgetProviderのonUpdateでWorkManagerのPeriodicWorkを登録する場所と手順
onUpdate内でWorkManagerに登録するPeriodicWorkRequestを作ります。短周期は避けて最小でも15分以上に設定し、Constraintsで条件を調整します。
enqueueUniquePeriodicWorkを使って既存のWorkと衝突しないようにします。既にある場合は置換するか保持するかを選んで二重実行を防ぎます。
ウィジェット配置時と端末再起動時に確実に登録するようにします。アプリ起動時に保険で確認するのも有効です。
Work内でBluetoothLeScannerで該当デバイスをスキャンしBluetoothGattでBattery Serviceを読み取る具体的な手順
Work内でBluetoothLeScannerを短時間だけ動かし、フィルタで該当デバイスを絞って検出します。長時間のスキャンは避けてバッテリーを節約します。
発見したデバイスにBluetoothGattで接続し、onServicesDiscoveredでBattery Service(UUID)を探します。サービス検出後にCharacteristicを読みます。
readCharacteristicで値を取得したら速やかにgatt.disconnectとgatt.closeを呼んでリソースを解放します。タイムアウト処理も入れておくと安心です。
取得したバッテリー値をRemoteViewsでウィジェットに反映する具体的なコードの配置場所
Worker内でAppWidgetManagerを取得し、対象のappWidgetIdに対するRemoteViewsを生成します。WorkerはUIスレッド外なので注意します。
setTextViewTextでパーセント表示やアイコン切替を行い、updateAppWidgetでウィジェットを更新します。複数ウィジェットがある場合は個別に処理します。
画像生成など重い処理は避け、できるだけ簡潔な表示更新にしてユーザー体験を維持します。
ペアリング済みオーディオ機器からシステム通知でバッテリーを受け取るパターン


ペアリング済みのオーディオ機器はシステム側でバッテリー情報を通知してくれる場合があります。Androidは機器側からの情報をブロードキャストで流すことがあるため、これを受け取ればスキャンを省略できます。
ただし機種依存やOSバージョン差があるので、受信できない場合に備えてBLE読み取りのフォールバックを用意しておくと確実です。受信時にウィジェット更新をトリガーすると効率的です。
BroadcastReceiverでBluetoothDevice.ACTION_BATTERY_LEVEL_CHANGEDを受け取る登録場所と実装のやり方
常時受け取りたい場合はManifestに登録する方法もあるが、省電力制約で制限されることがあるため、必要に応じて動的登録を使い分けます。
onReceiveでIntentのEXTRA_BATTERY_LEVELなどを確認してバッテリー値を取得し、該当ウィジェットを更新する処理へ渡します。nullチェックは忘れないでください。
不要な権限を要求しないことと、受信内容の正当性を確認することがセキュリティ上重要です。
BluetoothProfileを使って接続済みデバイス一覧を取得しバッテリー値を問い合わせる実践手順
BluetoothAdapter.getProfileProxyでA2DPやHEADSETなどのプロキシを取得し、サービス接続のコールバックで準備完了を待ちます。
プロキシのgetConnectedDevicesで接続中のBluetoothDeviceを列挙し、それぞれについてバッテリー情報の有無を確認します。
高レベルAPIでバッテリーが取得できればそれを使い、得られない場合はGATTでBattery Serviceを読むフォールバックを行います。
ウィジェット個別に表示するデバイスを選べる設定画面を作るパターン


ウィジェットごとに表示デバイスを選べる設定画面を用意すると便利です。ユーザーは表示したい機器を選ぶだけでよく、複数ウィジェットで別々の機器を監視できます。
選択情報をappWidgetIdに紐づけて保存し、WorkerやBroadcastReceiverはその設定を参照して更新する流れにすると実運用で扱いやすくなります。
AppWidgetの設定画面ActivityでBluetoothDeviceを選択しSharedPreferencesに保存してappWidgetIdに紐付ける手順
設定ActivityでBluetoothAdapter.getBondedDevicesや短時間のBLEスキャン結果を一覧化してユーザーが選べるUIを用意します。
ユーザーが選んだデバイスのアドレスをSharedPreferencesに’widget_
setResultでappWidgetIdを含むIntentを返し、Activityをfinishしてウィジェットの設定を確定します。
実体験に基づく応用で使い勝手を良くする方法


ちょっとした工夫でウィジェットの使い勝手はぐっと良くなります。Bluetooth機器のバッテリー表示を見やすくするために表示順や更新トリガーを整えると日常で役立ちます。
ここでは現場で役立った応用アイデアを分かりやすく紹介します。閾値通知や一覧化、更新最適化などを組み合わせると実用性が高まります。



まずは小さな変更から試してみてください。表示順や閾値の調整だけでも毎日の確認がぐっと楽になりますよ。
複数のBluetooth機器を1つのウィジェットで一覧表示する応用パターン


複数のBluetooth機器を一つのウィジェットで一覧表示すると管理がとても楽になります。スクロールで切り替えたりフィルタで絞ると目的の機器がすぐ見つかります。
- 優先度で並べる。よく使う機器を上に置くと確認が速くなります。
- フィルタを付ける。イヤホンだけやスピーカーだけを絞ると一覧がすっきりします。
- 簡易ステータスを添える。充電中や接続中のマークを付けると一目で状況が分かります。
RemoteViewsServiceとRemoteViewsFactoryで一覧UIを作りデータソースをWorkManagerと同期する具体的な実装場所
| 項目 | 内容 |
|---|---|
| RemoteViewsService | ウィジェットのListやStack用Serviceとして定義する。AppWidgetProviderからIntentで接続し一覧を返す入口にする。 |
| RemoteViewsFactory | 実際の行ビューを作る場所。データ取得とRemoteViews生成をここで行いWorkManagerの同期結果を参照する。 |
| WorkManager | バックグラウンドでバッテリー情報を定期取得してデータベースやSharedPreferencesに保存する。UIはここを読み込む。 |
低バッテリーをウィジェットと通知で連携して知らせる応用パターン


ウィジェットだけで知らせるより通知と連携すると見逃しが減ります。ウィジェットで閾値チェックを行い条件を満たしたらNotificationCompatで通知を出す流れが使いやすいです。
- 閾値はウィジェットごとに保存する。ユーザーごとにカスタム可能にすると親切です。
- 通知には設定画面へ飛ぶアクションを付ける。すぐ確認や設定変更ができて便利です。
- 通知の重複を避けるために最後通知時刻を保存する。短時間で何度も通知しないよう制御します。
ウィジェット設定で閾値を保存し閾値を越えたらNotificationCompatで通知を出す実装手順
AppWidgetの設定画面やAppWidgetConfigureActivityで閾値を受け取りSharedPreferencesやRoomにウィジェットIDキーで保存する。
WorkManagerやウィジェット更新処理で現在のバッテリー値を読み閾値と比べる。条件を満たしたら通知処理を起動する。
通知チャネルを作成し優先度やアクションを設定してNotificationCompatで表示する。タップで設定画面や詳細へ遷移させる。
ウィジェットのバッテリー消費を抑える更新最適化のやり方


ウィジェットの更新は無闇に増やすと電池を食います。WorkManagerの周期やバックオフを賢く使いDozeやBattery Saverを尊重すると長時間の利用でも安心です。
手動更新ボタンを用意してユーザーが任意で更新できるようにすると普段の負担が減ります。常時短周期にせず必要なタイミングで更新する設計が喜ばれます。
WorkManagerの制約やバックオフを使って更新間隔を調整しDozeやBattery Saverを尊重する設定方法と手動更新ボタンの実装場所
PeriodicWorkRequestに適切な周期を与えsetBackoffCriteriaで再試行の挙動を設定する。Constraintsでバッテリーやネットワーク条件を指定する。
短すぎる周期は避ける。必要なら手動更新に誘導して自動更新は低頻度にするなど端末の省電力機能を尊重する。
ウィジェットレイアウトに更新ボタンを置きPendingIntentでAppWidgetProviderの更新処理を呼ぶようにする。ユーザーがすぐ更新できるようにする。
よくある質問


- ウィジェットに接続されたBluetooth機器のバッテリー表示が更新されない
多くは端末側がバッテリー情報を出していないかアプリに必要なBluetooth権限がないことが原因です。まず接続機器がGATTのBattery Serviceをサポートしているか確認してください。Android 12以降はBLUETOOTH_CONNECTなどの権限が必要なのでマニフェストと実行時権限を見直してください。
- 定期取得を続けるとスマホの電池が減るのが心配
頻繁なスキャンや接続は電池を消費します。WorkManagerで間隔を長めに設定したり、BLEの通知機能が使える場合は通知で変化を受け取る方式にすると負担が減ります。更新はまとめて行うように調整すると安心です。
- ウィジェットをタップして手動で更新できるか
できます。RemoteViewsのクリックでPendingIntentを送ってServiceやWorkerに更新を依頼すると安全に動きます。バックグラウンド制限があるので即時更新ばかりにならないようにしておくと安定します。
- 複数のBluetooth機器を表示したら動作が遅くなった
同時に多数接続すると処理が追いつかなくなりがちです。接続は順次行い結果をSharedPreferencesやRoomにキャッシュしておき、ウィジェット表示はキャッシュから素早く読み出すと体感が良くなります。接続のタイムアウトやリトライも入れておくと安定します。
まとめ


ここまでで、ウィジェットにBluetooth機器のバッテリー残量を表示するための選び方と実装イメージを紹介しました。ポイントは、機器がBattery Serviceを持つか端末側のプロファイルから値を取得できるかを確認し、その上で定期更新の仕組みを用意することです。
- 1.機器のバッテリー情報が取れるか確認する。
- 2.BLEならBattery Serviceを読み、クラシックなら対応プロファイルやシステムAPIを使う。
- 3.AppWidgetProviderでRemoteViewsを用意し、WorkManagerなどで定期更新する。
- 4.接続切れや権限エラーを考慮して値をキャッシュする。
実機での動作確認を必ず行い、スキャンや更新頻度は電池消費を意識して調整してください。WorkManagerを使えば端末側の制限やスリープに強くなります。



最初は小さく作って動かしながら学ぶとスムーズです。困ったときはログを見れば大抵原因が分かりますよ。
Androidの権限とバックグラウンド実行制限に気を付けてください。
