一、应用的角标如下面的红点,提示用户有新的信息更新。角标,英语是badge,也就是“徽章,像章,奖章; 象征,标记”的意思。一般来说,应用的角标是用来标记有多少条提醒(Notification)没读(unread),一旦点击提示进应用阅读了,角标也会消失。

android 三角角标 安卓角标_android

二、如何实现呢?原生是不支持应用角标的,是各个手机厂商自己在系统中实现的应用角标,并且部分厂商提供了设置的方式,所以需要对各个厂商的系统进行适配。

三、华为手机的实现代码,参考华为开发者文档,需要添加权限

<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
    <uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE "/>
private static boolean setHuaweiBadge(int count, Context context) {
        try {
            String launchClassName = getLauncherClassName(context);
            if (TextUtils.isEmpty(launchClassName)) {
                return false;
            }
            Bundle bundle = new Bundle();
            bundle.putString("package", context.getPackageName());
            bundle.putString("class", launchClassName);
            bundle.putInt("badgenumber", count);
            context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher" +
                    ".settings/badge/"), "change_badge", null, bundle);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

文档中心https://developer.huawei.com/consumer/cn/doc/30802

android 三角角标 安卓角标_bundle_02

四、三星手机角标实现代码,三星手机发送一个notification后(或者已经有未读notification)和应用关闭的情况在角标才有效,这点跟华为不一样。

private static boolean setSamsungBadge(int count, Context context) {
        try {
            String launcherClassName = getLauncherClassName(context);
            if (TextUtils.isEmpty(launcherClassName)) {
                return false;
            }
            Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");
            intent.putExtra("badge_count", count);
            intent.putExtra("badge_count_package_name", context.getPackageName());
            intent.putExtra("badge_count_class_name", launcherClassName);
            context.sendBroadcast(intent);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

五、源码实例测试

1、MainActivity.java

package com.giada.myapplication;


import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 为应用添加角标,提示用户有新的未读消息
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private static int badgeCount = 100; //角标数量
    NotificationManager notificationManager;
    public static int notificationId  = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.badge_count_reduce_btn).setOnClickListener(this);
        findViewById(R.id.badge_count_add_btn).setOnClickListener(this);
        //设置角标数量
        BadgeUtils.setBadgeCount(this,100);
    }

    private static String getLauncherClassName(Context context) {
        ComponentName launchComponent = getLauncherComponentName(context);
        if (launchComponent == null) {
            return "";
        } else {
            return launchComponent.getClassName();
        }
    }

    private static ComponentName getLauncherComponentName(Context context) {
        Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context
                .getPackageName());
        if (launchIntent != null) {
            return launchIntent.getComponent();
        } else {
            return null;
        }
    }
    private static boolean setHuaweiBadge(int count, Context context) {
        try {
            String launchClassName = getLauncherClassName(context);
            if (TextUtils.isEmpty(launchClassName)) {
                return false;
            }
            Bundle bundle = new Bundle();
            bundle.putString("package", context.getPackageName());
            bundle.putString("class", launchClassName);
            bundle.putInt("badgenumber", count);
            context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher" +
                    ".settings/badge/"), "change_badge", null, bundle);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    public static boolean setNotificationBadge(int count, Context context) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService
                (Context.NOTIFICATION_SERVICE);
        if (notificationManager == null) {
            return false;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 8.0之后添加角标需要NotificationChannel
            NotificationChannel channel = new NotificationChannel("badge", "badge",
                    NotificationManager.IMPORTANCE_DEFAULT);
            channel.setShowBadge(true);
            notificationManager.createNotificationChannel(channel);
        }
        Intent intent = new Intent(context, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
        Notification notification = new NotificationCompat.Builder(context, "badge")
                .setContentTitle("应用角标")
                .setContentText("您有" + count + "条未读消息")
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap
                        .ic_launcher))
                .setSmallIcon(R.mipmap.ic_launcher_round)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent)
                .setChannelId("badge")
                .setNumber(count)
                .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL).build();
        // 小米
        try {
            Field field = notification.getClass().getDeclaredField("extraNotification");
            Object extraNotification = field.get(notification);
            Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int
                    .class);
            method.invoke(extraNotification, count);
        } catch (Exception e) {
            e.printStackTrace();
        }
        notificationManager.notify(notificationId++, notification);
        return true;
    }
    private static boolean setSamsungBadge(int count, Context context) {
        try {
            String launcherClassName = getLauncherClassName(context);
            if (TextUtils.isEmpty(launcherClassName)) {
                return false;
            }
            Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");
            intent.putExtra("badge_count", count);
            intent.putExtra("badge_count_package_name", context.getPackageName());
            intent.putExtra("badge_count_class_name", launcherClassName);
            context.sendBroadcast(intent);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.badge_count_reduce_btn:
                //Android原生方式 角标数量减1
               // BadgeUtils.setBadgeCount(this,--badgeCount);
                if (Build.MANUFACTURER.equalsIgnoreCase("HUAWEI")) {
                    setHuaweiBadge(--badgeCount, this);
                } else if (Build.MANUFACTURER.equalsIgnoreCase("Samsung")) {
                    setSamsungBadge(--badgeCount, this);
                    setNotificationBadge(badgeCount,this);
                    finish();
                }else {
                    setSamsungBadge(--badgeCount, this);
                    setNotificationBadge(badgeCount,this);
                    finish();
                }
                break;
            case R.id.badge_count_add_btn:

                if (Build.MANUFACTURER.equalsIgnoreCase("HUAWEI")) {
                    setHuaweiBadge(++badgeCount, this);
                } else if (Build.MANUFACTURER.equalsIgnoreCase("Samsung")) {
                    setSamsungBadge(++badgeCount, this);
                    setNotificationBadge(badgeCount,this);
                    finish();
                }else{
                    setSamsungBadge(++badgeCount, this);
                    setNotificationBadge(badgeCount,this);
                    finish();
                }

                break;

        }
    }
}

2、布局文件app\src\main\res\layout\activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:gravity="center"
    tools:context="com.giada.myapplication.MainActivity">

    <!--角标数量减1-->
    <Button
        android:id="@+id/badge_count_reduce_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="角标数量减1"
        android:layout_marginTop="10dp"/>

    <!--角标数量加1-->
    <Button
        android:id="@+id/badge_count_add_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="角标数量加1"
        android:layout_marginTop="50dp"/>


</LinearLayout>

3、测试界面

android 三角角标 安卓角标_android 三角角标_03

 六、三星手机和华为手机测试效果

android 三角角标 安卓角标_android 三角角标_04

android 三角角标 安卓角标_android_05

 

七、最有价值的参考文章

Android开发:史上最全Android应用角标适配方法 - 简书

有关 Android 应用桌面角标 (BadgeNumber) 实现的探讨 - 灰信网(软件开发博客聚合)

文档中心

八、其他参考文章

https://www.jb51.net/article/111315.htm

https://www.jb51.net/article/119787.htm