在下面的實現代碼中,有不少公用的代碼,咱們提取出來一些公用方法,代碼以下: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. }
小米在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都可經過通知的方式設置角標。測試
能夠經過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)都可直接設置。
舊款的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) 國內外郵件類應用(各區域各屬於用戶量第一梯隊的應用)。
舊款的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. }
能夠經過廣播機制直接設置應用角標,且應用在前臺和被殺掉後仍可顯示。
實現代碼:
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:可直接設置。
官方不支持。
目前可能僅支持系統應用、微信和QQ,不支持支付寶,未找到設置角標相關文檔。
目前僅支持系統應用和微信,甚至不支持QQ。
目前僅支持系統應用。
找不到相關文檔。
僅支持經過通知設置角標,且角標數字爲收到通知的條數,沒法自定義角標數目。
測試結果:
樂2 Pro:可經過通知方式設置。
實現代碼:
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. }
暫無測試機測試
目前僅支持系統應用和微信,甚至不支持QQ。
可經過廣播機制直接設置角標。
實現代碼:
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可直接設置
可經過通知設置角標數量,和小米相似,不一樣之處是隻要通知欄的通知一直存在,數字就一直存在,且應用在前臺仍可經過通知設置。
實現代碼:
與小米實現代碼相同。
測試結果:
諾基亞7:可經過通知設置。
實現代碼:
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. }
暫無測試機測試
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):支持通知設置,可是長按圖標不會顯示數量。