> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ditto.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Java Android

> You can integrate the Ditto SDK into Kotlin projects to develop for the Android platform.

## Prerequisites

Following are the minimum requirements that must be met before attempting to install Ditto.

* Android version 6.0 (Marshmallow)
* `minSdk` version 23.0
* `compileSdk` version 34.0
* Java Development Kit (JDK) version 11.0

## Setting Up Your Environment

Include the Maven Central repository in your Gradle file, and then synchronize it with your project.

<Steps>
  <Step>
    From your project-level `build.gradle` file located in the project's root directory, ensure the `mavenCentral()` repository is included in the `repositories` section:

    ```Gradle Gradle theme={null}
    allprojects {
        repositories {
            mavenCentral()
        }
    }
    ```
  </Step>

  <Step>
    Synchronize your project with the Gradle file by clicking **File > Sync Project with Gradle Files**
  </Step>
</Steps>

## Adding the Ditto SDK Dependency

Add the Ditto SDK to your app's `build.gradle` file in the `dependencies` block with the appropriate version:

```js build.gradle theme={null}
implementation "live.ditto:ditto:5.0.0"
```

## Configuring Permissions

The Android operating system limits access to some device functionality for end-user control and privacy. In order to use this functionality, configure your app to declare and request permissions from end users at runtime:

<Steps>
  <Step>
    Review permissions used by Ditto. (Declaring Permissions)
  </Step>

  <Step>
    Proactively check permission status to avoid unnecessary delay between granting access and Ditto being able to use the feature. (Requesting Permissions)
  </Step>
</Steps>

### Declaring Permissions in the Android Manifest

Android requires certain permissions to be explicitly requested by the app to access features like Bluetooth Low Energy and Wi-Fi Aware. These permissions must be declared in the app's manifest file and requested from the end user at runtime.

The Ditto SDK's AndroidManifest.xml includes all of the necessary permissions for enabling its mesh network capabilities. These permissions will automatically be merged with your app's permissions, so you should be aware of them.

<CodeGroup>
  ```xml AndroidManifest.xml theme={null}
  <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
  <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" tools:targetApi="s" />
  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" tools:targetApi="s" />
  <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" tools:targetApi="s" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="32" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
  <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" tools:targetApi="tiramisu" />
  ```
</CodeGroup>

Some of these permissions have an android:maxSdkVersion attribute which means they are not used on devices running newer versions of Android. This is a best practice to respect users' privacy when those permissions are not necessary.

However, some apps may still need to use one or more of the above permissions across more versions of Android. This can be accomplished by overriding the permission configuration in your app's `AndroidManifest.xml`

To override any of these permission limitations in your app, do the following:

<Steps>
  <Step>
    Open the `AndroidManifest.xml` located in the `app/src/main` directory of your project.
  </Step>

  <Step>
    Within the same `<manifest>` tag, just before the `<application>` tag, add the relevant permissions you want to configure (location example):

    <CodeGroup>
      ```xml AndroidManifest.xml theme={null}
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:remove="android:maxSdkVersion" />
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" tools:remove="android:maxSdkVersion" />
      ```
    </CodeGroup>

    Note the additional `tools:remove` attribute. This tells the manifest merger to selectively remove the `android:maxSdkVersion` behavior from the associated permissions, changing them to apply to all Android versions.
  </Step>
</Steps>

<Info>
  For more information, see the official [Permissions on Android](https://developer.android.com/guide/topics/permissions/overview "Permissions on Android") and [Merge manifest files](https://developer.android.com/build/manage-manifests "Merge manifest files") documentation.
</Info>

### Requesting Permissions at Runtime

In addition to being declared in the manifest, some permissions need to be requested from the user at runtime. To ensure your app has the required permissions for sync, use the DittoSyncPermissions helper class from the Ditto SDK. This helper class:

* Simplifies the process of requesting end-user permissions at runtime with a single method call (ensurePermissions) for all necessary permissions.

* Handles any errors encountered during the permissions request process.

### Using the Helper

To use the `DittoSyncPermissions` helper class:

<Steps>
  <Step>
    Import the `DittoSyncPermissions` helper class in the main activity of your app:

    ```java Java theme={null}
    import live.ditto.transports.DittoSyncPermissions;
    ```
  </Step>

  <Step>
    Call the following in your `Activity` or Fragment's `onCreate` method:

    ```java Java theme={null}
    void requestPermissions() {
       DittoSyncPermissions permissions = new DittoSyncPermissions(this);
       String[] missing = permissions.missingPermissions(permissions.requiredPermissions());
       if (missing.length > 0) {
          this.requestPermissions(missing, 0);
       }
    }
    ```
  </Step>

  <Step>
    Refresh permissions after permissions are granted.

    On Android, after permissions are granted, Ditto may not immediately recognize the change, causing a delay in syncing. To address this, whenever a relevant permission changes, call `refreshPermissions()` on your Ditto instance to quickly check and start syncing with the new permissions.  This can be done in the `onRequestPermissionsResult()` activity lifecycle method:

    ```java Java theme={null}
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
       super.onRequestPermissionsResult(requestCode, permissions, grantResults);
       this.ditto.refreshPermissions();
    }
    ```
  </Step>
</Steps>

For more information about requesting permissions in a user-friendly way, refer to the official <a href="https://developer.android.com/training/permissions/requesting" target="_blank">Requesting Runtime Permissions</a> documentation

## Integrating and Initializing

Using the Application-level `Context`, integrate Ditto into your app's `onCreate` method. 

Most apps require that Ditto run as a *singleton*. A singleton is an implementation ensuring your Ditto instance accesses and shares a single object instance throughout your app.

To store the Ditto instance as a singleton object, create a custom `Application` subclass for your Android app. Include the necessary setup configuration below in the `onCreate` method. 

<Info>
  By doing so, you ensure that there is only one instance of Ditto throughout the app's lifecycle, and it remains available for use by any activity or component that needs it. This approach helps in efficient resource management and avoids unnecessary object instantiation and destruction.
</Info>

<Steps>
  <Step>
    Add Ditto to your application  by placing it in your `Application.onCreate` method.

    <Warning>
      To ensure your app maintains a single Ditto instance throughout its lifetime and prevents it from going out of scope or getting garbage collected, place Ditto in the Application-level `Context` instead of the `Context` from any activity where you initially instantiated the Ditto instance.
    </Warning>

    ```java Java theme={null}
    import com.ditto.java.Ditto;
    import com.ditto.java.DittoConfig;
    import com.ditto.java.Authenticator;
    import android.content.Context;

    // Get Android application context
    Context applicationContext = getApplicationContext();

    // Configure Ditto with your database ID
    String databaseId = "REPLACE_ME_WITH_YOUR_DATABASE_ID";
    DittoConfig config = DittoConfig.onlinePlayground(
        databaseId,
        applicationContext
    );

    try {
        // Open Ditto with the configuration
        Ditto ditto = Ditto.open(config, applicationContext);

        // Set up authentication expiration handler
        ditto.getAuth().setExpirationHandler((ditto1, secondsRemaining) -> {
            ditto1.getAuth().login(
                "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN",
                Authenticator.DEVELOPMENT_PROVIDER,
                (clientInfo, error) -> {
                    if (error != null) {
                        // Handle authentication error
                        Log.e("Ditto", "Auth error: " + error.getMessage());
                    }
                }
            );
        });

        // Start sync (v5 pattern: ditto.getSync().start())
        ditto.getSync().start();
    } catch (DittoError e) {
        // Handle error in Ditto initialization
        Log.e("Ditto", "Init error: " + e.getMessage());
    }
    ```
  </Step>

  <Step>
    Replace `YOUR_APP_ID` and `YOUR_PLAYGROUND_TOKEN` with your access credentials available in the portal.

    <Info>
      For instructions on how to obtain your access credentials, see [Getting SDK Connection Details](/cloud/portal/getting-sdk-connection-details).
    </Info>
  </Step>
</Steps>

## Proguard

When building a release version of an Android app with minification enabled, the app may crash at runtime due to ProGuard or R8 shrinking or obfuscating necessary code. To ensure the app runs smoothly in release builds, it's important to explicitly retain critical classes and methods. This can be achieved by adjusting your ProGuard rules to prevent essential code from being removed or altered during the minification process.

To help identify issues caused by missing or obfuscated classes, here's a typical crash log that you might encounter when the necessary ProGuard rules are not applied:

```
java.lang.NoSuchMethodError: no static method "Llive/ditto/internal/swig/ffi/dittoffiJNI;.SwigDirector_Retainable_retain(Llive/ditto/internal/swig/ffi/Retainable;)”
```

To ensure optimal app performance when using the Ditto SDK, update your ProGuard rules to retain critical classes. Depending on the features you're using, you’ll need to add specific rules to prevent ProGuard from stripping essential code:

**Ditto Native Bindings - Required for All Ditto SDK Use:**

This rule ensures that all native bindings related to Ditto are preserved and available at runtime.

```
-keep class live.ditto.internal.swig.ffi.** { *; }
```

**Ditto Blanket Exclusion - Required for Presence**

This rule retains all Ditto classes, which is essential for features like [Presence Viewer](/sdk/latest/sync/using-mesh-presence#presence-viewer), and ensures Jackson classes are preserved for proper JSON deserialization.

```
-keep class live.ditto.** { *; }
-keepnames class com.fasterxml.jackson.** { *; }
```

* `keep class live.ditto.internal.swig.ffi.**` ensures that all classes and interfaces under the live.ditto.internal.swig.ffi package (including sub-packages) are retained.
* `{ *; }` specifies that all members (fields, methods, constructors, etc.) of these classes should be preserved as well.
* This rule prevents ProGuard from shrinking, obfuscating, or modifying these classes, ensuring that your app functions correctly in a minified release build.

## Declaring a Foreground Service

A [foreground service](https://developer.android.com/develop/background-work/services/fgs) allows your app to continue syncing data with Ditto while running in the background. A foreground service is not required to use Ditto, but without it your app will stop syncing whenever it is in the background.

To declare the foreground service, add the following to your `AndroidManifest.xml`:

```xml theme={null}
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" tools:targetApi="upside_down_cake" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" tools:targetApi="tiramisu" />

<application ...>
    <service
        android:name="live.ditto.transports.foregroundservice.DefaultDittoForegroundService"
        android:exported="false"
        android:foregroundServiceType="connectedDevice"
        android:stopWithTask="true">
        <meta-data android:name="notificationChannelName" android:value="Background Data Sync" />
        <meta-data android:name="notificationChannelId" android:value="BackgroundDataSyncId" />
        <meta-data android:name="smallIcon" android:resource="@drawable/small_app_icon" />
        <meta-data android:name="notificationTitle" android:value="Syncing Data" />
        <meta-data android:name="notificationText" android:value="Syncing data across connected devices" />
        <meta-data android:name="notificationId" android:value="1001" />
    </service>
</application>
```

Make sure you customize the service metadata--it will be displayed to the user in the foreground service notification. Note that your `small_app_icon` drawable must be monochrome white.

The foreground service will be automatically started and stopped on `startSync()` and `stopSync()`, respectively.

For more information about the Ditto foreground service consult the [API Reference](https://software.ditto.live/android/Ditto/4.14.1/api-reference/ditto/live.ditto.transports.foregroundservice/index.html).
