前言:本文主要讲述了以下三方面:

  1. 怎么在Android系统下让自家的应用图标像iOS系统那样支持数字角标的显示?
  2. 在网上找不到现成的解决方案的情况下,该如何去寻找问题的突破口?
  3. 一种简洁性和扩展性都比较高的封装思路。

先放一个传送门:GitHub传送门

1.Android系统下如何支持应用桌面角标(BadgeNumber)的显示

iOS系统下的应用桌面角标

其实本来Android原生系统是不支持应用桌面角标(BadgeNumber)显示的。我们目前看到的能支持应用桌面角标显示的Android系统,都是第三方厂商自己定制的。通过实现一套自己的launcher并且提供外部接口给第三方应用来调用即可。

我们公司的APP里涉及到IM的功能。所以经常会有用户向客服反馈,为什么QQ、微信都支持应用桌面角标的显示,但你们的APP却不行......本着用户就是上帝的原则,于是应用桌面角标显示的优化就提上了日程。其实,测试部门在之前就已经跟我们提过这事了,只不过当时正忙于项目开发,没时间优化。前段时间需求不多的时候,给公司的Android应用加上了桌面角标显示的支持。现在将这个优化的过程总结一下。

目前已经存在的开源库

如果大家有接触过这方面的优化,应该很快就可以在搜索引擎上找到某个被推荐次数较多的开源库 ShortcutBadger。

虽然这个库适配的覆盖机型貌似很多,但在实际的测试中发现,某些方法可能对于目前市面上的国产流行机型已经不奏效了。所以,不建议大家直接将这个开源项目用到项目中去。作为学习和参考倒是一个不错的选择。而且,在实际方案抉择的过程中,我们发现,公司的APP主流机型排行榜中,前十的机型几乎被OPPO、vivo、华为、小米这四个品牌屠榜了。所以,我们的优化目标暂时就先定下来了:先集中精力适配市面上的这四个主流品牌机型。其他的冷门机型,后面再慢慢完善。(其实实际上我们也找不来那么多冷门的机型进行测试,所以对于没自身确认过奏效的方案,即使网上已经有人给出,出于谨慎还是先不采纳)

国产主流机型应用角标的适配(OPPO、vivo、华为、小米)

在开始之前,先声明一下。第一,不是所有的国产手机都能找到支持角标显示的方案(即使理论上可以,可能人家只对QQ微信等一些国民级的应用开放设置应用角标的白名单)。第二,本文中涉及到的方案都是经过实际测试且奏效的了(因为测试手机有限,所以不敢说针对这四个品牌的手机机型百分百支持,但支持大部分的机型应该是没问题的)。而且,有些品牌的手机适配方案很容易找到,有些品牌的适配方案则很难找到,这部分我会放到后面的章节来说。下面直接上适配方案:

华为:

先在AndroidManifest文件里配置好下面的权限:

 <!--华为手机更新应用桌面角标需要的权限--><uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>

设置角标的方法如下:

 public static void setBadgeNumber(Context context, int number) {try {if (number < 0) number = 0;Bundle bundle = new Bundle();bundle.putString("package", context.getPackageName());String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();bundle.putString("class", launchClassName);bundle.putInt("badgenumber", number);context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, bundle);} catch (Exception e) {e.printStackTrace();}}

OPPO:

    public static void setBadgeNumber(Context context, int number) {try {if (number == 0) {number = -1;}Intent intent = new Intent("com.oppo.unsettledevent");intent.putExtra("pakeageName", context.getPackageName());intent.putExtra("number", number);intent.putExtra("upgradeNumber", number);if (canResolveBroadcast(context, intent)) {context.sendBroadcast(intent);} else {try {Bundle extras = new Bundle();extras.putInt("app_badge_count", number);context.getContentResolver().call(Uri.parse("content://com.android.badge/badge"), "setAppBadgeCount", null, extras);} catch (Throwable t) {t.printStackTrace();}}} catch (Exception e) {e.printStackTrace();}}public static boolean canResolveBroadcast(Context context, Intent intent) {PackageManager packageManager = context.getPackageManager();List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);return receivers != null && receivers.size() > 0;}

vivo:

public static void setBadgeNumber(Context context, int number) {try {Intent intent = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");intent.putExtra("packageName", context.getPackageName());String launchClassName = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent().getClassName();intent.putExtra("className", launchClassName);intent.putExtra("notificationNum", number);context.sendBroadcast(intent);} catch (Exception e) {e.printStackTrace();}}

小米:

小米的设置应用角标方式比较有个性,跟其他厂商的不太一样,是跟Notification绑定在一起的。而且小米系统还有个比较特殊的地方,如果在应用内直接调用设置角标的方法,设置角标会不生效,所以只能在应用在后台并且收到推送的情况下进行角标的设置。另外,即使你设置了角标的显示,只要用户点击应用图标进入到应用内,应用的角标就会自动消失掉,即使应用内还存在新的未读消息。所以,针对小米机型,建议在收到推送后并且进行notification的时机更新应用角标

//在调用NotificationManager.notify(notifyID, notification)这个方法之前先设置角标显示的数目public static void setBadgeNumber(Notification notification, int number) {try {Field field = notification.getClass().getDeclaredField("extraNotification");Object extraNotification = field.get(notification);Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class);method.invoke(extraNotification, number);} catch (Exception e) {e.printStackTrace();}}

2.在网上找不到现成的解决方案的情况下,该如何去寻找问题的突破口?

在上面的适配方案中,最容易找到而且奏效的就是华为和小米的适配方案。而OPPO的适配方案,即使找到了,在现有的测试机型上却不奏效;vivo的是适配方案则是最难找的。既然在网上找不到,而QQ和微信貌似又是适配得最好的,这就说明,QQ和微信的源码里肯定有现成的解决方案。那么,不如尝试一下反编译,看看能不能从这两个超级APP中找到一些灵感?

在对QQ的apk进行反编译后,在某各类下果然找到了设置应用角标的实现类:

QQ设置桌面角标的实现类

从上图可以看出,QQ对于各种厂商的适配算是比较完善的了。除了小米、华为、OPPO、vivo,还适配了联想、三星、索尼等。

不同机型的适配方法也都有具体的实现:(下面是手Q对于OPPO和vivo的适配)

手Q对于OPPO和vivo的适配

但是,我们也不能直接拷贝过来就使用。因为说不定有些方法只针对QQ才生效呢是吧?

在对微信的apk进行反编译后,也能找到关于应用角标适配的代码:

微信对于vivo手机桌面角标的适配

总之,对比了一下QQ和微信的源码,在某些机型的适配方式上,可能两边会有些出入。实现方式可能也不太一样。但不得不说,不亏是大厂的APP,看了源码后,实现是学习了很多,特使是一些细节上的处理。

上面总结出的适配方案,其实就是在参考了网上各种资料以及QQ和微信的源码之后总结出来的可行的适配方案。如果还不满足大家的需求,大家可以去找一下QQ和微信的源码来进行研读,并总结出一套属于自己的适配方案。

3.一种扩展性比较高的简洁的封装思路

看完了QQ和微信的源码后,我发现两边都有一个共同点,那就是某个实现类里塞了很多适配的方法。估计也是可能涉及到不同的人在不同时期维护的历史原因。但一个类里面的代码太多了,可能会对查阅以及后续维护造成一些不便。

这里,我参考了Android源码里面NotificationManagerCompat这个类的实现方式。Android源码中本身就涉及到很多关于不同版本的适配的场景。某个方法,在不同的版本下,可能实现方式不太一样。于是,怎么在不断往某个类增加不同的实现方式的情况下,保持代码的美观以及扩展性易读性变成了一个问题。NotificationManagerCompat这个类的实现就十分简洁美观。下面是一部分源码截图,有兴趣的可以直接去看一下完整的源码。

下面就是模仿后的实现:

public class BadgeNumberManager {private Context mContext;private BadgeNumberManager(Context context) {mContext = context;}public static BadgeNumberManager from(Context context) {return new BadgeNumberManager(context);}private static final BadgeNumberManager.Impl IMPL;/*** 设置应用在桌面上显示的角标数字* @param number 显示的数字*/public void setBadgeNumber(int number) {IMPL.setBadgeNumber(mContext, number);}interface Impl {void setBadgeNumber(Context context, int number);}static class ImplHuaWei implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerHuaWei.setBadgeNumber(context, number);}}static class ImplVIVO implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {BadgeNumberManagerVIVO.setBadgeNumber(context, number);}}static class ImplBase implements Impl {@Overridepublic void setBadgeNumber(Context context, int number) {//do nothing}}static {String manufacturer = Build.MANUFACTURER;if (manufacturer.equalsIgnoreCase("Huawei")) {IMPL = new ImplHuaWei();} else if (manufacturer.equalsIgnoreCase("vivo")) {IMPL = new ImplVIVO();} else if (manufacturer.equalsIgnoreCase("XXX")) {//其他品牌机型的实现类IMPL = new ImplXXX();......} else {IMPL = new ImplBase();}}
}

使用的时候,只需要调用BadgeNumberManager.from(context).setBadgeNumber(num)就行了。BadgeNumberManagerHuaWeiBadgeNumberManagerVIVO等都是针对某个手机品牌的具体实现类。

当然,这只是一种实现的思路而已。具体去实现的时候,请根据自己项目的实际情况,怎样实现扩展性可读性较高就选哪种。

4.后记

如果有关于别的机型的适配方案,欢迎在评论下留言(最好是自己亲自测试过并且有效的)。如果文章中有出现错误的地方,欢迎指正。如果对于文章中的某些部分有不同的理解和想法,或者有更好的想法, 也欢迎留言讨论。

5.填坑记录(2017.12.11)

  1. 经过测试,目前暂时不支持的机型:华为荣耀6、OPPO A59、OPPO R9,OPPO R11、vivo X9i(截止至2017.12.11)

  2. 一开始以为某些机型不支持可能是少了某些跟角标设置相关的权限,于是反编译微信、QQ、支付宝,从这些App中收集AndroidManifest里配置的可能跟角标设置相关的权限,并添加到Demo中来测试,后来发现还是不行

  3. 针对华为手机,在某些机型上,例如华为 mate9,在manifest里除了需要配置com.huawei.android.launcher.permission.CHANGE_BADGE权限之外,还需要配置android.permission.INTERNET权限才可以正常设置桌面角标(不过一般的App应该都会配置了android.permission.INTERNET权限)

  4. 关于OPPO手机,在一些较旧的机型上可以正常设置桌面角标,但在一些比较新的机型上(例如OPPO R9,OPPO R11等),只有在通知权限管理中,有“在桌面图标上显示角标”这个选项的App才可以正常设置角标。目前就只发现QQ,微信,钉钉有这个权限,就连支付宝都没有这个权限。于是尝试着写了个Demo,将Demo的包名改成了微信的包名,然后在通知权限管理中,就出现了“在桌面图标上显示图标”这个选项。所以,在新的机型上,OPPO应该是根据包名来维护了一个白名单,只针对一些比较大型的IM类型的App开放桌面角标设置的权限。所以,这个问题暂时还没有解决方法

转载自:https://www.jianshu.com/p/199a9238015f

Android 角标设置相关推荐

  1. android 角标最新设置方案

    1.先大致说下主流厂商目前对角标的支持吧. 华为:支持. 小米:支持. vivo:中高端支持.老版本不支持(7.0.8.0设备). oppo:.需要申请:[应用服务]教你如何给应用软件申请Push角标 ...

  2. android 角标数字管理,Android应用推送角标设置方法

    原标题:Android应用推送角标设置方法 Android最初原生是没有角标的,各大手机厂商推出了角标,适配也是相对麻烦,需要去适配各家,这里做了整理及使用方法 先把工具类贴出来 importandr ...

  3. Android应用推送角标设置方法

    Android最初原生是没有角标的,各大手机厂商推出了角标,适配也是相对麻烦,需要去适配各家,这里做了整理及使用方法 先把工具类贴出来 package cn.com.goldwind.eis.util ...

  4. php 友盟推送角标,桌面角标设置以及消息推送服务

    更新记录 0.01(2020-05-09) 1.添加角标设置 2.添加清除角标 3.添加品牌获取 4.添加通知栏推送 5.添加点击通知栏进入APP 平台兼容性 Android iOS × 原生插件通用 ...

  5. Android 角标 小圆点 右上角显示数字 自定义角度

    效果如图 首先添加依赖: // 角标implementation 'q.rorbin:badgeview:1.1.3' 设置角标 比较关键的是布局配合 <FrameLayoutandroid:i ...

  6. Android 角标适配

    小米手机 默认逻辑 当应用向通知栏发送了一条通知 (除了进度条样式和常驻通知外),应用图标的右上角就会显示「1」.值得一提,角标的数字代表应用的通知数,即应用发送了「x」条通知,角标就会显示为「x」. ...

  7. php 友盟推送角标,android集成友盟推送实现离线在线推送及桌面图标角标设置

    本人亲测有效,有问题欢迎评论,互相学习 1.集成友盟推送-根据友盟文档集成即可实现在线推送 2.集成后想要实现点击跳转到指定页面,那么就要根据后台返回的数据进行跳转 (1)在线推送-在applicat ...

  8. UNI-APP 桌面LOGO角标设置(ios)

    使用uni-push后在ios上桌面图标显示角标, 并且不消失 var UIApplication = plus.ios.import("UIApplication"); var ...

  9. android 角标框架,Android 实现桌面未读角标

    在小米 三星  索尼 手机 :图标上显示数字(未读消息数):这部分代码,是从QQ5.0.apk中找的. 小米已经测试通过了, 三星和索尼的,由于没有相应的手机,没有测试,有的,可能修改一下代码(判断是 ...

  10. Android设置应用数字角标

    最近遇到一个需求,需要将APP内某几个tab的未读消息数显示到桌面的应用角标上,于是查阅了一番资料,并咨询了几家应用开放平台,踩了几个小坑,最终勉强实现了自己的需求.由于国内主流手机为华为.小米.vi ...

最新文章

  1. LeetCode Search in Rotated Sorted Array II
  2. JavaScrip有哪些优点
  3. 下拉列表项过多会导致浏览器卡死
  4. windows 自动备份mysql方案
  5. iOS警报– UIAlertController
  6. php 学习笔记之搭建开发环境(mac版)
  7. spark记录(7)SparkCore的调优之数据倾斜调优
  8. Java-第N篇推荐的一些学习书籍
  9. C语言实现学生成绩管理系统设计
  10. CAJ云阅读怎么用,可以修改caj文件吗?
  11. NoSQL03 - 主从复制、RDB/AOF持久化 数据类型
  12. 单片机c语言reti的用法,51系列单片机的RETI指令分析
  13. 【LeetCode/力扣】1723. 完成所有工作的最短时间
  14. DSML_用Excel实现按行排序后按列排序,最后高亮重复值
  15. Web服务------LNMP架构的安装(Nginx,Mysql,PHP,Discus论坛 安装详解)
  16. Golang系列之整数类型基本介绍
  17. Windows 更改终端服务(RDP 远程桌面) 默认远程端口的方法
  18. 格林时间转换成正常时间
  19. orc识别较慢_关于半自动标注工具PPOCRLabel运行速度由快逐渐变慢的问题
  20. 基于PHP+MySQL实现(Web)英语学习与测试平台【100010284】

热门文章

  1. luogu 2735 电网 皮克公式
  2. IOS支持IPv6 DNS64/NAT64网络
  3. 优启通如何写入linux启动盘,优启通u盘启动盘制作工具使用教程(附下载)
  4. 数商云在线供应链系统服务方案:构建企业供应链平台业务、功能、技术管理架构
  5. 物联网共享单车有什么物联技术?
  6. 5分钟快速入门大数据、数据挖掘、机器学习
  7. 用sci-hub的文献检索方法
  8. flink job 提交模式
  9. asp.net母版页学习总结
  10. [jzoj 6080] [GDOI2019模拟2019.3.23] IOer 解题报告 (数学构造)