[Android] ServiceとWindowManagerを使って常駐アプリを作成

アプリ画面に常駐するアイコンやCPU情報の表示などは、ServiceとWindowManagerで作成できますが、Android6.0からPermissionによるユーザーの許可が必要になりました。

system_alart_window_1
system_alart_window_2

Android Studio 2.1.2
Android 6.0

 

sponsored link

SYSTEM_ALERT_WINDOW

 
常駐アプリのためにSYSTEM_ALERT_WINDOWのPermissionの設定が必要ですが、SYSTEM_ALERT_WINDOWによるとAPI23以上では明示的なユーザー許可を「permission management screen」から取得しないといけないようです。

intent action ACTION_MANAGE_OVERLAY_PERMISSION を投げて、 Settings.canDrawOverlays() から許可の有無を確認するようにします。

 
「他のアプリに重ねて表示を許可」を尋ねる表示が出てきます。
 
system_alart_window_1
 

WindowManager.LayoutParams

 
Androidの表示レーヤーはたくさんあり、それぞれ情報のpriorityによって上位から設定されています。以下レイヤー表示例
スクリーンショット 2016-07-01 13.58.36

  • システムエラーが表示される最上位レイヤー
  • TYPE_SYSTEM_OVERLAY
  • ロック画面
  • TYPE_STATUS_BAR
  • TYPE_SYSTEM_ALERT
  • TYPE_PRIORITY_PHONE
  • TYPE_TOAST
  • TYPE_PHONE
  • 通常のアプリが表示されるレイヤー

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

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

 

startService()

 
常駐するアプリとするためにServiceのstartService()を使います。
常駐するものとしてImageViewのアイコン(少々大きめですが)にしました。

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

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

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

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

service_layer.xml

 
User Permissionの設定とServiceの記述をしておきます。
AndroidManifest.xml

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

system_alart_window_2
[モデル 河村友歌]
 

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