所谓后台,我的意思是应用程序的活动目前对用户都不可见?


当前回答

这样怎么样:

boolean isBackgrounded() {
    try {
        context.startService(new Intent(action));
        return false;
    }
    catch (IllegalStateException exc) {
        // "Not allowed to start service Intent: app is in background"
        return true;
    }
}

其他回答

自从Android API 16以来,有一个简单的方法来检查应用程序是否在前台。这可能不是万无一失的,但Android上没有万无一失的方法。当你的服务接收到来自服务器的更新,并且必须决定是否显示通知时,这个方法就足够好了(因为如果UI是前台,用户会注意到更新而不通知)。

RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
isInBackground = myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND;

这篇旧文章的另一个解决方案(对那些可能有帮助的人来说):


<application android:name=".BaseApplication" ... >

public class BaseApplication extends Application {

    private class Status {
        public boolean isVisible = true;
        public boolean isFocused = true;
    }

    private Map<Activity, Status> activities;

    @Override
    public void onCreate() {
        activities = new HashMap<Activity, Status>();
        super.onCreate();
    }

    private boolean hasVisibleActivity() {
        for (Status status : activities.values())
            if (status.isVisible)
                return true;
        return false;
    }

    private boolean hasFocusedActivity() {
        for (Status status : activities.values())
            if (status.isFocused)
                return true;
        return false;
    }

    public void onActivityCreate(Activity activity, boolean isStarting) {
        if (isStarting && activities.isEmpty())
            onApplicationStart();
        activities.put(activity, new Status());
    }

    public void onActivityStart(Activity activity) {
        if (!hasVisibleActivity() && !hasFocusedActivity())
            onApplicationForeground();
        activities.get(activity).isVisible = true;
    }

    public void onActivityWindowFocusChanged(Activity activity, boolean hasFocus) {
        activities.get(activity).isFocused = hasFocus;
    }

    public void onActivityStop(Activity activity, boolean isFinishing) {
        activities.get(activity).isVisible = false;
        if (!isFinishing && !hasVisibleActivity() && !hasFocusedActivity())
            onApplicationBackground();
    }

    public void onActivityDestroy(Activity activity, boolean isFinishing) {
        activities.remove(activity);
        if(isFinishing && activities.isEmpty())
            onApplicationStop();
    }

    private void onApplicationStart() {Log.i(null, "Start");}
    private void onApplicationBackground() {Log.i(null, "Background");}
    private void onApplicationForeground() {Log.i(null, "Foreground");}
    private void onApplicationStop() {Log.i(null, "Stop");}

}

public class MyActivity extends BaseActivity {...}

public class BaseActivity extends Activity {

    private BaseApplication application;

    @Override
    protected void onCreate(Bundle state) {
        application = (BaseApplication) getApplication();
        application.onActivityCreate(this, state == null);
        super.onCreate(state);
    }

    @Override
    protected void onStart() {
        application.onActivityStart(this);
        super.onStart();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        application.onActivityWindowFocusChanged(this, hasFocus);
        super.onWindowFocusChanged(hasFocus);
    }

    @Override
    protected void onStop() {
        application.onActivityStop(this, isFinishing());
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        application.onActivityDestroy(this, isFinishing());
        super.onDestroy();
    }

}

根据CommonsWare和Key所说的,你可以扩展Application类,并让你所有的活动在onPause/onResume方法上调用它。这将允许您知道哪些活动是可见的,但这可能会得到更好的处理。

你能详细说明一下你的想法吗?当你说在后台运行,你的意思是简单地让你的应用程序仍然在内存中,即使它目前不在屏幕上?你有没有考虑过使用服务作为一种更持久的方式来管理你的应用程序,当它不在焦点?

由于没有提到它,我将建议读者探索通过Android架构组件提供的ProcessLifecycleOwner

我想出的最好的解决办法是使用计时器。

你已经在onPause()中启动了一个定时器,并在onResume()中取消了相同的定时器,有一个定时器的实例(通常在应用程序类中定义)。计时器本身被设置为在2秒后(或您认为合适的任何时间间隔)运行Runnable,当计时器触发时,您设置一个标志,将应用程序标记为在后台。

在取消定时器之前的onResume()方法中,您可以查询后台标志来执行任何启动操作(例如开始下载或启用位置服务)。

这个解决方案允许您在back堆栈上有几个活动,并且不需要任何权限来实现。

如果你也使用事件总线,这个解决方案也很有效,因为你的计时器可以简单地触发一个事件,应用程序的各个部分可以相应地做出响应。