如何判断APP在前台还是后台?
创始人
2025-07-11 13:20:06
0

如何判断一个APP在前台还是后台?可以通过RunningTasks,RunningProcess 以及ActivityLifecycleCallback判定。

RunningTasks方式

注意:getRunningTask方法在5.0以上已经被废弃,只能返回自己和系统的一些不敏感的task,不再返回其他应用的task,用此方法来判断自身App是否处于后台是有效的,但是无法判断其他应用是否处于前台。

private fun getTopApplication() {

    //首先获取到ActivityManager
    val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

    if (activityManager.getRunningTasks(1) == null){
        Log.e(TAG, "getForegroundActivity: ")
        return
    }

    var runningTaskInfo = activityManager.getRunningTasks(1)[0]
    if (runningTaskInfo == null) {
        Log.e(TAG, "runningTaskInfo is null")
        return
    }

    runningTaskInfo.topActivity?.let {
        Log.e(TAG, "top application is ${it.packageName}")
    }
}

RunningProcess方式

注意:RunningProcess方法在5.0以上已经被废弃,例如,在聊天类型的App中,大部分时间需要常驻后台来不间断地获取服务器的消息,就必须把Service设置成START_STICKY,kill后会被重启(等待5s左右)来保证Service常驻后台。如果Service设置了这个属性,这个App的进程就可以判断为前台。

appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
private fun isAppForeground(): Boolean {
    val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    var runningAppProcesses = activityManager.runningAppProcesses

    if (runningAppProcesses == null) {
        Log.e(TAG, "runningAppProcesses is null")
        return false
    }

    runningAppProcesses.forEach {
        if (it.processName == packageName && (it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)) {
            return true
        }
    }
    return false
}

ActivityLifecycleCallbacks方式

class MyActivityLifecycleCallbacks(
    var onActivityCreatedAction: ((Activity, Bundle?) -> Unit)? = null,
    var onActivityStartedAction: ((Activity) -> Unit)? = null,
    var onActivityResumedAction: ((Activity) -> Unit)? = null,
    var onActivityPausedAction: ((Activity) -> Unit)? = null,
    var onActivityStoppedAction: ((Activity) -> Unit)? = null,
    var onActivitySaveInstanceStateAction: ((Activity, Bundle) -> Unit)? = null,
    var onActivityDestroyedAction: ((Activity) -> Unit)? = null

) : Application.ActivityLifecycleCallbacks {

    private var mCount=0
    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        onActivityCreatedAction?.invoke(activity, savedInstanceState)
    }

    override fun onActivityStarted(activity: Activity) {
        mCount++
        onActivityStartedAction?.invoke(activity)
    }

    override fun onActivityResumed(activity: Activity) {
        onActivityResumedAction?.invoke(activity)
    }

    override fun onActivityPaused(activity: Activity) {
        onActivityPausedAction?.invoke(activity)
    }

    override fun onActivityStopped(activity: Activity) {
        mCount--
        onActivityStoppedAction?.invoke(activity)
    }

    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
        onActivitySaveInstanceStateAction?.invoke(activity, outState)
    }

    override fun onActivityDestroyed(activity: Activity) {
        onActivityDestroyedAction?.invoke(activity)
    }

    /**
     * 这里我们把mCount的实际数值返回回去
     */
    fun getCount():Int = mCount
}

这里我们对ActivityLifecycleCallbacks的实现类做了一层封装,利用Kotlin的高阶函数,当我们需要去实现那个声明周期的回调的时候,就通过高阶函数来提供回调处理,否则默认不做任何处理。然后我们在Application的onCreate中进行注册:

class LifeApplication : Application() {

    private val TAG = "LifeApplication"

    private val mActivityLifecycleCallbacks by lazy {
        MyActivityLifecycleCallbacks(
            onActivityCreatedAction = { activit, bundle ->
            Log.e(TAG, "onCreate: ")
        },
        onActivityStoppedAction = { activity ->
            Log.e(TAG, "onStop ")
        },
        onActivityDestroyedAction = { activity ->
            Log.e(TAG, "onDestroy")
        })
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
        //注册生命周期回调事件
        registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks)
    }

    /**
     * 用于判断当前进程是否处于前台
     */
    fun isForegroundMethod(): Boolean = mActivityLifecycleCallbacks.getCount() > 0

    companion object{
        private var instance :LifeApplication?= null
        fun getInstance () = instance!!
    }

当我们不管是点击Back键还是Home键都会回调到onStop方法,我们在onStart和onStop中分别对mCount值做了加减,这样我们可以通过该数值来判断当前App是前台还是后台。

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
P2P的自白|我不生产内容,我... 现在一提起P2P,人们就会联想到正在被有关部门“围剿”的互联网理财服务。×租宝事件使得劳...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...