---
title: Installing Kotlin SDK
slug: v4-4/kCukH_z3FQy6iiFBUR1nr
docTags: 
createdAt: 2023-07-28T20:16:57.748Z
---

You can integrate the Ditto SDK into Kotlin projects to develop native apps for the Android platform.&#x20;

:::hint{type="info"}
For a complete overview of the platforms, transports, and devices the Kotlin SDK supports, see [Compatibility with Kotlin](docId\:kA8uWS5Tc-0KjQl4mhau1).
:::

To install the Kotlin SDK and start syncing offline:

::::WorkflowBlock
:::WorkflowBlockItem
Confirm that you meet the minimum requirements. ([Prerequisites](./#prerequisites))
:::

:::WorkflowBlockItem
Prepare your environment for Ditto. ([Setting Up Your Environment](./#setting-up-your-environment))
:::

:::WorkflowBlockItem
Configure your app permissions. ([Setting Up Permissions](./#setting-up-permissions))
:::

:::WorkflowBlockItem
Authenticate with the Big Peer and then start syncing offline. ([Integrating and Initializing](./#integrating-and-initializing))
:::
::::

# 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 31.0
- Java Development Kit (JDK) version 11.0

# Setting Up Your Environment

:::::WorkflowBlock
::::WorkflowBlockItem
Confirm that `mavenCentral()` is in the project-level `build.gradle`:

:::CodeblockTabs
Bash

```none
allprojects {
    repositories {
        mavenCentral()
    }
}
```
:::
::::

::::WorkflowBlockItem
In the individual module `build.gradle` file:

:::CodeblockTabs
Bash

```none
dependencies {
  // ...
  implementation "live.ditto:ditto:4.+"
}
```
:::
::::
:::::

# Setting Up Permissions

The Android operating system limits access to some device functionality for end-user control and privacy.&#x20;

To fully unlock Ditto's capabilities, configure your app to automatically request all necessary permissions from end users at runtime.&#x20;

## Android Manifest Permissions

The Ditto Android SDK includes a set of permissions that are required to use all
the device features necessary to enable sync. The permissions below will be
automatically merged into your app's final manifest.

:::CodeblockTabs
AndroidManifest.xml

```xml
<manifest
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">

<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" />
```
:::

The `tools:targetApi` attribute causes the permission to only be requested on
devices running the specified API level or higher. This avoids errors in older
OS versions that do not recognize the permission.

The `android:maxSdkVersion` attribute causes permission to only be requested
on devices running the specified SDK level or lower. This avoids asking for more
permissions than Ditto needs; however, it will prevent your app from being able
to request permission on devices running a newer OS version.&#x20;

To opt out of this behavior and request permission on all OS versions, see the following
snippet:

:::CodeblockTabs
Location Permission Override

```xml
<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" />
```
:::

Note that you may need to add the `xmlns:tools="http://schemas.android.com/tools"`
namespace attribute to your app's root `<manifest>` tag as shown in the
`AndroidManifest.xml` example above.

This will configure your app's build to ignore the `android:maxSdkVersion`
attribute in our SDK allowing the permission to be requested on any SDK version.
This technique can be used to tweak any permissions to your liking.

For more details, see the documentation for the [Bluetooth ](https://developer.android.com/guide/topics/connectivity/bluetooth/permissions)and [WiFi Aware ](https://developer.android.com/guide/topics/connectivity/wifi-permissions)permissions in the Android Documentation.

## Runtime Permissions

Android requires certain permissions to be explicitly requested by the app to access features like Bluetooth Low Energy (LE) and Wi-Fi Aware. To comply, configure the manifest file for your app to request permissions from end users at runtime.&#x20;

To improve the user experience for your app, request all necessary permissions at once by calling the DittoSyncPermissions helper in your Activity or Fragment's `onCreate` method:

The `DittoSyncPermissions` object requires a Context. You can get the context by invoking `getApplicationContext()`, `getContext()`, `getBaseContext()` or this when in a class that extends from Context, such as the Application, Activity, Service, and IntentService Classes.

```kotlin
fun checkPermissions() {
    val missing = DittoSyncPermissions(this).missingPermissions()
    if (missing.isNotEmpty()) {
        this.requestPermissions(missing, 0)
    }
}
```

Alternatively, `requireActivity()` is a way to force the code to only work on a Fragment that has a Context.

```kotlin
fun checkPermissions() {
    val activity = requireActivity()
    val missing = DittoSyncPermissions(activity).missingPermissions()
    if (missing.isNotEmpty()) {
        activity.requestPermissions(missing, 0)
    }
}
```

On Android, after granting location access, Ditto may not immediately recognize the permission, causing a delay in syncing.&#x20;

To address this, whenever a relevant permission changes, call `refreshPermissions()` to quickly check and start syncing with the new permissions.

```kotlin
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    // Regardless of the outcome, tell Ditto that permissions maybe changed
    ditto?.refreshPermissions()
}
```

For more information about requesting permissions in a user-friendly way refer to Android's documentation: [Request App Permissions](https://developer.android.com/training/permissions/requesting).

# Integrating and Initializing

:::::WorkflowBlock
:::WorkflowBlockItem
Add Ditto to your application.

We recommend placing this in your Application.onCreate method. Note that the `Context` you want to reference here is the `Application level` `Context`, rather than whatever Activity you might happen to be instantiating the Ditto instance from initially.&#x20;

This is because you need to ensure that your app is keeping a single Ditto instance alive for the entire lifetime of the application so it is not going out of scope or getting garbage collected.

```kotlin
try {
    val androidDependencies = DefaultAndroidDittoDependencies(context)
    val identity = DittoIdentity.OnlinePlayground(
        androidDependencies,
        appId = "REPLACE_ME_WITH_YOUR_APP_ID",
        token = "REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN"
    )
    DittoLogger.minimumLogLevel = DittoLogLevel.DEBUG
    ditto = Ditto(androidDependencies, identity)
    ditto.startSync()
} catch (e: DittoError) {
    Log.e("Ditto error", e.message!!)
}
```
:::

::::WorkflowBlockItem
Replace `YOUR_APP_ID` and `YOUR_PLAYGROUND_TOKEN` with your access credentials available from the portal.&#x20;

:::hint{type="info"}
For instructions on how to obtain your access credentials, see [Onboarding](docId\:JQjYL9gbvsgI9vlW3Ywvc). For an introduction to authentication in Ditto, see *Ditto Basics* > [Authentication and Initialization](docId\:c802C1qiAkfgA2QxmcyWu).
:::
::::
:::::

