开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,该页面详述了相关内容。

关键词:

客户评论

我要评论