多个风味的静态Android快捷方式?

26

是否有可能定义多个版本的静态快捷方式而不重复复制shortcuts.xml文件? 我有两个版本:

  • 主要版本 (包名:com.test)
  • 免费版本 (包名:com.test.free)

shortcuts.xml如下所示:

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
    android:enabled="true"
    android:icon="@drawable/ic_shortcut_add_photo"
    android:shortcutId="new_photo"
    android:shortcutLongLabel="@string/new_photo"
    android:shortcutShortLabel="@string/new_photo">

    <intent
        android:action="android.intent.action.VIEW"
        android:targetClass="com.test.MainActivity"
        android:targetPackage="com.test"/>
</shortcut>

问题在于Intent中的包名不能引用字符串资源,必须在xml中硬编码

为了为免费版本提供快捷方式,我需要复制shortcuts.xml并将targetPackage更改为com.test.free,这是一个不好的解决方案。


问题在于意图中的包名不能引用字符串资源,必须在xml中硬编码。这并不让人感到惊讶,而且这确实是个问题。为了为免费版本提供快捷方式,我必须复制shortcuts.xml并将targetPackage更改为com.test.free,这是一个糟糕的解决方案。你可能能够找到一些现有的Gradle插件,可以让你从单个源代码生成这些内容。 - CommonsWare
2
@CommonsWare 这听起来像是一个针对常见问题的过于复杂的解决方法。 - André Roß
目前这不是一个非常普遍的问题,因为应用程序快捷方式已经存在了两个星期?你可能是地球上第二个需要担心这个问题的开发者。虽然资源以前可能会引用应用程序ID(例如,首选项XML),但它们似乎并没有被广泛使用。除此之外,我建议的几乎就是工具链可以给你的全部内容(例如,清单合并样式字符串插值)。 - CommonsWare
1
我应该是第三个。在我的情况下,我有两种版本,快捷方式对于这两种版本都是相同的,但是由于软件包是硬编码的,所以它无法工作。 有人有解决方案吗? 我想知道他们是否遵循了清单相同的模式,您可以省略软件包并使用“.something”来代替类。 - gmazzo
我自己也遇到了这个问题...看到谷歌从7.0版本中删除它以纠正一些最后一分钟的问题,然后在7.1中再次添加它,但似乎没有为这样微不足道的事情提供简单的支持,这似乎相当疯狂... - slott
4个回答

8

您可以在相应的构建变体文件夹中使用具有不同targetPackage(根据您的应用程序ID)的多个shortcuts.xml。例如:

app/src/debug/res/xml/shortcuts.xml

app/src/staging/res/xml/shortcuts.xml

对我来说它可行。


7
我创建了一个插件,使得在资源文件中可以使用manifestPlaceholders,并且可与android gradle插件的3.0.0版本一起使用。 https://github.com/timfreiheit/ResourcePlaceholdersPlugin src/main/res/shortcuts.xml:
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
    android:enabled="true"
    android:icon="@drawable/ic_shortcut_add_photo"
    android:shortcutId="new_photo"
    android:shortcutLongLabel="@string/new_photo"
    android:shortcutShortLabel="@string/new_photo">

    <intent
        android:action="android.intent.action.VIEW"
        android:targetClass="com.test.MainActivity"
        android:targetPackage="${applicationId}"/>
</shortcut>

1
这实际上非常好,而且解决了问题,没有任何 hack,谢谢。 - Patrick
它在AGP 7.3.0++上出现了故障 https://github.com/timfreiheit/ResourcePlaceholdersPlugin/issues/11 - Morgan Koh

3

重要提示:由于资源处理方式的更改,此解决方案仅适用于Android gradle插件版本3.0之前的版本。

我们刚遇到了这个问题,因为在调试构建中给我们的应用程序ID加上了.debug后缀。这是我们的解决方法(请注意,这是从我们代码库中未经测试的适应):

src/main/res/shortcuts.xml

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
    android:enabled="true"
    android:icon="@drawable/ic_shortcut_add_photo"
    android:shortcutId="new_photo"
    android:shortcutLongLabel="@string/new_photo"
    android:shortcutShortLabel="@string/new_photo">

    <intent
        android:action="android.intent.action.VIEW"
        android:targetClass="com.test.MainActivity"
        android:targetPackage="@string/application_id"/>
</shortcut>

<android模块名称>/build.gradle

apply plugin: 'com.android.application'

//region: Fix shortcuts.xml by manually replacing @string/application_id

final String APPLICATION_ID_STRING_RES_KEY    = "application_id"

android.applicationVariants.all { variant ->

  // Add the application id to the strings resources
  // We do this so that in the future if google fixes the 
  // processing of the shortcuts.xml we can leave this
  // and remove the `mergeResources.doLast` block below
  resValue "string", APPLICATION_ID_STRING_RES_KEY, variant.applicationId

  // Manually replace @string/application_id with `variant.applicationId`
  variant.mergeResources.doLast {
    println("variant = ${variant.applicationId}")

    final File valuesFile = file("${buildDir}/intermediates/res/merged/${variant.dirName}/xml/shortcuts.xml")
    final String content = valuesFile.getText('UTF-8')
    final String updatedContent = content
        .replace("@string/${APPLICATION_ID_STRING_RES_KEY}", variant.applicationId)

    valuesFile.write(updatedContent, 'UTF-8')
  }
}

//endregion  

android {
  ...
}

1
{btsdaf} - Jawnnypoo
确认,使用字符串res将无法与aapt2/plugin v3配合使用。 - Patrick
1
回答已更新,反映出此解决方案不适用于新的Android Gradle插件v3。目前还没有找到新的解决方案,如果有的话,我会再次更新。 - Bulwinkel

2
在调查过程中,我发现了这个库,似乎可以解决问题:

https://github.com/Zellius/android-shortcut-gradle-plugin

缺点:您不能将shortcuts.xml文件放在您的应用程序的res文件夹中,因为插件会获取该文件并修改它以自动添加targetPackage,然后在构建时将其放置,如果您已经定义了一个,则会导致重复资源错误。
除此之外,看起来工作得很好!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接