26

Is it possible to define static shortcuts for multiple flavors without duplicating the shortcuts.xml ? I have two flavors:

  • main (package: com.test)
  • free (package: com.test.free)

The shortcuts.xml looks like this:

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

The problem is that the package name in the intent can not refer to a string resource and must be hardcoded in the xml.

To also provide the shortcuts for the free flavor i have to copy the shortcuts.xml and change the targetPackage to com.test.free which is a bad solution.

André Roß
  • 279
  • 3
  • 5
  • "The problem is that the package name in the intent can not refer to a string resource and must be hardcoded in the xml" -- I am not surprised, and that's really the problem. "To also provide the shortcuts for the free flavor i have to copy the shortcuts.xml and change the targetPackage to com.test.free which is a bad solution" -- you might be able to find some existing Gradle plugin that would let you code generate those from a single source. – CommonsWare Nov 01 '16 at 13:47
  • 2
    @CommonsWare That sounds like a too complicated workaround for a common problem – André Roß Nov 01 '16 at 13:52
  • It is not a very common problem at the moment, insofar as app shortcuts have been around for, what, two weeks? You might be the second developer on the planet who has had to worry about the problem so far. While resources could have references to application IDs before (e.g., preference XML), they do not seem to be used that much. Beyond that, what I suggested is pretty much all the toolchain could give you (e.g., manifest merger-style string interpolation). – CommonsWare Nov 01 '16 at 13:55
  • 1
    I whould be the third then. In my case, I have two flavors and the shortcuts are the same for both of them but, as the package is hardcoded, it won't work. Anyone has a solution for this? I'm wondering if they have followed the same pattern than manifest, and you can just omit the package and use ".something" for the class. – gmazzo Nov 03 '16 at 19:19
  • Just hit this issue myself... Seeing that Google pulled this from version 7.0 to correct some last minute issues and adding it again in 7.1 without easy support for something as trivial as this seems pretty crazy... – slott Jan 10 '17 at 12:09

4 Answers4

8

You can have multiple shortcuts.xml with different targetPackage (according to your app ids) in the respective build variants folder. For example :

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

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

It works for me.

Rakesh
  • 1,205
  • 1
  • 14
  • 33
7

I created a plugin which make it possible to use manifestPlaceholders in resources and is usable with version 3.0.0 of the android gradle plugin

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>
Tim Freiheit
  • 246
  • 2
  • 6
3

IMPORTANT: This solution only works for android gradle plugin versions prior to 3.0 due to changes in the way resources are processed.

So just hit this problem now because of the .debug suffix on our application id for debug builds. This is our workaround (note this an untested adaption from our codebase):

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 module name>/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 {
  ...
}
Bulwinkel
  • 2,111
  • 25
  • 23
  • 1
    Thanks for the answer, unfortunately, I don't think this works with Android Studio 3.0/AAPT2. Looks like shortcuts.xml doesn't exist anymore in the build folder, and instead has xml_shortcuts.xml.flat, which is seemingly a different file format that I cannot easily figure out how to edit. – Jawnnypoo Oct 24 '17 at 20:26
  • Confirm, using string res wil NOT work with aapt2/plugin v3 – Patrick Nov 18 '17 at 12:36
  • 1
    Answer updated to reflect that this solution does not work with the new android gradle plugin v3. Haven't found a new solution yet, will update again when/if I do. – Bulwinkel Nov 20 '17 at 04:36
2

When investigating this, I came across this library, which seems to do the trick:

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

Downside: You cannot have your shortcuts.xml within the res folder of your app, as the plugin takes the file, modifies it to automatically add the targetPackage, and then drops it in during build time, and if you already have one defined, it will cause a duplicate resources error.

Other than that downside, seems to work great!

Jawnnypoo
  • 993
  • 12
  • 18