android - Prevención de la expansión de la barra de estado
statusbar lockscreen (8)
¿Hay alguna forma de evitar que los usuarios deslicen la barra de estado (expandir) o se vuelvan a colapsar?
Estoy probando un reemplazo de la pantalla de bloqueo y parece que es una característica imprescindible. ¿Hay alguna forma posible de hacerlo sin requerir privilegios de root?
En realidad, puede evitar que la barra de estado se expanda sin rootear el teléfono. Vea este enlace . Esto dibuja una ventana a la altura de la barra de estado y consume todos los eventos táctiles.
Llame al siguiente código justo después de 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://.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;
}
}
Esto realmente se puede hacer a través de un pequeño truco que descubrí accidentalmente, pero requiere el permiso android.permission.SYSTEM_ALERT_WINDOW
:
Lo que debe hacer es agregar una vista del tamaño exacto de la barra de estado directamente al WindowManager con ciertos parámetros que cubren la barra de estado y le impide recibir eventos táctiles:
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);
Básicamente, esto creará una vista transparente sobre la barra de estado que recibirá todos los eventos táctiles y evitará que los eventos lleguen a la barra de estado y, por lo tanto, evitará que se amplíe.
NOTA: Este código no está probado, pero el concepto funciona.
Lo siento pero no funciona. el uso de FLAG_LAYOUT_IN_SCREEN
impide capturar eventos táctiles.
Y BTW: para agregar una vista a la ventana use el administrador de ventanas:
WindowManager winMgr = (WindowManager)getSystemService(WINDOW_SERVICE);
winMgr.addView(disableStatusBar, handleParams);
Para una pantalla de bloqueo ¿Por qué no solo usa lo siguiente en su actividad principal:
@Override
public void onAttachedToWindow() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
Si el usuario no tiene un conjunto de bloqueo de pantalla seguro, la aplicación le permitirá bajar la barra de estado y abrir actividades, pero eso no importa, ya que el usuario obviamente no quiere una pantalla segura de todos modos.
Si el usuario tiene un conjunto de pantalla de bloqueo seguro, la aplicación mostrará la barra de estado pero no permitirá interacciones con ella. Esto se debe a que el teléfono todavía está realmente bloqueado y solo su actividad puede operar hasta que el usuario desbloquee el teléfono. También, al cerrar la aplicación, se abrirá la pantalla de bloqueo estándar segura. Todo esto es altamente deseable porque no tiene que pasar todo ese tiempo codificando características seguras que no puede garantizar que sean tan seguras como las de valores.
Si realmente no quieres que el usuario pueda interactuar con la barra de estado, tal vez puedas omitir la llamada FLAG_DISMISS_KEYGUARD
. Luego, justo antes de que estés a punto de desbloquear el teléfono, configura la bandera como mostré en el primer bloque. No sé si esta última parte funciona pero vale la pena intentarlo.
Espero que ayude
Respuesta corta: esto es imposible!
Ahora debería estar interesado en saber por qué esto es imposible:
Hay dos permisos para manipular la barra de estado del sistema, EXPAND_STATUS_BAR y STATUS_BAR . La primera puede ser solicitada por cualquier aplicación, pero la última se reserva para las aplicaciones firmadas con la firma de la plataforma (aplicaciones del sistema, no de terceros). Es posible expandir / contraer la barra de estado del sistema (vea "¿Cómo abrir o expandir la barra de estado a través de la intención?" ) Pero tenga en cuenta que se requiere reflexión porque la clase StatusBarManager no es parte del SDK. Una aplicación sin el permiso STATUS_BAR mencionado anteriormente no puede acceder al método de desactivación, que utiliza el marcador de Android para evitar que la barra de estado se expanda.
Fuentes: experiencia personal :-)
Probé las soluciones mencionadas por GrantLand y PoOk, pero ambas no funcionaron en mi caso. Sin embargo, otra solución Borrar / Ocultar la lista de tareas recientes hizo el truco para mí. Estoy escribiendo una aplicación de inicio para la cual tuve que deshabilitar un menú de aplicaciones recientes para que el usuario no pueda abrir una aplicación bloqueada desde allí. Además, tuve que evitar la expansión de la barra de notificación y este truco me hizo lograr ambas cosas. Reemplace el método OnWindowFocusChanged en su actividad y verifique si esto es lo que quería.
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);
}
}
En primer lugar , es imposible modificar la barra de estado si su aplicación no está firmada con la certificación rom del teléfono; si intenta modificarla, obtendrá una excepción de seguridad.
Actualización : en las nuevas API, el método es "collapsePanels" en lugar de "collapse".
La única forma que encontré después de varias horas de trabajo es anular el método "onWindowFocusChanged" de la actividad y cuando pierde el enfoque (tal vez el usuario ha tocado la barra de notificaciones), obligue a colapsar la Barra de estado, aquí está el código (trabajando en un Defy + 2.3.5).
Debe declarar el siguiente permiso en el manifiesto:
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
Y anula el siguiente método:
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)
{
}
}
Actualización : Tendrá que usar su propio cuadro de diálogo de alerta personalizado anulando su método onWindowFocusChanged también, porque los cuadros de diálogo de alerta tienen su propio enfoque.
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);