21

ユーザーがステータスバーをスライド(展開)したり、折りたたんだりするのを防ぐ方法はありますか?

ロックスクリーンの交換を試していますが、これは必須の機能のようです。root権限を必要とせずにそれを行うための可能な方法はありますか?

4

8 に答える 8

20

電話を応援しなくても、ステータスバーが拡大するのを実際に防ぐことができます。このリンクを参照してください。これにより、ウィンドウがステータス バーの高さに描画され、すべてのタッチ イベントが消費されます。

onCreate() の直後に次のコードを呼び出します。

public static void preventStatusBarExpansion(Context context) {
    WindowManager manager = ((WindowManager) context.getApplicationContext()
            .getSystemService(Context.WINDOW_SERVICE));

    Activity activity = (Activity)context;
    WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
    localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
    localLayoutParams.gravity = Gravity.TOP;
    localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|

    // this is to enable the notification to recieve touch events
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

    // Draws over status bar
    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

    localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
    //https://stackoverflow.com/questions/1016896/get-screen-dimensions-in-pixels
    int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
    int result = 0;
    if (resId > 0) {
        result = activity.getResources().getDimensionPixelSize(resId);
    }

    localLayoutParams.height = result;

    localLayoutParams.format = PixelFormat.TRANSPARENT;

    customViewGroup view = new customViewGroup(context);

    manager.addView(view, localLayoutParams);
}

public static class customViewGroup extends ViewGroup {

    public customViewGroup(Context context) {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v("customViewGroup", "**********Intercepted");
        return true;
    }
}
于 2015-07-10T20:04:49.947 に答える
18

簡単な答え: これは不可能です。

これが不可能な理由を知りたい場合は、次のようにします。

システム ステータス バーを操作するためのアクセス許可には、EXPAND_STATUS_BARSTATUS_BARの 2 つがあります。前者は任意のアプリケーションから要求できますが、後者はプラットフォーム署名で署名されたアプリケーション (サードパーティではなくシステム アプリケーション) 用に予約されています。システム ステータス バーを展開/折りたたむことは可能ですが( 「Intent を使用してステータス バーを開くまたは展開する方法」を参照)、 StatusBarManagerクラスは SDK の一部ではないため、リフレクションが必要であることに注意してください。ステータスバーが展開されないようにするために Android ダイヤラーによって使用される disable メソッドは、前述の STATUS_BAR パーミッションなしではアプリケーションからアクセスできません。

ソース: 個人的な経験:-)

于 2011-10-02T13:23:32.847 に答える
15

まず第一に、アプリが電話の ROM 認証で署名されていない場合、ステータス バーを変更することは不可能です。変更しようとすると、セキュリティ例外が発生します。

更新: 新しい API では、メソッドは「collapse」ではなく「collapsePanels」です。

数時間の作業の後に私が見つけた唯一の方法は、アクティビティの「onWindowFocusChanged」メソッドをオーバーライドし、フォーカスを失ったときに (ユーザーが通知バーに触れた可能性があります)、StatusBar を強制的に折りたたむことです。コードは次のとおりです。 (Defy+ 2.3.5 で作業中)。

マニフェストで次のアクセス許可を宣言する必要があります。

 <uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/> 

そして、次のメソッドをオーバーライドします。

public void onWindowFocusChanged(boolean hasFocus)
{
        try
        {
           if(!hasFocus)
           {
                Object service  = getSystemService("statusbar");
                Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
                Method collapse = statusbarManager.getMethod(Build.VERSION.SDK_INT > 16 ? "collapsePanels" : "collapse");
                collapse.setAccessible(true);
                collapse.invoke(service);
           }
        }
        catch(Exception ex)
        {
        }
}

更新: アラート ダイアログには独自のフォーカスがあるため、onWindowFocusChanged メソッドもオーバーライドして、独自のカスタム アラート ダイアログを使用する必要があります。

于 2012-04-30T08:22:28.373 に答える
13

これは実際には、私が偶然発見した小さなハックを介して実行できますが、許可が必要android.permission.SYSTEM_ALERT_WINDOWです:

あなたがすることは、ステータスバーをカバーし、タッチイベントの受信を防ぐ特定のパラメーターを使用して、ステータスバーの正確なサイズのビューを WindowManager に直接追加することです。

View disableStatusBarView = new View(context);

WindowManager.LayoutParams handleParams = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.FILL_PARENT,
    <height of the status bar>,
    // This allows the view to be displayed over the status bar
    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
    // this is to keep button presses going to the background window
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
    // this is to enable the notification to recieve touch events
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
    // Draws over status bar
    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
    PixelFormat.TRANSLUCENT);

handleParams.gravity = Gravity.TOP;
context.getWindow().addView(disableStatusBarView, handleParams);

これは基本的に、すべてのタッチ イベントを受信し、イベントがステータス バーに到達するのをブロックするステータス バー上に透明なビューを作成し、したがって展開されないようにします。

注: このコードはテストされていませんが、概念は機能します。

于 2011-10-03T04:20:27.017 に答える
8

GrantLandPoOkで言及されている解決策を試しましたが、私の場合はどちらもうまくいきませんでした。ただし、最近のタスクリストをクリア/非表示にする別のソリューションが私にとってはうまくいきました。ユーザーがロックされたアプリをそこから開けないように、最近のアプリケーション メニューを無効にする必要があるランチャー アプリを作成しています。また、通知バーの拡張を防ぐ必要があり、このトリックにより両方を達成できました。アクティビティでOnWindowFocusChangedメソッドをオーバーライドし、これが必要かどうかを確認します。

public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

        Log.d("Focus debug", "Focus changed !");

    if(!hasFocus) {
        Log.d("Focus debug", "Lost focus !");

        Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        sendBroadcast(closeDialog);
    }
}
于 2014-02-19T07:23:06.407 に答える
3

ロック画面の場合、主なアクティビティで以下を使用してみませんか:

@Override
public void onAttachedToWindow() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}

ユーザーが安全なロック画面を設定していない場合、アプリはユーザーがステータスバーをプルダウンしてアクティビティを開くことを許可しますが、ユーザーは明らかに安全な画面を望んでいないため、それは問題ではありません.

ユーザーが安全なロック画面を設定している場合、アプリはステータス バーを表示しますが、それを操作することはできません。これは、電話がまだ実際にはロックされており、ユーザーが電話のロックを解除するまで、あなたのアクティビティのみが操作を許可されているためです。また、とにかくアプリを閉じると、標準の安全なロック画面が開きます. ストック機能と同じくらい安全であると保証できない安全な機能のコーディングに時間を費やす必要がないため、これはすべて非常に望ましいことです。

ユーザーがステータス バーを操作できないようにする場合は、フラグのFLAG_DISMISS_KEYGUARD呼び出しを省略することができます。次に、電話のロックを解除する直前に、最初のブロックで示したようにフラグを設定します。この最後の部分が機能するかどうかはわかりませんが、試してみる価値はあります。

それが役立つことを願っています

于 2012-12-16T03:08:11.337 に答える
1

申し訳ありませんが、動作しません。を使用FLAG_LAYOUT_IN_SCREENすると、タッチ イベントをキャッチできなくなります。

そしてところで:ウィンドウにビューを追加するには、ウィンドウマネージャーを使用します:

WindowManager winMgr = (WindowManager)getSystemService(WINDOW_SERVICE);
winMgr.addView(disableStatusBar, handleParams); 
于 2011-12-24T16:03:57.847 に答える
-4
requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
于 2011-09-17T21:01:09.147 に答える