Android设置应用数字角标

最近遇到一个需求,需要将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平台的角标实现的一个记录,希望能对各位有一点点帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值