0 公用方法
在下面的实现代码中,有很多公用的代码,我们提取出来一些公用方法,代码如下:
1. private static String getLauncherClassName(Context context) {
2. ComponentName launchComponent = getLauncherComponentName(context);
3. if (launchComponent == null) {
4. return "";
5. } else {
6. return launchComponent.getClassName();
7. }
8. }
10. private static ComponentName getLauncherComponentName(Context context) {
11. Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context
12. .getPackageName());
13. if (launchIntent != null) {
14. return launchIntent.getComponent();
15. } else {
16. return null;
17. }
18. }
1 小米(支持)
小米在MIUI6及以上版本中是通过发送通知来设置角标的。当APP向通知栏发送了一条通知 (通知不带进度条并且用户可以删除的),那么桌面APP icon角标就会显示1。此时app显示的角标数是和通知栏里app发送的通知数对应的,即向通知栏发送了多少通知就会显示多少角标。
可以通过反射机制来定义每次通知的消息个数,应用的角标数为每条通知定义的通知个数的总和
我们发送了两条通知,一条通知为5个消息,一条为10个消息,应用角标显示为15个。此时,如果用户点击或移除掉5条消息的那个通知,应用角标会变成10。
另外,仅在APP在后台时收到通知会显示角标,而APP在前台时不会显示,APP被杀掉后通知及角标消失。
实现代码:
1. public static boolean setNotificationBadge(int count, Context context) {
2. NotificationManager notificationManager = (NotificationManager) context.getSystemService
3. (Context.NOTIFICATION_SERVICE);
4. if (notificationManager == null) {
5. return false;
6. }
7. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
8. // 8.0之后添加角标需要NotificationChannel
9. NotificationChannel channel = new NotificationChannel("badge", "badge",
10. NotificationManager.IMPORTANCE_DEFAULT);
11. channel.setShowBadge(true);
12. notificationManager.createNotificationChannel(channel);
13. }
14. Intent intent = new Intent(context, MainActivity.class);
15. PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
16. Notification notification = new NotificationCompat.Builder(context, "badge")
17. .setContentTitle("应用角标")
18. .setContentText("您有" + count + "条未读消息")
19. .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap
20. .ic_launcher))
21. .setSmallIcon(R.mipmap.ic_launcher_round)
22. .setAutoCancel(true)
23. .setContentIntent(pendingIntent)
24. .setChannelId("badge")
25. .setNumber(count)
26. .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL).build();
27. // 小米
28. try {
29. Field field = notification.getClass().getDeclaredField("extraNotification");
30. Object extraNotification = field.get(notification);
31. Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int
32. .class);
33. method.invoke(extraNotification, count);
34. } catch (Exception e) {
35. e.printStackTrace();
36. }
37. notificationManager.notify(notificationId++, notification);
38. return true;
39. }
测试结果:
小米6、小米5S、小米MIX、小米5X、小米4、红米Note 4X、小米2S均可通过通知的方式设置角标。
2 华为(支持)
可以通过ContentResolver方法直接设置应用角标,且应用在前台和被杀掉后仍可显示。
实现代码:
1. private static boolean setHuaweiBadge(int count, Context context) {
2. try {
3. String launchClassName = getLauncherClassName(context);
4. if (TextUtils.isEmpty(launchClassName)) {
5. return false;
6. }
7. Bundle bundle = new Bundle();
8. bundle.putString("package", context.getPackageName());
9. bundle.putString("class", launchClassName);
10. bundle.putInt("badgenumber", count);
11. context.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher" +
12. ".settings/badge/"), "change_badge", null, bundle);
13. return true;
14. } catch (Exception e) {
15. e.printStackTrace();
16. return false;
17. }
18. }
测试结果:
荣耀8、华为P10、华为Mate10、华为麦芒(MLA-AL00)均可直接设置。
3 OPPO(不支持)
旧款的OPPO手机有两种方法设置,没有测试机测试,不知道是否可行,实现代码如下:
1. private static boolean setOPPOBadge(int count, Context context) {
2. try {
3. Bundle extras = new Bundle();
4. extras.putInt("app_badge_count", count);
5. context.getContentResolver().call(Uri.parse("content://com.android.badge/badge"),
6. "setAppBadgeCount", String.valueOf(count), extras);
7. return true;
8. } catch (Exception e) {
9. e.printStackTrace();
10. return false;
11. }
12. }
13. private static boolean setOPPOBadge2(int count, Context context) {
14. try {
15. Intent intent = new Intent("com.oppo.unsettledevent");
16. intent.putExtra("packageName", context.getPackageName());
17. intent.putExtra("number", count);
18. intent.putExtra("upgradeNumber", count);
19. PackageManager packageManager = context.getPackageManager();
20. List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);
21. if (receivers != null && receivers.size() > 0) {
22. context.sendBroadcast(intent);
23. } else {
24. Bundle extras = new Bundle();
25. extras.putInt("app_badge_count", count);
26. context.getContentResolver().call(Uri.parse("content://com.android.badge/badge"),
27. "setAppBadgeCount", null, extras);
28. }
29. return true;
30. } catch (Exception e) {
31. e.printStackTrace();
32. return false;
33. }
34. }
新款的OPPO仅支持内置应用、微信和QQ显示角标,若要使用角标功能,必须提交申请,审核通过了才能开放,官方给的具体审核标准如下:
申请角标接入规则(应用必须适配OPPO手机,保证角标功能测试通过)
a) 系统应用;
b) 国内外各区域用户量排名Top5的三方即时通讯类应用,且只允许显示即时通信消息类通知(如QQ、微信、facebook、line);
c) OPPO公司内部费商业化及运营性质的办公类型即时通信应用(如Teamtalk);
d) 国内外邮件类应用(各区域各属于用户量第一梯队的应用)。
4 vivo(不支持)
旧款的vivo手机实现代码:
1. private static boolean setVivoBadge(int count, Context context) {
2. try {
3. String launcherClassName = getLauncherClassName(context);
4. if (TextUtils.isEmpty(launcherClassName)) {
5. return false;
6. }
7. Intent intent = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");
8. intent.putExtra("packageName", context.getPackageName());
9. intent.putExtra("className", launcherClassName);
10. intent.putExtra("notificationNum", count);
11. context.sendBroadcast(intent);
12. return true;
13. } catch (Exception e) {
14. e.printStackTrace();
15. return false;
16. }
17. }
5 三星(支持)
可以通过广播机制直接设置应用角标,且应用在前台和被杀掉后仍可显示。
实现代码:
1. private static boolean setSamsungBadge(int count, Context context) {
2. try {
3. String launcherClassName = getLauncherClassName(context);
4. if (TextUtils.isEmpty(launcherClassName)) {
5. return false;
6. }
7. Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE");
8. intent.putExtra("badge_count", count);
9. intent.putExtra("badge_count_package_name", context.getPackageName());
10. intent.putExtra("badge_count_class_name", launcherClassName);
11. context.sendBroadcast(intent);
12. return true;
13. } catch (Exception e) {
14. e.printStackTrace();
15. return false;
16. }
17. }
测试结果:
三星S9+:需和通知的方式结合才能显示角标。
三星 Galaxy S6 edge:可直接设置。
6 魅族(不支持)
官方不支持。
7 360(不支持)
目前可能仅支持系统应用、微信和QQ,不支持支付宝,未找到设置角标相关文档。
8 锤子(不支持)
目前仅支持系统应用和微信,甚至不支持QQ。
9 努比亚(不支持)
目前仅支持系统应用。
10 金立(不支持)
找不到相关文档。
11 乐视(支持,无法自定义数目)
仅支持通过通知设置角标,且角标数字为收到通知的条数,无法自定义角标数目。
测试结果:
乐2 Pro:可通过通知方式设置。
12 联想ZUK(支持)
实现代码:
1. private static boolean setZukBadge(int count, Context context) {
2. try {
3. Bundle extra = new Bundle();
4. ArrayList<String> ids = new ArrayList<>();
5. // 以列表形式传递快捷方式id,可以添加多个快捷方式id
6. // ids.add("custom_id_1");
7. // ids.add("custom_id_2");
8. extra.putStringArrayList("app_shortcut_custom_id", ids);
9. extra.putInt("app_badge_count", count);
10. Uri contentUri = Uri.parse("content://com.android.badge/badge");
11. Bundle bundle = context.getContentResolver().call(contentUri, "setAppBadgeCount", null,
12. extra);
13. return bundle != null;
14. } catch (Exception e) {
15. e.printStackTrace();
16. return false;
17. }
18. }
暂无测试机测试
13 中兴(不支持)
目前仅支持系统应用和微信,甚至不支持QQ。
14 HTC(支持)
可通过广播机制直接设置角标。
实现代码:
1. private static boolean setHTCBadge(int count, Context context) {
2. try {
3. ComponentName launcherComponentName = getLauncherComponentName(context);
4. if (launcherComponentName == null) {
5. return false;
6. }
8. Intent intent1 = new Intent("com.htc.launcher.action.SET_NOTIFICATION");
9. intent1.putExtra("com.htc.launcher.extra.COMPONENT", launcherComponentName
10. .flattenToShortString());
11. intent1.putExtra("com.htc.launcher.extra.COUNT", count);
12. context.sendBroadcast(intent1);
14. Intent intent2 = new Intent("com.htc.launcher.action.UPDATE_SHORTCUT");
15. intent2.putExtra("packagename", launcherComponentName.getPackageName());
16. intent2.putExtra("count", count);
17. context.sendBroadcast(intent2);
19. return true;
20. } catch (Exception e) {
21. e.printStackTrace();
22. return false;
23. }
24. }
测试结果:
HTC D820u、HTC M8St可直接设置
15 诺基亚(支持)
可通过通知设置角标数量,和小米类似,不同之处是只要通知栏的通知一直存在,数字就一直存在,且应用在前台仍可通过通知设置。
实现代码:
与小米实现代码相同。
测试结果:
诺基亚7:可通过通知设置。
16 索尼(支持)
实现代码:
1. private static boolean setSonyBadge(int count, Context context) {
2. String launcherClassName = getLauncherClassName(context);
3. if (TextUtils.isEmpty(launcherClassName)) {
4. return false;
5. }
6. try {
7. //官方给出方法
8. ContentValues contentValues = new ContentValues();
9. contentValues.put("badge_count", count);
10. contentValues.put("package_name", context.getPackageName());
11. contentValues.put("activity_name", launcherClassName);
12. SonyAsyncQueryHandler asyncQueryHandler = new SonyAsyncQueryHandler(context
13. .getContentResolver());
14. asyncQueryHandler.startInsert(0, null, Uri.parse("content://com.sonymobile.home" +
15. ".resourceprovider/badge"), contentValues);
16. return true;
17. } catch (Exception e) {
18. try {
19. //网上大部分使用方法
20. Intent intent = new Intent("com.sonyericsson.home.action.UPDATE_BADGE");
21. intent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", count > 0);
22. intent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME",
23. launcherClassName);
24. intent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", String
25. .valueOf(count));
26. intent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context
27. .getPackageName());
28. context.sendBroadcast(intent);
29. return true;
30. } catch (Exception e1) {
31. e1.printStackTrace();
32. return false;
33. }
34. }
35. }
37. static class SonyAsyncQueryHandler extends AsyncQueryHandler {
38. SonyAsyncQueryHandler(ContentResolver cr) {
39. super(cr);
40. }
41. }
暂无测试机测试
17 原生Android(部分支持,无法直接显示数目)
Android 8.0及之后的版本Google官方API支持通过发送系统通知的方式设置应用角标,但是不支持显示数量,而是一个小点儿,如下图所示。
在发送通知时可以设置消息数量,部分手机在长按图标时会显示所有通知设置的数量的总和。如上图所示,该示例中我们发送了两条通知,一条设置消息数量为88,一条为12,所以总和显示为100。
实现代码:
与小米实现代码相同。
测试结果:
Pixel 2 XL(Android 9.0):支持通知设置。
Nexus 6P(Android 8.1.0)、Nexus 5X(Android 8.1.0):不支持。
一加OnePlus3(Android 8.0.0):支持通知设置,但是长按图标不会显示数量。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。