Home | History | Annotate | Download | only in articles
      1 page.title=Best Practices for Unique Identifiers
      2 page.metaDescription=How to manage unique identifiers the right way for users.
      3 page.tags=ids, user data
      4 meta.tags="ids", "user data"
      5 page.image=images/cards/card-user-ids_2x.png
      6 
      7 page.article=true
      8 @jd:body
      9 
     10 <div id="tb-wrapper">
     11 <div id="tb">
     12     <h2>In this document</h2>
     13     <ol>
     14       <li><a href="#tenets_of_working_with_android_identifiers">Tenets of Working with
     15       Android Identifiers</a></li>
     16       <li><a href="#version_specific_details_identifiers_in_m">Identifiers in Android 6.0+</a></li>
     17       <li><a href="#working_with_advertising_ids">Working with Advertising IDs</a></li>
     18       <li><a href="#working_with_instance_ids_&_guids">Working with Instance IDs and GUIDs</a></li>
     19       <li><a href="#understand_identifier_characteristics">Understanding Identifier
     20       Characteristics</a>
     21       <ol>
     22         <li><a href="#scope">Scope</a></li>
     23         <li><a href="#resettability_&_persistence">Resettability &amp; persistence</a></li>
     24         <li><a href="#uniqueness">Uniqueness</h3>
     25         <li><a href="#integrity_protection_and_non-repudiability">Integrity protection and
     26         non-repudiability</a></li>
     27       </ol>
     28       </li>
     29       <li><a href="#use_appropriate_identifiers">Common Use Cases and the Identifier to Use</a>
     30       <ol>
     31         <li><a href="#a_track_signed-out_user_preferences">Tracking signed-out user
     32         preferences</a></li>
     33         <li><a href="#b_track_signed-out_user_behavior">Tracking signed-out user behavior</a></li>
     34         <li><a href="#c_generate_signed-out_anonymous_user_analytics">Generating
     35         signed-out/anonymous user analytics</a></li>
     36         <li><a href="#d_track_signed-out_user_conversion">Tracking signed-out user
     37         conversion</a></li>
     38         <li><a href="#e_handle_multiple_installations">Handling multiple installations</a></li>
     39         <li><a href="#f_anti-fraud_enforcing_free_content_limits_detecting_sybil_attacks">Anti-fraud:
     40         Enforcing free content limits / detecting Sybil attacks</a></li>
     41         <li><a href="#g_manage_telephony_&_carrier_functionality">Managing telephony and carrier
     42         functionality</a></li>
     43         <li><a href="#h_abuse_detection_identifying_bots_and_ddos_attacks">Abuse detection:
     44         Identifying bots and DDoS attacks</a></li>
     45         <li><a href="#i_abuse_detection_detecting_high_value_stolen_credentials">Abuse detection:
     46         Detecting high value stolen credentials</a></li>
     47       </ol>
     48       </li>
     49     </ol>
     50   </div>
     51 </div>
     52 
     53 <p>
     54   While there are valid reasons why your application may need to identify a
     55   device rather than an instance of the application or an authenticated user on
     56   the device, for the vast majority of applications, the ultimate goal is to
     57   identify a particular <em>installation</em> of your app (not the actual
     58   physical device).
     59 </p>
     60 
     61 <p>
     62   Fortunately, identifying an installation on Android is straightforward using
     63   an Instance ID or by creating your own GUID at install time. This document
     64   provides guidance for selecting appropriate identifiers for your application,
     65   based on your use-case.
     66 </p>
     67 
     68 <p>
     69   For a general look at Android permissions, please see <a href=
     70   "{@docRoot}training/articles/user-data-overview.html">Permissions
     71   and User Data</a>. For specific best practices for
     72   working with Android permissions, please see <a href=
     73   "{@docRoot}training/articles/user-data-permissions.html">Best Practices for
     74   App Permissions</a>.
     75 </p>
     76 
     77 
     78 <h2 id="tenets_of_working_with_android_identifiers">Tenets of Working with Android Identifiers</h2>
     79 
     80 <p>
     81   We recommend that you follow these tenets when working with Android
     82   identifiers:
     83 </p>
     84 
     85 <p>
     86   <em><strong>#1: Avoid using hardware identifiers.</strong></em> Hardware
     87   identifiers such as SSAID (Android ID) and IMEI can be avoided in most
     88   use-cases without limiting required functionality.
     89 </p>
     90 
     91 <p>
     92   <em><strong>#2: Only use Advertising ID for user profiling or ads
     93   use-cases.</strong></em> When using an <a href=
     94   "https://support.google.com/googleplay/android-developer/answer/6048248?hl=en">
     95   Advertising ID</a>, always respect the <a href=
     96   "https://play.google.com/about/developer-content-policy.html#ADID">Limit Ad
     97   Tracking</a> flag, ensure the identifier cannot be connected to personally
     98   identifiable information (PII) and avoid bridging Advertising ID resets.
     99 </p>
    100 
    101 <p>
    102   <em><strong>#3: Use an Instance ID or a privately stored GUID whenever
    103   possible for all other use-cases except payment fraud prevention and
    104   telephony.</strong></em> For the vast majority of non-ads use-cases, an
    105   instance ID or GUID should be sufficient.
    106 </p>
    107 
    108 <p>
    109   <em><strong>#4: Use APIs that are appropriate to your use-case to minimize
    110   privacy risk.</strong></em> Use the
    111   <a href="http://source.android.com/devices/drm.html">DRM
    112   API</a> API for high value content
    113   protection and the <a href="{@docRoot}training/safetynet/index.html">SafetyNet
    114   API</a> for abuse prevention. The Safetynet API is
    115   the easiest way to determine whether a device is genuine without incurring
    116   privacy risk.
    117 </p>
    118 
    119 <p>
    120   The remaining sections of this guide elaborate on these rules in the context
    121   of developing Android applications.
    122 </p>
    123 
    124 <h2 id="version_specific_details_identifiers_in_m">Identifiers in Android 6.0+</h2>
    125 
    126 <p>
    127   MAC addresses are globally unique, not user-resettable and survive factory
    128   reset. It is generally not recommended to use MAC address for any form of
    129   user identification. As a result, as of Android M, local device MAC addresses
    130   (for example, Wifi and Bluetooth) <em><strong>are not available via third party
    131   APIs</strong></em>. The {@link android.net.wifi.WifiInfo#getMacAddress WifiInfo.getMacAddress()}
    132   method and the {@link android.bluetooth.BluetoothAdapter#getAddress
    133   BluetoothAdapter.getDefaultAdapter().getAddress()} method will
    134   both return <code>02:00:00:00:00:00</code>..
    135 </p>
    136 
    137 <p>
    138   Additionally, you must hold the following permissions to access MAC addresses
    139   of nearby external devices available via Bluetooth and Wifi scans:
    140 </p>
    141 
    142 <table>
    143  <tr>
    144     <th><strong>Method/Property</strong></td>
    145     <th><strong>Permissions Required</strong></td>
    146  </tr>
    147  <tr>
    148     <td>
    149       <code><a href="{@docRoot}reference/android/net/wifi/WifiManager.html#getScanResults()">WifiManager.getScanResults()</a></code>
    150     </td>
    151     <td>
    152       <code>ACCESS_FINE_LOCATION</code> or <code>ACCESS_COARSE_LOCATION</code>
    153     </td>
    154  </tr>
    155  <tr>
    156     <td>
    157       <code><a href="{@docRoot}reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND">BluetoothDevice.ACTION_FOUND</a></code>
    158     </td>
    159     <td>
    160       <code>ACCESS_FINE_LOCATION</code> or <code>ACCESS_COARSE_LOCATION</code>
    161     </td>
    162  </tr>
    163  <tr>
    164     <td>
    165       <code><a href="{@docRoot}reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(android.bluetooth.le.ScanCallback)">BluetoothLeScanner.startScan(ScanCallback)</a></code>
    166     </td>
    167     <td>
    168       <code>ACCESS_FINE_LOCATION</code> or <code>ACCESS_COARSE_LOCATION</code>
    169     </td>
    170  </tr>
    171 </table>
    172 
    173 
    174 <h2 id="working_with_advertising_ids">Working with Advertising IDs</h2>
    175 
    176 <p>
    177   Advertising ID is a user-resettable identifier and is appropriate for Ads
    178   use-cases, but there are some key points to bear in mind when using it:
    179 </p>
    180 
    181 <p>
    182   <em><strong>Always respect the users intention in resetting the advertising
    183   ID</strong></em>. Do not bridge user resets by using a more persistent device
    184   identifier or fingerprint to link subsequent Advertising IDs together without
    185   the users consent. The <a href=
    186   "https://play.google.com/about/developer-content-policy.html">Google Play
    187   Developer Content Policy</a> states:
    188 </p>
    189 
    190 <div style="padding:.5em 2em;">
    191 <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;">
    192 <p>...if reset, a new advertising
    193   identifier must not be connected to a previous advertising identifier or data
    194   derived from a previous advertising identifier without the explicit consent
    195   of the user.</span></p>
    196 </div>
    197 </div>
    198 
    199 <p>
    200   <em><strong>Always respect the associated Personalized Ads
    201   flag</strong></em>. Advertising IDs are configurable in that users can limit
    202   the amount of tracking associated with the ID. Always use the <code><a href=
    203   "https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#isLimitAdTrackingEnabled()">
    204   AdvertisingIdClient.Info.isLimitAdTrackingEnabled()</a></code> method to
    205   ensure you are not circumventing your users' wishes. The <a href=
    206   "https://play.google.com/about/developer-content-policy.html">Google Play
    207   Developer Content Policy</a> states:
    208 </p>
    209 
    210 
    211 <div style="padding:.5em 2em;">
    212 <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;">
    213 <p>...you must abide by a users Opt out of interest-based advertising or 'Opt
    214   out of Ads Personalization' setting. If a user has enabled this setting, you
    215   may not use the advertising identifier for creating user profiles for
    216   advertising purposes or for targeting users with personalized advertising.
    217   Allowed activities include contextual advertising, frequency capping,
    218   conversion tracking, reporting and security and fraud detection.</span></p>
    219 </div>
    220 </div>
    221 
    222 <p>
    223   <em><strong>Be aware of any privacy or security policies associated with SDKs
    224   you use that are related to Advertising ID use.</strong></em> For example, if
    225   you are using the Google Analytics SDK
    226   <code><a href=
    227   "https://developers.google.com/android/reference/com/google/android/gms/analytics/Tracker.html#enableAdvertisingIdCollection(boolean)">mTracker.enableAdvertisingIdCollection(true)</a></code>
    228   method, make sure to review and adhere to all applicable <a href=
    229   "https://developers.google.com/analytics/devguides/collection/android/v4/policy">
    230   Analytics SDK policies</a>.
    231 </p>
    232 
    233 <p>
    234   Also, be aware that the <a href=
    235   "https://play.google.com/about/developer-content-policy.html">Google Play
    236   Developer Content Policy</a> requires that the Advertising ID must not be
    237   connected to personally-identifiable information or associated with any
    238   persistent device identifier (for example: SSAID, MAC address, IMEI, etc.,)
    239   without the explicit consent of the user.
    240 </p>
    241 
    242 <p>
    243   As an example, suppose you want to collect information to populate database
    244   tables with the following columns:
    245 </p>
    246 
    247 <table>
    248  <tr>
    249     <td>
    250       <table>
    251        <tr>
    252           <td class="tab2">
    253       <code>timestamp</code></td>
    254           <td class="tab2">
    255       <code>ad_id</code></td>
    256           <td>
    257       <code><strong>account_id</strong></code></td>
    258           <td class="tab2">
    259       <code>clickid</code></td>
    260        </tr>
    261       </table>
    262 
    263       <p>TABLE-01</p>
    264     </td>
    265     <td>
    266       <table>
    267        <tr>
    268           <td>
    269       <code><strong>account_id</strong></code></td>
    270           <td class="tab2">
    271       <code>name</code></td>
    272           <td class="tab2">
    273       <code>dob</code></td>
    274           <td class="tab2">
    275       <code>country</code></td>
    276        </tr>
    277       </table>
    278       <p>TABLE-02</p>
    279     </td>
    280  </tr>
    281 </table>
    282 
    283 
    284 <p>
    285   In this example, the <code>ad_id</code> column could be joined to PII via the
    286   <code>account_id</code> column in both tables, which would be a violation of
    287   the <a href=
    288   "https://play.google.com/about/developer-content-policy.html">Google Play
    289   Developer Content Policy</a>, if you did not get explicit permission from
    290   your users.
    291 </p>
    292 
    293 <p>
    294   Keep in mind that links between Advertiser ID and PII aren't always this
    295   explicit. It's possible to have quasi-identifiers that appear in both PII
    296   and Ad ID keyed tables, which also cause problems. For example, assume we
    297   change TABLE-01 and TABLE-02 as follows:
    298 </p>
    299 
    300 <table>
    301  <tr>
    302     <td><table>
    303  <tr>
    304     <td>
    305       <code><strong>timestamp</strong></code></td>
    306           <td class="tab2">
    307       <code>ad_id</code></td>
    308           <td>
    309       <code>clickid</code></td>
    310           <td>
    311       <code><strong>dev_model</strong></code></td>
    312        </tr>
    313       </table>
    314 
    315       </pre>
    316       <p>TABLE-01</p>
    317     </td>
    318     <td>
    319       <table>
    320        <tr>
    321           <td>
    322       <code><strong>timestamp</strong></code></td>
    323           <td class="tab2">
    324       <code>demo</code></td>
    325           <td class="tab2">
    326       <code>account_id</code></td>
    327           <td>
    328       <code><strong>dev_model</strong></code></td>
    329           <td class="tab2">
    330       <code>name</code></td>
    331        </tr>
    332       </table>
    333       <p>TABLE-02</p>
    334     </td>
    335  </tr>
    336 </table>
    337 
    338 
    339 <p>
    340   In this case, with sufficiently rare click events, it's still possible to
    341   join between the Advertiser ID TABLE-01 and the PII contained in TABLE-2
    342   using the timestamp of the event and the device model.
    343 </p>
    344 
    345 <p>
    346   While it is often difficult to guarantee that no such quasi-identifiers exist
    347   in a dataset, the most obvious join risks can be prevented by generalizing
    348   unique data where possible. In the example, this would mean reducing the
    349   accuracy of the timestamp so that multiple devices with the same model appear
    350   for every timestamp.
    351 </p>
    352 
    353 <p>
    354   Other solutions include:
    355 </p>
    356 
    357 <ul>
    358 <li><em><strong>Not designing tables that explicitly link PII with Advertising
    359 IDs</strong></em>. In the first example above this would mean not including the
    360 account_id column in TABLE-01.</li>
    361 
    362 <li><em><strong>Segregating and monitoring access control lists for users or roles
    363 that have access to both the Advertising ID keyed data and PII</strong></em>. If the
    364 ability to access both sources simultaneously (for example, to perform
    365 a join between two tables) is tightly controlled and audited, it reduces the
    366 risk of association between the Advertising ID and PII. Generally speaking,
    367 controlling access means:
    368 
    369 <ol>
    370   <li> Keeping access control lists (ACLs) for Advertiser ID keyed data and PII disjoint to
    371   minimize the number of individuals or roles that are in both ACLs, and</li>
    372   <li> Implementing access logging and auditing to detect and manage any exceptions to
    373   this rule.</li>
    374 </ol>
    375 </li>
    376 </ul>
    377 
    378 <p>
    379   For more information on working responsibly with Advertising IDs, please see
    380   the <a href=
    381   "https://support.google.com/googleplay/android-developer/answer/6048248?hl=en">
    382   Advertising ID</a> help center article.
    383 </p>
    384 
    385 <h2 id="working_with_instance_ids_&_guids">Working with Instance IDs and GUIDs</h2>
    386 
    387 <p>
    388   The most straightforward solution to identifying an application instance
    389   running on a device is to use an Instance ID, and this is the recommended
    390   solution in the majority of non-ads use-cases. Only the app instance for
    391   which it was provisioned can access this identifier, and it's (relatively)
    392   easily resettable because it only persists as long as the app is installed.
    393 </p>
    394 
    395 <p>
    396   As a result, Instance IDs provide better privacy properties compared to
    397   non-resettable, device-scoped hardware IDs. They also come with a key-pair
    398   for message signing (and similar actions) and are available on Android, iOS
    399   and Chrome. Please see the <a href=
    400   "https://developers.google.com/instance-id/">What is Instance ID?</a> help
    401   center document for more information.
    402 </p>
    403 
    404 <p>
    405   In cases where an Instance ID isn't practical, custom globally unique IDs
    406   (GUIDs) can also be used to uniquely identify an app instance. The simplest
    407   way to do so is by generating your own GUID using the following code.
    408 </p>
    409 
    410 <pre>String uniqueID = UUID.randomUUID().toString();</pre>
    411 
    412 <p>
    413   Because the identifier is globally unique, it can be used to identify a
    414   specific app instance. To avoid concerns related to linking the identifier
    415   across applications, GUIDs should be stored in internal storage rather than
    416   external (shared) storage. Please see <a href=
    417   "{@docRoot}guide/topics/data/data-storage.html">Storage Options</a> guide for
    418   more information.
    419 </p>
    420 
    421 
    422 <h2 id="understand_identifier_characteristics">Understanding Identifier Characteristics</h2>
    423 
    424 <p>
    425   The Android Operating system offers a number of IDs with different behavior
    426   characteristics and which ID you should use depends on how those following
    427   characteristics work with your use-case. But these characteristics also come
    428   with privacy implications so it's important to understand how these
    429   characteristics play together.
    430 </p>
    431 
    432 <h3 id="scope">Scope</h3>
    433 
    434 <p>
    435   Identifier scope explains which systems can access the identifier. Android
    436   identifier scope generally comes in three flavors:
    437 </p>
    438 
    439 <ul>
    440   <li> <em>Single app</em>.  the ID is internal to the app and not accessible to other apps.
    441   <li> <em>Group of apps</em> - the ID is accessible to a pre-defined group of related apps.
    442   <li> <em>Device</em> - the ID is accessible to all apps installed on the device.
    443 </ul>
    444 
    445 <p>
    446   The wider the scope granted to an identifier, the greater the risk of it
    447   being used for tracking purposes. Conversely, if an identifier can only be
    448   accessed by a single app instance, it cant be used to track a device across
    449   transactions in different apps.
    450 </p>
    451 <h3 id="resettability_&_persistence">Resettability and persistence</h3>
    452 
    453 <p>
    454   Resettability and persistence define the lifespan of the identifier and
    455   explain how it can be reset. Common reset triggers are: in-app resets, resets
    456   via System Settings, resets on launch, and resets on installation. Android
    457   Identifiers can have varying lifespans, but the lifespan is usually related
    458   to how the ID is reset:
    459 </p>
    460 <ul>
    461   <li> <em>Session-only</em> - a new ID is used every time the user restarts the app.
    462   <li> <em>Install-reset</em> - a new ID is used every time user uninstalls and reinstalls the app.
    463   <li> <em>FDR-reset</em> - a new ID is used every time the user factory-resets the device.
    464   <li> <em>FDR-persistent</em> - the ID survives factory reset.
    465 </ul>
    466 
    467 <p>
    468   Resettability gives users the ability to create a new ID that is
    469   disassociated from any existing profile information. This is important
    470   because the longer, and more reliably, an identifier persists (e.g. across
    471   factory resets etc.), the greater the risk that the user may be subjected to
    472   long-term tracking. If the identifier is reset upon app reinstall, this
    473   reduces the persistence and provides a means for the ID to be reset, even if
    474   there is no explicit user control to reset it from within the app or the
    475   System Settings.
    476 </p>
    477 <h3 id="uniqueness">Uniqueness</h3>
    478 
    479 <p>
    480   Uniqueness establishes the likelihood that identical identifiers exist within
    481   the associated scope. At the highest level, a globally unique identifier will
    482   never have a collision - even on other devices/apps. Otherwise, the level of
    483   uniqueness depends on the size of the identifier and the source of randomness
    484   used to create it. For example, the chance of a collision is much higher for
    485   random identifiers seeded with the calendar date of installation (e.g.,
    486   2015-01-05) than for identifiers seeded with the Unix timestamp of
    487   installation (e.g., 1445530977).
    488 </p>
    489 
    490 <p>
    491   In general, user account identifiers can be considered unique (i.e., each
    492   device/account combo has a unique ID). On the other hand, the less unique
    493   an identifier is within a population (e.g. of devices), the greater the
    494   privacy protection because it's less useful for tracking an individual user.
    495 </p>
    496 
    497 <h3 id="integrity_protection_and_non-repudiability">Integrity protection and
    498 non-repudiability</h3>
    499 
    500 <p>
    501   An identifier that is difficult to spoof or replay can be used to prove that
    502   the associated device or account has certain properties (e.g. its not a
    503   virtual device used by a spammer). Difficult to spoof identifiers also
    504   provide <em>non-repudiability</em>. If the device signs a message with a
    505   secret key, it is difficult to claim someone elses device sent the message.
    506   Non-repudiability could be something a user wants (e.g. authenticating a
    507   payment) or it could be an undesirable property (e.g. sending a message they
    508   regret).
    509 </p>
    510 
    511 
    512 <h2 id="use_appropriate_identifiers">Common Use Cases and the Identifier to Use</h2>
    513 
    514 <p>
    515   This section provides alternatives to using hardware IDs such as IMEI or
    516   SSAID for the majority of use-cases. Relying on hardware IDs is discouraged
    517   because the user cannot reset them and generally has limited control over
    518   their collection.
    519 </p>
    520 
    521 <h3 id="a_track_signed-out_user_preferences">Tracking signed-out user preferences</h3>
    522 
    523 <p>
    524   <em>In this case, you are saving per-device state on the server side.</em>
    525 </p>
    526 
    527 <p>
    528   <strong>We Recommend</strong>: Instance ID or a GUID.
    529 </p>
    530 
    531 <p>
    532   <strong>Why this Recommendation?</strong>
    533 </p>
    534 
    535 <p>
    536   Persisting information through reinstalls is not recommended because users
    537   may want to reset their preferences by reinstalling the app.
    538 </p>
    539 
    540 <h3 id="b_track_signed-out_user_behavior">Tracking signed-out user behavior</h3>
    541 
    542 <p>
    543   <em>In this case, you have created a profile of a user based on their
    544   behavior across different apps/sessions on the same device.</em>
    545 </p>
    546 
    547 <p>
    548   <strong>We Recommend</strong>: Advertising ID.
    549 </p>
    550 
    551 <p>
    552   <strong>Why this Recommendation?</strong>
    553 </p>
    554 
    555 <p>
    556   Use of the Advertising ID is mandatory for Advertising use-cases per the
    557   <a href="https://play.google.com/about/developer-content-policy.html">Google
    558   Play Developer Content Policy</a> because the user can reset it.
    559 </p>
    560 
    561 <h3 id="c_generate_signed-out_anonymous_user_analytics">Generating signed-out/anonymous user analytics</h3>
    562 
    563 <p>
    564   <em>In this case, you are measuring usage statistics and analytics for
    565   signed-out or anonymous users.</em>
    566 </p>
    567 
    568 <p>
    569   <strong>We Recommend</strong>: Instance ID; if an Instance ID is
    570   insufficient, you can also use a GUID.
    571 </p>
    572 
    573 <p>
    574   <strong>Why this Recommendation?</strong>
    575 </p>
    576 
    577 <p>
    578   An Instance ID or a GUID is scoped to the app that creates it, which prevents
    579   it from being used to track users across apps. It is also easily reset by
    580   clearing app data or reinstalling the app. Creating Instance IDs and GUIDs is
    581   straightforward:
    582 </p>
    583 
    584 <ul>
    585   <li> Creating an Instance ID: <code>String iid = InstanceID.getInstance(context).getId()</code>
    586   <li> Creating a GUID: <code>String uniqueID = UUID.randomUUID().toString</code>
    587 </ul>
    588 
    589 <p>
    590   Be aware that if you have told the user that the data you are collecting is
    591   anonymous, you should <em><strong>ensure you are not connecting the
    592   identifier to PII</strong></em> or other identifiers that may be linked to
    593   PII.
    594 </p>
    595 
    596 <p>
    597   You can also use Google Analytics for Mobile Apps, which offers a solution
    598   for per-app analytics.
    599 </p>
    600 
    601 <h3 id="d_track_signed-out_user_conversion">Tracking signed-out user conversion</h3>
    602 
    603 <p>
    604   <em>In this case, you are tracking conversions to detect if your marketing
    605   strategy was successful.</em>
    606 </p>
    607 
    608 <p>
    609   <strong>We Recommend</strong>: Advertising ID.
    610 </p>
    611 
    612 <p>
    613   <strong>Why this Recommendation?</strong>
    614 </p>
    615 
    616 <p>
    617   This is an ads-related use-case which may require an ID that is available
    618   across different apps so using an Advertising ID is the most appropriate
    619   solution.
    620 </p>
    621 
    622 <h3 id="e_handle_multiple_installations">Handling multiple installations</h3>
    623 
    624 <p>
    625   <em>In this case, you need to identify the correct instance of the app when
    626   it's installed on multiple devices for the same user.</em>
    627 </p>
    628 
    629 <p>
    630   <strong>We Recommend</strong>: Instance ID or GUID.
    631 </p>
    632 
    633 <p>
    634   <strong>Why this Recommendation?</strong>
    635 </p>
    636 
    637 <p>
    638   Instance ID is designed explicitly for this purpose; its scope is limited to
    639   the app so that it cannot be used to track users across different apps and it
    640   is reset upon app reinstall. In the rare cases where an Instance ID is
    641   insufficient, you can also use a GUID.
    642 </p>
    643 
    644 <h3 id="f_anti-fraud_enforcing_free_content_limits_detecting_sybil_attacks">Anti-fraud: Enforcing free content limits / detecting Sybil attacks</h3>
    645 
    646 <p>
    647   <em>In this case, you want to limit the number of free content (e.g.
    648   articles) a user can see on a device.</em>
    649 </p>
    650 
    651 <p>
    652   <strong>We Recommend</strong>: Instance ID or GUID.
    653 </p>
    654 
    655 <p>
    656   <strong>Why this Recommendation?</strong>
    657 </p>
    658 
    659 <p>
    660   Using a GUID or Instance ID forces the user to reinstall the app in order to
    661   overcome the content limits, which is a sufficient burden to deter most
    662   people. If this is not sufficient protection, Android provides a
    663   <a href="http://source.android.com/devices/drm.html">DRM API</a>
    664   which can be used to limit access to content.
    665 </p>
    666 
    667 <h3 id="g_manage_telephony_&_carrier_functionality">Managing telephony and carrier functionality</h3>
    668 
    669 <p>
    670   <em>In this case, your app is interacting with the device's phone and texting
    671   functionality.</em>
    672 </p>
    673 
    674 <p>
    675   <strong>We Recommend</strong>: IMEI, IMSI, and Line1 (requires <code>PHONE</code>
    676   permission group in Android 6.0 (API level 23) and higher).
    677 </p>
    678 
    679 <p>
    680   <strong>Why this Recommendation?</strong>
    681 </p>
    682 
    683 <p>
    684   Leveraging hardware identifiers is acceptable if it is required for
    685   telephony/carrier related functionality; for example, switching between
    686   cellular carriers/SIM slots or delivering SMS messages over IP (for Line1) -
    687   SIM-based user accounts. But it's important to note that in Android 6.0+
    688   these identifiers can only be used via a runtime permission and that users
    689   may toggle off this permission so your app should handle these exceptions
    690   gracefully.
    691 </p>
    692 
    693 <h3 id="h_abuse_detection_identifying_bots_and_ddos_attacks">Abuse detection:
    694 Identifying bots and DDoS attacks</h3>
    695 
    696 <p>
    697   <em>In this case, you are trying to detect multiple fake devices attacking
    698   your backend services.</em>
    699 </p>
    700 
    701 <p>
    702   <strong>We Recommend:</strong> The Safetynet API.
    703 </p>
    704 
    705 <p>
    706   <strong>Why this Recommendation?</strong>
    707 </p>
    708 
    709 <p>
    710   An identifier in isolation does little to indicate that a device is genuine.
    711   You can verify that a request comes from a genuine Android device (as opposed
    712   to an emulator or other code spoofing another device) using the Safetynet
    713   API's <code>SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)</code>
    714   method to verify the integrity of a device making a request. For more
    715   detailed information, please see <a href=
    716   "{@docRoot}training/safetynet/index.html">Safetynet's API documentation</a>.
    717 </p>
    718 
    719 <h3 id="i_abuse_detection_detecting_high_value_stolen_credentials">Abuse detection:
    720 Detecting high value stolen credentials</h3>
    721 
    722 <p>
    723   <em>In this case, you are trying to detect if a single device is being used
    724   multiple times with high-value, stolen credentials (e.g. to make fraudulent
    725   payments).</em>
    726 </p>
    727 
    728 <p>
    729   <strong>We Recommend</strong>: IMEI/IMSI (requires <code>PHONE</code>
    730   permission group in Android 6.0 (API level 23) and higher.)
    731 </p>
    732 
    733 <p>
    734   <strong>Why this Recommendation?</strong>
    735 </p>
    736 
    737 <p>
    738   With stolen credentials, devices can be used to monetize multiple high value
    739   stolen credentials (such as tokenized credit cards). In these scenarios,
    740   software IDs can be reset to avoid detection, so hardware identifiers may be
    741   used.
    742 </p>