一、应用的角标如下面的红点,提示用户有新的信息更新。角标,英语是badge,也就是“徽章,像章,奖章; 象征,标记”的意思。一般来说,应用的角标是用来标记有多少条提醒(Notification)没读(unread),一旦点击提示进应用阅读了,角标也会消失。
二、如何实现呢?原生是不支持应用角标的,是各个手机厂商自己在系统中实现的应用角标,并且部分厂商提供了设置的方式,所以需要对各个厂商的系统进行适配。
三、华为手机的实现代码,参考华为开发者文档,需要添加权限
<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
四、三星手机角标实现代码,三星手机发送一个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应用角标适配方法 - 简书
有关 Android 应用桌面角标 (BadgeNumber) 实现的探讨 - 灰信网(软件开发博客聚合)
八、其他参考文章
https://www.jb51.net/article/111315.htm
https://www.jb51.net/article/119787.htm