Home | History | Annotate | Download | only in features
      1 page.title=App Links
      2 page.image=images/cards/card-app-linking_2x.png
      3 page.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 &gt; Apps &gt; Configure apps (gear icon) &gt; 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 intents 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   &lt;activity ...&gt;
    101       &lt;intent-filter&gt;
    102           &lt;action android:name="android.intent.action.VIEW" /&gt;
    103           &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    104           &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    105           &lt;data android:scheme="http" /&gt;
    106           &lt;data android:scheme="https" /&gt;
    107           &lt;data android:host="www.android.com" /&gt;
    108       &lt;/intent-filter&gt;
    109   &lt;/activity&gt;
    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 apps 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 &lt;activity ...&gt;
    155 
    156     &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
    157         &lt;action android:name="android.intent.action.VIEW" /&gt;
    158         &lt;category android:name="android.intent.category.DEFAULT"gt;
    159         &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    160         &lt;data android:scheme="http" android:host="www.android.com" /&gt;
    161         &lt;data android:scheme="https" android:host="www.android.com" /&gt;
    162     &lt;/intent-filter&gt;
    163 
    164 &lt;/activity&gt;
    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 URIs 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 apps 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 &lt;application&gt;
    189 
    190   &lt;activity android:name=MainActivity&gt;
    191     &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
    192       &lt;action android:name="android.intent.action.VIEW" /&gt;
    193       &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    194       &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    195       &lt;data android:scheme="http" android:host="www.domain1.com" /&gt;
    196       &lt;data android:scheme="https" android:host="www.domain1.com" /&gt;
    197     &lt;/intent-filter&gt;
    198   &lt;/activity&gt;
    199   &lt;activity android:name=SecondActivity&gt;
    200     &lt;intent-filter&gt;
    201       &lt;action android:name="android.intent.action.VIEW" /&gt;
    202       &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    203       &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    204       &lt;data android:scheme="https" android:host="www.domain2.com" /&gt;
    205     &lt;/intent-filter&gt;
    206   &lt;/activity&gt;
    207 
    208 &lt;/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 &lt;application&gt;
    226   &lt;activity android:name=MainActivity&gt;
    227     &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
    228       &lt;action android:name="android.intent.action.VIEW" /&gt;
    229       &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    230       &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    231       &lt;data android:scheme="http" android:host="www.example.com" /&gt;
    232       &lt;data android:scheme="https" android:host="mobile.example.com" /&gt;
    233     &lt;/intent-filter&gt;
    234   &lt;/activity&gt;
    235 &lt;/application&gt;
    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 apps 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 apps 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>
    345 https://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>
    359 https://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 URIs 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>
    416 https://digitalassetlinks.googleapis.com/v1/statements:list?
    417    source.web.site=https://<strong>&lt;domain1&gt;:&lt;port&gt;</strong>&amp;
    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>
    432 adb 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>
    462 App 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>
    470 Package: com.android.vending
    471 Domains: play.google.com market.android.com
    472 Status: 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 users 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 apps 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   &lt;application&gt;
    512 
    513       &lt;activity android:name=MainActivity&gt;
    514           &lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
    515               &lt;action android:name="android.intent.action.VIEW" /&gt;
    516               &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    517               &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    518               &lt;data android:scheme="http" android:host="www.example.com" /&gt;
    519               &lt;data android:scheme="https" android:host="mobile.example.com" /&gt;
    520           &lt;/intent-filter&gt;
    521           &lt;intent-filter&gt;
    522               &lt;action android:name="android.intent.action.VIEW" /&gt;
    523               &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    524               &lt;data android:scheme="http" android:host="www.example2.com" /&gt;
    525           &lt;/intent-filter&gt;
    526       &lt;/activity&gt;
    527 
    528       &lt;activity android:name=SecondActivity&gt;
    529           &lt;intent-filter&gt;
    530               &lt;action android:name="android.intent.action.VIEW" /&gt;
    531               &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    532               &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    533               &lt;data android:scheme="http" android:host="account.example.com" /&gt;
    534           &lt;/intent-filter&gt;
    535       &lt;/activity&gt;
    536 
    537       &lt;activity android:name=ThirdActivity&gt;
    538         &lt;intent-filter&gt;
    539             &lt;action android:name="android.intent.action.VIEW" /&gt;
    540             &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    541             &lt;data android:scheme="http" android:host="map.example.com" /&gt;
    542         &lt;/intent-filter&gt;
    543         &lt;intent-filter&gt;
    544             &lt;action android:name="android.intent.action.VIEW" /&gt;
    545             &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
    546             &lt;data android:scheme="market" android:host="example.com" /&gt;
    547         &lt;/intent-filter&gt;
    548       &lt;/activity&gt;
    549 
    550   &lt;/application&gt;
    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