最全 Android 應用角標適配方法

0 公用方法

在下面的實現代碼中,有不少公用的代碼,咱們提取出來一些公用方法,代碼以下:css

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發送的通知數對應的,即向通知欄發送了多少通知就會顯示多少角標。java

能夠經過反射機制來定義每次通知的消息個數,應用的角標數爲每條通知定義的通知個數的總和android

咱們發送了兩條通知,一條通知爲5個消息,一條爲10個消息,應用角標顯示爲15個。此時,若是用戶點擊或移除掉5條消息的那個通知,應用角標會變成10。微信

另外,僅在APP在後臺時收到通知會顯示角標,而APP在前臺時不會顯示,APP被殺掉後通知及角標消失。app

實現代碼async

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.      }

測試結果ide

小米六、小米5S、小米MIX、小米5X、小米四、紅米Note 4X、小米2S都可經過通知的方式設置角標。測試

2 華爲(支持)

能夠經過ContentResolver方法直接設置應用角標,且應用在前臺和被殺掉後仍可顯示。ui

實現代碼spa

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.      }

測試結果

榮耀八、華爲P十、華爲Mate十、華爲麥芒(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):支持通知設置,可是長按圖標不會顯示數量。

相關文章
相關標籤/搜索