12

Android M has added support for App links by creating a special assetlinks.json on the web server to delegate link handling to a mobile app.

For example, here's the content of such file:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.costingtons.app",
    "sha256_cert_fingerprints": ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:"
     "A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

Currently, the relation is defined as common.handle_all_urls which means any url will be routed to the app.

I would like the app to open specific routes, for example https://costingtons.com/products/a-product would open in the app but https://costingtons.com would open the web version.

Apple Universal Links similar configuration file can define paths to be opened in the app, and the syntax supports pattern matching like /products/* etc.

Is there any way to do something like that with App Links in Android ?

Michael
  • 22,196
  • 33
  • 132
  • 187

3 Answers3

11

As far as I can tell, there's no way to set up the assetlinks file to determine which paths can/should open the app (the way that you can with the iOS AASA file).

However, since Android employs Intent Filters, you can use those to restrict which paths should open the app. Per an earlier comment, the assetlinks file only says which URLs can open the app. It's up to the app to define which URLs should open the app.

So with your above example, you'd need to define an Intent Filter for one of your activities which would look something like:

<intent-filter android:autoVerify="true">
    <category android:name="android.intent.category.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <!-- Only accept URLs that look like https://costingtons.com/products/* -->
    <data
        android:scheme="https"
        android:host="costingtons.com"
        android:pathPrefix="/products/" />
</intent-filter>

The biggest limitation that I've found with this is that there's no way to exclude certain paths (i.e. NOT URLs with a prefix of xyz), so you'd have to come up with an exhaustive set of Intent Filters matching all URLs that you DO want to allow into the app.

Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89
themarshal
  • 1,056
  • 1
  • 11
  • 20
  • This answer was very helpful. One detail though: the asterisk in `pathPrefix` doesn't seem to work as expected. Simply `pathPrefix="/products/"` would match all paths starting with `/products/`. – Jonik Jan 02 '20 at 14:41
7

The assetlinks.json file specifies that that particular app is allowed to open all URLs, but the app itself (via the intent filter in its AndroidManifest) can be more restrictive so that it only opens the product links, and not the general website link.

Furthermore even if the intent filter is invoked for a particular URL, the receiver can still decide not to handle it, leaving it to the next handler (often the browser). (Maybe you want the app to handle links when on cellular, but let the browser handle them when on wifi).

zmarties
  • 4,809
  • 22
  • 39
  • 2
    *"the receiver can still decide not to handle it, leaving it to the next handler"* - Is this documented anywhere ? I still think that the responsibility of deciding which paths should be handled by the app should belong to the website and not the app. For example, a website may want to let 3rd party app to handle specific section of the website but not others, but is forced to let the app handle everything – Michael Mar 08 '16 at 12:02
  • 1
    This mechanism isn't really designed for third party apps, but only for first party ones that control both the website (to add the json file) and the app. – zmarties Mar 08 '16 at 12:48
  • 3
    *"the receiver can still decide not to handle it, leaving it to the next handler"* - Do you know how this is done ? – Michael Mar 10 '16 at 06:58
  • Hi, Michael. Are you find a way to fix this problem ? – Binus Jun 22 '16 at 17:27
0

@zmarties is right, the only thing you need to do is to make sure your Manifest.xml is configured to support https://yourdomain.com/product/* and not https://yourdomain.com/otherthings, https://yourdomain.com/otherthings will then open a web browser instead.

How to prove that?

ASOS and most e-commerce apps I know have app indexing enabled.

With ASOS Android app installed:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "https://www.asos.com/men/shoes-boots-trainers/cat?cid=4209"

Will bring up a category screen in their Android app,

whereas, the following will open up web browsers:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "https://www.asos.com/dummycrazyurl"
ericn
  • 12,476
  • 16
  • 84
  • 127