表示レイヤーについて

アプリケーション開発だけを行っていると、システム全体の表示レイヤーを意識しないと思います。
あらためて表示レイヤーの確認を行います。


確認OSバージョン

Android OS 2.3 GingerBread


レイヤーの宣言場所

各レイヤーの宣言場所はこちら。
\frameworks\policy\src\com\android\internal\policy\impl
- PhoneWindowManager.java
windowTypeToLayerLw()でwindowTypeから各レイヤー値に変換します。

レイヤー名 用途
2 WALLPAPER_LAYER 壁紙
2 APPLICATION_LAYER 一般アプリケーション
3 PHONE_LAYER 着信などの電話用
4 SEARCH_BAR_LAYER 検索バー
5 STATUS_BAR_PANEL_LAYER StatusBarをexpandしたパネル
6 SYSTEM_DIALOG_LAYER 電源OFFダイアログなど
7 TOAST_LAYER トースト表示
8 STATUS_BAR_LAYER StatusBar
9 PRIORITY_PHONE_LAYER SIMエラー表示など
10 SYSTEM_ALERT_LAYER ANRやLowバッテリー通知
11 SYSTEM_ERROR_LAYER システムエラー通知
12 INPUT_METHOD_LAYER 文字入力UI
13 INPUT_METHOD_DIALOG_LAYER 文字入力UIのダイアログ
14 KEYGUARD_LAYER キーガード表示
15 KEYGUARD_DIALOG_LAYER シャットダウン中やSIMロック表示、キーガード表示中の電源OFFダイアログなど
16 SYSTEM_OVERLAY_LAYER キーガードより上位に表示するシステムオーバーレイ※1
17 SECURE_SYSTEM_OVERLAY_LAYER ※2

※1
アプリケーションでも使用可能。ただし、キーガードと干渉するためこのレイヤーにはフォーカスを与えてはいけない。


※2
システムのみ使用可能

SYSTEM_OVERLAY_LAYERについて

ちょっと気になったので調べてみました。
WindowManagerからセットするときは、以下のパラメータを指定。

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY


Activityから"TYPE_SYSTEM_OVERLAY"をセットしても、キーガードの上位に表示されませんでした。
おそらく、PhoneWindow( = DecorView)が影響してるかも。

以下のようにServiceからaddViewするとうまく表示されました。
ただし、ServiceがKillされると当然、表示も消えます。

public class DialogTestService extends Service {

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public void onStart(Intent intent, int startId) {
        LayoutInflater layoutInflater = LayoutInflater.from(this);
        View view = layoutInflater.inflate(R.layout.main, null);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        	    WindowManager.LayoutParams.WRAP_CONTENT,
        	    WindowManager.LayoutParams.WRAP_CONTENT,
        	    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
        	    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
        	    PixelFormat.TRANSLUCENT);

    	WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    	wm.addView(view, params);    
	}
}