---
# System prepended metadata

title: Android SDK 接入文档
tags: [android]

---

Android SDK 接入文档

本文描述接入sendingnetwork-android-sdk的基本步骤。完成代码请参考[sdk demo](https://github.com/LinX-OpenNetwork/sendingnetwork-Android-sdk/tree/main/app)

## Prerequisites

| Components | Requirements                                                                                                                                                                                                                    |
|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| OS         | Android 6.0 or above                                                                                                                                                                                                                 |
| Software   | Android Sutdio 4.0 or above;<br/>[Sending.Network Android SDK](https://github.com/Sending-Network/sendingnetwork-android-sdk)<br/> Note: Please visit our [official website](https://sending.network/) to submit a request for the source code. |

## 一、配置文件初始化

### Gradle

在top level build.gradle文件中添加以下配置:

```gradle
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' }
    }
}
```

在app module build.gradle文件中添加sendingnetwork-android-sdk依赖。(将`x.y.z`替换为最新版本)

```groovy
// sdk依赖
implementation 'io.github.sending-network:sendingnetwork-android-sdk:x.y.z'
```
如果需要使用本地homeserver，则添加sendingnetwork-android-service依赖。(将`x.y.z`替换为最新版本)
```groovy
// 本地server依赖
implementation 'io.github.sending-network:sendingnetwork-android-service:x.y.z'
```

## AndroidManifest.xml file

Your application should at least contains the provider "InitializationProvider" to remove 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>
    
        // 在使用本地homeserver场景时需要声明DendriteService，否则无需声明
        <service android:name="org.matrix.android.sdk.server.DendriteService"
                 android:enabled="true"/>

    </application>

```

## 二、代码初始化和DID登录


### Application初始化
在Application子类的onCreate方法中创建Matrix对象。
``` kotlin
    override fun onCreate() {
        super.onCreate()
        Timber.plant(Timber.DebugTree())
        // 初始化Matrix对象
        matrix = Matrix(
            context = this,
            matrixConfiguration = MatrixConfiguration(
                roomDisplayNameFallbackProvider = RoomDisplayNameFallbackProviderImpl()
            )
        )
        // 如果已经存在登录session，则开始sync消息；否则需要在登录页完成登录流程
        val lastSession = matrix.authenticationService().getLastAuthenticatedSession()
        if (lastSession != null) {
            SessionHolder.currentSession = lastSession
            lastSession.open()
            lastSession.syncService().startSync(true)
        }
    }
```

### HomeServer连接配置
根据使用场景，sdk支持两种方式连接homeserver。
1. 连接远程homeserver节点
```kotlin
// 连接远程homeserver
val homeserverUrl = "https://homeserver-domain"
val homeServerConnectionConfig = HomeServerConnectionConfig.Builder()
                .withHomeServerUri(Uri.parse(homeserver))
                .build()
```
2. 启动并连接本地homeserver
```kotlin
// 启动homeserver服务
val intent = Intent(context, DendriteService::class.java)
context.startService(intent)

// 连接本地homeserver
val homeserverUrl = "http://localhost:65432"
val homeServerConnectionConfig = HomeServerConnectionConfig.Builder()
                .withHomeServerUri(Uri.parse(homeserver))
                .build()
```

### DID登录

客户端通过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 mesasge signature with the developer key.
5. Request for a message signature with user wallet account.
6. Login by passing the two signatures to SDN server.
```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()
}
```

服务端需使用对应语言的web3库函数完成签名操作，客户端向服务端请求签名的示例代码如下：
```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
    }
```



## 三、创建和展示私聊房间
通过对方的UserId创建私聊房间，并获取房间详情。
```kotlin
val session = SessionHolder.currentSession
val otherUserId = "@sdn_0829932f18b936f9c878bf1332b53214c11380cb:0829932f18b936f9c878bf1332b53214c11380cb"
// 创建私聊房间
val roomId = session.roomService().createDirectRoom(otherUserId)
val room? = session.getRoom(roomId)
// 展示房间信息
room?.getRoomSummaryLive()?.observe(viewLifecycleOwner) { roomSummary ->
    // display room summary on application UI
}
```

## 四、发送和接受消息事件
通过对方的UserId创建私聊房间，并获取房间详情。
```kotlin
// 发送消息事件
room?.sendService()?.sendTextMessage("Hello!")

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

// 在listener回调方法中接受消息事件
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
    // timeline有更新时回调此方法
    // 处理TimelineEvent事件
}
```

## 五、打开视频聊天会议
通过房间id打开视频聊天会议。
```kotlin
import org.sdn.android.sdk.api.meet.SdnMeetActivity

fun joinRoomMeeting(context: Context, roomId: String) {
        SdnMeetActivity.launch(context, roomId)
}
```