所谓背景,指的是应用程序的所有活动当前对用户都不可见。
请查看onActivityDestroyed函数中的注释。
适用于SDK目标版本14> :
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
public static int active = 0;
@Override
public void onActivityStopped(Activity activity) {
Log.i("Tracking Activity Stopped", activity.getLocalClassName());
active--;
}
@Override
public void onActivityStarted(Activity activity) {
Log.i("Tracking Activity Started", activity.getLocalClassName());
active++;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
}
@Override
public void onActivityResumed(Activity activity) {
Log.i("Tracking Activity Resumed", activity.getLocalClassName());
active++;
}
@Override
public void onActivityPaused(Activity activity) {
Log.i("Tracking Activity Paused", activity.getLocalClassName());
active--;
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
active--;
// if active var here ever becomes zero, the app is closed or in background
if(active == 0){
...
}
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Tracking Activity Created", activity.getLocalClassName());
active++;
}
}
没有一个答案完全适合特定情况,如果您想知道特定活动是否在前台,并且如果您是没有直接访问应用程序的SDK。对于我来说,我在后台线程中刚刚收到了新聊天消息的推送通知,并且只想在聊天屏幕不在前台时显示系统通知。
使用其他答案中推荐的ActivityLifecycleCallbacks
,我创建了一个小型实用程序类,其中包含逻辑以确定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
}
}
}
这个在2023年仍然有效
1-请进入您的应用程序类。 (如果您没有任何应用程序类,则请添加一个扩展Application的类)
2-然后在您的应用程序类中添加私有静态变量以存储状态。
3-然后在您的应用程序中实现LifecycleEventObserver及其单个方法“onStateChanged”
4-最后,在您的应用程序中添加静态方法,以从任何活动或片段中获取私有变量的状态
public class MyApp extends Application implements LifecycleEventObserver{
private static boolean activityVisible;
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event)
{
if (event == Lifecycle.Event.ON_STOP) {
activityVisible = false;
}
else if (event == Lifecycle.Event.ON_PAUSE){
activityVisible = false;
}
else if (event == Lifecycle.Event.ON_RESUME){
activityVisible = true;
}
else if (event == Lifecycle.Event.ON_START) {
activityVisible = true;
}
}
public static boolean checkIfActivityVisible(){
return activityVisible;
}
}
这里有多种方法
import android.app.Application
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
class TestApplication: Application(), LifecycleEventObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this);
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Log.i("AppForegrounded", "Hello event ${event}")
if (event == Lifecycle.Event.ON_RESUME) {
isAppInForeground = true
} else {
isAppInForeground = false
}
}
companion object {
var isAppInForeground = false
}
}
然后在Activity中将其用作
TestApplication.isAppInForeground
请确保在清单文件中提及此应用程序类
<manifest>
<application
android:name=".app.TestApplication"
</application>
</manifest>
class TestApplication: Application(), DefaultLifecycleObserver {
override fun onCreate() {
super<Application>.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this);
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
isAppInForeground = true
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
isAppInForeground = false
}
companion object {
var isAppInForeground = false
}
}
val isAppInForeground = ProcessLifecycleOwner.get().lifecycle.currentState == Lifecycle.State.RESUMED
val isAppInBackground = ProcessLifecycleOwner.get().lifecycle.currentState == Lifecycle.State.CREATED
可能已经晚了,但如果有人来访问,这是我建议的解决方案, 应用程序想要知道它处于后台或前台状态的原因可能有很多,其中一些是, 1. 当用户在BG中时显示烤面包和通知。 2.第一次用户从BG进入时执行某些任务,例如投票,重绘等。
Idolon和其他人提出的解决方案解决了第一部分,但没有解决第二部分。如果您的应用程序中有多个活动,并且用户在它们之间切换,则到您进入第二个活动时,可见标志将为false。因此,无法确定地使用它。
我做了一些CommonsWare建议的事情,“如果服务确定没有可见的活动,并且保持这种状态一段时间,在下一个逻辑停止点停止数据传输。”
加粗的那一行非常重要,可以用来实现第二个项目。所以我在获得onActivityPaused()时,不直接将可见性更改为false,而是设置一个3秒的计时器(这是下一个活动应该启动的最大时间),如果在接下来的3秒钟内没有onActivityResumed()调用,则更改可见性为false。
同样,在onActivityResumed()中,如果有计时器,则会取消计时器。总之,visible变成了isAppInBackground。
抱歉无法复制粘贴代码...
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
Editor editor = sharedPrefs.edit();
editor.putBoolean("visible", false);
editor.commit();
并且可以通过其他方式在需要时进行阅读,例如:
// Show a Toast Notification if App is not visible (ie in background. Not running, etc)
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if(!sharedPrefs.getBoolean("visible", true)){...}
可能不太优雅,但对我来说很好用...
我想建议您使用另一种方法来实现这个。
我猜您想在程序启动时显示启动屏幕,如果它已经在后台运行,则不要显示它。
您的应用程序可以持续将当前时间写入特定文件。当您的应用程序启动时,请检查最后一个时间戳,如果current_time-last_time>您指定的最新时间的时间范围,则意味着您的应用程序已停止,可能被系统或用户本身杀死。
@Override protected void onApplicationSentToBackground() { }
- Chuck D