You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter应用移除后台后“显示在其他应用上层”功能3-4小时后失效问题求助

Flutter应用移除后台后“显示在其他应用上层”功能3-4小时后失效问题求助

兄弟,我之前也踩过类似的Android后台保活+悬浮窗失效的坑,你这个情况大概率是系统的后台进程回收和省电机制在搞事情,咱们一步步来排查解决:

  • 先把承载悬浮窗的服务改成前台服务
    现在Android对后台进程管控特别严,普通后台Service很容易被系统回收,哪怕你有悬浮窗权限。你得把显示悬浮窗的Service设为前台服务,而且Android 8.0+要求必须绑定一个可见的通知(不能是静默的),这样系统会把进程优先级拉高,不容易被干掉。
    具体操作需要用Flutter的MethodChannel调用原生Android代码:在Service的onCreate或者onStartCommand方法里调用startForeground(NOTIFICATION_ID, notification),提前创建好对应的通知渠道,通知内容可以写“XX悬浮窗服务运行中”之类的,让用户知道你的应用在后台干活。

  • 把应用加入电池优化白名单
    不管是原生Android还是国产ROM(小米、华为、OPPO这些),电池优化功能都会杀掉后台进程来省电,3-4小时的存活时间刚好符合系统进入Doze模式(空闲省电模式)的时间点。
    你可以在代码里请求忽略电池优化的权限:首先在AndroidManifest.xml里加权限声明:

    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    

    然后在合适的时机(比如用户开启悬浮窗功能时)弹出请求:

    Intent intent = new Intent();
    String packageName = getPackageName();
    PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
    if (!pm.isIgnoringBatteryOptimizations(packageName)) {
        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
        startActivity(intent);
    }
    

    记得要跟用户说明为什么要开这个权限,比如“为了保证悬浮窗持续运行,需要关闭电池优化”,别让用户觉得你在偷电。

  • 检查ROM的后台自启动权限
    很多国产ROM有自己的后台管控逻辑,比如小米的“自启动管理”、华为的“后台活动限制”,如果没开自启动,系统回收进程后就没法自动拉起。你可以在应用的设置页里加个引导,告诉用户去系统设置里开启你的应用的自启动权限,这个是硬需求,不然光靠代码很难绕过。

  • 给Service设置重启策略
    在Service的onStartCommand方法里返回START_STICKY或者START_REDELIVER_INTENT,这样当Service被系统回收后,系统会尝试重新启动它:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 这里初始化悬浮窗的逻辑
        return START_STICKY;
    }
    

    不过要注意,START_STICKY在Doze模式下可能不会生效,所以还是要结合前面的前台服务和电池优化白名单一起用。

  • 兜底检查悬浮窗权限
    虽然你已经获取了SYSTEM_ALERT_WINDOW权限,但偶尔系统可能会因为某些原因重置权限状态?(概率不大,但可以做兜底)每次尝试显示悬浮窗前,先检查权限是否存在:

    if (!Settings.canDrawOverlays(context)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }
    

总结一下,你这个问题的核心就是系统的省电机制把你的后台进程干掉了,优先搞定前台服务和电池优化白名单,再配合自启动权限,应该就能解决3-4小时后悬浮窗失效的问题了。

内容来源于stack exchange

火山引擎 最新活动