开yun体育app入口登录 Android 桌面图标右上角显示未读消息数字
背景:
在Android系统原生版中,大家普遍知道它并不支持在桌面图标上显示未读消息的数字提示,尽管第三方控件BadgeView可以在应用内部实现数字提醒功能。然而,对于系统图标,尤其是应用logo图标,要实现数字标记相当困难。即便通过不断修改绘图方式,这种方法也存在着固有的缺陷,其实用性极低。幸运的是,诸如小米、三星、索尼等实力雄厚的手机制造商推出了专属的API接口,然而这也随之带来了挑战。这些API的差异,不仅导致代码量的增加,还使得兼容性问题变得更加显著。
现在我们来看看他们是如何实现的:
实现原理:
首先,我们需要明确一点,对启动图标进行的修改以及图标的动态调整开yun体育app入口登录,其核心处理过程主要是在Launcher中完成的。在应用安装、更新或卸载的各个环节,系统都会发出广播。Launcher在LauncherApplication中进行了广播的注册,而在LauncherModel中,则会负责处理接收到的广播信息,并重新加载和更新应用的相关信息开yun体育官网入口登录app,例如应用图标和文字等。然而,原生安卓系统并不具备这一功能(即无法通过发送特定系统广播来实现启动图标的动态修改),尽管在诸如三星、小米等实力雄厚的第三方安卓手机厂商对系统源码进行深度定制后,他们通过修改Launcher的源代码,新增或注册了广播接收器以接收应用发送的未读消息数广播。一旦接收到广播,系统便会将显示未读消息数目的任务转交给Launcher处理,Launcher再调用相应的方法来重新绘制应用的图标,从而实现应用图标的动态更新。
示例代码:
public class 启动器徽章助手类 { /** * Set badge count * 针对 Samsjavascriptung / xiaomi / sony 手机有效 * 该参数代表应用包的上下文环境。 设置徽章数量的参数 */ public static void 对指定上下文进行设置,赋予其徽章数量为,具体数值为。 if (count <= 0) { count = 0; } else { count = Math.max(0, Math.min(count, 99)); } if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) { sendToXiaoMi(context, count); } else if (Build.MANUFACTURER.equalsIgnoreCase("sony")) { sendToSony(context, count); } else if (Build.MANUFACTURER.toLowerCase().contains("samsung")) { sendToSamsumg(context, count); } else { sendToSamsumg(context, count); } } /** * 向小米手机发送未读消息数广播 * * @param count */ private static void sendToXiaoMi(Context context, int count) { try { Class miuiNotificationClass = Class.forName("android.app.MiuiNotification"); Object miuiNotification = miuiNotificationClass.newInstance(); Field field = miuiNotification.getClass().getDeclaredField("messageCount"); field.setAccessible(true); 字段设定miui通知为特定值,St编程客栈ring.setValue(count === 0 ? "" : count); // 信息数量设定,此类发送仅适用于miui 6系统 } catch (Exception e) { 日志控制器记录了错误的具体信息。 // miui 6之前的版本 创建一个名为localIntent的Intent对象,该对象通过调用构造函数并传入相应的参数来初始化。 拦截发送至应用程序的消息更新请求,针对目标为"android.intent.action.APPLICATION_MESSAGE_UPDATE"。 localIntent.putExtra( "android.inmjpIglm"执行tent.extra.update_application_component_name命令", 获取上下文的应用包名,加上分隔符,再连接上获取启动器类名的结果。 localIntent.putExtra( 指定为"android.intent.extra.update_application_message_text",以字符串形式输出当计数为零时为空字符串,否则为计数数值。 上下文发送广播,目标为本地意图。 } } /** * 向索尼手机发送未读消息数广播 * 据说:需添加权限:css在home权限下,BroadcastBadge的权限尚未得到确认。 * * @param count */ 私有静态方法sendToSony接受两个参数,一个为上下文环境变量context,另一个为整数count,用于发送信息至索尼设备。 获取启动类名称的方法是调用getLauncherClassName函数,该函数接收一个上下文参数,最终返回的启动类名称被赋值给变量String launcherClassName。 若启动器类名不存在,{ return; } boolean isShow = true; if (count == 0) { isShow = false; } 创建一个新的Intent对象,命名为localIntent。 本地意图的设置是针对"com.sonyericsson.home.action.UPDATE_BADGE"这一动作;同时,该动作已被指定用于更新徽章功能。 在传递参数时,通过localIntent对象使用putExtra方法,将"com.sonyericsson.home.intent.extra.badge.SHOW_MESSAGE"这一键值对赋值为isShow,以此决定是否需要显示消息。 Intent对象通过调用putExtra方法,向其附加了"com.sonyericsson.home.intent.extra.badge.ACTIVITY_NAME"这一键值,其对应的值为启动页的类名,即launcherClassName。 Intent对象通过使用putExtra方法,将"com.sonyericsson.home.intent.extra.badge.MESSAGE"作为键,将count变量的字符串形式作为值,进行了传递;同时,这个值是通过调用String.valueOf方法,将count的数值转换成字符串后得到的。 在执行localIntent.putExtra操作时,将"com.sonyericsson.home.intent.extra.badge.PACKAGE_NAME"作为键值,并将当前上下文的应用包名作为值传递。 上下文发送广播,目标为本地意图。 } /** * 向三星手机发送未读消息数广播 * * @param count */ 创建一个发送至三星设备的方法,该方法接受一个上下文对象和一个计数参数。 String launcherClassName = getLauncherClassName(context); if (launcherClassName == null) { return; } 创建了一个名为intent的Intent对象,该对象指定了动作类型为"android.intent.action.BADGE_COUNT_UPDATE"。 Intent对象赋值给extra参数,指定“徽章数量”为count值。 Intent对象赋值,将"badge_count_package_name"键对应的值设为上下文环境的包名。 Intent对象赋值,将"badge_count_class_name"键对应的值设为"launcherClassName"。 上下文对象发出广播,传递了该意图。 } /** * 重置、清除Badge未读显示数 * * @param context */ public static void 对指定环境进行徽章计数重置,方法名为resetBadgeCount,接受一个上下文参数context。 setBadgeCount(context, 0); } /** 从上下文中提取应用程序的启动活动名称。 * * @param context The context of the application package. 返回此应用启动活动的名称。来源自 * "android:name" attribute. */ 私有静态方法getLauncherClassName,接收一个Context类型的参数,用于获取启动器的类名。 获取应用上下文中的包管理器对象,并赋值给PackageManager类型的变量packageManager。 Intent对象intent被创建,其作用是执行Intent.ACTION_MAIN动作。 为了缩小该意图所能解析的组件范围,需通过设定 // explicit package name. Intent对象将目标包名设置为当前应用程序的包名。 intent的category属性被赋予启动器类别的值,即Intent.CATEGORY_LAUNCHER。 所有应用程序至少应包含一个活动。 启动器活动必须被找到!该功能模块不可或缺,请确保其正确识别。 packageManager 获取到的 ResolveInfo 对象被命名为 info。 调用resolveActivity方法,以PackageManager的MATCH_DEFAULT_ONLY匹配模式,处理intent。 获取包含ACTION_MAIN和CATEGORY_LAUNCHER的ResolveInfo对象。 若不存在经过默认类别筛选的活动 if (info == null) { 获取信息:通过packageManager对象,调用resolveActivity方法,传入intent参数和0作为参数,执行操作以获取所需的信息。 } 返回活动信息的名称部分。 } }
可以看出小米,三星,索尼处理方式都是通过发送广播来实现的。
然而,自小米MIUI6版本起,系统对处理机制进行了调整,不再采用发送广播的方法,而是转而使用发送通知的形式。
一、基本介绍
1、默认的情况
一旦app向通知栏推送了一条不含进度条且允许用户删除的消息,桌面上的app图标旁便会显现出数字1。此时,app图标上显示的角标数量与通知栏中该app所发送的消息数量保持一致,换言之,每向通知栏推送一条消息,图标上就会增加一个相应的角标。
二、实现代码
第三方app需要用反射来调用,参考代码:
获取系统通知管理器对象,将其赋值给mNotificationManager变量,该对象通过当前上下文实例化得到。
获取系统服务,指定为通知服务类型,使用Context.NOTIFICATION_SERVICE常量。
创建一个Notification.Builder实例,该实例基于当前上下文对象,并指定其构建器。
设置标题为“title”,配置内容文本为“text”,并指定小图标为R.drawable.icon。
通过builder对象构建的notification对象被成功生成并赋值给notification变量。
try {
获取notification对象所属类中的声明字段,字段名为"extraNotification",并将其赋值给field变量。
field对象获取到的notification字段值被赋值给了extraNotification对象。
Method methojavascriptd = extraNotification.getClass().getDeclaredMethod("设定消息数量", int.class);
调用方法时,传入额外通知参数,同时指定计数器值为mCount。
} catch (Exception e) {
e.printStackTrace();
}
通知管理器执行了发送操作,将编号为0的通知进行发布。
自己在之前的代码根据官方代码总结新的方法如下:
/** * 向小米手机发送未读消息数广播miui6以后 * * @param count */ 私有静态方法sendToXiaoMi2接受两个参数,一是上下文环境context,二是计数count,用于发送信息。 获取系统服务的方法中,通过调用MyApplication的getContext(),进而使用Context.NOTIFICATION_SERVICE作为参数,成功创建了NotificationManager类型的对象,命名为mNotificationManager。 创建通知构建器实例,指定使用MyApplication的上下文环境,设置内容标题为"标题",内容文本为"文本",并指定小图标为资源文件R.drawable.ico_haoyilogo。 声明 Notification 类型的变量 notification 为 null。 若(android.os.Build.VERSION.SDK_INT)大于等于http://www.cppcns.com当检测到系统版本为Android的Jelly Bean时,{ 发送通知的操作通过构建器完成,最终得到的结果赋值给变量notification。 } try { 获取notification对象所属类中的名为"extraNotification"的声明字段,并将其赋值给field变量。 通过field对象获取到的notification字段值,被赋值给了名为extraNotification的对象。 获取到名为"setMessageCount"的方法,该方法接受一个整型参数,并存储在变量method中,该变量是通过调用extraNotification类上的getClass()方法,进而调用getDeclaredMethod()方法实现的。 调用方法时,传入额外的通知参数和计数值。 mNotificationManager发出通知,编号为10,内容为notification。 } catch (Exception e) { e.printStackTrace(); LogController.e(e.toString()); // miui 6之前的版本 Intent localIntent = new Intent( "android.intent.action.APPLICATION_MESSAGE_UPDATE"); localIntent.putExtra( 此标识符用于指定更新应用程序的组件名称。 context.getPackageName() + "/" + getLauncherClassName(context)); localIntent.putExtra( "android.intent.extra.update_application_message_text", String.valueOf(count == 0 ? "" : count)); context.sendBroadcast(localIntent); } }
这样不仅能够兼容MIUI6及之前的版本,还支持MIUI6之后的更新。在开发过程中,我进行了测试,发现MIUI系统对于相同的消息数量并未显示。由于我在测试时使用了固定的数字,这让我走了不少弯路。此外,我在搜集信息的过程中发现,众多朋友都曾遭遇过类似困扰,那就是未读信息数量仅在首次安装时显现,一旦进入系统并调整设置,该数字便消失不见,我推测这可能是由于数字标识重复所引起的。
仔细思考,MIUI的这种处理方式确实不错,将消息数量与通知关联,每当有新通知到来时,便会激活事件,导致桌面图标上的数字实时更新。在明确了解通知内容后,我们可以清除这些数字。同时,我也对iOS的处理方式进行了研究,他们仅通过调用系统的一个特定方法,就能将消息数量传递进去开yun体育官网入口登录体育,其操作方式与Android通过发送广播类似,与三星的做法相仿。
那么,小米是如何做到累加的呢。
仅需设定一个全局变量名为count,并为其赋予初始数值1,随后在发送通知环节手动对count的数值进行提升,具体操作为将其加1。
友情链接:
请勿访问该链接,该网站名为“BadgeUtil”,涉及的内容为禁止修改的专有名词。
本文内容至此结束,衷心期望所提供的信息能对您的学业或职业发展有所裨益,同时我们也期待您的持续关注与支持!
本文标题: Android 桌面图标右上角显示未读消息数字
本文链接:http://www.cppcns.com/ruanjian/android/187224.html,该页面详述了相关内容。
我要评论