| **Warning:** This document is confidential and access is governed by your non-disclosure agreement with Google.
| **Note:** The features described on this page are available to select Play partners in an early access program (EAP).

Play for On-device AI brings the benefits of [Android
App Bundles](https://developer.android.com/guide/app-bundle) and Google Play delivery to custom ML model
distribution. It lets you publish a single artifact to Play containing your
code, assets, and ML models and to choose from a number of delivery modes and
targeting options.

## Benefits

- Upload a single publishing artifact to Google Play and delegate hosting, delivery, updates, and targeting to Play at no additional cost.
- Deliver your ML models at install-time or at runtime when your app requests them. Install-time delivery can guarantee that a very large model is present when your app is opened.
- Target ML models so they're delivered to custom device groups at install-time based on device model, system properties, or RAM.
- Keep app updates small and optimized with Play's automatic patching, which means only the differences in files need to be downloaded.

## Considerations

- By using Play for On-device AI you agree to the terms in the [Google Play
  Developer Distribution
  Agreement](https://play.google.com/about/developer-distribution-agreement.html) and the [Play Core Software Development Kit Terms of
  Service](https://developer.android.com/guide/playcore#license).
- To help you complete Google Play's data safety section requirements, you can use the information provided on how [Play Feature
  Delivery](https://developer.android.com/guide/playcore/feature-delivery#play_feature_delivery) handles data.
- Developers participating in the early access program are expected to evaluate Play for On-device AI and to provide feedback to Google Play.
- Individual ML packs can be up to 1.5GB, based on its compressed download size. The maximum cumulative app size of any version of your app generated from your app bundle is 4GB.
- Apps over 1GB in size must target min SDK Level 21 or higher.
- Once installed, ML packs are updated with the app binary, which requires uploading a new AAB release.
- During the early access program, Play for On-device AI is subject to change.

## How to use Play for On-device AI

Play for On-device AI uses ML packs. You package custom models that are
ready for distribution in ML packs in your app bundle. You can choose whether
the ML pack should be delivered at install-time or on-demand. For install-time
delivery, you can create custom rules so that your ML pack is only delivered to
a subset of devices. This lets you, for example, deliver a custom model
to a specific device model or to devices that have a minimum amount of RAM.

By packaging ML packs with your app bundle, you can use all of Play's existing
testing and release tools, such as test tracks and staged rollouts to manage
your app's distribution with your custom models.

ML packs are updated together with the app binary. If your new app release
doesn't make changes to an ML pack, then Play's automatic patching
process will ensure the user doesn't have to re-download it. Play will
just download what's changed when it updates the app.

### Developer journey

At a high level, here's how you can start using Play for On-device AI:

1. Provide your Play developer account ID to Google Play to join the EAP.
2. Package your models into ML packs into your Android App Bundle and specify how the ML packs should be delivered.
3. \[Optional\] If you plan to deliver ML packs to custom device groups, create them in a device targeting configuration using the Play Developer API.
4. \[Optional\] If you're using on-demand delivery, integrate the [Play Feature
   Library](https://developer.android.com/guide/playcore/feature-delivery/on-demand#include-play-feature-delivery) into your app to download your ML packs as needed.
5. Test and release your app bundle to Google Play.

### Provide your Play developer account ID

Since this feature is in early access, your developer account needs to be
allow-listed to have access to Play for On-device AI. Confirm the Play
developer account IDs and app package names to your Google Play partner manager
or Play for On-device AI team member. At this time, we're inviting select Play
partners to test this feature.

### Extract your ML model into a feature module

Create a feature module in Android Studio:

1. Select **File \> New \> New Module** from the menu bar.
2. In the **Create New Module** dialog, select **Dynamic Feature Module** and click **Next**.
3. Follow the steps suggested by the Wizard to configure the module. [More
   detailed steps are outlined
   here](https://developer.android.com/guide/playcore/feature-delivery/install-time?_gl=1*szedu6*_up*MQ..*_ga*ODgzMjQ0NTA0LjE3MDk1NTAzOTc.*_ga_6HH9YJMN9M*MTcwOTU1MDM5Ni4xLjAuMTcwOTU1MDM5Ni4wLjAuMA..#create_dynamic_feature). Note that ML packs can be [delivered](https://developer.android.com/guide/playcore/feature-delivery#customize_delivery) at install-time, so they will be immediately available, at install-time to a subset of devices based on conditions, or on-demand when your app requests them. This can be configured in the Wizard.
4. Add your ML model(s) to the feature module. For example, if your module is called "mymodule", then you can add your model(s) to `mymodule/src/main/assets/`.

### Mark the module as an ML pack

Next, mark your module as an ML pack by adding a `dist:type="ml-pack"` attribute
to the `dist:module` element in the AndroidManifest.xml file of your module.  

    <!-- File: mymodule/src/main/AndroidManifest.xml -->
    ...
    <manifest ...>
      <dist:module
          ...
          dist:type="ml-pack">
          ...
      </dist:module>
    </manifest>

### \[Optional\] Configure install-time delivery

If you're delivering an ML pack to all devices at install-time, consider
making it [removable](https://developer.android.com/guide/playcore/feature-delivery/install-time#make-removable)
and [uninstalling it](https://developer.android.com/guide/playcore/feature-delivery/on-demand#uninstall_modules)
once it's not needed to free up the user's device storage.

### \[Optional\] Configure on-demand delivery

To download ML packs at runtime based on your own client-side and server-side
logic, follow the instructions to [configure on-demand delivery](https://developer.android.com/guide/playcore/feature-delivery/on-demand)
for feature modules.

### \[Optional\] Configure conditional delivery at install-time

It's possible to deliver your ML packs to a subset of devices at install-time
based on conditions you specify. You can control downloading an ML pack
based on the following conditions:

- Device model
- Device RAM
- [Device hardware and software features](https://developer.android.com/guide/topics/manifest/uses-feature-element#features-reference)
- Android API level
- User country

#### Deliver ML packs based on API level and user country conditions

To specify minimum or maximum device API levels or to specify countries to
exclude (or include), follow the instructions to [configure conditional delivery](https://developer.android.com/guide/playcore/feature-delivery/conditional)
for feature modules.

#### Deliver ML packs based on device model, RAM, and system features conditions

ML packs support custom device groups which you can use to target specific
device models, set device RAM thresholds, or target system properties. Custom
device groups are based on rules that you specify using 'selectors'. A custom
device group can be a single device model or it can be a more complicated
combination of custom rules that you specify. Device group 'selectors' can be
based on:

- Device model
- Device RAM
- [System features](https://developer.android.com/guide/topics/manifest/uses-feature-element#features-reference)

Device groups have the following properties:

- Each device group can have one or more selectors.
- A device belongs to a group if it matches the criteria in at least one selector (in other words, an OR condition).
- If a selector has multiple criteria, then the device must meet all of its criteria (in other words, an AND condition).
- Devices can belong to more than one device group.
- Your app can have up to 100 device groups.

These instructions explain how to create device groups using the Play Developer
API. Then you can specify in your ML pack which device groups it's
targeting.

#### **Setup the Google Play Developer API**

To configure device groups you will need to use the [Publisher
API](https://developers.google.com/android-publisher) to upload your config to
Google Play. There are a few [steps you'll need to follow to get
started](https://developers.google.com/android-publisher/getting_started):

1. [Create (if needed) and link your API project to your Google Play
   Console](https://developers.google.com/android-publisher/getting_started#linking_your_api_project)
2. [Set-up an API Access
   Client](https://developers.google.com/android-publisher/getting_started#setting_up_api_access_clients)

You can find the [API reference
here](https://developers.google.com/android-publisher/api-ref/rest). Later on,
if you choose to upload your build using the API, you will be using the [Edits
methods](https://developers.google.com/android-publisher/edits). Additionally,
it is encouraged to [review this
page](https://developers.google.com/android-publisher/api_usage) before using
the API.

#### **Use the Device Targeting Configuration API**

You can use the following API call to create your device targeting
configuration:

#### Create a device targeting configuration

|---|---|
| HTTP request | `POST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs` |
| Path parameters | N/A |
| Request Body | [Device Config](https://developer.android.com/google/play/ml-packs#dtco) |
| Response Body | [Device Config](https://developer.android.com/google/play/ml-packs#dtco) |

###### Device targeting config object

    {
      device_groups: [
        {
          name: string,
          device_selectors: [
            {
              device_ram : {
                min_bytes: integer
                max_bytes: integer
              },
              included_device_ids: [
                {
                  build_brand: string,
                  build_device: string
                }
              ],
              excluded_device_ids: [
                {
                  build_brand: string,
                  build_device: string
                }
              ],
              required_system_features: [
                {
                  name: string
                }
              ],
              forbidden_system_features: [
                {
                  name: string
                }
              ]
            }
          ]
        }
      ]
    }

The field definitions are as follows:

- **device_confid_id** (integer): ID corresponding to this device configuration.
- **device_groups** (object): Group definitions

  - **name** (string): Name of the device group (a string ID you define).
  - **device_selectors** (object): Device requirements for a device to belong to this group.
  - **device_ram** (object): Device RAM requirements
    - **min_bytes** (integer, *inclusive)*: Minimum required RAM (in bytes)
    - **max_bytes** (integer, *exclusive)*: Maximum required RAM (in bytes)
  - **included_device_ids** (object): Device models to be included in this selector **(max of 10000 device_ids per group)** A device needs to be in this list to match the selector. This is a necessary but not sufficient condition to match the full selector (see earlier note about combining requirements in a selector)
    - **build_brand** (string): Device manufacturer
    - **build_device** (string): Device model code
  - **excluded_device_ids** (object): Device models to be excluded in this selector **(max of 10000 device_ids per group)** A device from this list won't match the selector even if it matches all other requirements in the selector.
    - **build_brand** (string): Device manufacturer
    - **build_device** (string): Device model code
  - **required_system_features** (object): Features that a device needs
    to have to be included by this selector **(max of 100 features
    per group)**. A device needs to have all system features in this
    list to match the selector. This is a necessary but not sufficient
    condition to match the full selector (see earlier note about
    combining requirements in a selector).

    System [feature reference](https://developer.android.com/guide/topics/manifest/uses-feature-element#features-reference)
    - **name** (string): A system feature
  - **forbidden_system_features** (object): Features that a device mustn't
    have to be included by this selector **(max of 100 features per group)**.
    If a device has any of the system features in this list, it doesn't
    match the selector, even if it matches all other requirements in
    the selector.

    System [feature reference](https://developer.android.com/guide/topics/manifest/uses-feature-element#features-reference)
    - **name** (string): A system feature

You can find the correct formatting for the device manufacturer and model code
by using the [device catalog](https://play.google.com/console/developers/devices)
on the Google Play Console, by either:

- Inspecting individual devices using the device catalog, and finding the manufacturer and model code in the locations as shown in the following example (For a Google Pixel 8, the manufacturer is "google" and the model code is "shiba")

![Pixel 8 device catalog](https://developer.android.com/static/images/google/play/pixel-8.png)

- Downloading a CSV of supported devices, and using the *Manufacturer* and *Model Code* for the *build_brand* and *build_device* fields, respectively.

For example, the following group matches all devices with more than 4GB of RAM,
except Pixel 5 (google redfin) and including Pixel 3 (google blueline, which has
less than 4GB RAM):  

    device_groups: [
       {
         name: "my_group_1",
         device_selectors: [
           {
             device_ram: {
               min_bytes: 4294967296
             },
             excluded_device_ids: [
               {
                 build_brand: "google",
                 build_device: "redfin"
               }
             ]
           },
           {
             included_device_ids: [
               {
                 build_brand: "google",
                 build_device: "blueline"
               }
             ]
           }
         ]
       }
    ]

You can read it as:

\[ (RAM \> 4GB) AND NOT (google redfin) \] OR \[ (google blueline) \]
| **Warning:** Including multiple rules as part of the same
| selector will create a logical AND, for example:  
|
| ```json
|   {
|     device_ram: {
|         min_bytes: 7516192768
|     },
|     included_device_ids: [
|           {
|                build_brand: 'google',
|                build_device: 'flame'
|           }
|     ],
|   }
| ```
|
| will create the condition for all devices with \> 7GB of RAM AND it
| is a Pixel 4 - also written as follows:
|
| ![](https://developer.android.com/static/images/google/play/intersect.png)
|
| Otherwise, if you want an OR condition, group them as separate
| selectors, for example:  
|
| ```json
|   {
|     device_ram: {
|         min_bytes: 7516192768
|     },
|   },
|   {
|     included_device_ids: [
|           {
|                build_brand: 'google',
|                build_device: 'flame'
|           }
|     ],
|   }
| ```
|
| will create the condition for all devices with \> 7GB of RAM OR
| it is a Pixel 4 - also written as follows:
|
| ![](https://developer.android.com/static/images/google/play/union.png)

#### Get device config by ID

You can retrieve a specific device configuration by ID using the
following call:

|---|---|
| HTTP request | `GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs/{deviceTierConfigId}` |
| Path parameters | N/A |
| Request Body | N/A |
| Response Body | [Device Config](https://developer.android.com/google/play/ml-packs#dtco) |

#### Get list of device configs

You can get the last 10 device configurations given the following call
(or optimally specify a set of ten using the *page_token* query parameter):

|---|---|
| HTTP request | `GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs` |
| Path parameters | N/A |
| Query parameters | **page_token** (optional) - Used to specify a specific group of 10 DTCs. This is useful if you have created more than 10 DTCs, and would like to see DTCs that were created before the most recent 10. |
| Request Body | N/A |
| Response Body | [List of Device Configs](https://developer.android.com/google/play/ml-packs#dtco) page_token |

#### **Specify which device group should receive each ML Pack**

In order to specify which device groups should receive your ML pack, modify the
module's AndroidManifest like so:  

    <!-- File: mymodule/src/main/AndroidManifest.xml -->

      <dist:module
          ...
          dist:type="ml-pack">
        <dist:delivery>
          <dist:install-time>
            <dist:conditions>
              <dist:device-groups>
                <dist:device-group dist:name="GROUP_1"/>
                <dist:device-group dist:name="GROUP_2"/>
              </dist:device-groups>
            </dist:conditions>
          </dist:install-time>
        </dist:delivery>
      </dist:module>
    </manifest>

Now you can upload your bundle to an internal track and test that
both your model and targeting are working as intended.

### Test and release your app on Google Play

| **Note:** Using the API is the only way to link a specific device targeting config, otherwise, when you upload your app bundle in the Play Console, it will apply the **latest** device targeting config to your AAB.

Now you can follow standard practices to test and release your app bundle on
Google Play:

- Use [internal app sharing](https://support.google.com/googleplay/android-developer/answer/9844679) to test a build locally, including how on-demand delivery works.
- Use [Play's test tracks](https://support.google.com/googleplay/android-developer/answer/9845334) to gather feedback from gradually larger groups of testers.
- Use [Play's pre-launch report](https://support.google.com/googleplay/android-developer/answer/9842757) to understand how your app ran on real Android devices.
- Use [staged rollouts](https://support.google.com/googleplay/android-developer/answer/6346149) to release your app to a small percentage of your audience before rolling it out to more users so you can catch issues, halt a release, and quickly roll out a fix.

If you're using conditional delivery for your ML packs at install-time, the Play
Console will use your *latest* device targeting configuration. If you want to
specify the device targeting config for your build, you can release your app
bundle using the [Play Developer Publishing API](https://developers.google.com/android-publisher#publishing)
. To specify with device config to use with the Publishing API, you add the
config ID to the deviceTierConfigId query parameter while calling the
[edits.bundle.upload method](https://developers.google.com/android-publisher/api-ref/rest/v3/edits.bundles/upload)
, like this:  

    https://androidpublisher.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editId}/bundles?deviceTierConfigId="{deviceTierConfigId}"

## Provide feedback

Participants in the early access program should report issues and provide
feedback. You can reach out to your Google Play partner manager or contact the
Play for On-device AI team.

## Related content

Learn more about [Android App Bundles](https://developer.android.com/guide/app-bundle),
[Play Asset Delivery](https://developer.android.com/guide/playcore/asset-delivery), and
[Play Feature Delivery](https://developer.android.com/guide/playcore/feature-delivery).