当关闭通知消息权限后无法显示系统Toast的解决方案

2016-11-10 yiguo_blin 鸿洋


本文由yiguo_blin投稿。

yiguo_blin的博客地址:

http://blog.csdn.net/qq_25867141




1 前言   

不知道大家是否遇到了当你们的App在5.0以上系统中被用户关闭消息通知后(其实用户本身只是想关闭Notification的,猜测),系统的Toast也神奇的无法显示。当然这个问题并不复杂,有很多种解决方案,我们逐一探讨一下,然后来看看到底哪种方式会好一点。


2

问题分析

   

直接跟踪Toast的源码,其实我们可以发现,果真Toast其实是通过NotificationManagerService 维护一个toast队列,然后通知给Toast中的客户端 TN 调用 WindowManager 添加view。那么当用户关闭通知权限后自然也无法显示Toast了。




3

解决思路

   

这边就来说说我这边的几种解决方案,就是大致我能想到的,哈哈。


  • 自己仿照系统的Toast然后用自己的消息队列来维护,让其不受NotificationManagerService影响。

  • 通过WindowManager自己来写一个通知。

  • 通过Dialog、PopupWindow来编写一个自定义通知。

  • 通过直接去当前页面最外层content布局来添加View。


仿照系统Toast自己来维护Toast消息队列


这部分我就不写了,大家有兴趣可以看下解决小米MIUI系统上后台应用没法弹Toast的问题 (http://caizhitao.com/2016/02/09/android-toast-compat/)这篇博文,东西写的很详细,内容也很细,大家可以看看。


通过WindowManager自己来写一个通知


说起WindowManager,其实我对这个东西的第一印象就是强大,悬浮窗什么的其实都是通过WindowManager来实现的,那么我们来看看怎么实现,我就直接上代码了



嗯,这样写应该是没问题的,然后为啥没有效果呢??好吧,其实写了这么多,就是给自己挖坑,很明显,这个东西在现在的5.0以上机器中有一个悬浮窗权限,而且系统默认是关闭该权限的,只有用户手动打开才能显示,而且代码中也要添加如下一条权限。

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

那么问题又回来了,用户一般不会打开,这不是又白搞么。


通过Dialog、PopupWindow来编写一个自定义通知。


这个方案貌似也是可行的,代码就不写了,提醒一点就是一般来说Dialog和PopupWindow显示时有一个隔板,用户是无法点击其余部分控件的,所以记得加上以上属性。




通过直接去当前页面最外层content布局来添加View。


说说这种方式吧,其实刚开始我也是没有想到的,因为一般很少回去直接拿Activity最外层的content布局去创建一个View并且显示在上面的。

(ViewGroup) ((Activity) context).findViewById(android.R.id.content);

其实我们是可以直接通过findViewById去直接拿到最外层布局的哦,当然context记得一定是Activity。 


然后通过以下代码就可以直接把布局显示在当前content布局之上。

ViewGroup container = (ViewGroup) ((Activity) context)
    .findViewById(android.R.id.content);
View v = ((Activity) context).getLayoutInflater()
    .inflate(R.layout.etoast,container);

这种方式是不是有点奇怪,好吧,我也是这么想的,不过感觉还是非常的实在的,也不复杂,东西也不多,直接上代码。



简单说下吧,代码应该是很简单的,然后简单封装了和Toast相同的几个方法。嗯,其实大家也应该能发现我这边的布局其实是一直都在的,只是直接GONE掉了。所以呢,还是有待优化的地方,当然可以去想想是不是可以直接remove()掉什么的。


我这边也没有用队列,我觉得在一个Toast显示的期间如果再需要显示另一个Toast,直接把当前的文本改过来就好了,没有必要搞个队列的,而且系统Toast我最厌恶的就是这个了,用户如果不停的点击,那Toast一个接一个的显示,这个我觉得是不合理的。


上面的布局文件我也贴一下吧。有一点大家还是要注意下,因为我在完善的过程中其实遇到了很多种情况的BUG,所以最终需要大家再BaseActivity中的onDestory()方法中去手动调用一下EToast.reset();具体可以看源码中的解释。 


etoast.xml




shape_eroast_bg.xml




4

优化

   

上面的几种方式我大致也都走了一遍,其实我觉得都没啥区别,看你喜欢用哪种吧。我其实是采用了第四种,因为第一种的话我是不喜欢队列的,比如5个Toast排队还要一个一个等待显示,这样的体验我是不喜欢的。


第二种就不推荐了,因为又涉及到了其他的权限。第三种我没试,实现应该是不难的,效果的话也是随你喜欢。最后我采用的是第四种,因为这种方式之前是没有用到过的,也尝试一下。


那么来说说优化,如果直接替换掉系统的Toast,那相当的暴力,肯定妥妥的。那么我们能不能智能的去判断一下呢,如果用户没有关闭通知权限,那么久跟随系统的Toast去吧,这样好让App采用系统风格,对吧。 


方法是有的,如下:




据说android24 可以使用NotificationManagerCompat.areNotificationsEnabled()来判断,具体大家可以尝试。


那么如何来替换老项目中的Toast呢? 


我这边的话自定义Toast就是EToast了。为什么要E开头呢,因为公……你懂的。然后写一个Toast的工具类,如下:




然后直接把你项目的import Android.widget.Toast 全局替换成import 你Toast的包名 即可。


如果发现我上面有什么问题或者有好的解决方案的话欢迎和我留言讨论,比比在此谢过啦~




如果你有好的文章想和大家分享,欢迎投稿,直接向我投递文章链接即可。

欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号:

阅读原文


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值