solucion - Ejecutar código cuando la aplicación de Android se cierra/envía al fondo
todas las aplicaciones se detienen android (7)
Tengo una aplicación de Android que envía algunos datos a un servicio web. Necesito enviar estos datos tan pronto como se cierra la aplicación o se envían a fondo ... Pero, ¿cómo puedo lograr esto?
Mi solución actual es ejecutarlo en OnPause () en mi actividad hogareña, pero necesito que esto se ejecute sin importar en qué actividad esté el usuario al cerrar la aplicación. ¿Es posible o tengo que agregar el método OnPause a ¿todas las actividades?
Creo que necesita ejecutar su propio hilo que verificará si todas las actividades en ejecución en segundo plano o destruidas.
MyBasicActivity extends Activity
{
private static ArrayList<MyBasicActivity> activities=new ArrayList<MyBasicActivities);
private boolean started;
public void onCreate()
{
activities.add(this);
}
public void onDestroy()
{
activities.remove(this);
}
public void onStart()
{
this.started=true;
}
public void onPause()
{
this.started=false;
}
public boolean isStarted()
{
return started;
}
}
MyThread implements Runnable
{
private ArrayList<MyBasicActivity> activities;
public MyThread(ArrayList<MyBasicActivity> activities)
{
this.activities=activities;
}
void run()
{
while(!stopped)
{
boolean inBackground=true;
for(MyBasicActivity activity:activities)
{
if(activity.isStarted())
{
inBackground=false;
break;
}
}
if(inBackground)
//run your code here;
sleep(10000); //10 secs
}
}
}
Este es el método que utilicé y parece funcionar bastante bien:
Tengo una clase de aplicación de primer nivel que extiende la aplicación como tal
public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
También necesita registrar este objeto de Aplicación en su archivo de manifiesto:
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:name=".MyApplication">
Observe cómo también implemento la interfaz ActivityLifeCycleCallbacks. Esta interfaz tiene los siguientes métodos:
public static interface ActivityLifecycleCallbacks {
void onActivityCreated(android.app.Activity activity, android.os.Bundle bundle);
void onActivityStarted(android.app.Activity activity);
void onActivityResumed(android.app.Activity activity);
void onActivityPaused(android.app.Activity activity);
void onActivityStopped(android.app.Activity activity);
void onActivitySaveInstanceState(android.app.Activity activity, android.os.Bundle bundle);
void onActivityDestroyed(android.app.Activity activity);
}
Debe implementar esos métodos y luego registrarse para estos eventos en sus aplicaciones onCreate () de la siguiente manera
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
Esto llamará a la devolución de llamada (el objeto MyApplication) cada vez que ocurra un método de ciclo de vida de actividad, como onCreate (), onPause, etc. En su onActivityPaused () puede verificar si la aplicación está atrasada o no llamando al método @peceps: isApplicationSentToBackground ( ...)
Así es como se ve mi código entonces ...
/**
* Application.ActivityLifecycleCallbacks methods
*/
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
try {
boolean foreground = new ForegroundCheckTask().execute(getApplicationContext()).get();
if(!foreground) {
//App is in Background - do what you want
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
Cree una nueva clase para ir a la comprobación de primer plano (que es una tarea asincrónica). ¿ Verá que la aplicación de Android está en primer plano o no? para más.
class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {
@Override
protected Boolean doInBackground(Context... params) {
final Context context = params[0];
return isAppOnForeground(context);
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
Tal vez esto puede ser útil, dime si funcionó para ti. solo cuando regrese del fondo el valor de las actividades sería 0 (cero) el resto del tiempo sería un número mayor que 0 (cero) cuando se ejecuta onRestart ().
public class FatherClass extends Activity {
private static int activities = 0;
public void onCreate(Bundle savedInstanceState, String clase) {
super.onCreate(savedInstanceState);
}
protected void onRestart()
{
super.onRestart();
if(activities == 0){
Log.i("APP","BACK FROM BACKGROUND");
}
}
protected void onStop(){
super.onStop();
activities = activities - 1;
}
protected void onStart(){
super.onStart();
activities = activities + 1;
}
}
Todas sus clases deben extenderse desde esta clase para que esto funcione.
Explicación : OnStart se ejecuta una, la actividad es "visible" y la opción " onStop" cuando la actividad es "no visible". Entonces cuando su APLICACIÓN (dice APP no actividad) va al fondo todas las actividades son "no visibles" entonces ejecutan el método onStop, entonces la idea detrás de esto es AGREGAR UNO cada vez que se inició una actividad, y RESTANTE UNO cada vez se oculta una actividad, por lo que si el valor de la variable "actividades" es cero, significa que todas las actividades que comenzaron en algún punto ahora no son visibles, por lo que cuando tu APP vuelve de fondo y ejecuta el método onReestart en la actividad de "frontal" puede verificar si proviene de fondo o simplemente está reiniciando una actividad.
anula el método onStop()
de tu actividad de Inicio y ejecuta allí el código.
puede utilizar el método AppCoupleForegroundStateChange () que llama cuando la aplicación está abierta y cerrada. Este método solo se invoca cuando su aplicación viene en primer plano / fondo. El método onAppForegroundStateChange () es mejor que el método onPause () porque el método onPause también se invoca cada vez que se va a otra actividad.
puedes usar este método así
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
AppForegroundStateManager.getInstance().addListener(this);
}
@Override
public void onAppForegroundStateChange(AppForegroundStateManager.AppForegroundState newState) {
if (AppForegroundStateManager.AppForegroundState.IN_FOREGROUND == newState) {
// App just entered the foreground. Do something here!
} else {
// App just entered the background. Do something here!
}
}
}
¡Compruebe primero esta solución https://.com/a/5862048/1037294 antes de decidir usar el código a continuación!
Para verificar si su aplicación se envía a segundo plano, puede llamar a este código en onPause()
o onStop()
en cada actividad de su aplicación:
/**
* Checks if the application is being sent in the background (i.e behind
* another application''s Activity).
*
* @param context the context
* @return <code>true</code> if another application will be above this one.
*/
public static boolean isApplicationSentToBackground(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
Para que esto funcione, debes incluir esto en tu AndroidManifest.xml
<uses-permission android:name="android.permission.GET_TASKS" />
Editar
Esta respuesta solo sirve para un propósito, es decir, ejecutar un código en onPause()
para todas las actividades. No le permite ejecutar un código cuando su aplicación se envía a segundo plano.
Respuesta original
Realice una actividad denominada YourBasicActivity
y anule su método onPause()
y amplíe cada actividad de YourBasicActivity