# Android client SDK

The Sending.Network Android SDK provides a messaging framework that enables you to integrate chatroom and notification services within your mobile applications. \
\
This quickstart will walk you through a simple demo that makes basic API calls like user registration, room creation, etc. Please refer to the SDK demo for the completed code.

## Prerequisites <a href="#prerequisites" id="prerequisites"></a>

| Components | Requirements                                                                                                                                              |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OS         | Android 6.0 or above                                                                                                                                      |
| Software   | <ul><li>Android Studio 4.0 or above</li><li><a href="https://github.com/Sending-Network/sendingnetwork-android">Sending.Network Android SDK</a></li></ul> |

## Configure your build

### Gradle

Add the following code to the top-level *build.gradle* configuration file:

```groovy
buildscript {
    ext.kotlin_version = "1.6.0"
    repositories {
        google()
        jcenter()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.3"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}
```

Add the `sendingnetwork-android-sdk` dependency in app module *build.gradle* file. Replace the `x.y.z` with the SDK version number.

<pre class="language-groovy"><code class="lang-groovy"><strong>// SDK dependency
</strong>implementation 'io.github.sending-network:sendingnetwork-android-sdk:x.y.z'
</code></pre>

If you intend to run a local P2P node, add the `sendingnetwork-android-service` as well. Replace the `x.y.z` with the SDK version number.

```groovy
// P2P node dependency
implementation 'io.github.sending-network:sendingnetwork-android-service:x.y.z'
```

### AndroidManifest.xml file

Your application should at least contain the provider `InitializationProvider` to remove the initialization of the `WorkManager` as below:

```xml
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:name=".SampleApp"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        [...]

        // This is required as the WorkManager is already initialized by the SDK
        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:ignore="MissingClass"
            tools:node="merge">
            <meta-data
                android:name="androidx.work.WorkManagerInitializer"
                android:value="androidx.startup"
                tools:node="remove" />
        </provider>
    
        // Declare the RadixService only when running a local P2P node
        <service android:name="org.sdn.android.sdk.server.RadixService"
                 android:enabled="true"/>

    </application>
```

## Initialization and DID login

### Application initialization

Create `SDNClient` instance from the `onCreate()` method of the child class of `Application`.

```kotlin
    override fun onCreate() {
        super.onCreate()
        Timber.plant(Timber.DebugTree())
        // Initialize the Client instance
        client = Client(
            context = this,
            clientConfiguration = ClientConfiguration(
                roomDisplayNameFallbackProvider = RoomDisplayNameFallbackProviderImpl()
            )
        )
        // If there has been a session then starts syncing messages.
        // Otherwise complete the login process on the login page.
        val lastSession = client.authenticationService().getLastAuthenticatedSession()
        if (lastSession != null) {
            SessionHolder.currentSession = lastSession
            lastSession.open()
            lastSession.syncService().startSync(true)
        }
    }
```

### Network configuration

There are two ways to join the SDN network. You can create a local P2P service to communicate with the SDN network. Or, you may connect to an existing Edge Node and enjoy the P2P messaging.

* To connect to a remote Edge Node:

{% hint style="info" %}
Please contact <developer@sending.network> for a test server URL and set it as the `nodeUrl`.
{% endhint %}

```kotlin
// Connect to a remote Edge Node
val nodeUrl = "https://node-domain"
val nodeConnectionConfig = nodeConnectionConfig.Builder()
                .withNodeUri(Uri.parse(node))
                .build()
```

* To run a local P2P node:

```kotlin
// Start the node service
val intent = Intent(context, RadixService::class.java)
context.startService(intent)

// Connect to local P2P service
val nodeUrl = "http://localhost:65432"
val nodeConnectionConfig = NodeConnectionConfig.Builder()
                .withNodeUri(Uri.parse(node))
                .build()
```

### DID login

You will need a developer key to access the Edge Network. To request and utilize a developer key, please refer to the guide provided [here](/sending.network/sdk-documentation/developer-key.md).

The client calls the login-related APIs through `AuthenticationService`:

1. Query for existing DIDs associated with current wallet address.
2. Obtain login message by using one of the DIDs or the wallet address if no DID exists.
3. Request for a message signature with the developer key.
4. Request for a message signature with the user's wallet account.
5. Login by passing the two signatures to the edge node.

```kotlin
val address = ""
val privateKey = ""
val ecKeyPair: ECKeyPair = ECKeyPair.create(privateKey.decodeHex().toByteArray())
val authService = SampleApp.getSDNClient(requireContext()).authenticationService()
try {
    val loginDidMsg = authService.didPreLogin(edgeNodeConnectionConfig, address)
    // sign with user wallet
    val token = signMessage(ecKeyPair, loginDidMsg.message)
    // sign with developer key from server side
    val appToken = signWithServerDeveloperKey((loginDidMsg.message))
    authService.didLogin(edgeNodeConnectionConfig, address,
        loginDidMsg.did, loginDidMsg.randomServer, loginDidMsg.updated, token, appToken)
} catch (failure: Throwable) {
    Toast.makeText(requireContext(), "Failure: $failure", Toast.LENGTH_SHORT).show()
    null
}?.let {
    SessionHolder.currentSession = it
    it.open()
    it.syncService().startSync(true)
    displayRoomList()
}
```

Your developer key server needs to perform the signing operation. Below is an example code for the client to request a signature from the server:"

```kotlin
suspend fun signWithServerDeveloperKey(message: String): String {
        val retrofit: Retrofit = Retrofit.Builder()
            .baseUrl("https://rewards.sending.network")
            .addConverterFactory(MoshiConverterFactory.create(Moshi.Builder().add(KotlinJsonAdapterFactory()).build()))
            .client(OkHttpClient())
            .build()
        val signService = retrofit.create(SignService::class.java)
        val signResp = signService.signMessage(SignRequest(message))
        return signResp.signature
    }
```

### Create a private chat

Invite a user to a private chat room with the user id.

```kotlin
val session = SessionHolder.currentSession
val otherUserId = "@sdn_0829932f18b936f9c878bf1332b53214c11380cb:0829932f18b936f9c878bf1332b53214c11380cb"
// Create a private chat room
val roomId = session.roomService().createDirectRoom(otherUserId)
val room? = session.getRoom(roomId)
// Display the room information
room?.getRoomSummaryLive()?.observe(viewLifecycleOwner) { roomSummary ->
    // display room summary on application UI
}
```

### Send and receive messages

```kotlin
// Send a message
room?.sendService()?.sendTextMessage("Hello!")

// Set timeline listener
val timelineSettings = TimelineSettings(initialSize = 30)
val timeline = room?.timelineService()?.createTimeline(null, timelineSettings)?.also {
    it.addListener(this)
    it.start()
}

// set callback function in the listener
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
    // call this method to process the timeline event
    // when there's an update in timeline
}
```

### Initiating Video Conference

Open a video conference by using the room ID.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sending-network.gitbook.io/sending.network/sdk-documentation/android-client-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
