申请"允许显示在其他应用的上层"权限发现的一些bug

来源:6-1 页面滑动流畅度FPS优化实战

默小铭

2021-04-22 15:55:20

问题描述:

在手机设置 "允许显示在其他应用的上层" 页面,如果不勾上权限的情况,再返回App,会一直端创建这个手机设置页面


分析了一下代码

 //监听前后台
    ActivityManager.instance.addFrontBackCallback(object :
        ActivityManager.FrontBackCallback {
        override fun onChanged(front: Boolean) {
            if (front) {
                play()
            } else {
                stop()
            }
        }

    })
}

private fun play() {
    //判断是否有"允许显示在其他应用的上层"权限
    if (!hasOverlayPermission()) {
        startOverlaySettingActivity()
        HiLog.e("app has no overlay permission")
        return
    }

    frameMonitor.start()
    if (!isPlaying) {
        isPlaying = true
        windowManager!!.addView(fpsView, params)
    }

}

private fun startOverlaySettingActivity() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        application.startActivity(
            Intent(
                Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + application.packageName)
            ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        )
    }
}

private fun hasOverlayPermission(): Boolean {
    return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(
        application
    )
}


原因是一开始,点击Debugtool开关直接调用play(),跳转到手机设置页面后,直接点返回

然后这个检测应用是否在前台的方法一检测到app在前台就又调用play(),一直点返回,条件一直满足,就一直启动手机设置页面了,


尝试过的解决方式:

1. 这个FpsMonitor类又不是Activity,不能用onActivityResult处理页面返回(否决)

2. SingleTask

然后就是看代码 addFlag(Intent.FLAG_ACTIVITY_NEW_TASK),一开始以为是SingTask模式,百度说 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);

也是singleTask,转成 kotlin   |  符号  变成 or 了,然后编译报错,麻烦老师说下解决方法,还有这个符号转成kotlin是啥?


3. 后面最后觉得比较合适的是调整流程,把权限判断放在toggle(),在点击时判断权限,但这样写,申请完权限后,回到app,fps小弹窗卡住了不更新数据,退出app才正常


fun toggle() {
//判断是否有"允许显示在其他应用的上层"权限
   if (!hasOverlayPermission()) {
startOverlaySettingActivity()
HiLog.e("app has no overlay permission")
return
   }
if (isPlaying) {
stop()
} else {
play()
}
}


后面我打日志发现更新textView那里不更新了,因为init{} 代码块只执行一次


private fun play() {
//显示当前fps
   frameMonitor.addListener(object : FpsCallback {
override fun onFrame(fps: Double) {
HiLog.e("FpsMonitor", fps)
fpsView.text = decimal.format(fps)
}
})

frameMonitor.start()
if (!isPlaying) {
isPlaying = true
       windowManager!!.addView(fpsView, params)
}

}

把更新textView代码挪去play() 就可以了

写回答

1回答

LovelyChubby

2021-04-22

1.  跳转到设置页面打开悬浮权限,如果没打开,页面回来之后确实还是会执行play,再跳转到权限设置页面。
这个问题加一个boolean值判断一下吧,已经跳转过了,就不跳了,toast提示下

2.java 中的操作符 |  是或的意思,转换到kotlin是or

0

移动端架构师

亲历日活千万级APP全流程落地,成为技术强+思维深+视野广 的P7级移动端架构师

578 学习 · 452 问题

查看课程