とにかく、ユーザーがステータスバーをスライド(展開)したり折りたたんだりできないようにする方法はありますか?
私はロック画面の交換を試してみましたが、それは必須機能のようです。ルート権限を必要とせずにそれを行うための可能な方法はありますか?
あなたは実際に電話を応援することなく、ステータスバーが拡大するのを防ぐことができます。 このリンク を参照してください。これは、ステータスバーの高さにウィンドウを描画し、すべてのタッチイベントを消費します。
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;
}
}
短い答え:これは不可能です!
これがなぜ不可能であるかを知るために興味があるはずです:
システムステータスバーを操作するには、2つの権限 EXPAND_STATUS_BAR と STATUS_BAR があります。前者は任意のアプリケーションから要求できますが、後者はプラットフォーム署名で署名されたアプリケーション(サードパーティではなくシステムアプリケーション)用に予約されています。システムステータスバーを展開/折りたたむことは可能です( 「インテントを通じてステータスバーを開くまたは展開する方法」を参照してください) )ただし、 StatusBarManager クラスはSDKの一部ではないため、リフレクションが必要です。 Androidダイヤラがステータスバーの展開を防ぐために使用する)無効化メソッドは、前述のSTATUS_BAR権限がないアプリケーションからはアクセスできません。
出典:個人的な経験:-)
まず第一に、スマートフォンのrom認定でアプリが署名されていない場合、ステータスバーを変更することはできません。変更しようとすると、セキュリティ例外が発生します。
pdate:新しい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("collapse");
collapse .setAccessible(true);
collapse .invoke(service);
}
}
catch(Exception ex)
{
}
}
pdate:警告ダイアログには独自のフォーカスがあるため、onWindowFocusChangedメソッドもオーバーライドして、独自のカスタム警告ダイアログを使用する必要があります。
これは実際、私が誤って発見した小さなハックを介して行うことができますが、許可が必要です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);
これは基本的に、すべてのタッチイベントを受け取り、イベントがステータスバーに到達するのをブロックするステータスバーの上に透明なビューを作成し、それによってイベントが展開されないようにします。
注:このコードはテストされていませんが、コンセプトは機能します。
GrantLandとPoOkが、どちらの場合も機能しませんでした。しかし、別の解決策 最近のタスクリストをクリア/非表示にする は、私にとってはトリックでした。ユーザーがロックされたアプリを開けないように、最近のアプリケーションメニューを無効にする必要があるランチャーアプリを書いています。また、通知バーの拡大を防ぐ必要があり、このトリックによって両方を達成することができました。アクティビティの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);
}
}
ロック画面の場合メインアクティビティで以下を使用しないでください。
@Override
public void onAttachedToWindow() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
ユーザーが安全なロック画面を設定していない場合、アプリはステータスバーをプルダウンしてアクティビティを開くことができますが、ユーザーが安全な画面を望んでいないことは明らかであるため、問題はありません。
ユーザーが安全なlocksreenセットを持っている場合、アプリはステータスバーを表示しますが、それとの相互作用を許可しません。これは、電話がまだ実際にロックされており、ユーザーが電話のロックを解除するまで、アクティビティのみが操作を許可されるためです。また、とにかくアプリを閉じると、標準の安全なロック画面が開きます。保証することができない安全な機能を標準の機能と同じくらい安全にコーディングするのにその時間を費やす必要がないので、これらすべてが非常に望ましいです。
ユーザーがステータスバーを操作できるようにしたくない場合は、フラグFLAG_DISMISS_KEYGUARD
を省略できます。次に、電話のロックを解除する直前に、最初のブロックで示したようにフラグを設定します。この最後の部分が機能するかどうかはわかりませんが、試してみる価値はあります。
それが役に立てば幸い
申し訳ありませんが、機能しません。 FLAG_LAYOUT_IN_SCREEN
を使用すると、タッチイベントをキャッチできなくなります。
ところで、ウィンドウにビューを追加するには、ウィンドウマネージャーを使用します。
WindowManager winMgr = (WindowManager)getSystemService(WINDOW_SERVICE);
winMgr.addView(disableStatusBar, handleParams);