【Android组件核心面试题】如何判断一个 APP 在前台还是后台?

如何判断一个 APP 在前台还是后台?

这道题想考察什么?
  1. 是否了解如何判断一个 APP 在前台还是后台与真实场景使用,是否熟悉如何判断一个 APP 在前台还是后台在工作中的表现是什么?
考察的知识点
  1. 如何判断一个 APP 在前台还是后台的概念在项目中使用与基本知识
考生应该如何回答
1.你在工作中是如何对如何判断一个 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方式实现:

Android5.0之后已经被废弃。

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

appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND

下述code永远成立,这样就无法判断到底那个是前台了

	/**
     * 判断当前应用是否处于前台
     */
    private fun isAppForeground(): Boolean {
        val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        /**
         * 存活的App进程
         */
        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
    }
	 /**
     * 用于判断那个应用是处于前台的
     */
    private fun getForegroundApp(): String? {

        val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        var runningAppProcesses = activityManager.runningAppProcesses
        if (runningAppProcesses.isNullOrEmpty()) {
            return null
        }

        runningAppProcesses.forEach {

            if (it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND || it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                return it.processName
            }
        }

        return null
    }
ActivityLifecycleCallbacks方式实现:

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

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
}

然后我们在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是前台还是后台

最后

我整理了一套Android面试题合集,除了以上面试题,还包含【Java 基础、集合、多线程、虚拟机、反射、泛型、并发编程、Android四大组件、异步任务和消息机制、UI绘制、性能调优、SDN、第三方框架、设计模式、Kotlin、计算机网络、系统启动流程、Dart、Flutter、算法和数据结构、NDK、H.264、H.265.音频编解码、FFmpeg、OpenMax、OpenCV、OpenGL ES
在这里插入图片描述

有需要的朋友可以扫描下方二维码,免费领取全部面试题+答案解析!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值