Bloquear la aplicación de Android después de una cierta cantidad de tiempo de inactividad

Mi aplicación Android requiere que se ingrese una contraseña en la primera actividad. Quiero poder enviar automáticamente la aplicación a la pantalla de entrada de contraseña después de que la aplicación haya estado inactiva durante un período de tiempo fijo.

La aplicación tiene múltiples actividades, pero me gustaría que el tiempo de espera fuera global para todas las actividades. Por lo tanto, no sería suficiente crear un subproceso temporizador en el método onPause() de una Activity .

No estoy seguro de cuál es la mejor definición para que la aplicación esté inactiva, pero ninguna actividad activa sería suficiente.

Sé que otra respuesta es aceptada ya, pero me encontré con este trabajo en un problema similar y creo que voy a tratar de un enfoque alternativo mucho más simple que me pareció que también puede documentar si alguien quiere tratar de ir por el mismo Path.enter código aquí

La idea general es simplemente hacer un seguimiento de la hora del reloj del sistema en una SharedPreference siempre que cualquier Activity hace una pausa – suena bastante simple, pero por desgracia, hay un agujero de seguridad si eso es todo lo que usa, ya que el reloj se reinicia al reiniciar. Para evitar esto:

  • Tener una subclase de Application o una clase compartida de singleton estática con un estado global desbloqueado desde inicial (inicialmente falso). Este valor debe vivir mientras el proceso de su aplicación.
  • Guarde la hora del sistema (en tiempo real desde el arranque) en la onPause Activity relevante en una SharedPreference si el estado de la aplicación actual está desbloqueado.
  • Si el estado desbloqueado desde la inicialización de la aplicación es falso (inicio limpio de la aplicación, ya sea la aplicación o el teléfono reiniciado), muestre la pantalla de bloqueo. De lo contrario, compruebe el valor SharedPreference el SharedPreference la actividad bloqueable; Si es inexistente o mayor que el valor SharedPreference + el intervalo de tiempo de espera, también mostrará la pantalla de bloqueo.
  • Cuando la aplicación esté desbloqueada, establezca el estado desbloqueado desde que se inicia en la aplicación a true.

Además del tiempo de espera, este método bloqueará automáticamente tu aplicación si la aplicación se cancela y se reinicia o si reinicia el teléfono, pero no creo que sea un problema especialmente malo para la mayoría de las aplicaciones. Es un poco más seguro y puede bloquear sin necesidad a los usuarios que cambian de tarea mucho, pero creo que es una compensación vale la pena para el código reducido y la complejidad por una eliminación total de cualquier problema de fondo / wakelock preocupaciones (sin servicios, alarmas o receptores necesarios ).

Para evitar la interrupción del proceso de bloqueo de la aplicación independientemente del tiempo, en lugar de compartir un Singleton en la aplicación para unlocked-desde-arranque, podría utilizar SharedPreference y registrar un oyente para la intención de difusión de arranque del sistema para establecer que Preferencia a false. Eso re-agrega algo de la complejidad de la solución inicial con el beneficio de ser un poco más de conveniencia en el caso de que el proceso de la aplicación se destruye mientras está en segundo plano dentro del intervalo de tiempo de espera, aunque para la mayoría de las aplicaciones es probablemente exceso.

Traté de esto usando AlarmManager para programar y cancelar la acción de tiempo de espera.

Luego en el evento onPause () de todas mis actividades, programo la alarma. En el evento onResume () de todas mis actividades, compruebo si la alarma se apaga. Si la alarma se apaga, apago mi aplicación. Si la alarma no se ha apagado, la cancelo.

He creado Timeout.java para gestionar mis alarmas. Cuando se dispara la alarma, se dispara una intención:

 public class Timeout { private static final int REQUEST_ID = 0; private static final long DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes private static PendingIntent buildIntent(Context ctx) { Intent intent = new Intent(Intents.TIMEOUT); PendingIntent sender = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, PendingIntent.FLAG_CANCEL_CURRENT); return sender; } public static void start(Context ctx) { ctx.startService(new Intent(ctx, TimeoutService.class)); long triggerTime = System.currentTimeMillis() + DEFAULT_TIMEOUT; AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); am.set(AlarmManager.RTC, triggerTime, buildIntent(ctx)); } public static void cancel(Context ctx) { AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); am.cancel(buildIntent(ctx)); ctx.startService(new Intent(ctx, TimeoutService.class)); } } 

Luego, creé un servicio para capturar la intención generada por la alarma. Establece un estado global en mi instancia de la clase de aplicación para indicar que la aplicación debe bloquearse:

 public class TimeoutService extends Service { private BroadcastReceiver mIntentReceiver; @Override public void onCreate() { super.onCreate(); mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ( action.equals(Intents.TIMEOUT) ) { timeout(context); } } }; IntentFilter filter = new IntentFilter(); filter.addAction(Intents.TIMEOUT); registerReceiver(mIntentReceiver, filter); } private void timeout(Context context) { App.setShutdown(); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.cancelAll(); } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(mIntentReceiver); } public class TimeoutBinder extends Binder { public TimeoutService getService() { return TimeoutService.this; } } private final IBinder mBinder = new TimeoutBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } } 

Por último, he creado una subclase de actividad que todas las actividades de mi aplicación subclase de gestión de bloqueo y desbloqueo:

 public class LockingActivity extends Activity { @Override protected void onPause() { super.onPause(); Timeout.start(this); } @Override protected void onResume() { super.onResume(); Timeout.cancel(this); checkShutdown(); } private void checkShutdown() { if ( App.isShutdown() ) { finish(); } } } 

El uso de onPause y onResume para iniciar y detener el tiempo de espera me da la siguiente semántica. Mientras una de las actividades de mi aplicación esté activa, el reloj de tiempo de espera no se está ejecutando. Puesto que utilicé un tipo de alarma de AlarmManager.RTC, cuando el teléfono va a dormir el reloj del timeout funciona. Si el tiempo de espera ocurre mientras el teléfono está dormido, entonces mi servicio recogerá el tiempo de espera tan pronto como el teléfono se despierte. Además, el reloj se ejecuta cuando cualquier otra actividad está abierta.

Para una versión más detallada de éstos, puedes ver cómo los implementé realmente en mi aplicación https://github.com/bpellin/keepassdroid

Compruebe cómo OpenIntents Safe implementa esta funcionalidad.

Este ha sido un mensaje muy útil para mí. Para respaldar el concepto dado por @Yoni Samlan. Lo he implementado de esta manera

 public void pause() { // Record timeout time in case timeout service is killed long time = System.currentTimeMillis(); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor edit = preferences.edit(); edit.putLong("Timeout_key", time);// start recording the current time as soon as app is asleep edit.apply(); } public void resume() { // Check whether the timeout has expired long cur_time = System.currentTimeMillis(); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); long timeout_start = preferences.getLong("Timeout_key", -1); // The timeout never started if (timeout_start == -1) { return; } long timeout; try { //timeout = Long.parseLong(sTimeout); timeout=idle_delay; } catch (NumberFormatException e) { timeout = 60000; } // We are set to never timeout if (timeout == -1) { return; } if (idle){ long diff = cur_time - timeout_start; if (diff >= timeout) { //Toast.makeText(act, "We have timed out", Toast.LENGTH_LONG).show(); showLockDialog(); } } } 

Método de pausa de llamada de onPause y reanudar el método de onResume.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.