Android如何通过代码动态更换应用图标与推送通知图标?
在Android中根据用户类型动态更换应用图标和推送通知图标
可行性结论
完全可行,但应用图标和推送通知图标的实现逻辑不同,需分别处理:
一、动态更换应用图标
Android 8.0(API 26)及以上版本支持通过activity-alias机制实现应用图标的动态切换,具体步骤如下:
在Manifest中配置多组图标入口
在启动页Activity的同级位置,为学生、教师分别添加activity-alias标签,指定专属图标并默认禁用:<!-- 默认启动页(默认图标) --> <activity android:name=".MainActivity" android:icon="@mipmap/ic_default_launcher" android:roundIcon="@mipmap/ic_default_launcher_round"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 学生用户入口(学生图标) --> <activity-alias android:name=".StudentMainAlias" android:targetActivity=".MainActivity" android:icon="@mipmap/ic_student_launcher" android:roundIcon="@mipmap/ic_student_launcher_round" android:enabled="false" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <!-- 教师用户入口(教师图标) --> <activity-alias android:name=".TeacherMainAlias" android:targetActivity=".MainActivity" android:icon="@mipmap/ic_teacher_launcher" android:roundIcon="@mipmap/ic_teacher_launcher_round" android:enabled="false" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias>认证完成后切换图标
通过PackageManager启用对应用户类型的activity-alias,禁用默认入口,随后重启应用使图标生效:private fun switchAppIcon(isStudent: Boolean) { val packageManager = packageManager val defaultComponent = ComponentName(this, MainActivity::class.java) val targetComponent = if (isStudent) { ComponentName(this, ".StudentMainAlias") } else { ComponentName(this, ".TeacherMainAlias") } // 禁用默认入口 packageManager.setComponentEnabledSetting( defaultComponent, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ) // 启用目标入口 packageManager.setComponentEnabledSetting( targetComponent, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) // 重启应用 val intent = packageManager.getLaunchIntentForPackage(packageName)?.apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) } startActivity(intent) finish() }注意事项
- 图标切换后,系统Launcher可能需要几秒到几分钟的缓存刷新时间,部分厂商设备可能需要用户手动重启Launcher才能看到变化;
- 该功能仅支持API 26及以上版本,低版本设备无法实现应用图标动态切换;
- 每个
activity-alias必须配置与默认入口相同的intent-filter,且targetActivity指向同一个主Activity。
二、动态更换推送通知图标
通知图标的切换更为灵活,无需提前在Manifest中配置,可在构建通知时动态指定:
保存用户类型标识
认证完成后,将用户类型(学生/教师)保存到本地(如SharedPreferences):val sharedPref = getSharedPreferences("UserPrefs", Context.MODE_PRIVATE) sharedPref.edit().putBoolean("isStudent", isStudent).apply()构建通知时动态设置图标
在创建通知时,根据本地保存的用户类型选择对应的图标资源:private fun sendNotification() { val sharedPref = getSharedPreferences("UserPrefs", Context.MODE_PRIVATE) val isStudent = sharedPref.getBoolean("isStudent", true) val notificationIcon = if (isStudent) { R.drawable.ic_student_notification } else { R.drawable.ic_teacher_notification } val notification = NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL_ID") .setSmallIcon(notificationIcon) .setContentTitle("新通知") .setContentText("您有一条新消息") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(1, notification) }后台推送消息的处理
如果使用FCM等推送服务,可在客户端的消息接收服务(如FirebaseMessagingService)中拦截消息并替换图标:class MyFirebaseMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { val sharedPref = getSharedPreferences("UserPrefs", Context.MODE_PRIVATE) val isStudent = sharedPref.getBoolean("isStudent", true) val iconRes = if (isStudent) R.drawable.ic_student_notification else R.drawable.ic_teacher_notification // 构建并发送自定义通知 val notification = NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL_ID") .setSmallIcon(iconRes) .setContentTitle(remoteMessage.notification?.title) .setContentText(remoteMessage.notification?.body) .build() val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(System.currentTimeMillis().toInt(), notification) } }
内容的提问来源于stack exchange,提问作者Khalida Aliyeva
相关产品推荐
相关产品推荐

