最近遇到一个需求,需要将APP内某几个tab的未读消息数显示到桌面的应用角标上,于是查阅了一番资料,并咨询了几家应用开放平台,踩了几个小坑,最终勉强实现了自己的需求。由于国内主流手机为华为、小米、vivo、OPPO,故目前只准备实现这四款机型的角标功能,不过OPPO在咨询客服的时候被告知不开放数字角标的功能,因此目前就实现了华为、小米与vivo的需求。(不管什么机型都需要确认桌面图标角标权限是开启状态)
一、华为机型
华为提供有实现方式,需要注意的地方只有两点,一个是在manifest中添加权限,
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>另一个是填写的地方是项目的launcherActivity,具体代码如下:
/**
* 华为手机 创建角标
* @param context
* @param num 角标数
*/
public void setHuaWeiBadgeNum(Context context,int num) {
try {
Bundle bunlde = new Bundle();
bunlde.putString("package", context.getPackageName());
bunlde.putString("class", "com.xxxx.xxxx.LauncherActivity");//此处为启动页路径
bunlde.putInt("badgenumber", num);
context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, bunlde);
} catch (Exception e) {
e.printStackTrace();
}
}
二、小米机型
小米厂商的角标设置别出心裁,厂商通过通知消息来创建角标信息,所以,想要让小米手机显示应用角标,需要搭配通知一起使用。这不是什么问题,问题是当我按照文档中实现后,发现应用只有第一次会显示角标,之后都不会再显示了。其实这时候小米是创建了角标,不过由于APP在前台,所以创建后又消失了,导致我以为没有创建成功。发现这个问题后,我的实现方式就改为,当APP退到后台的时候 再去创建通知,这样角标就能正常显示了。
注意点:
1、 提前把手机的通知过滤给关掉,不然只会有通知不会有角标显示。
2、 如果消息通知使用同一个id,则需要每次发送通知前将上一条消息清除掉,否则不会 显示角标。
/**
* 小米手机创建通知信息并创建角标
* @param context
* @param num
*/
public void setXiaoMiBadgeNum(Context context,int num) {
try{
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String title = "消息提示";
String desc = "您有" + num + "条未读消息";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
String channelId = "default";
String channelName = "默认通知";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(true);
notificationManager.createNotificationChannel(channel);
}
Notification notification = new NotificationCompat.Builder(context, "default")
.setContentTitle(title)
.setContentText(desc)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.icon_logo)
.setAutoCancel(true)
.setChannelId("default")
.setNumber(num)
.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL)
.build();
notificationManager.cancel(1);
Field field = notification.getClass().getDeclaredField("extraNotification");
Object extraNotification = field.get(notification);
Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class);
method.invoke(extraNotification, num);
notificationManager.notify(1, notification);
}catch (Exception e){
e.printStackTrace();
}
}
在application里监听APP退到后台
BaseApplication.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
if (Build.MANUFACTURER.equalsIgnoreCase("xiaomi") && !AppUtils.isForeground()) {
new AppBadgeUtil().setXiaoMiBadgeNum(activity);
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
//当前应用是否处于前台
public static boolean isForeground() {
android.app.ActivityManager am = (ActivityManager) BaseApplication.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
String currentPackageName = cn.getPackageName();
if (!TextUtils.isEmpty(currentPackageName) && currentPackageName.equals(BaseApplication.getPackageName())) {
return true;
}
return false;
}
三、vivo机型
vivo之前是不开放角标的,现在官方文档里开放了角标并且提供了对应的方法,与华为用法差不多,不过存在一定的限制条件。一、不能使用vivo自身的推送渠道,二、手机需要8.0及以上的Android版本。
官方文档中提示8.0以上版本需要添加flag
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
不过在intent的源码中,FLAG_RECEIVER_INCLUDE_BACKGROUND是被@hide修饰的,外部无法调用,所以这里直接将它对应的int值填入
vivo也需要在manifest中添加权限,不要忘记了:
<uses-permission android:name="com.vivo.notification.permission.BADGE_ICON" />
/**
* vivo手机创建角标
* 只有非vivo推送渠道并且8.0以上手机才可以使用下列方式
* @param context
* @param num
*/
@SuppressLint("WrongConstant")
public void setVivoBadgeNum(Context context,int num) {
Intent intent = new Intent();
intent.setAction("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");
intent.addFlags(0x01000000);
intent.putExtra("packageName", context.getPackageName());
intent.putExtra("className", "com.xxxx.xxxx.LauncherActivity");
intent.putExtra("notificationNum", num);
context.sendBroadcast(intent);
}
角标实现的方式如果平台支持那么都会提供方法,但是其中很多细节都需要自己去慢慢摸索,上面是我对华为、小米、vivo平台的角标实现的一个记录,希望能对各位有一点点帮助。