• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Handling App Links
2page.image=images/cards/card-app-linking_2x.png
3page.keywords=applinking, deeplinks, intents
4page.tags=androidm,marshmallow
5@jd:body
6
7<div id="tb-wrapper">
8  <div id="tb">
9    <h2>This lesson teaches you to</h2>
10    <ol>
11        <li><a href="#url-handling">Understand URI Request Handling</a> </li>
12        <li><a href="#intent-handler">Create an Intent Handler for URIs</a></li>
13        <li><a href="#request-verify">Request App Links Verification</a></li>
14        <li><a href="#web-assoc">Declare Website Associations</a></li>
15        <li><a href="#testing">Test App Links</a></li>
16    </ol>
17  <h2>See also</h2>
18  <ol>
19    <li><a href="{@docRoot}tools/help/app-link-indexing.html">Supporting URLs and App Indexing in Android Studio</a></li>
20  </ol>
21  </div>
22</div>
23
24
25
26<p>
27  Users following web links on devices are frequently presented with confusing choices. Tapping a
28  link often results in the system asking the user which app should handle that link. For example,
29  clicking a URI in an email from a bank might result in a dialog asking the user whether to use
30  the browser, or the bank's own app, to open the link. Android 6.0 (API level 23) and higher allow
31  an app to designate itself as the default handler of a given type of link. If the user doesn't
32  want the app to be the default handler, they can override this behavior from
33  <strong>Settings</strong>.
34</p>
35
36<p>
37  Automatic handling of links requires the cooperation of app developers and website owners.
38  A developer must configure their app to declare associations with one or more websites, and to
39  request that the system verify those associations. A website owner must, in turn, provide
40  that verification by publishing a <a href="http://developers.google.com/digital-asset-links/"><i>Digital
41  Asset Links</i></a> file. The general steps for creating verified app links are as follows:
42</p>
43
44<ol>
45  <li>In your app manifest, create intent filters for your website URIs.</li>
46  <li>Configure your app to request verification of app links.</li>
47  <li>Publish a Digital Asset Links JSON file on your websites to provide verification.</li>
48</ol>
49
50<h2 id="url-handling">Understand URI Request Handling</h2>
51
52<p>
53  The app links feature allows your app to become the default handler for the website URIs you
54  specify, as long as the user has not already chosen a default app to handle that URI pattern.
55  When a clicked link or programmatic request invokes a web URI intent, the Android system
56  uses the following criteria, in descending order, to determine how to handle the request:
57</p>
58
59<ol>
60  <li>
61    <strong>The user has set app link associations</strong>: If the user has designated an app to
62    handle app links, the system passes the web URI request to that app. A user can set this
63    association in one of two ways: clicking <strong>Always</strong> when selecting an app
64    from an app-selection dialog; or, opening <em>Settings &gt; Apps &gt; (gear icon)
65    &gt; App links</em>, selecting an app to use, and setting the app's
66    <strong>App links</strong> property to the <strong>Open in this app</strong> option.
67  </li>
68
69  <li>
70    <strong>The user has set no association, and there is one supporting app</strong>: If the user
71    has not set a preference that matches the web URI request, and there is only one app declaring
72    support for the intent’s URI pattern, the system automatically passes the request to that app.
73  </li>
74
75  <li>
76    <strong>The user has set no association, and there are multiple supporting apps</strong>: If
77    there are multiple apps declaring support for the web URI pattern, the system displays an
78    app-selection dialog, prompting the user to select the most appropriate app.
79  </li>
80</ol>
81
82<p>
83  In case 2, if the user has newly installed the app, and the system has
84  verified it as a handler for this type of link, the system sets the app as the default handler. In
85  the other two cases, the presence of a verified app link handler has no effect on system behavior.
86</p>
87
88
89<h2 id="intent-handler">Create an Intent Handler for URIs</h2>
90
91<p>
92  App links are based on the <a href="{@docRoot}guide/components/intents-filters.html">Intent</a>
93  framework, which enables apps to handle requests from the system or other apps. Multiple apps may
94  declare the same web link URI patterns in their intent filters. When a user clicks on a web link
95  that does not have a default launch handler, the platform selects an app to handle the request,
96  using the criteria described in <a href="#url-handling">Understanding URI Request Handling</a>.
97</p>
98
99<p>
100  To enable your app to handle links, use intent filters in your app manifest to declare the URI
101  patterns that your app handles. The following example shows an intent filter that can
102  handle links to {@code http://www.android.com} and {@code https://www.android.com}:
103</p>
104
105<pre>
106&lt;activity ...&gt;
107    &lt;intent-filter&gt;
108        &lt;action android:name="android.intent.action.VIEW" /&gt;
109        &lt;category android:name="android.intent.category.DEFAULT" /&gt;
110        &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
111        &lt;data android:scheme="http" /&gt;
112        &lt;data android:scheme="https" /&gt;
113        &lt;data android:host="www.android.com" /&gt;
114    &lt;/intent-filter&gt;
115&lt;/activity&gt;
116</pre>
117
118<p>
119  As this example shows, intent filters for app links must declare an {@code android:scheme}
120  value of {@code http}, {@code https}, or both. The filter must not declare
121  any other schemes. The filter must also include the {@code android.intent.action.VIEW} and
122  {@code android.intent.category.BROWSABLE} category names.
123</p>
124
125<p>
126  This manifest declaration defines the connection between your app and a website. However, in
127  order to have the system treat your app as the default handler for a set of URIs, you must
128  also request that the system verify this connection.
129  The next section explains how to implement this verification.
130</p>
131
132
133<h2 id="request-verify">Request App Links Verification</h2>
134
135<p>
136  In addition to using intent filters to declare an association between your app and a website,
137  your manifest must also include an additional declaration for requesting automatic verification.
138  When this declaration is present, the Android system attempts to verify your app after
139  installation. If the verification succeeds, and the user has not set an alternate
140  preference for handling your website URIs, the system automatically routes those URI requests to
141  your app.
142</p>
143
144<p>
145  The system performs app-link verifications by comparing the host names in the data elements of
146  the app’s intent filters against the Digital Asset Links files ({@code assetlinks.json}) hosted
147  on the respective web domains. To enable the system to verify a host, make sure that your intent
148  filter declarations include the {@code android.intent.action.VIEW} intent action and {@code
149  android.intent.category.BROWSABLE} intent category.
150</p>
151
152
153<h3 id="config-verify">Enabling automatic verification</h3>
154
155<p>
156  To enable link handling verification for your app, set the {@code android:autoVerify} attribute to
157  {@code true} on at least one of the web URI intent filters in your app manifest, as shown in the
158  following manifest code snippet:
159</p>
160
161<pre>
162&lt;activity ...&gt;
163
164    &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
165        &lt;action android:name="android.intent.action.VIEW" /&gt;
166        &lt;category android:name="android.intent.category.DEFAULT" /&gt;
167        &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
168        &lt;data android:scheme="http" android:host="www.android.com" /&gt;
169        &lt;data android:scheme="https" android:host="www.android.com" /&gt;
170    &lt;/intent-filter&gt;
171
172&lt;/activity&gt;
173</pre>
174
175<p>
176  When the {@code android:autoVerify} attribute is present, installing your app causes the system
177  to attempt to verify all hosts associated with the web URIs in all of your app's intent filters.
178  The system treats your app as the default handler for the specified URI pattern only if it
179  successfully verifies <em>all</em> app link patterns declared in your manifest.
180</p>
181
182
183<h3 id="multi-host">Supporting app linking for multiple hosts</h3>
184
185<p>
186  The system must be able to verify every host specified in the app’s web URI intent filters’ data
187  elements against the Digital Asset Links files hosted on the respective web domains. If any
188  verification fails, the app is not verified to be a default handler for any of the web URI
189  patterns defined in the app's intent filters. For example, an app with the following intent
190  filters would fail verification if an {@code assetlinks.json} file were not found at both
191  {@code https://www.domain1.com/.well-known/assetlinks.json} and
192  {@code https://www.domain2.com/.well-known/assetlinks.json}:
193</p>
194
195<pre>
196&lt;application&gt;
197
198  &lt;activity android:name=”MainActivity”&gt;
199    &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
200      &lt;action android:name="android.intent.action.VIEW" /&gt;
201      &lt;category android:name="android.intent.category.DEFAULT" /&gt;
202      &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
203      &lt;data android:scheme="http" android:host="www.domain1.com" /&gt;
204      &lt;data android:scheme="https" android:host="www.domain1.com" /&gt;
205    &lt;/intent-filter&gt;
206  &lt;/activity&gt;
207  &lt;activity android:name=”SecondActivity”&gt;
208    &lt;intent-filter&gt;
209      &lt;action android:name="android.intent.action.VIEW" /&gt;
210      &lt;category android:name="android.intent.category.DEFAULT" /&gt;
211      &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
212      &lt;data android:scheme="https" android:host="www.domain2.com" /&gt;
213    &lt;/intent-filter&gt;
214  &lt;/activity&gt;
215
216&lt;/application
217</pre>
218
219
220<h3 id="multi-subdomain">Supporting app linking for multiple subdomains</h3>
221
222<p>
223  The Digital Asset Links protocol treats subdomains as unique, separate hosts. If your intent
224  filter lists both the {@code www.example.com} and {@code mobile.example.com} subdomains as
225  hosts, you must host a separate {@code assetlink.json} file on each subdomain. For example, an
226  app with the following intent filter declaration would pass verification only if the website
227  owner published valid {@code assetlinks.json} files at both
228  {@code https://www.example.com/.well-known/assetlinks.json} and
229  {@code https://mobile.example.com/.well-known/assetlinks.json}:
230</p>
231
232<pre>
233&lt;application&gt;
234  &lt;activity android:name=”MainActivity”&gt;
235    &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
236      &lt;action android:name="android.intent.action.VIEW" /&gt;
237      &lt;category android:name="android.intent.category.DEFAULT" /&gt;
238      &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
239      &lt;data android:scheme="http" android:host="www.example.com" /&gt;
240      &lt;data android:scheme="https" android:host="mobile.example.com" /&gt;
241    &lt;/intent-filter&gt;
242  &lt;/activity&gt;
243&lt;/application&gt;
244</pre>
245
246
247<h2 id="web-assoc">Declare Website Associations</h2>
248
249<p>
250  For app link verification to be successful, website owners must declare associations
251  with apps. A site owner declares the relationship to an app by hosting a Digital Asset Links JSON
252  file, with the name {@code assetlinks.json}, at the following well-known location on the domain:
253</p>
254
255<pre>
256https://<em>domain</em>[:<em>optional_port</em>]/.well-known/assetlinks.json
257</pre>
258
259<p class="note">
260  <strong>Important:</strong> The system verifies the JSON file via the encrypted HTTPS protocol.
261  Make sure that your hosted file is accessible over an HTTPS connection, regardless of whether
262  your app's intent filter includes {@code https}.
263</p>
264
265<p>
266  A Digital Asset Links JSON file indicates the Android apps that are associated with the website.
267  The JSON file uses the following fields to identify associated apps:
268</p>
269
270<ul>
271  <li>{@code package_name}: The package name declared in the app's manifest.</li>
272
273  <li>{@code sha256_cert_fingerprints}: The SHA256 fingerprints of your app’s signing certificate.
274    You can use the following command to generate the fingerprint via the Java keytool:
275
276    <pre class="no-pretty-print">
277$ keytool -list -v -keystore my-release-key.keystore
278    </pre>
279
280    This field supports multiple fingerprints, which can be used to support different versions
281    of your app, such as debug and production builds.
282  </li>
283</ul>
284
285<p>
286  The following example {@code assetlinks.json} file grants link-opening rights to a
287  {@code com.example} Android app:
288</p>
289
290<pre>
291[{
292  "relation": ["delegate_permission/common.handle_all_urls"],
293  "target": {
294    "namespace": "android_app",
295    "package_name": "com.example",
296    "sha256_cert_fingerprints":
297    ["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"]
298  }
299}]
300</pre>
301
302
303<h3 id="multiple-apps">Associating a website with multiple apps</h3>
304
305<p>
306  A website can declare associations with multiple apps within the same {@code assetlinks.json}
307  file. The following file listing shows an example of a statement file that declares association
308  with two apps, separately, and resides at
309  <code>https://www.example.com/.well-known/assetlinks.json</code>:
310</p>
311
312<pre>
313[{
314  "relation": ["delegate_permission/common.handle_all_urls"],
315  "target": {
316    "namespace": "android_app",
317    "package_name": <strong>"example.com.puppies.app"</strong>,
318    "sha256_cert_fingerprints":
319    ["<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>"]
320  }
321  },
322  {
323  "relation": ["delegate_permission/common.handle_all_urls"],
324  "target": {
325    "namespace": "android_app",
326    "package_name": "<strong>example.com.monkeys.app</strong>",
327    "sha256_cert_fingerprints":
328    ["<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>"]
329  }
330}]
331</pre>
332
333<p>
334  Different apps may handle links for different resources under the same web host. For example,
335  app1 may declare an intent filter for {@code https://example.com/articles}, and app2 may declare
336  an intent filter for {@code https://example.com/videos}.
337</p>
338
339<p class="note">
340  <strong>Note:</strong> Multiple apps associated with a domain may be signed with the same or
341  different certificates.
342</p>
343
344
345<h3 id="multi-site">Associating multiple websites with a single app</h3>
346
347<p>
348  Multiple websites can declare associations with the same app in their respective {@code
349  assetlinks.json} files. The following file listings show an example of how to declare the
350  association of domain1 and domain2 with app1. The first listing shows the association of
351  domain1 with app1:
352</p>
353
354<pre>
355https://www.domain1.com/.well-known/assetlinks.json
356
357[{
358  "relation": ["delegate_permission/common.handle_all_urls"],
359  "target": {
360    "namespace": "android_app",
361    "package_name": "<strong>com.mycompany.app1</strong>",
362    "sha256_cert_fingerprints":
363    ["<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>"]
364  }
365}]
366</pre>
367
368<p>The next listing shows the association of domain2 with app1. Only the very last line, which
369specifies the URL, is different:</p>
370
371<pre>
372https://www.domain2.com/.well-known/assetlinks.json
373
374[{
375  "relation": ["delegate_permission/common.handle_all_urls"],
376  "target": {
377    "namespace": "android_app",
378    "package_name": "<strong>com.mycompany.app1</strong>",
379    "sha256_cert_fingerprints":
380    ["<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>"]
381  }
382}]
383</pre>
384
385<h2 id="testing">Test App Links</h2>
386
387<p>
388  When implementing the app linking feature, you should test the linking functionality to
389  make sure the system can associate your app with your websites, and handle URI requests,
390  as you expect.
391</p>
392
393
394<h3 id="test-hosts">Confirm the list of hosts to verify</h3>
395
396<p>
397  When testing, you should confirm the list of associated hosts that the system should verify
398  for your app. Make a list of all web URIs whose corresponding intent filters include the following
399  attributes and elements:
400</p>
401
402<ul>
403  <li>{@code android:scheme} attribute with a value of {@code http} or {@code https}
404  </li>
405  <li>{@code android:host} attribute with a domain URI pattern
406  </li>
407  <li>{@code android.intent.action.VIEW} category element
408  </li>
409  <li>{@code android.intent.category.BROWSABLE} category element
410  </li>
411</ul>
412
413<p>
414  Use this list to check that a Digital Asset Links JSON file is provided on each named host
415  and subdomain.
416</p>
417
418
419<h3 id="test-dal-files">Confirm the Digital Asset Links files</h3>
420
421<p>
422  For each website, use the Digital Asset Links API to confirm that the Digital Asset Links JSON
423  file is properly hosted and defined:
424</p>
425
426<pre>
427https://digitalassetlinks.googleapis.com/v1/statements:list?
428   source.web.site=https://<strong>&lt;domain1&gt;:&lt;port&gt;</strong>&amp;
429   relation=delegate_permission/common.handle_all_urls
430</pre>
431
432
433<h3 id="test-intent">Testing a web URI intent</h3>
434
435<p>
436  Once you have confirmed the list of websites to associate with your app, and you have confirmed
437  that the hosted JSON file is valid, install the app on your device. Wait at least 20 seconds for
438  the asynchronous verification process to complete. Use the following command to check
439  whether the system verified your app and set the correct link handling policies:
440</p>
441
442<pre>
443adb shell am start -a android.intent.action.VIEW \
444    -c android.intent.category.BROWSABLE \
445    -d "http://&lt;domain1&gt;:&lt;port&gt;"
446</pre>
447
448
449<h3 id="check-link-policies">Check link policies</h3>
450
451<p>
452  As part of your testing process, you can check the current system settings for link handling.
453  Use the following command to get a listing of existing link-handling policies for all
454  applications:
455</p>
456
457<pre>
458adb shell dumpsys package domain-preferred-apps
459 --or--
460adb shell dumpsys package d
461</pre>
462
463<p class="note">
464  <strong>Note:</strong> Make sure you wait at least 20 seconds after installation of your app to
465  allow for the system to complete the verification process.
466</p>
467
468<p>
469  The command returns a listing of each user or profile defined on the device,
470  preceded by a header in the following format:
471</p>
472
473<pre>
474App linkages for user 0:
475</pre>
476
477<p>
478  Following this header, the output uses the following format to list the link-handling settings
479  for that user:
480</p>
481
482<pre>
483Package: com.android.vending
484Domains: play.google.com market.android.com
485Status: always : 200000002
486</pre>
487
488<p>This listing indicates which apps are associated with which domains for that user:</p>
489
490<ul>
491  <li>{@code Package} - Identifies an app by its package name, as declared in its manifest.
492  </li>
493  <li>{@code Domains} - Shows the full list of hosts whose web links this app handles, using
494  blank spaces as delimiters.
495  </li>
496  <li>{@code Status} - Shows the current link-handling setting for this app. An app that has
497  passed verification, and whose manifest contains {@code android:autoVerify="true"}, shows a status
498  of {@code always}. The hexadecimal number after this status is related to the Android system's
499  record of the user’s app linkage preferences. This value does not indicate whether verification
500  succeeded.
501  </li>
502</ul>
503
504<p class="note">
505  <strong>Note:</strong> If a user changes the app link settings for an app before verification
506  is complete, you may see a false positive for a successful verification, even though
507  verification has failed. This verification failure, however, does not matter if the user
508  explicitly enabled the app to open supported links without asking. This is because
509  user preferences take precedence over programmatic verification (or lack of it). As a result,
510  the link goes directly to your app, without showing a dialog, just as if verification had
511  succeeded.
512</p>
513
514
515
516<h3 id="test-example">Test example</h3>
517
518<p>
519  For app link verification to succeed, the system must be able to verify your app with all of
520  the websites that you specify in your app’s intent filters, and that meet the criteria for app
521  links. The following example shows a manifest configuration with several app links defined:
522</p>
523
524<pre>
525&lt;application&gt;
526
527    &lt;activity android:name=”MainActivity”&gt;
528        &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
529            &lt;action android:name="android.intent.action.VIEW" /&gt;
530            &lt;category android:name="android.intent.category.DEFAULT" /&gt;
531            &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
532            &lt;data android:scheme="http" android:host="www.example.com" /&gt;
533            &lt;data android:scheme="https" android:host="mobile.example.com" /&gt;
534        &lt;/intent-filter&gt;
535        &lt;intent-filter&gt;
536            &lt;action android:name="android.intent.action.VIEW" /&gt;
537            &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
538            &lt;data android:scheme="http" android:host="www.example2.com" /&gt;
539        &lt;/intent-filter&gt;
540    &lt;/activity&gt;
541
542    &lt;activity android:name=”SecondActivity”&gt;
543        &lt;intent-filter&gt;
544            &lt;action android:name="android.intent.action.VIEW" /&gt;
545            &lt;category android:name="android.intent.category.DEFAULT" /&gt;
546            &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
547            &lt;data android:scheme="http" android:host="account.example.com" /&gt;
548        &lt;/intent-filter&gt;
549    &lt;/activity&gt;
550
551      &lt;activity android:name=”ThirdActivity”&gt;
552        &lt;intent-filter&gt;
553            &lt;action android:name="android.intent.action.VIEW" /&gt;
554            &lt;category android:name="android.intent.category.DEFAULT" /&gt;
555            &lt;data android:scheme="http" android:host="map.example.com" /&gt;
556        &lt;/intent-filter&gt;
557        &lt;intent-filter&gt;
558            &lt;action android:name="android.intent.action.VIEW" /&gt;
559            &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
560            &lt;data android:scheme="market" android:host="example.com" /&gt;
561        &lt;/intent-filter&gt;
562      &lt;/activity&gt;
563
564&lt;/application&gt;
565</pre>
566
567<p>
568  The list of hosts that the platform would attempt to verify from the above manifest is:
569</p>
570
571<pre>
572www.example.com
573mobile.example.com
574www.example2.com
575account.example.com
576</pre>
577
578<p>
579  The list of hosts that the platform would not attempt to verify from the above manifest is:
580</p>
581
582<pre>
583map.example.com (it does not have android.intent.category.BROWSABLE)
584market://example.com (it does not have either an “http” or “https” scheme)
585</pre>
586