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
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在华为手机上,可以通过 BadgeProvider 提供的 API 来设置应用角标数。具体实现方法如下: 1. 首先,需要在 AndroidManifest.xml 文件中注册一个广播接收器,用于接收设置应用角标数的请求。代码如下: ```xml <receiver android:name=".BadgeReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BADGE_COUNT_UPDATE" /> <action android:name="android.intent.action.PACKAGE_REPLACED" /> <data android:scheme="package" /> </intent-filter> </receiver> ``` 2. 在 BadgeReceiver 中处理接收到的设置应用角标数的请求。代码如下: ```java public class BadgeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction() != null) { switch (intent.getAction()) { case "android.intent.action.BADGE_COUNT_UPDATE": // 获取应用的包名和角标数 String packageName = intent.getStringExtra("badge_package_name"); int badgeCount = intent.getIntExtra("badge_count", 0); // 设置应用角标数 setBadgeCount(context, packageName, badgeCount); break; case "android.intent.action.PACKAGE_REPLACED": // 应用更新后需要重新设置角标数 setBadgeCount(context, context.getPackageName(), 0); break; } } } /** * 设置应用角标数 */ private void setBadgeCount(Context context, String packageName, int badgeCount) { try { Bundle extras = new Bundle(); extras.putString("package", packageName); extras.putString("class", getLauncherClassName(context)); extras.putInt("badgenumber", badgeCount); context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, extras); } catch (Exception e) { e.printStackTrace(); } } /** * 获取应用的启动 Activity 的类名 */ private String getLauncherClassName(Context context) { PackageManager pm = context.getPackageManager(); Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setPackage(context.getPackageName()); List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0); if (resolveInfos != null && resolveInfos.size() > 0) { return resolveInfos.get(0).activityInfo.name; } return ""; } } ``` 3. 在应用设置角标数时,可以通过 Intent 来发送广播请求。代码如下: ```java int badgeCount = 10; Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); intent.putExtra("badge_package_name", getPackageName()); intent.putExtra("badge_count", badgeCount); sendBroadcast(intent); ``` 需要注意的是,华为手机上的角标设置功能只在 EMUI 4.1 及以上版本上支持。如果您的应用需要在其他手机上设置角标数,可以使用第三方库 ShortcutBadger。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值