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):支持通知设置,但是长按图标不会显示数量。


BalaBala
0 声望0 粉丝