# Installation and configuration (Android)

In this article, you will find out how to install, configure, and initialize the Synerise SDK in an Android mobile application. While performing the actions from this guide, keep the presented order.  


<div class="admonition admonition-important"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

The [Settings](/developers/mobile-sdk/settings#pre-initialization-settings) article contains additional information about SDK behaviors you may need prior to configuration.

</div></div></div>
 

If you want to find out what kind of benefits you can get from integrating with mobile SDK, go [here](/developers/mobile-sdk/overview). 

## Requirements
---
You need:  
* Access to a [workspace](/docs/settings/business-profile)
* A Profile [API Key](/docs/settings/tool/api#adding-api-keys)  
    When creating the API key, use allowlisting or denylisting to only allow the events you intend to use.
* Minimum Android SDK version: 24
* Supported targetSDKVersion: 33

### 3rd Party Frameworks

- [RxJava](https://github.com/ReactiveX/RxJava)
- [RxAndroid](https://github.com/ReactiveX/RxAndroid)
- [OkHttp](https://github.com/square/okhttp)
- [Retrofit](https://github.com/square/retrofit)
- [OkHttp](https://github.com/square/okhttp)
- [Picasso](https://github.com/square/picasso)
- [Fresco](https://github.com/facebook/fresco)
- [ConstraintLayout](https://github.com/androidx/constraintlayout)
- [Joda-Time](https://github.com/JodaOrg/joda-time)

## Installation
---
1. Set maven path in your `root/build.gradle` file:

    
   <pre><code class="language-groovy">...
       allprojects {
           repositories {
               google()
               jcenter()
               maven { url 'https://pkgs.dev.azure.com/Synerise/AndroidSDK/_packaging/prod/maven/v1' }
           }
       }</code></pre>


2. Add dependency to your `project/build.gradle` file:

    
   <pre><code class="language-groovy">buildscript {
           repositories {
               google()
               jcenter()
           }
           dependencies {
               classpath 'com.android.tools.build:gradle:3.4.2'
           }
       }</code></pre>

    
    
   <div class="admonition admonition-important"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

   We guarantee stability only on Android Gradle plugin 3.4.2 or lower.

   </div></div></div>


3. Import dependency in your `app/build.gradle` file and apply the plugin:
    
   <pre><code class="language-groovy">apply plugin: 'com.android.application'

       ...
       dependencies {
       ...
       // Synerise Android SDK;
       implementation 'com.synerise.sdk:synerise-mobile-sdk:ANDROID_SDK_VERSION'
       // Replace ANDROID_SDK_VERSION with the version, for example 5.4.0;
       // Check latest version at https://github.com/Synerise/android-sdk/blob/master/CHANGELOG.md
       }</code></pre>

4. *For Android Studio versions older than 3.5*: Go to **File > Settings > Build, Execution, Deployment > Instant Run** and make sure that Instant Run is disabled.


## Configuration
---

For your convenience, [Synerise.Builder](/developers/mobile-sdk/class-reference/android/lifecycle#synerise-builder) makes it possible to configure SDK behavior depending on your needs.

<div class="admonition admonition-note"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

The `Synerise.Builder.with(..)` method is mandatory.

</div></div></div>


The basic callbacks you need:
- [.pushRegistrationRequired(OnRegisterForPushListener)](/developers/mobile-sdk/class-reference/android/lifecycle#synerise-builder) - Synerise SDK may request registering a customer for push notifications. This callback is called after a customer signs in, signs up, or deletes an account.
- [.baseUrl(String)](/developers/mobile-sdk/class-reference/android/lifecycle#synerise-builder) - This callback lets you provide your custom base URL to use your own domain for connecting to the Synerise API.
    
  <div class="admonition admonition-note"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

  If you use Synerise hosted on:  
  - Google Cloud ([app.geb.synerise.com](https://app.geb.synerise.com)), use `baseUrl(https://api.geb.snrapi.com)`
  - Microsoft Azure USA ([app.azu.synerise.com](https://app.azu.synerise.com)), use `baseUrl(https://api.azu.snrapi.com)`

  </div></div></div>
  

- `.mesaggingServiceType(MessagingServiceType)` - This callback sets the messaging provider: Huawei Mobile Services (HMS) or Google Mobile Services (GMS). When publishing the app to appGallery, we recommend using HMS.



<details class="accordion"><summary>Click to expand the full list of callbacks</summary><div class="accordion-content"><table> <thead> <tr> <th>Callbacks</th> <th>Description</th> </tr> </thead> <tbody><tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.build()</a></td> <td>Builds the Synerise SDK with the provided data. The <code>Synerise.Builder.build()</code> method can be called only once during the entire application lifecycle, so you must call this method in your <code>Application</code> class.</td> </tr> <tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.crashHandlingEnabled(boolean)</a></td> <td>For more information, see the <a href="/developers/mobile-sdk/miscellaneous/#crash-handling">Crash Handling</a> section.</td> </tr> <tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.notificationDefaultChannelId(String)</a></td> <td>Sets the ID of Push Notification Channel.</td> </tr> <tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.notificationDefaultChannelName(String)</a></td> <td>Sets the name of Push Notification Channel.</td> </tr> <tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.notificationHighPriorityChannelId(String)</a></td> <td>Sets the ID of High Priority Push Notification Channel.</td> </tr> <tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.notificationHighPriorityChannelName(String)</a></td> <td>Sets the name of High Priority Push Notification Channel.</td> </tr> <tr> <td><code>.rxJavaErrorHandlingEnabled(boolean)</code></td> <td>If set to true, Synerise handles rxJava errors. <br>If false, you need to call rxJavaPlugins.setErrorHandler on your own.</td> </tr> <tr> <td><a href="/developers/mobile-sdk/class-reference/android/lifecycle/#synerise-builder">.syneriseDebugMode(boolean)</a></td> <td>When true, enables full network traffic logs. It is not recommended to use debug mode in a release version of your app. Debug mode is disabled by default.</td> </tr> <tr> <td><code>Synerise.settings.injector.automatic = boolean;</code></td> <td>When true, enables automatic mode in the injector.</td> </tr> <tr> <td><code>Synerise.settings.tracker.autoTracking.trackMode = TrackMode</code></td> <td>Sets the mode for view tracking.</td> </tr> <tr> <td><code>Synerise.settings.tracker.locationAutomatic = boolean;</code></td> <td>Use to obtain customer location and send the location event automatically.</td> </tr> <tr> <td><code>Synerise.settings.tracker.setAutoFlushTimeout(int);</code></td> <td>Sets the maximum time (in ms) since the last event queue was sent before attempting to automatically send another queue. Default value: 5000 ms. Minimum value: 50 ms.</td> </tr> <tr> <td><code>Synerise.settings.tracker.setMaximumBatchSize(int);</code></td> <td>Sets the maximum number of events which may be sent in a single batch. Default value: 100. You can set the value between 1 and 100.</td> </tr> <tr> <td><code>Synerise.settings.tracker.setMinimumBatchSize(int);</code></td> <td>Sets the minimum number of events in queue required to send them. Default value: 10. You can set the value between 1 and 100.</td> </tr> </tbody></table></div></details>


## Initialization
---


<div class="admonition admonition-warning"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" /></svg></div><div class="admonition-body"><div class="admonition-content">

Synerise SDK must be initialized in the [Application class](https://developer.android.com/reference/android/app/Application). This is because Synerise SDK performs some operations while the application is running in the background.

</div></div></div>


1. Initialize Synerise Android SDK by using the `with` method and provide:  
    - `Application name`   
    - `Application instance` 
    - [API Key](/docs/settings/tool/api)
        1. To get the Profile (client) API key, go to **Synerise > Settings > API keys**.
        2. On the list of the keys, select the one you created as a part of [requirements](#requirements).
        3. In the **General** section, click **Show**.  
        4. Copy the API key. 
    
2. Add the key in your `Application` sub-class:  
    
   <div class="content-tabs code-tabs" data-tab-group="tabgrp-601">
   <div class="tab-buttons"><button class="tab-button" data-tab-id="tabgrp-601-0" data-tab-group="tabgrp-601" data-tab-active="true">Swift</button><button class="tab-button" data-tab-id="tabgrp-601-1" data-tab-group="tabgrp-601">kotlin</button></div>

   <div class="tab-panel" data-tab-id="tabgrp-601-0" data-tab-group="tabgrp-601" data-tab-active="true">

   ```Swift
   public class App extends MultiDexApplication {
           @Override
           public void onCreate() {
               super.onCreate();
               initSynerise();
           }
           private void initSynerise() {
               String syneriseClientApiKey = getString(R.string.synerise_clientool/api_key);
               String appId = getString(R.string.app_name);
               Synerise.settings.tracker.autoTracking.trackMode = FINE;
               Synerise.settings.tracker.setMinimumBatchSize(10);
               Synerise.settings.tracker.setMaximumBatchSize(100);
               Synerise.settings.tracker.setAutoFlushTimeout(5000);
               Synerise.settings.injector.automatic = false;
               Synerise.settings.tracker.locationAutomatic = true;
               Synerise.Builder.with(this, syneriseClientApiKey, appId)
                               .notificationIcon(R.drawable.notification_icon)
                               .notificationIconColor(ContextCompat.getColor(this, R.color.amaranth))
                               .syneriseDebugMode(true)
                               .pushRegistrationRequired(this)
                               .locationUpdateRequired(this)
                               .notificationDefaultChannelId("your-channel-id")
                               .notificationDefaultChannelName("your-channel-name")
                               .notificationHighPriorityChannelId("your-high-channel-id")
                               .notificationHighPriorityChannelName("your-high-channel-name")
                               .baseUrl("http://your-base-url.com/")
                               .setRequestValidationSalt("YOUR_REQUEST_VALIDATION_SALT")
                               .build();
           }
       }
   ```

   </div>

   <div class="tab-panel" data-tab-id="tabgrp-601-1" data-tab-group="tabgrp-601">

   ```kotlin
   class App : MultiDexApplication() {
           override fun onCreate() {
               super.onCreate()
               initSynerise()
           }
           private fun initSynerise() {
               val syneriseClientApiKey = accountManager!!.getClientProfileApiKey()
               val appId = getString(R.string.app_name)
               Synerise.settings.tracker.autoTracking.trackMode = FINE;
               Synerise.settings.tracker.setMinimumBatchSize(10);
               Synerise.settings.tracker.setMaximumBatchSize(100);
               Synerise.settings.tracker.setAutoFlushTimeout(5000);
               Synerise.settings.injector.automatic = false;
               Synerise.settings.tracker.locationAutomatic = true;
               Synerise.Builder.with(this, syneriseClientApiKey, appId)
                   .notificationIcon(R.drawable.ic_cart)
                   .notificationIconColor(ContextCompat.getColor(this, R.color.amaranth))
                   .syneriseDebugMode(true)
                   .pushRegistrationRequired(this)
                   .locationUpdateRequired(this)
                   .notificationDefaultChannelId("your-channel-id")
                   .notificationDefaultChannelName("your-channel-name")
                   .notificationHighPriorityChannelId("your-high-channel-id")
                   .notificationHighPriorityChannelName("your-high-channel-name")
                   .baseUrl("http://your-base-url.com/")
                   .setRequestValidationSalt("YOUR_REQUEST_VALIDATION_SALT")
                   .build()
           }
       }
   ```

   </div>
   </div>


3. Add the key in your `/values` strings file (for example, `strings.xml`):


   <pre><code class="language-XML">&lt;resources&gt;

       &lt;string name="app_name" translatable="false"&gt;Your GREAT application name&lt;/string&gt;
       &lt;string name="synerise_client_api_key" translatable="false"&gt;EF1AD0E0-532B-6AEE-6010-DEDC78F6E155&lt;/string&gt; &lt;!-- replace with valid client api key --&gt;

       ...

   &lt;/resources&gt;</code></pre>



<div class="admonition admonition-important"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

Secure sensitive keys (for example, `apiKey` and `requestValidationSalt`) with mechanisms like string obfuscation or encryption.

</div></div></div>


## Troubleshooting
---

### MultiDex {id=troubleshooting-multidex}

Sometimes, MultiDex errors may occur. In that case, enable MultiDex as follows (API >= 21):

<pre><code class="language-groovy">defaultConfig {
    applicationId "com.your.app"
    minSdkVersion 21
    ...
    multiDexEnabled true
}</code></pre>
  

or for API < 21:  


<pre><code class="language-groovy">defaultConfig {
    applicationId "com.your.app"
    minSdkVersion 20
    ...
    multiDexEnabled true
}</code></pre>


<pre><code class="language-groovy">dependencies {
    ...
    // MultiDex
    implementation 'com.android.support:multidex:1.0.3'
    ...
}</code></pre>


<pre><code class="language-java">public class YourApp extends MultiDexApplication {

    @Override
    public void onCreate() {
        super.onCreate();
        ...
    }</code></pre>


You can find more information about MultiDex at [this link](https://developer.android.com/studio/build/multidex.html). 

### AndroidManifest Merger {id=troubleshooting-androidmanifest-merger}

Sometimes, AndroidManifest Merger errors may occur. In that case, paste the following code in your AndroidManifest application tag.

<pre><code class="language-XML">&lt;application
    ...
    tools:replace="android:theme"&gt;</code></pre>


Also, if your app did not ask for location permission, remove it from your app with:

<pre><code class="language-xml">&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:node="remove"/&gt;</code></pre>


## Work Manager
Work Manager is a mechanism to schedule and run code in the background to keep your app up to date. Synerise supports using Work Manager since SDK version **5.21.0**.
  
### Benefits
Currently, the SDK uses background tasks only to refresh the registration token for push notifications every 20 days. In these situations, the SDK invokes the [onRegisterForPushRequired(origin:)](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-register-for-push-listener-on-register-for-push-required-with-origin) callback method or [onRegisterForPushRequired()](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-register-for-push-listener-on-register-for-push-required) callback method.
  
### Setting up

Work Manager is configured out of the box without any special configuration.

## Proguard configuration

The Synerise Android SDK obfuscates code on its own. We highly recommend keeping the entire SDK. Rules:

```
# keep entire Synerise SDK
-keep class com.synerise.sdk.** { *; }
-keepclassmembers class com.synerise.sdk.** { *; }
-keepclassmembers class com.synerise.sdk.** {
    public <init>();
}
```



