记录下这个需求的研究 写的超级随意 大家凑合看 不懂再问 一起探讨
因为我们的产品也需要有即时通讯了 消息更新不可避免
首先 要实现这个功能 当然是要借助系统的Launcher。
而谷歌并没有开放出这个标准的接口或者方法
于是各大厂商都对Launcher这块做了各自的改动,这也给第三方开发者想要统一处理这个需求加大了难度。
网上demo也有一些 大部分是通过发送广播的方式,来通知系统更新图标上的数字
比如我之前在github上找到一个demoTestShortCut 就很不错, 针对三星(亲测)、索尼、小米 小米貌似在miui系统里已经内部处理了这种情况 发通知栏消息的时候 会自动加数字
/*** * 三星手机:应用图标的快捷方式上加数字 * @param context * @param num */ public static void samsungShortCut(Context context, String num) { int numInt = Integer.valueOf(num); if (numInt < 1) { num = "0"; }else if (numInt > 99){ num = "99"; } String activityName = getLaunchActivityName(context); Intent localIntent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); localIntent.putExtra("badge_count", Integer.parseInt(num)); localIntent.putExtra("badge_count_package_name", context.getPackageName()); localIntent.putExtra("badge_count_class_name", activityName); context.sendBroadcast(localIntent); }
/*** * 索尼手机:应用图标的快捷方式上加数字 * @param context * @param num */ public static void sonyShortCut(Context context, String num) { String activityName = getLaunchActivityName(context); if (activityName == null){ return; } Intent localIntent = new Intent(); int numInt = Integer.valueOf(num); boolean isShow = true; if (numInt < 1){ num = ""; isShow = false; }else if (numInt > 99){ num = "99"; } localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE", isShow); localIntent.setAction("com.sonyericsson.home.action.UPDATE_BADGE"); localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME", activityName); localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.MESSAGE", num); localIntent.putExtra("com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME", context.getPackageName()); context.sendBroadcast(localIntent); }
/*** * 在小米应用图标的快捷方式上加数字<br> * * * @param context * @param num 显示的数字:大于99,为"99",当为""时,不显示数字,相当于隐藏了)<br><br> * * 注意点: * context.getPackageName()+"/."+clazz.getSimpleName() (这个是启动activity的路径)中的"/."不能缺少 * */ public static void xiaoMiShortCut(Context context,Class<?> clazz, String num) { Log.e(TAG, "xiaoMiShortCut...."); Intent localIntent = new Intent("android.intent.action.APPLICATION_MESSAGE_UPDATE"); localIntent.putExtra("android.intent.extra.update_application_component_name", context.getPackageName()+"/."+clazz.getSimpleName()); if(TextUtils.isEmpty(num)){ num = ""; }else{ int numInt = Integer.valueOf(num); if (numInt > 0){ if (numInt > 99){ num = "99"; } }else{ num = "0"; } } localIntent.putExtra("android.intent.extra.update_application_message_text", num); context.sendBroadcast(localIntent); }
但没办法,我们的产品需要针对的是下面这三个厂商
华为 OPPO VIVO 使用上面的demo确没办法做到,所以还得继续研究
于是在找了很多资料没有结果以后 我决定反编译QQ和微信的源码来研究 (注:有很多机型qq和微信也没办法做到这个需求)
先从qq开始 反编译以后 在源码里搜索了很多关键字
终于让我找到了这个类 BadgeUtilImpl.class
太兴奋了。
public static void changeOPPOBadge(Context paramContext, int paramInt) { int i = 99; if (!isEnabled(paramContext)); for (int j = 0; ; j = paramInt) { if (j > i); while (true) { if (QLog.isColorLevel()) QLog.d("BadgeUtilImpl", 2, "changeOPPOBadge mcount=" + i); try { Bundle localBundle = new Bundle(); localBundle.putInt("app_badge_count", i); paramContext.getContentResolver().call(Uri.parse("content://com.android.badge/badge"), "setAppBadgeCount", null, localBundle); return; i = j; } catch (Exception localException) { QLog.d("BadgeUtilImpl", 2, "OPPOBadge badge get a crash" + localException.getMessage()); return; } } } }
public static String getLauncherClassName(Context paramContext) { String str; if (!TextUtils.isEmpty(mLauncherClassName)) str = mLauncherClassName; while (true) { return str; PackageManager localPackageManager = paramContext.getPackageManager(); Intent localIntent = new Intent("android.intent.action.MAIN"); localIntent.addCategory("android.intent.category.LAUNCHER"); try { Iterator localIterator = localPackageManager.queryIntentActivities(localIntent, 0).iterator(); while (true) if (localIterator.hasNext()) { ResolveInfo localResolveInfo = (ResolveInfo)localIterator.next(); if (!localResolveInfo.activityInfo.applicationInfo.packageName.equalsIgnoreCase(paramContext.getPackageName())) continue; str = localResolveInfo.activityInfo.name; mLauncherClassName = str; if (!QLog.isColorLevel()) break; QLog.d("BadgeUtilImpl", 2, "getLauncherClassName" + mLauncherClassName); return str; } } catch (Exception localException) { return null; } } return null; }
public static void setBadge(Context paramContext, int paramInt) { setBadge(paramContext, paramInt, false); }
public static void setBadge(Context paramContext, int paramInt, boolean paramBoolean) { if (QLog.isColorLevel()) QLog.d("BadgeUtilImpl", 2, "setBadge count=" + paramInt + "|forceSet=" + paramBoolean); if ((!isEnabled(paramContext)) && (!paramBoolean)); do { return; if (isQQLanucher()) setQQLauncherBadges(paramContext, paramInt); if (Build.MANUFACTURER.equalsIgnoreCase("ZUK")) changeZUKBadge(paramContext, paramInt); if (islenovoLanucher("com.lenovo.launcher")) setLenovoBadge(paramContext, paramInt); if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) { changeMIBadge(paramContext, paramInt); return; } if (Build.MANUFACTURER.equalsIgnoreCase("samsung")) { setSamsungBadge(paramContext, paramInt); return; } if (!Build.MANUFACTURER.equalsIgnoreCase("huawei")) continue; setHuaweiBadge(paramContext, paramInt); return; } while (!Build.MANUFACTURER.equalsIgnoreCase("OPPO")); changeOPPOBadge(paramContext, paramInt); }
public static void setHuaweiBadge(Context paramContext, int paramInt) { while (true) { try { if (!QLog.isColorLevel()) continue; QLog.d("BadgeUtilImpl", 2, "huawiBadge mcount=" + paramInt); String str = getLauncherClassName(paramContext); if (str == null) { return; Bundle localBundle = new Bundle(); localBundle.putString("package", paramContext.getPackageName()); localBundle.putString("class", str); localBundle.putInt("badgenumber", paramInt); paramContext.getContentResolver().call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, localBundle); return; } } catch (Throwable localThrowable) { return; } if (paramInt <= 99) continue; paramInt = 99; } }
qq这里面有针对华为和OPPO的
我用华为荣耀6亲测过有效 但是华为Meta却不行(我试过 微信和qq同样不行)
OPPO的没效果 提示没有此Uri (OPPO r7 qq和微信及其他第三方app 也都不能显示数字)
再来看看vivo
qq没法显示数字 但是微信会显示 于是驱使我研究微信的源码
微信的源码混淆的比较多 找起来比qq费事 不过还是让我找到了线索
在这个包目录下com.tencent.mm.booter.notification 找到了类文件d
找到了这段代码
Intent localIntent1 = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM"); localIntent1.putExtra("packageName", context.getPackageName()); localIntent1.putExtra("className", MainActivity.class.getName()); localIntent1.putExtra("notificationNum", paramInt); context.sendBroadcast(localIntent1);
经测试 vivo 也可以显示了..
总结一句:网上找不到资料的时候 就去研究第三方app源码吧 也许能事半功倍呢 虽然有点不厚道 哈哈