原来这样可以优雅地解决小米手机后台弹窗权限问题

本文针对小米手机特有的“后台弹出界面”权限问题提供了解决方案。通过代码判断权限状态,并引导用户手动开启,确保应用在后台也能正常启动界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

640?wx_fmt=jpeg


/   今日科技快讯   /


7月23日,据外媒报道,微软宣布将向总部位于美国旧金山的人工智能研究公司OpenAI投资10亿美元,为其云计算平台开发AI技术。


/   作者简介   /


本篇文章转载自nodzhang的博客,分享了他对于小米手机后台弹出界面权限的适配方案,相信会对大家有所帮助!


原文地址:

https://juejin.im/post/5d328ce3e51d454fbf540aad


/   前言   /


在一个风和日丽的下午,突然收到测试同学反馈在小米手机中有些页面无法正常启动的消息,我便立刻去排查代码,发现都是常规启动Activity的操作,却真的无法实现了,这让人感觉十分诡异。而这一现象只在小米手机中发生,所以断定肯定和小米手机的MIUI系统有关系,经过排查发现是小米手机中“后台弹出界面”的权限默认被拒绝了,这样在后台Service中或者其他一些后台操作都无法启动Activity了。


/   分析一波   /


在小米手机的应用权限管理中有一个“后台弹出界面权限”,该项权限会限制当APP处在后台时弹出Activity的动作,该权限时默认关闭的,可以在小米系统的权限管理页看到:


640?wx_fmt=jpeg


这个时候正常的startActivity()方法无法弹出Activity,在Log中筛选MIUILOG查看系统日志:


640?wx_fmt=png


我们可以看到其中有权限拒绝的具体说明:



 


可以看到是权限原因拒绝了启动Activity动作,随后我们在小米的官方论坛中也看到了他们的声明:


640?wx_fmt=png


/   解决方案   /


自从2019年5月份开始,小米开启了这项权限判断,所以之前可以正常弹出的界面现在无法弹出了。我们尝试了一些方法来绕过这个权限判断,比如启动一个前台Service来跳转、在Toast中来跳转,都无法绕过该权限判断,所以绕过权限这条路是不能走了,只能想办法正面解决。


商务谈判,让小米MIUI给默认开启此权限


我们普通APP安装后,此项权限默认是关闭的,当然有些大型APP具备和小米商务谈判的能力,小米会在系统设置中默认给予开启,比如“搜狗输入法”就是默认开启此权限的。


但是只有具备足够影响力的公司才能与小米谈判,而且要满足他们的各种条件,才能让其系统中默认为我们开启此权限,我们普通APP是做不到的,所以此方法不适用于我们普通APP。


进行权限判断,通过代码请求开启权限


我们面对普通权限请求一般处理方案是这样的,先判断是会否具有此项权限,如果没有就请求开启此权限。但是对于小米的这种厂商独有的权限,我们的难点在于没有相关API可以判断是否具备此权限,也没有API去申请此权限,所以这条路是不通的。当然可以通过反射之类的方法,去调用他系统层的一些东西,不过这样不太靠谱,研发代价也比较大,所以可以说是没有直接解决方案的。


那么这个问题就无解了么?我通过一系列讨论最后通过迂回方法进行解决,得出最终可用解决方案:


  1. 判断要启动的Activity是否被成功启动,如果没有则代表没有获取到权限。


  2. 弹窗提示用户去开启该权限。(由于没有后台弹出权限,无法直接跳转到系统的权限设置页,所以弹窗提示)


这里难点在于判断Activity是否被成功打开了,至于弹窗引导自己定制引导内容即可。下面一节,具体对如何判断Activity被成打开进行说明。


/   判断Activity是否被成功启动   /


这里同样也尝试了多种方案,比如:


在每个Activity的OnCreate()方法中进行处理(最终放弃)


当startActivity()后做一个0.5s倒计时逻辑,在要启动的Activity的OnCreate()方法中发一个广播来去掉该倒计时,如果没有被取消那么就说明没有启动成功。这样需要在每个Activity中做处理,过于繁琐,所以放弃。


通过Activity栈获取栈顶Activity判断(最终放弃)


当startActivity()后做一个0.5s倒计时逻辑,然后通过Activity栈的管理获得栈顶Activity,判断是否打开成功。这样避免每个Activity都要处理,比如我们可以查到常用方法是这样的 :



 


这个问题在于这些方法在Android 5.1之后也失效了,网上也有其他方法,使用usageStatsManager.queryUsageStats要获取额外的权限,所以也不是合理的方法。最终这个方法也不能实现可用性。


最终解决方案


工具类统一处理startActivity()方法,同时开启一个0.5s的倒计时。在Application中自己管理记录栈顶的Activity,用于判断栈顶Activity并完成是否成功打开,如果没有打开则展示引导弹窗。


这样把启动Activity和权限判断都在一个工具类中处理,以后只需要调用这个工具类,就实现了启动Activity、判断权限、以及权限弹窗引导。同时自己进行Activity栈的管理,解决了无法在各个Android版本上完成对Activity启动判断的问题。


首先在Application中监听所有Activity的生命周期,来记录栈顶Activity:



 


然后在工具类中做统一处理:



 


最后使用的时候直接调用工具类的方法startActivity()即可:



/   总结   /


小米后台弹出权限问题的解决,是通过曲线救国的方法解决的,因为没有直接的API可调用。这里封装成了一个工具类,任何需要添加权限判断的地方只需要调用工具类的方法就行了,这样既实现了统一管理,又方便调用,所以这是我们最终采用的方案。


推荐阅读:

Android Q新特性,一起来学习折叠屏应该如何适配

7张图带你轻松理解Java 线程安全

动手开发一个滴滴出行,是的,你没有看错!


欢迎关注我的公众号

学习技术或投稿


640.png?


640?wx_fmt=jpeg

长按上图,识别图中二维码即可关注


<think>好的,我现在需要帮助用户解决小米手机上使用uniPush2.0时离线消息通知没有横幅出的问题。首先,我得回顾用户提供的引用内容,看看有没有相关的线索。 根据引用[2]中提到,离线推送需要配置厂商的消息分类,否则可能收不到离线消息。这可能涉及到小米手机的通知设置,特别是横幅通知权限问题。用户的问题核心在于如何检测和请求这个权限,并在未开启时引导用户设置。 首先,我应该考虑如何在Android系统中检测通知权限,尤其是针对小米设备的横幅通知。通常,Android应用可以通过NotificationManager来检查是否拥有通知权限,但不同厂商可能有不同的设置路径。例如,小米可能需要特定的权限或额外的配置。 接下来,引导用户开启权限。这通常包括检查权限是否被授予,如果没有,则跳转到应用的设置页面或者直接跳转到小米的通知设置页面。这里可能需要使用Intent来打开特定的设置界面,但需要注意不同MIUI版本的路径可能不同,可能存在兼容性问题。 另外,引用[2]还提到离线推送需要配置厂商的消息分类,这可能意味着在uniPush的后台需要为小米通道正确配置消息分类,否则即使权限开启,通知可能也不会显示。因此,可能需要用户确认uniPush后台小米通道配置是否正确,消息分类是否符合小米的要求。 最后,测试和注意事项部分需要考虑用户可能遇到的常见问题,比如设置路径变化、需要重启应用等。同时,如果问题依旧存在,可能需要进一步检查日志或联系uniPush技术支持。 总结步骤应该是: 1. 检查通知权限是否开启。 2. 如果未开启,引导用户跳转到设置页面。 3. 确认uniPush后台小米通道配置正确。 4. 测试并处理可能的兼容性问题。 需要确保代码示例正确,比如使用checkNotificationPermission方法来检测权限,并处理返回结果。同时,提供设置跳转的Intent结构,可能需要特定包名和类名来直接打开小米的通知设置。 可能还需要提醒用户,不同MIUI版本路径不同,如果直接跳转失败,可以引导用户手动查找设置。此外,厂商通道的消息分类配置是否正确也会影响横幅显示,这部分需要用户自查uniPush的后台配置。 最后,确保回答结构清晰,分步骤说明,并包含代码示例和注意事项,帮助用户逐步解决问题。</think>### 解决方案:检查并请求小米手机横幅通知权限 #### 1. **检查通知权限状态** 在Android系统中,需要先确认应用是否已获取通知权限,并特别针对小米手机的横幅通知(悬浮通知)进行检测。可通过以下代码实现: ```java // 检查通知权限是否开启 public boolean checkNotificationPermission(Context context) { NotificationManagerCompat manager = NotificationManagerCompat.from(context); return manager.areNotificationsEnabled(); } // 检查是否为小米设备并验证横幅通知设置 public boolean isMiuiBannerEnabled(Context context) { if (!"xiaomi".equalsIgnoreCase(Build.MANUFACTURER)) return false; try { ContentResolver resolver = context.getContentResolver(); return Settings.Secure.getInt(resolver, "miui_notification_banner") == 1; } catch (Exception e) { e.printStackTrace(); return false; } } ``` #### 2. **引导用户开启权限** 若检测到权限未开启,需跳转到小米手机通知设置页: ```java // 跳转至小米应用通知设置页 public void openMiuiNotificationSettings(Activity activity) { try { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.notification.settings.AppNotificationSettingsActivity")); intent.putExtra("app_package", activity.getPackageName());
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值