[Android] WindowManagerを使ってServiceから画像を表示させ続ける

他のアプリ画面上にアイコン画像などを表示させることが、ServiceとWindowManagerを組み合わせるとできます。
 
system alart window 2 - [Android] WindowManagerを使ってServiceから画像を表示させ続ける

Android Studio 3.5.3
API 29

 



SYSTEM_ALERT_WINDOW

 
通常、別のアプリが起動すると、当初あったアプリはバックグラウンドに移動させられてしまいます。ここではそのバックグラウンドから画像を表示させて、後から起動したアプリの上にかぶせてみようというものです。
 
Serviceなので確かにバックグラウンドで長期間のタスクを実行してくれますが、システムがユーザーに電池を消費していると知らせたりしますので、アプリをアンインストールされないように注意しましょう。

  • API 23からPermissionによるユーザーの許可が必要
  • API 26からは使えるレイヤーがTYPE_APPLICATION_OVERLAYになりそれまでの上位レイヤーは非推奨
  • API 28からはForeground Serviceでのパーミッシンが必要

 

 

Settings.canDrawOverlays()

 
SYSTEM_ALERT_WINDOWのPermissionの設定が必要です。
SYSTEM_ALERT_WINDOW によるとAPI23以上では明示的なユーザー許可を「permission management screen」から取得します。
 
intent action ACTION_MANAGE_OVERLAY_PERMISSION を投げて、 Settings.canDrawOverlays() から許可の有無を確認するようにします。

 
「他のアプリに重ねて表示を許可」を尋ねる表示が出てきます。
 
system alart window 1 170x300 - [Android] WindowManagerを使ってServiceから画像を表示させ続ける

 

TYPE_APPLICATION_OVERLAY

 
Androidの表示レーヤーはたくさんあり、それぞれ情報のpriorityによって上位から設定されています。以下レイヤー表示例
92a39cb3fb841ae8294f2f309684b43a 300x262 - [Android] WindowManagerを使ってServiceから画像を表示させ続ける

API level 26まではいくつかのレイヤーが使えたのですが、残念ながら使用することは非推奨となりました。代わりにTYPE_APPLICATION_OVERLAYを使います。

  • Critical system windows: the status bar or IME
  • TYPE_APPLICATION_OVERLAY
  • Activity windows

レイヤー表示はWindowManager.LayoutParamsを使って設定していきます。

レイヤータイプとflagsは様々ありますのでWindowManager.LayoutParams Referenceを確認してください。

 

サンプルコード

 
常時表示するアプリとするためにServiceの startService() あるいは startForegroundService() を使い、画像としてImageViewのアイコン(少々大きめですが)にしました。

service 00 100x100 - [Android] WindowManagerを使ってServiceから画像を表示させ続ける
Servce はバックグラウンドで作業をさせたい場合に使います。システムは直ぐにスリープに入れてしまいます。それでも裏で色々やりたい場合...

また、startしたServiceは停止させるようにしておかないとトラブルになりますので、この常駐アイコンをタッチすることにより停止できるようにします。

API 28からforeground Serviceを使う場合はPermissionをAndroidManifestに記述する必要があります。Foreground_Service | Manifest.permission
 
MainActivity.java

 
Serviceが呼ばれたら、WindowManagerにViewを追加して表示させます。
TestService.java

 
MainActivityのレイアウトでは、サービスを起動するだけのボタンをとりあえずつくっておきますが、なくてもできないことはありません。
activity_main.xml

 
常駐するアイコンなど、OverlayするViewのレイアウトを作成します。今回はテストのためちょっと大きめの画像を張り付けてみます。

service_layer.xml

 
strings.xml

 
user-permissionとServiceの記述をしておきます。

AndroidManifest.xml

 
Permissionを許可した後に、Serviceをスタートするとアイコンが表示されて、他のレイヤーの上位にいることがわかります。
 

 
startService()の場合は、しばらくするとシステムから終了させられてしまいます。startForegroundService()を使うとアプリ終了してもstatus barにアイコンが表示されてForegroundにあるアプリのようになり、シツコイ感もあります。尚、startForegroundService()はOreoからなので切り分けが必要です。
 
[モデル 河村友歌]
 
 
関連ページ:

 
References:
WindowManager.LayoutParams
SYSTEM_ALERT_WINDOW
ACTION_MANAGE_OVERLAY_PERMISSION
canDrawOverlays(android.content.Context)
 

誤字脱字、意味不明で分からにゃイ、
などのご意見はこちらから mailフォーム

ブックマークしておくと便利です このエントリーをはてなブックマークに追加

アプリ開発が上達するお勧め

アプリ開発を始めたけどわからないところがあり、誰かに聞きたいけど周りにはそんな人はいない…あるいは、会社で働いていて日中そんなに時間をとれないなど、オンラインのプログラミングスクールがいいでしょう。

オンラインスクールは色々ありますが、以下の3つはAndroidが学習できる老舗スクールです。


TECH ACADEMY
Androidアプリコース


こういうものではアプリ作れないと言う意見もありますが、それは結局本人のやる気があるかないかです。やる気があっても独学では突破しにくいところは教えてもらうのが一番早い。


侍エンジニア塾
侍エンジニア塾 無料体験レッスン


とても簡単なことなのに本やネットの画像だけでは分かりにくいことはあります。実際に質問してピンポイントで教えてもらうと、なんだそんなこと、と言うのがけっこうあります。


CodeCamp
~約8,000名の受講生と80社以上の導入実績~
現役エンジニアのオンライン家庭教師CodeCamp




直接(ネットで)誰か分かる人に聞いた方が早く解決して、上達も早いと思います。




シェアする

  • このエントリーをはてなブックマークに追加

フォローする