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


当前回答

官方文件:

系统区分前台和后台应用程序。(用于服务限制的后台定义与内存管理使用的定义不同;一个应用程序可能在后台的内存管理,但在前台的能力,启动服务。)一个应用程序被认为是在前台,如果以下任何一个是真的:

它有一个可见的活动,无论该活动是启动还是暂停。 它有一个前台服务。 另一个前台应用通过绑定到它的一个服务或使用它的一个内容提供者来连接到该应用。例如,如果另一个应用绑定到它的: 输入法设置 壁纸服务 通知侦听器 语音或文字服务

如果这些条件都不为真,应用程序被认为是在后台。

其他回答

唯一正确的解决方法:

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        MyApp.mainActivity = this;
        super.onCreate(savedInstanceState);
        ...
    }

MyApp.java:

public class MyApp extends Application implements LifecycleObserver {

    public static MainActivity mainActivity = null;

    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onAppBackgrounded() {
        // app in background
        if (mainActivity != null) {
            ...
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onAppForegrounded() {
        // app in foreground
        if (mainActivity != null) {
            ...
        }
    }

}

在@玉米秆回答的基础上,包括一些有用的功能。

额外的功能:

引入了单例模式,所以你可以在应用程序的任何地方这样做: 增加了重复事件的处理(见注释//对可见性的变化采取一些行动和//对前景的变化采取一些行动)

App.java

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        registerActivityLifecycleCallbacks(AppLifecycleHandler.getInstance());
    }
}

AppLifecycleHandler.java

public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    private int resumed;
    private int started;

    private final String DebugName = "AppLifecycleHandler";

    private boolean isVisible = false;
    private boolean isInForeground = false;

    private static AppLifecycleHandler instance;

    public static AppLifecycleHandler getInstance() {
        if (instance == null) {
            instance = new AppLifecycleHandler();
        }

        return instance;
    }

    private AppLifecycleHandler() {
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
    }

    @Override
    public void onActivityResumed(Activity activity) {
        ++resumed;
        android.util.Log.w(DebugName, "onActivityResumed -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
        setForeground((resumed > 0));
    }

    @Override
    public void onActivityPaused(Activity activity) {
        --resumed;
        android.util.Log.w(DebugName, "onActivityPaused -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
        setForeground((resumed > 0));
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    @Override
    public void onActivityStarted(Activity activity) {
        ++started;
        android.util.Log.w(DebugName, "onActivityStarted -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
        setVisible((started > 0));
    }

    @Override
    public void onActivityStopped(Activity activity) {
        --started;
        android.util.Log.w(DebugName, "onActivityStopped -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
        setVisible((started > 0));
    }

    private void setVisible(boolean visible) {
        if (isVisible == visible) {
            // no change
            return;
        }

        // visibility changed
        isVisible = visible;
        android.util.Log.w(DebugName, "App Visiblility Changed -> application is visible: " + isVisible);

        // take some action on change of visibility
    }

    private void setForeground(boolean inForeground) {
        if (isInForeground == inForeground) {
            // no change
            return;
        }

        // in foreground changed
        isInForeground = inForeground;
        android.util.Log.w(DebugName, "App In Foreground Changed -> application is in foreground: " + isInForeground);

        // take some action on change of in foreground

    }

    public static boolean isApplicationVisible() {
        return AppLifecycleHandler.getInstance().started > 0;
    }

    public static boolean isApplicationInForeground() {
        return AppLifecycleHandler.getInstance().resumed > 0;
    }
}

我想建议你用另一种方法来做这件事。

我猜你想在程序启动时显示启动屏幕,如果它已经在后端运行,不要显示它。

您的应用程序可以连续地将当前时间写入特定的文件。 当你的应用程序正在启动时,检查最后的时间戳,如果current_time-last_time>是你指定的写入最近时间的时间范围,这意味着你的应用程序已经停止,要么是由系统杀死,要么是用户自己杀死。

除非你自己跟踪它,否则无法确定你的任何活动是否可见。也许你应该考虑问一个新的StackOverflow问题,解释一下你想从用户体验中获得什么,这样我们也许可以给你其他的实现想法。

如果你想知道一个特定的活动是否在前台,如果你是一个没有直接访问应用程序的SDK,那么没有一个答案非常适合特定的情况。对我来说,我在后台线程刚刚收到一个新的聊天消息的推送通知,只想在聊天屏幕不在前台时显示系统通知。

使用ActivityLifecycleCallbacks,正如在其他答案中推荐的那样,我已经创建了一个小的util类,它包含MyActivity是否在前台的逻辑。

class MyActivityMonitor(context: Context) : Application.ActivityLifecycleCallbacks {

private var isMyActivityInForeground = false

init {
    (context.applicationContext as Application).registerActivityLifecycleCallbacks(this)
}

fun isMyActivityForeground() = isMyActivityInForeground

override fun onActivityPaused(activity: Activity?) {
    if (activity is MyActivity) {
        isMyActivityInForeground = false
    }
}

override fun onActivityResumed(activity: Activity?) {
    if (activity is MyActivity) {
        isMyActivityInForeground = true
    }
}

}