【问题标题】:Is there any way to dynamically change an app icon like Calendar app does?有没有办法像日历应用一样动态更改应用图标?
【发布时间】:2016-04-08 03:06:21
【问题描述】:

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

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

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

【问题讨论】:

  • 您正在查看应用程序小部件,或者无论您的主屏幕是什么,无论您的日历应用程序是什么,它都有特殊的挂钩。通常,应用程序无法更新其图标。 “但我的不一样”——然后请详细说明其他问题是什么以及为什么你的问题不同。
  • @CommonsWare 我刚刚更改了我的文本。正如您在问题中看到的那样,这不是实际的小部件,而是应用程序图标。它会在主屏幕和菜单中发生变化。
  • 然后,无论您的主屏幕是什么,无论您的日历应用程序是什么,以及您的闹钟应用程序是什么,它都有特殊的挂钩。一般情况下,应用无法更新其图标。
  • @CommonsWare 钩子是什么意思?

标签: android dynamic icons android-calendar


【解决方案1】:

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

钩子是什么意思?

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

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

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

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

  • 只有一小部分设备会支持这些专有 API

  • 通过逆向工程应用发现的未记录和不受支持的 API 可能会发生变化,并且可能会以意想不到的方式中断

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

为了解决这个问题,我可以编写一个主屏幕。也许我想为应用程序提供一些动态更改图标的方法,即使没有标准。也许我没有。也许我根本不打算使用图标,因为我的主屏幕针对视障人士进行了优化,所以它使用文本到语音和硬件键输入。这是我的主屏幕实现,我可以为所欲为。

【讨论】:

  • 我不认为是这样。例如,日历图标也适用于我设备上的箭头启动器。有更好的解决方案表明可以使用不同的方法(虽然没有官方)。其中之一是:stackoverflow.com/a/19593601/2591556
  • @commonsware 此功能在 Android Nougat 及更高版本的 Google 日历中提供。问题是它是否适用于所有开发人员?
  • @JPVentura:目前没有。即使谷歌打开了它(例如,在 Android P 中),它的可用性也必须由主屏幕的开发人员选择加入。当前的 API 中根本没有任何内容可以强制主屏幕显示与其可能缓存的图标不同的图标。
【解决方案2】:

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

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

【讨论】:

  • 那些应用程序使用小部件来执行此操作,因为它们会及时更新。但是,如果该点只是出于特定原因更改图标,则可以使用<activity-alias> 到达。我在我的项目中使用过它
  • @LennonPetrick 小部件仅出现在桌面上,但我也在谈论启动器。并且将小部件添加到桌面的过程与添加图标不同。所以我 100% 确定它不是小部件。
  • @oleg.semen 是的,这是有道理的。他们可能有不同的方法,因为如果您使用activity-alias>,桌面中的快捷方式往往会在您激活它时被删除。也许是因为日历和时钟应用程序来自设备所有者,例如三星,我不知道。
【解决方案3】:

事实上,即使在 Android O 的应用程序抽屉中,时钟应用程序图标也会显示当前时间,而日历应用程序图标也会显示当前日期。

This article explains:

著名的 Action Launcher 背后的开发者 Chris Lacy 在 Android O 中的 Clock 应用程序的 APK 文件中发现了一些东西:manifest.xml 提到小时、分钟和秒作为具有默认值的层,并且该图标具有用于背景和不同元素的单独图像。

这从逻辑上导致他推断从 Android O 开始,时钟应用程序的图标将被动画以显示当前时间。当时钟作为快捷方式放置在主屏幕上时以及它位于应用程序抽屉内时,都会发生这种情况。

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

【讨论】:

    【解决方案4】:

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

    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”。

    图标主题也包含每个日期的单独图标。

    【讨论】:

    • 它只允许您访问图标。我想动态更改应用程序的图标。
    • 对...换句话说,如果没有启动器执行逻辑,它看起来是不可能的。另一种选择是更新的小部件。但是,这并不是您要问的。
    【解决方案5】:

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

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

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

    该设备是运行 Android 8 的 Nubia X。

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

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

    【讨论】:

      【解决方案6】:

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

      <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>
      

      根据您的要求启用和禁用活动别名。

      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

      【讨论】:

        【解决方案7】:

        在此处为@commonsware's 答案添加更多上下文。

        对谷歌如何使用他们的日历和时钟应用程序进行了更多挖掘。

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

        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

        因此,目前唯一的解决方法是拥有多个 具有不同图标的活动别名,然后在这些别名之间切换。

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

        【讨论】:

          猜你喜欢
          • 2018-02-24
          • 2012-12-20
          • 2020-10-04
          • 2020-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-30
          相关资源
          最近更新 更多