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)
}
```