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
Components
Requirements
OS
Android 6.0 or above
Software
Android Studio 4.0 or above
Configure your build
Gradle
Add the following code to the top-level build.gradle configuration file:
Your application should at least contain the provider InitializationProvider to remove the initialization of the WorkManager as below:
<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.
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:
Please contact developer@sending.network for a test server URL and set it as the nodeUrl.
// 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:
// 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.
The client calls the login-related APIs through AuthenticationService:
Query for existing DIDs associated with current wallet address.
Obtain login message by using one of the DIDs or the wallet address if no DID exists.
Request for a message signature with the developer key.
Request for a message signature with the user's wallet account.
Login by passing the two signatures to the edge node.
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:"
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.
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
// 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
}