search
LoginSignup
33

More than 5 years have passed since last update.

posted at

updated at

AndroidでViewを他のアプリの上に表示する (APIバージョン別 対応方法まとめ)

久しぶりにAndroidのコードを書いていたら、ビューを他のアプリに重ねて表示しようとして盛大に躓いたのでメモ。
要点だけ抜き出しているので、細かなコードは参考サイトとして挙げているリンク先を参照のこと。

Android 4.0 ~ 5.0 (APIレベル 14~22)

  • AndroidManifestにパーミッションを記述する
AndroidManifest.xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  • WindowManager#addViewする

LayoutParams生成時のレイヤータイプ(コンストラクタのint _type変数)に、WindowManager.LayoutParams.TYPE_SYSTEM_ALERT を渡す。

参考サイト : 画面上にアプリの情報を常時表示する

Android 6.0 ~ 7.1.1 (APIレベル 23~25)

Android 5.0までの対応に加えて以下の対応が必要。

  • RuntimePermissionに対応させる

APIが更新され、一部のパーミッションは個別にユーザが許可を出すことを求められるようになった。

まずは、Settings#canDrawOverlays を呼び出して、アプリの権限をチェックする。

権限がない場合は、オーバーレイ権限を変更する為の画面を呼び出す。
Intentには Settings.ACTION_MANAGE_OVERLAY_PERMISSION と、自アプリのパッケージ名を指定する。
(ユーザに対して表示して、利用開始時に権限設定を許可してもらう)

権限設定画面から自アプリに制御が戻ったら再度権限を確認し、権限が有効になっていたらAndroid 5.0までと同じ方法でビューを追加する。

参考サイト : MarshmallowでSYSTEM_ALERT_WINDOWの権限の扱いが変わった

Android 8.0 ~ (APIレベル 26~)

Android 7.1.1までの対応に加えて以下の対応が必要。

  • WindowManagerでTYPE_APPLICATION_OVERLAYレイヤーを使う

APIが更新され、TYPE_SYSTEM_ALERTレイヤーは利用できなくなった。
よって、今まで通りのレイヤータイプ WindowManager.LayoutParams.TYPE_SYSTEM_ALERT を使用するとエラーとなる。
(下記の例外が発生する。この例外で検索しても情報が見つからなくて困った)
java.lang.RuntimeException: Unable to start service com.example.app.TestService@57b8b88 with Intent { cmp=com.example.app/.TestService }: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@4938b2b -- permission denied for window type 2003

これを回避する為にはAPIレベルが26以上の場合に、LayoutParams生成時のレイヤータイプに WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY を渡すようにする。

参考サイト : Android O で WindowManager の振る舞いが変わる

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
33