Android应用关闭/发送到后台时运行代码

时间:2011-04-08 09:26:29

标签: android

我有一个Android应用程序,它将一些数据发送到Web服务。我需要在应用程序关闭或发送到后台后立即发送此数据。但是我该如何完成此操作?

我目前的解决方案是在我的家庭活动上的OnPause()上运行它,但无论关闭应用程序时用户所处的活动,我都需要运行它。这是可能的还是我必须添加所有活动的OnPause方法?

8 个答案:

答案 0 :(得分:25)

在您决定使用以下代码之前先检查此解决方案 https://stackoverflow.com/a/5862048/1037294


要检查您的应用是否已发送至后台,您可以在应用中的每项活动onPause()onStop()上调用此代码:

 /**
   * 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;
  }

为此,您应该在AndroidManifest.xml

中加入此内容
<uses-permission android:name="android.permission.GET_TASKS" />

答案 1 :(得分:22)

修改

此答案仅用于一个目的,即在onPause()中为所有活动运行代码。当您的应用程序发送到后台时,它不允许您运行代码。

原始答案

创建一个名为YourBasicActivity的活动并覆盖其onPause()方法,并从YourBasicActivity扩展每个活动

答案 2 :(得分:20)

这是我使用的方法,它看起来效果很好:

我有一个我自己的顶级应用程序类,它将应用程序扩展为

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {

您还需要在清单文件中注册此Application对象:

<application android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:name=".MyApplication">

注意我如何实现ActivityLifeCycleCallbacks接口。该界面具有以下方法:

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);
}

您需要实现这些方法,然后在应用程序onCreate()中注册这些事件,如下所示

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(this);
}

这将在活动生命周期方法发生时调用回调(MyApplication对象),例如onCreate(),onPause等。 在你的onActivityPaused()中,你可以通过调用@pepsps方法检查应用程序是否是后台的:isApplicationSentToBackground(...)

这就是我的代码然后......

/**
 * 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) {
}

创建一个新类以进行Foreground检查(这是一个异步。任务)。有关详情,请参阅check android application is in foreground or not?

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;
    }
}

答案 3 :(得分:3)

也许这可能会有所帮助,告诉我它是否适合你。 只有当你从后台返回时,活动的值才为0(零) 当onRestart()时,其余时间将是一个高于0(零)的数字 被执行。

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;
}

}

您的所有课程都必须从此课程扩展才能实现。

解释:当活动“不可见”时, onStart 执行活动“可见”,执行 onStop 。因此,当您的APP(它表示APP不是活动)进入后台时,所有活动都“不可见”,因此他们执行onStop方法,因此这背后的想法是每次活动时添加一个每次活动隐藏时都会启动,并且 SUBTRACT ONE ,所以如果变量“activities”的值为零,则表示在某些点开始的所有活动现在都不可见,所以当APP从后台返回并对“前面”中的活动执行 onRestart 方法,您可以检查是来自后台还是只是重新启动活动。

答案 4 :(得分:0)

覆盖您的Home活动的onStop()方法并在那里运行代码。

答案 5 :(得分:0)

我认为您需要运行自己的线程,该线程将检查所有正在运行的活动是在后台还是已销毁。

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
          }

    }
}

答案 6 :(得分:0)

您可以使用onAppForegroundStateChange()方法,该方法在应用程序打开和关闭时调用。此方法仅在您的应用程序进入前景/后台时调用。 onAppForegroundStateChange()方法比使用onPause()方法更好,因为每次进入其他活动时也会调用onPause方法。

你可以像这样使用这种方法

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!
        }
    }
}

答案 7 :(得分:0)

如果您要提交/保存用户输入的数据,则有比他尝试关闭应用程序时更好的方法。关闭应用程序的方法有很多。用户甚至可以关闭电话。因此,很难对所有这些措施都采取预防措施。

例如,如果您对Web服务的调用太慢,我建议您每次用户停止写入,每隔几秒钟或当他按下按钮时都提交数据。

这样,它更安全,更易于实现。