WindowManager解析(二)Androidサスペンションが入力方式をポップアップできない理由とサスペンションウィンドウを表示する権限がない

11041 ワード

Androidサスペンションは入力をポップアップできません
最近、懸濁窓の方面のものを研究して、1つの問題に出会って、私の懸濁窓の中に入力ボックスがあって、しかし入力法を弾き出さないで、それから1つの方法を見つけました:
WindowManagerのインスタンスの取得方法が正しくありません.以前は次のように取得されていました.
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

このように変更します.
mWindowManager = (WindowManager) 
mContext.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

1つは、現在のactivityのコンテキスト環境を介してウィンドウサービスを取得することであり、1つはアプリケーションを介してウィンドウサービスを取得することである.
発見はやはりだめで、それから私は長い時間をかけてグーグルでWindowManagerのソースコードの英語の注釈を翻訳してやっと発見して、もとは私は前に使ったのです:
                bigWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

LayoutParams.FLAG_NOT_TOUCH_MODALの意味は:
        /**
             :          ( #FLAG_NOT_FOCUSABLE   ),
                              。
                       ,           。
          */
        public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020;

つまり、後ろのクリックイベントをブロックしません.
LayoutParams.FLAG_NOT_FOCUSABLEの意味は:
        /**
             :             ,                  。
                          。
                #FLAG_NOT_TOUCH_MODAL      。
         *
         *
                                 ,
              Z-              (               Z-  ,
                     ,             。
             {@link #FLAG_ALT_FOCUSABLE_IM}       。
         * */
        public static final int FLAG_NOT_FOCUSABLE      = 0x00000008;

このウィンドウはソフト入力方式と対話する必要がなく、入力ボックスがポップアップされないことを説明し、これを外すと入力方式が正常に表示されますが、削除するともう一つの問題が発生します.それはシステムの戻りキーが使えないことです.
WindowManagerにEditTextを直接追加して文字を入力できるようにするには、次の2点を保証する必要があります.
タイプはLayoutParamsTYPE_SYSTEM_LayoutParamsではなくALERTTYPE_SYSTEM_ERROR
3つのボタンがない問題を防ぐflagにWindowManagerがないLayoutParams.FLAG_NOT_FOCUSABLE
入力ボックスがポップアップできない問題を防ぐflagにWindowManagementが必要です.LayoutParams.FLAG_NOT_TOUCH_MODAL
下のappでフォーカスやイベントが取得できない問題を防止
ソースコードの注釈を翻訳するのにこんなに時間がかかったのはメリットがあるようです.少なくともこの属性を使うのはなぜか知っています.ソースコードをよく勉強するには、ソースコードをもっと見て、注釈を翻訳しなければなりません.
アクセス権なしでサスペンションを表示
サスペンション窓の原理
浮遊窓機能をしたことがある人なら誰でも知っていますが、浮遊窓を表示するには、バックグラウンドでサービスを実行し、getSystemService(Context.WINDOW_SERVICE)でWindowManagerを入手し、addView、addViewの2番目のパラメータはWindowManagementです.LayoutParams, WindowManager.LayoutParamsにはメンバーtypeがあり、様々な値があり、一般的にTYPE_に設定されています.PHONEは多くのviewの上に浮かぶことができますが、この方法を呼び出すにはandroidを申請する必要があります.permission.SYSTEM_ALERT_WINDOWの権限は、多くの機種では、この権限の名前は懸濁窓と呼ばれています.例えば、小米の携帯電話ではデフォルトでこの権限を無効にしています.悪意のあるappでは、この権限で広告を弾くことがあります.そして、どのアプリケーションが弾いたのかを追跡するのは難しいです.この権限が無効になった場合、結果的には懸濁窓が表示されません.例えば、辞書のコピー検索機能があり、小米の携帯電話ではよく役に立たないが、実際にはユーザーに権限がなく、アプリケーションもユーザーに権限を開くように導いていません.
TYPE_の使用TOASTではフロートを表示できます
type値をWindowManagerとするLayoutParams.TYPE_PHONEとWindowManager.LayoutParams.TYPE_SYSTEM_ALERTはandroidを申請する必要がある.permission.SYSTEM_ALERT_WINDOW権限、そうでなければ表示できません.エラーを報告します.
E/AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRoot$W@b64b5458 -- permission denied for this window type

ただし、typeをTYPE_に設定TOASTはやはり奇効があり、androidは必要ありません.permission.SYSTEM_ALERT_WINDOWの権限で懸濁窓が表示されます.
の原因となる
Androidソースには、
public int checkAddPermission(WindowManager.LayoutParams attrs) {
    int type = attrs.type;

    if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
            || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
        return WindowManagerImpl.ADD_OKAY;
    }
    String permission = null;
    switch (type) {
        case TYPE_TOAST:
            // XXX right now the app process has complete control over
            // this...  should introduce a token to let the system
            // monitor/control what they are doing.
            break;
        case TYPE_INPUT_METHOD:
        case TYPE_WALLPAPER:
            // The window manager will check these.
            break;
        case TYPE_PHONE:
        case TYPE_PRIORITY_PHONE:
        case TYPE_SYSTEM_ALERT:
        case TYPE_SYSTEM_ERROR:
        case TYPE_SYSTEM_OVERLAY:
            permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
            break;
        default:
            permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
    }
    if (permission != null) {
        if (mContext.checkCallingOrSelfPermission(permission)
                != PackageManager.PERMISSION_GRANTED) {
            return WindowManagerImpl.ADD_PERMISSION_DENIED;
        }
    }
    return WindowManagerImpl.ADD_OKAY;
}

この方法はシステムのWindowManagerにaddViewをするときに権限チェックをするためのもので、そのtypeは私たちがWindowManagerを構築しています.LayoutParamsで付与されたtypeは、TYPE_を除いてTOASTは、他にも権限が必要で、コードの注釈は、開発者を制限するためにマークを導入すべきだと言っています.
互換性
  • type値はWindowManagement.LayoutParams.TYPE_TOASTに表示されるSystem overlay viewは、権限を必要とせず、どのプラットフォームでも表示できます.
  • ですが、APIレベル>=19でのみ目的を達成できます.APIレベル19以下は、タッチ(クリック)やキーを受信できないイベントを受信できないため、目的を達成できない.
  • API level<19のマシン(MIUIを除く)について、目的を達成するには、
  • が必要です.
    androidが必要だpermission.SYSTEM_ALERT_WINDOW権限typeをWindowManagerに設定LayoutParams.TYPE_PHONEまたはWindowManager.LayoutParams.TYPE_SYSTEM_ALERT MIUI V5
    懸濁窓に権限を与えた後、同じ3を表現します.ただし、浮遊窓に権限を与えない場合、フロントに適用した場合は表示できます.この点はとても違います.
    なぜTYPE_を採用するのかTOAST
    APIレベル19以降、TYPE_SYSTEM_ALERTでTYPE_にSYSTEM_ALERT効果.
    しかし、APIレベル23(Android 6.0)では、懸濁窓の権限も単独で出てきており、単独で開く必要があります.この処理は現在のSmartisanや小米と似ています.
    よってTYPE_を採用TOASTは、ルーフを開かない権限で表示させることができます.要求権限をできるだけ少なくするためだ.
    なぜAPIレベル19以降TYPE_TOASTはイベントを受け入れることができます
    PhoneWindowManager.adjustWindowParamsLw()は、APIレベル19の後に調整された.
    TYPE_を使うとTOAST、AndroidはこっそりFLAGを追加してくれます.NOT_FOCUSABLEとFLAG_NOT_TOUCHABLE、4.0.1から、FLAGを追加で削除します.WATCH_OUTSIDE_TOUCH. これで本当に何の事件もなくなった.
    そして4.4からTYPE_TOASTは削除されました.だから4.4からTYPE_を使いますTOASTはタッチイベントとキーイベントを同時に受信できるようになったが,4.4以前は表示のみでインタラクションはできなかった.
    眠れず起きられない万さんからのAndroidサスペンションはTYPEを使用TOASTのまとめ
    最後に
    TYPE_TOAST       ,    TYPE_TOAST      2.3         ,           .
                            ,                         Dialog,          Activity  Dialog,   Activity      20 Dialog,       .      Dialog      Window Type     Activity  ,                         .
      WindowType WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,         , MIUI     (     ,       )    .        WindowManager.LayoutParams.TYPE_TOAST,       ,MIUI     ,       ,      .         2.3         ,     Dialog        ,         ,     .        Type       ,     :TYPE_SEARCH_BAR:   
    TYPE_ACCESSIBILITY_OVERLAY:     
    TYPE_APPLICATION:     Activity   APP  TYPE_APPLICATION_ATTACHED_DIALOG:     Activity   APP  
    TYPE_APPLICATION_MEDIA:     (      )
    TYPE_APPLICATION_PANEL:     Activity   APP  (PopupWindow      Type)
    TYPE_APPLICATION_STARTING:     (      )
    TYPE_APPLICATION_SUB_PANEL:     Activity   APP  TYPE_BASE_APPLICATION:     (      )
    TYPE_CHANGED:     Activity   APP  
    TYPE_INPUT_METHOD:     (    )
    TYPE_INPUT_METHOD_DIALOG:     (    )
    TYPE_KEYGUARD_DIALOG:     
    TYPE_PHONE:      (     Activity    HOME                 )
    TYPE_TOAST:       ,         ,     Android2.3         
    TYPE_SYSTEM_ALERT:      ,       

    その他の実戦記事
    あなたのappはシステムのスクリーンショットの探究を使うことができません
    銀聯のように、あるActivityで携帯電話がスクリーンを切ることができず、adbも手に入らないようにするには、Activityに参加することができます.
    getWindow().addFlags(WindowManager.LayoutParams. FLAG_SECURE);
    ソース:
            /**
                 :           ,                       。
    
                               ,   android.view.Display#FLAG_SECURE。
             */
            public static final int FLAG_SECURE             = 0x00002000;

    参考記事
  • Androidはリフト窓を表示する権限を必要とせず、逆分析app
  • を兼ねている.
  • AndroidサスペンションTYPE_TOAST小結:ソース分析
  • Android懸濁窓の小結
  • Androidプロジェクト:入力方式ソフトキーボード表示/非表示の傍受と制御、InputMethodManager用法研究
  • Activity,Service,Windowでホームキーとリターンキーのいくつかの思考を傍受し、イベントをどのように伝えるか!
  • AndroidサスペンションでEditTextがフォーカスを取得できない/フォーカスを取得した後にキーが機能しないという問題
  • overlays-floating-window-like-facebook-messenger
  • WindowManagerを使用してAndroidサスペンション
  • を実現