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