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 > Apps > (gear icon) 65 > 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<activity ...> 107 <intent-filter> 108 <action android:name="android.intent.action.VIEW" /> 109 <category android:name="android.intent.category.DEFAULT" /> 110 <category android:name="android.intent.category.BROWSABLE" /> 111 <data android:scheme="http" /> 112 <data android:scheme="https" /> 113 <data android:host="www.android.com" /> 114 </intent-filter> 115</activity> 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<activity ...> 163 164 <intent-filter <strong>android:autoVerify="true"</strong>> 165 <action android:name="android.intent.action.VIEW" /> 166 <category android:name="android.intent.category.DEFAULT" /> 167 <category android:name="android.intent.category.BROWSABLE" /> 168 <data android:scheme="http" android:host="www.android.com" /> 169 <data android:scheme="https" android:host="www.android.com" /> 170 </intent-filter> 171 172</activity> 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<application> 197 198 <activity android:name=”MainActivity”> 199 <intent-filter <strong>android:autoVerify="true"</strong>> 200 <action android:name="android.intent.action.VIEW" /> 201 <category android:name="android.intent.category.DEFAULT" /> 202 <category android:name="android.intent.category.BROWSABLE" /> 203 <data android:scheme="http" android:host="www.domain1.com" /> 204 <data android:scheme="https" android:host="www.domain1.com" /> 205 </intent-filter> 206 </activity> 207 <activity android:name=”SecondActivity”> 208 <intent-filter> 209 <action android:name="android.intent.action.VIEW" /> 210 <category android:name="android.intent.category.DEFAULT" /> 211 <category android:name="android.intent.category.BROWSABLE" /> 212 <data android:scheme="https" android:host="www.domain2.com" /> 213 </intent-filter> 214 </activity> 215 216</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<application> 234 <activity android:name=”MainActivity”> 235 <intent-filter <strong>android:autoVerify="true"</strong>> 236 <action android:name="android.intent.action.VIEW" /> 237 <category android:name="android.intent.category.DEFAULT" /> 238 <category android:name="android.intent.category.BROWSABLE" /> 239 <data android:scheme="http" android:host="www.example.com" /> 240 <data android:scheme="https" android:host="mobile.example.com" /> 241 </intent-filter> 242 </activity> 243</application> 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><domain1>:<port></strong>& 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://<domain1>:<port>" 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<application> 526 527 <activity android:name=”MainActivity”> 528 <intent-filter <strong>android:autoVerify="true"</strong>> 529 <action android:name="android.intent.action.VIEW" /> 530 <category android:name="android.intent.category.DEFAULT" /> 531 <category android:name="android.intent.category.BROWSABLE" /> 532 <data android:scheme="http" android:host="www.example.com" /> 533 <data android:scheme="https" android:host="mobile.example.com" /> 534 </intent-filter> 535 <intent-filter> 536 <action android:name="android.intent.action.VIEW" /> 537 <category android:name="android.intent.category.BROWSABLE" /> 538 <data android:scheme="http" android:host="www.example2.com" /> 539 </intent-filter> 540 </activity> 541 542 <activity android:name=”SecondActivity”> 543 <intent-filter> 544 <action android:name="android.intent.action.VIEW" /> 545 <category android:name="android.intent.category.DEFAULT" /> 546 <category android:name="android.intent.category.BROWSABLE" /> 547 <data android:scheme="http" android:host="account.example.com" /> 548 </intent-filter> 549 </activity> 550 551 <activity android:name=”ThirdActivity”> 552 <intent-filter> 553 <action android:name="android.intent.action.VIEW" /> 554 <category android:name="android.intent.category.DEFAULT" /> 555 <data android:scheme="http" android:host="map.example.com" /> 556 </intent-filter> 557 <intent-filter> 558 <action android:name="android.intent.action.VIEW" /> 559 <category android:name="android.intent.category.BROWSABLE" /> 560 <data android:scheme="market" android:host="example.com" /> 561 </intent-filter> 562 </activity> 563 564</application> 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