| page.title=App Links |
| page.image=images/cards/card-app-linking_2x.png |
| page.keywords=applinking, deeplinks, intents |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#url-handling">Understanding URL Request Handling</a> </li> |
| <li><a href="#intent-handler">Create an Intent Handler for URLs</a></li> |
| <li><a href="#request-verify">Request App Links Verification</a></li> |
| <li><a href="#web-assoc">Declare Website Associations</a></li> |
| <li><a href="#testing">Testing App Links</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| |
| <p> |
| The M Developer Preview introduces a new option for handling web site links, allowing clicked |
| links to go directly to the website's official app, instead of asking the user to chose how to |
| handle the link. This feature saves the user time and helps developers deliver a better |
| experience. Users can also select whether an app should always open specific types of links |
| automatically or prompt the user each time. |
| </p> |
| |
| <p> |
| Handling links automatically requires the cooperation of app developers and website owners. |
| Developers must configure their apps to declare connections with websites and request |
| verification. Website owners can publish a |
| Digital Asset Links file |
| to allow Android to verify the association of apps with their sites. The general steps for |
| creating verified app links are as follows: |
| </p> |
| |
| <ol> |
| <li>Create intent filters within your app for your website URLs</li> |
| <li>Configure your app to request verification of app links</li> |
| <li>Publish a Digital Asset Links JSON file on your websites</li> |
| </ol> |
| |
| <h2 id="url-handling">Understanding URL Request Handling</h2> |
| |
| <p> |
| The app links feature allows your app to become the default handler for your website URLs, as |
| long as the user has not already chosen an app to handle that URL pattern. When a web URI intent |
| is invoked through a clicked link or programatic request, the Android system determines what app |
| is used to handle the intent. The system use these criteria, in order, to determine how to handle |
| the request: |
| </p> |
| |
| <ol> |
| <li> |
| <strong>User has set app link associations</strong>: If the user has designated an app to |
| handle app links, the system passes the web URI request to that app. Users set this association |
| by opening <strong>Settings > Apps > Configure apps (gear icon) > App links</strong>, |
| then selecting an app to use and configuring it's <strong>App links</strong> property to the |
| <em>Open in this app</em> option. |
| </li> |
| |
| <li> |
| <strong>No association set by user and a single supporting app</strong>: If the user |
| has not set a preference that matches the web URI request, and there is only one app declaring |
| support for the intent’s URI pattern, the system passes the request to that app. |
| </li> |
| |
| <li> |
| <strong>No association set by user and multiple supporting apps</strong>: If there is |
| no explicit user preference and there are multiple apps declaring support for the web URI |
| pattern, the system prompts the user to select one of the available apps |
| </li> |
| </ol> |
| |
| <p> |
| In case #2 (no user setting and no other app handlers), if an app is newly installed and verified |
| as a handler for this type of link, the system sets it as the default handler. In the other two |
| cases, the system behavior is the same, regardless of the presence of a verified app link |
| handler. |
| </p> |
| |
| |
| <h2 id="intent-handler">Create an Intent Handler for URLs</h2> |
| |
| <p> |
| App links are based on the <a href="{@docRoot}guide/components/intents-filters.html">Intent</a> |
| framework, which enables apps to handle requests from the system or other apps. Multiple apps may |
| declare matching web link URI patterns in their intent filters. When a user clicks on a web link |
| that does not have a default launch handler, the platform selects an app to handle the request, |
| based on the criteria described in the previous section. |
| </p> |
| |
| <p> |
| To enable your app to handle links, use intent filters in your app manifest to declare the URI |
| patterns to be handled by your app. The following sample code shows an intent filter that can |
| handle links to {@code http://www.android.com} and {@code https://www.android.com}: |
| </p> |
| |
| <pre> |
| <activity ...> |
| <intent-filter> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" /> |
| <data android:scheme="https" /> |
| <data android:host="www.android.com" /> |
| </intent-filter> |
| </activity> |
| </pre> |
| |
| <p> |
| As shown in the example above, intent filters for app links must declare an {@code android:scheme} |
| value of either {@code http} or {@code https}, or both. The filter should not declare |
| any other schemes. The filter must also include the {@code android.intent.action.VIEW}; and |
| {@code android.intent.category.BROWSABLE} category names. |
| </p> |
| |
| <p> |
| This manifest declaration defines the connection between your app and a website. However, in |
| order to have the system treat your app as the default handler for a set of URLs, you must |
| also request that the system verify this connection, which is explained in the next section. |
| </p> |
| |
| |
| <h2 id="request-verify">Request App Links Verification</h2> |
| |
| <p> |
| In addition to declaring an association between your app and a web site using intent filters, |
| your app must also request automatic verification with an additional manifest declaration. When |
| this declaration is set, the Android system attempts to verify your app after it is installed. |
| If the verification succeeds, and the user has not set a preference for your website URLs, the |
| system automatically routes those URL requests to your app. |
| </p> |
| |
| <p> |
| The system performs app link verifications by comparing the host names in the data elements of |
| the app’s intent filters against the Digital Asset Links files ({@code assetlinks.json}) hosted |
| on the respective web domains. To enable the system to verify a host, make sure that your intent |
| filter declarations include the {@code android.intent.action.VIEW} intent action and {@code |
| android.intent.category.BROWSABLE} intent category. |
| </p> |
| |
| |
| <h3 id="config-verify">Enabling automatic verification</h3> |
| |
| <p> |
| To enable link handling verification for your app, set the {@code android:autoVerify} attribute to |
| {@code true} on at least one of the web URI intent filters in your app manifest, as shown in the |
| following manifest code snippet: |
| </p> |
| |
| <pre> |
| <activity ...> |
| |
| <intent-filter <strong>android:autoVerify="true"</strong>> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT"gt; |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" android:host="www.android.com" /> |
| <data android:scheme="https" android:host="www.android.com" /> |
| </intent-filter> |
| |
| </activity> |
| </pre> |
| |
| <p> |
| When the {@code android:autoVerify} attribute is set, the system attempts to verify all hosts |
| associated with web URI’s in all of your app's intent filters when the app is installed. The |
| system treats your app as the default handler for the specified URI pattern only if it |
| successfully verifies <em>all</em> app link patterns declared in your manifest. |
| </p> |
| |
| |
| <h3 id="multi-host">Supporting app linking for multiple hosts</h3> |
| |
| <p> |
| The system must be able to verify each host specified in the app’s web URI intent filters’ data |
| elements against the Digital Asset Links files hosted on the respective web domains. If any |
| verification fails, the app is not verified to be a default handler for any of the web URL |
| patterns defined in its intent filters. For example, an app with the following intent filters |
| would fail verification if an {@code assetlinks.json} file were not found at both |
| {@code https://www.domain1.com/.well-known/assetlinks.json} and |
| {@code https://www.domain2.com/.well-known/assetlinks.json}: |
| </p> |
| |
| <pre> |
| <application> |
| |
| <activity android:name=”MainActivity”> |
| <intent-filter <strong>android:autoVerify="true"</strong>> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" android:host="www.domain1.com" /> |
| <data android:scheme="https" android:host="www.domain1.com" /> |
| </intent-filter> |
| </activity> |
| <activity android:name=”SecondActivity”> |
| <intent-filter> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="https" android:host="www.domain2.com" /> |
| </intent-filter> |
| </activity> |
| |
| </application |
| </pre> |
| |
| |
| <h3 id="multi-subdomain">Supporting app linking for multiple subdomains</h3> |
| |
| <p> |
| The Digital Asset Links protocol treats subdomains as unique, separate hosts. If your intent |
| filter lists both the {@code www.example.com} and {@code mobile.example.com} subdomains as |
| schemes, you must host separate {@code assetlink.json} file on each subdomain. For example, an |
| app with the following intent filter declaration would pass verification only if the website |
| owner published valid {@code assetlinks.json} files at both |
| {@code https://www.example.com/.well-known/assetlinks.json} and |
| {@code https://mobile.example.com/.well-known/assetlinks.json}: |
| </p> |
| |
| <pre> |
| <application> |
| <activity android:name=”MainActivity”> |
| <intent-filter <strong>android:autoVerify="true"</strong>> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" android:host="www.example.com" /> |
| <data android:scheme="https" android:host="mobile.example.com" /> |
| </intent-filter> |
| </activity> |
| </application> |
| </pre> |
| |
| |
| <h2 id="web-assoc">Declare Website Associations</h2> |
| |
| <p> |
| For app link verification to be successful, website owners must declare associations |
| with apps. A site owner declares the relationship to an app by hosting a Digital Asset Links JSON |
| file, with the name {@code assetlinks.json}, at the following well-known location on the domain: |
| </p> |
| |
| <pre> |
| https://<em>domain</em>[:<em>optional_port</em>]/.well-known/assetlinks.json |
| </pre> |
| |
| <p class="note"> |
| <strong>Important:</strong> With M Preview 3 and the Android 6.0 (API level 23) release, the JSON |
| file is verified via the encrypted HTTPS protocol. Make sure that your hosted file can be |
| accessed over an HTTPS connection, regardless of whether your app's intent filter declares an |
| {@code android:scheme} setting of {@code http}, {@code https} or both. |
| </p> |
| |
| <p> |
| A Digital Asset Links JSON file indicates the Android apps that are associated with the web site. |
| The JSON file identifies associated apps with the following fields: |
| </p> |
| |
| <ul> |
| <li>{@code package_name}: The package name declared in the app's manifest.</li> |
| |
| <li>{@code sha256_cert_fingerprints}: The SHA256 fingerprints of your app’s signing certificate. |
| You can use the Java keytool to generate the fingerprint using the following command: |
| <pre>keytool -list -v -keystore my-release-key.keystore</pre> |
| This field supports multiple fingerprints, which can be used to support different versions |
| of your app, such as debug and production builds. |
| </li> |
| </ul> |
| |
| <p> |
| The following example {@code assetlinks.json} file grants link opening rights to a |
| {@code com.example} Android application: |
| </p> |
| |
| <pre> |
| [{ |
| "relation": ["delegate_permission/common.handle_all_urls"], |
| "target": { |
| "namespace": "android_app", |
| "package_name": "com.example", |
| "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"] |
| } |
| }] |
| </pre> |
| |
| |
| <h3 id="multiple-apps">Associating a website with multiple apps</h3> |
| |
| <p> |
| A website can declare associations with multiple apps within the same {@code assetlinks.json} |
| file. The following file listing shows an example of a statement file that declares association |
| with two, separate apps and is hosted at |
| <code>https://www.example.com/.well-known/assetlinks.json</code>: |
| </p> |
| |
| <pre> |
| [{ |
| "relation": ["delegate_permission/common.handle_all_urls"], |
| "target": { |
| "namespace": "android_app", |
| "package_name": <strong>"example.com.puppies.app"</strong>, |
| "sha256_cert_fingerprints": |
| ["<strong>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</strong>"] |
| } |
| }, |
| { |
| "relation": ["delegate_permission/common.handle_all_urls"], |
| "target": { |
| "namespace": "android_app", |
| "package_name": "<strong>example.com.monkeys.app</strong>", |
| "sha256_cert_fingerprints": |
| ["<strong>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</strong>"] |
| } |
| }] |
| </pre> |
| |
| <p> |
| When multiple apps handle links to the same host, the system determines which one to use for |
| a given link based on the intent filters defined in each app’s manifest. Different apps may |
| handle links for different resources under the same web host. For example, app1 may |
| declare an intent filter for {@code https://example.com/articles}, and app2 may declare |
| an intent filter for {@code https://example.com/videos}. |
| </p> |
| |
| <p class="note"> |
| <strong>Note:</strong> Multiple apps associated with a domain may be signed with the same or |
| different certificates. |
| </p> |
| |
| |
| <h3 id="multi-site">Associating multiple websites with a single app</h3> |
| |
| <p> |
| Multiple websites can declare associations with the same app in their respective {@code |
| assetlinks.json} files. The following file listings show an example of how to declare the |
| association of domain1 and domain2 with app1: |
| </p> |
| |
| <pre> |
| https://www.domain1.com/.well-known/assetlinks.json |
| |
| [{ |
| "relation": ["delegate_permission/common.handle_all_urls"], |
| "target": { |
| "namespace": "android_app", |
| "package_name": "<strong>com.mycompany.app1</strong>", |
| "sha256_cert_fingerprints": |
| ["<strong>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</strong>"] |
| } |
| }] |
| </pre> |
| |
| <pre> |
| https://www.domain2.com/.well-known/assetlinks.json |
| |
| [{ |
| "relation": ["delegate_permission/common.handle_all_urls"], |
| "target": { |
| "namespace": "android_app", |
| "package_name": "<strong>com.mycompany.app1</strong>", |
| "sha256_cert_fingerprints": |
| ["<strong>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</strong>"] |
| } |
| }] |
| </pre> |
| |
| |
| |
| <h2 id="testing">Testing App Links</h2> |
| |
| <p> |
| When implementing the app linking feature, you should test the linking functionality to |
| make your app can be successfully associated with your websites and handle URL requests |
| as you expect. |
| </p> |
| |
| |
| <h3 id="test-hosts">Confirm the list of hosts to verify</h3> |
| |
| <p> |
| When testing, you should confirm the list of associated hosts that the system should verify |
| for your app. Make a list of all web URI’s in intent-filters in your manifest that |
| includes the following: |
| </p> |
| |
| <ul> |
| <li>{@code android:scheme} attribute with a value of {@code http} or {@code https} |
| </li> |
| <li>{@code android:host} attribute with a domain URI pattern |
| </li> |
| <li>{@code android.intent.action.VIEW} category element |
| </li> |
| <li>{@code android.intent.category.BROWSABLE} category element |
| </li> |
| </ul> |
| |
| <p> |
| Use this list to check that a Digital Asset Links JSON file is provided on each named host |
| and subdomain. |
| </p> |
| |
| |
| <h3 id="test-dal-files">Confirm the Digital Asset Links files</h3> |
| |
| <p> |
| For each website, confirm that the Digital Asset Links JSON file is properly hosted and |
| defined by using the Digital Asset Links API: |
| </p> |
| |
| <pre> |
| https://digitalassetlinks.googleapis.com/v1/statements:list? |
| source.web.site=https://<strong><domain1>:<port></strong>& |
| relation=delegate_permission/common.handle_all_urls |
| </pre> |
| |
| |
| <h3 id="test-intent">Testing a web URI intent</h3> |
| |
| <p> |
| Once you have confirmed the list of websites to associate with your app, and you have confirmed |
| that the hosted JSON file is valid, install the app on your device. Wait at least 20 seconds for |
| the asynchronous verification process to complete. Use the following command to check |
| if the system verified your app and set the correct link handling policies: |
| </p> |
| |
| <pre> |
| adb shell am start -a android.intent.action.VIEW \ |
| -c android.intent.category.BROWSABLE \ |
| -d "http://<domain1>:<port>" |
| </pre> |
| |
| |
| <h3 id="check-link-policies">Check link policies</h3> |
| |
| <p> |
| As part of your testing process, you can check the current system settings for link handling. |
| Use the following command to get a listing of link-handling policies for all applications: |
| </p> |
| |
| <pre> |
| adb shell dumpsys package domain-preferred-apps |
| --or-- |
| adb shell dumpsys package d |
| </pre> |
| |
| <p class="note"> |
| <strong>Note:</strong> Make sure you wait at least 20 seconds after installation of your app to |
| allow for the system to complete the verification process. |
| </p> |
| |
| <p> |
| The command returns a listing of each user or profile defined on the device, |
| indicated by a header in the following format: |
| </p> |
| |
| <pre> |
| App linkages for user 0: |
| </pre> |
| |
| <p> |
| Following this heading, the output lists the link-handling settings for that user in this format: |
| </p> |
| |
| <pre> |
| Package: com.android.vending |
| Domains: play.google.com market.android.com |
| Status: always : 200000002 |
| </pre> |
| |
| <p>This listing indicates the what apps are associated with what domains for that user, as |
| described below:</p> |
| |
| <ul> |
| <li>{@code Package} - Identifies an app by its package name, as declared in its manifest. |
| </li> |
| <li>{@code Domains} - Shows the full list of hosts whose web links this app handles. |
| </li> |
| <li>{@code Status} - Shows the current link-handling setting for this app. An app that set {@code |
| android:autoVerify="true"} value and passed verification is shown with a status of {@code |
| always}. The hexadecimal number after this status is related to the Android system's record of |
| the user’s app linkage preferences. This value is not relevant for interpreting whether the |
| verification operation passed. |
| </li> |
| </ul> |
| |
| <p class="note"> |
| <strong>Note:</strong>It is possible for a user to change the app link settings for an app |
| before the verification operation has completed. If this |
| situation occurs, you may see a false positive for a successful verification, even though |
| verification has failed. However, the user has already explicitly enabled the app to open |
| supported links without asking. In this case, no dialog is shown and the link goes directly to |
| your app, but only because explicit user preferences take precedence. |
| </p> |
| |
| |
| |
| <h3 id="test-example">Test example</h3> |
| |
| <p> |
| For app link verification to succeed, the system must be able to verify your app with all of |
| the websites referenced in your app’s intent filters, that meet the criteria for app links. |
| The following example manifest snippet shows app configuration with several app links defined: |
| </p> |
| |
| <pre> |
| <application> |
| |
| <activity android:name=”MainActivity”> |
| <intent-filter <strong>android:autoVerify="true"</strong>> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" android:host="www.example.com" /> |
| <data android:scheme="https" android:host="mobile.example.com" /> |
| </intent-filter> |
| <intent-filter> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" android:host="www.example2.com" /> |
| </intent-filter> |
| </activity> |
| |
| <activity android:name=”SecondActivity”> |
| <intent-filter> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="http" android:host="account.example.com" /> |
| </intent-filter> |
| </activity> |
| |
| <activity android:name=”ThirdActivity”> |
| <intent-filter> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| <data android:scheme="http" android:host="map.example.com" /> |
| </intent-filter> |
| <intent-filter> |
| <action android:name="android.intent.action.VIEW" /> |
| <category android:name="android.intent.category.BROWSABLE" /> |
| <data android:scheme="market" android:host="example.com" /> |
| </intent-filter> |
| </activity> |
| |
| </application> |
| </pre> |
| |
| <p> |
| The list of hosts that the platform would attempt to verify from the above manifest is: |
| </p> |
| |
| <pre> |
| www.example.com |
| mobile.example.com |
| www.example2.com |
| account.example.com |
| </pre> |
| |
| <p> |
| The list of hosts that the platform would not attempt to verify from the above manifest is: |
| </p> |
| |
| <pre> |
| map.example.com (it does not have android.intent.category.BROWSABLE) |
| market://example.com (it does not have either an “http” or “https” scheme) |
| </pre> |