有没有办法像日历应用程序那样动态更改应用程序图标?

Is there any way to dynamically change an app icon like Calendar app does?

我想创建一个 Android 应用程序,我想动态自动更新应用程序图标,类似于用户主屏幕上日历图标的更新方式。

日历会根据每一天更改其图标,显示月份的日期。还有一个闹钟应用程序可以更改其图标设置当前时间,换句话说,每分钟更改一次。

那不是小部件,而是真正的应用程序图标。那么它必须有办法这样做。如何在我的应用程序中执行此操作?

无论您的主屏幕是什么,都会为您的日历应用程序和闹钟应用程序提供特殊的挂钩。一般情况下,应用程序无法更新其图标。

What do you mean by hooks?

例如,三星可以在三星设备上发布三星日历应用程序。在这些三星设备上,三星的主屏幕可以有特殊的规则来呈现三星日历应用程序的图标,这些规则涉及显示月份中的某一天。这是因为三星写了主屏幕。如果您安装 third-party 主屏幕,它可能不会做同样的事情。毕竟我一个小时左右就可以写出一个主屏幕了,我很有信心不用为三星的日历应用程序做任何特别的事情。

没有什么可以阻止三星公开某种 API 以允许开发人员连接到三星的主屏幕并通知它有关此类事情的信息。三星是否 打算 供第三方使用 API,或者是否有人侵入三星如何为他们自己的应用程序做这件事,我不能说。

(顺便说一句,我在这里引用三星作为一个可能的例子——我不知道他们实际上有这种功能,如果有的话,他们在哪些设备上有)

我似乎记得有人有一个 GitHub 项目试图包装各种主屏幕的专有 API。 IIRC,一些支持的功能包括替换应用程序图标或添加徽章(例如,未读消息计数)。然而:

  • 只有一小部分设备会支持那些专有的 APIs

  • 未记录和不受支持的 APIs,通过 reverse-engineering 应用程序发现,可能会发生变化,并可能以意想不到的方式中断

我很确定 Android SDK 中没有任何东西支持动态应用程序图标。我所知道的唯一一件事,人们已经尝试过,是使用 <activity-alias> 来获得 N 个不同的 "activities",所有这些都指向相同的实现,但具有不同的图标。使用 PackageManagersetComponentEnabledSetting(),该应用会禁用旧的启动器别名并启用一个不同的别名,希望主屏幕能够接受并显示新图标。有几个。其他人只会在重新启动时发现更改。

为了解决这个问题,我可以写一个主屏幕。也许我想为应用程序提供一些即时更改图标的方法,即使没有标准。也许我不知道。也许我根本不打算使用图标,因为我的主屏幕针对视障人士进行了优化,所以它使用 text-to-speech 和硬件键输入。这是我的主屏幕实现,我可以做我想做的事。

我也有同样的问题,但是这里提供的答案没有回答。
我有 Google Pixel 2 和原始 Android Ore 8.1 在板上,有两个应用程序随时间变化:Calendar 时钟 Clock 应用程序时钟上的指针显示当前时间,Calendar 图标上的数字对应于当月的今天。
所以考虑到它是默认启动器,可能有一些 API 可以做类似的事情。

例如,它可能是反映行星在图标上位置的行星应用程序。或显示已用内存百分比的内存清理器...

事实上,即使在 AndroidO 的应用程序抽屉中,时钟应用程序图标显示当前时间,日历应用程序图标显示当前时间 day-of-month。

This article explains:

Chris Lacy, the developer behind the well-known Action Launcher, has uncovered something in the APK file of the Clock app that comes in Android O: the manifest.xml mentions hours, minutes, and seconds as layers with default values, and the icon has separate images for the background and different elements.

That logically lead him to deduce that starting with Android O, the Clock app's icon will be animated to show the current time. That will happen both when the Clock is placed as a shortcut on the homescreen and when it's inside the app drawer.

听起来 Pixel 启动器会根据时间和日期选择不同的图标图像层资源。

启动器通过从日历应用访问每一天的图标来处理动态日历。例如,使用 Google 日历,启动器开发人员可以执行以下操作:

Resources res = activity.getPackageManager()
                            .getResourcesForApplication("com.google.android.calendar");
int resId = res.getIdentifier("logo_calendar_01_regular", "drawable"
                            , "com.google.android.calendar");
Drawable icon = res.getDrawable(resId);

这将访问该月第 1 天的日历图标。要访问任何其他日期,"logo_calendar_01_regular" 将更改为当天。例如,第 7 天将是 "logo_calendar_07_regular"。 Google 日历也有两种样式,"logo_calendar_01_regular" 和 "logo_calendar_01_round"。

此外,图标主题还包含每个日期的单独图标。

我是一名启动器开发人员。

我没有做任何与动态图标挂钩相关的事情。我只是通过 Android API 提供的标准方式获取活动的图标。

而且我发现我的启动器确实在时钟应用程序图标中显示当前时间,在日历图标中显示当前日期。

该设备是运行 Android8.

的 Nubia X

操作系统应该对这两个应用程序进行处理,并在启动器不知情的情况下动态更改它们的图标。

这两个应用程序是由设备制造商开发的。你不应该能够像第三方开发者一样以正常的方式做同样的事情。

您可以在清单文件中为每个图标定义多个 activity-别名

<activity-alias
        android:name="OneLauncherAlias"
        android:enabled="true"
        android:icon="@drawable/one"
        android:label="One"
        android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>

根据您的要求启用和禁用 activity-别名。

packageManager.setComponentEnabledSetting(ComponentName(this@MainActivity, com.misles.dynamiclaunchericon.OneLauncherAlias::class.java), PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP)
packageManager.setComponentEnabledSetting(ComponentName(this@MainActivity, com.misles.dynamiclaunchericon.TwoLauncherAlias::class.java), PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP)

有关详细信息,请参阅本文 https://medium.com/@simonmisles/dynamic-launcher-icon-and-name-for-android-e40bf0561715

在此处为 答案添加更多上下文。

进一步研究 google 如何使用他们的日历和时钟应用程序。

他们似乎在启动器代码中有特殊情况,如下所示:

https://cs.android.com/android/platform/superproject/+/master:packages/apps/Launcher3/src/com/android/launcher3/icons/IconProvider.java;l=54;drc=337c81f6646e8d8351604ee2e1dd1884bc7d0452

这里: https://cs.android.com/android/platform/superproject/+/master:packages/apps/Launcher3/src/com/android/launcher3/icons/IconProvider.java;l=74;drc=337c81f6646e8d8351604ee2e1dd1884bc7d0452

所以目前唯一的解决方法是让多个 activity 使用不同图标的别名,然后在这些别名之间切换。

http://blog.jakelee.co.uk/programmatically-changing-app-icon/