diff --git a/android/build.gradle b/android/build.gradle index 07a1e49..11ef373 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,21 +1,27 @@ group 'io.agora.agora_rtm' +def safeExtGet(prop, fallback) { + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback +} + buildscript { + def kotlin_version = rootProject.ext.has('kotlin_version') ? rootProject.ext.get('kotlin_version') : '1.3.72' + repositories { + mavenCentral() google() - jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } rootProject.allprojects { repositories { + mavenCentral() google() - jcenter() + maven { url 'https://www.jitpack.io' } } } @@ -23,21 +29,27 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 28 + compileSdkVersion safeExtGet('compileSdkVersion', 28) + buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') + + defaultConfig { + minSdkVersion safeExtGet('minSdkVersion', 16) + targetSdkVersion safeExtGet('targetSdkVersion', 28) + + consumerProguardFiles 'consumer-rules.pro' + } sourceSets { main.java.srcDirs += 'src/main/kotlin' } - defaultConfig { - minSdkVersion 16 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } + lintOptions { disable 'InvalidPackage' } } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'io.agora.rtm:rtm-sdk:1.2.2' + api 'com.github.agorabuilder:rtm-sdk:1.4.7' + + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${safeExtGet('kotlin_version', '1.3.72')}" } diff --git a/android/consumer-rules.pro b/android/consumer-rules.pro new file mode 100644 index 0000000..b5b5975 --- /dev/null +++ b/android/consumer-rules.pro @@ -0,0 +1,5 @@ +-keepattributes *Annotation* +-keep class kotlin.** { *; } +-keep class org.jetbrains.** { *; } + +-keep class io.agora.**{*;} diff --git a/android/src/main/kotlin/io/agora/agorartm/AgoraRtmPlugin.kt b/android/src/main/kotlin/io/agora/agorartm/AgoraRtmPlugin.kt index 9c51ac8..b30895b 100644 --- a/android/src/main/kotlin/io/agora/agorartm/AgoraRtmPlugin.kt +++ b/android/src/main/kotlin/io/agora/agorartm/AgoraRtmPlugin.kt @@ -9,962 +9,985 @@ import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.PluginRegistry.Registrar -import kotlin.collections.ArrayList -import kotlin.collections.HashMap - -class AgoraRtmPlugin: MethodCallHandler { - private val registrar: Registrar - private val methodChannel: MethodChannel - private val eventHandler: Handler - private var nextClientIndex: Long = 0 - private var clients = HashMap() - - companion object { - @JvmStatic - fun registerWith(registrar: Registrar) { - val channel = MethodChannel(registrar.messenger(), "io.agora.rtm") - val plugin = AgoraRtmPlugin(registrar, channel) - channel.setMethodCallHandler(plugin) - } - } - - constructor(registrar: Registrar, channel: MethodChannel) { - this.registrar = registrar - this.methodChannel = channel - this.eventHandler = Handler(Looper.getMainLooper()) - } - - private fun getActiveContext(): Context { - return when { - (registrar.activity() == null) -> registrar.context() - else -> registrar.activity() - } - } - private fun runMainThread(f: () -> Unit) { - eventHandler.post(f) - } +class AgoraRtmPlugin : MethodCallHandler { + private val registrar: Registrar + private val methodChannel: MethodChannel + private val eventHandler: Handler + private var nextClientIndex: Long = 0 + private var clients = HashMap() - override fun onMethodCall(methodCall: MethodCall, result: Result) { - val methodName: String? = when { - methodCall.method is String -> methodCall.method as String - else -> null - } - val callArguments: Map? = when { - methodCall.arguments is Map<*, *> -> methodCall.arguments as Map - else -> null - } - val call: String? = when { - callArguments!!.get("call") is String -> callArguments.get("call") as String - else -> null + companion object { + @JvmStatic + fun registerWith(registrar: Registrar) { + val channel = MethodChannel(registrar.messenger(), "io.agora.rtm") + val plugin = AgoraRtmPlugin(registrar, channel) + channel.setMethodCallHandler(plugin) + } } - var params: Map = callArguments["params"] as Map - - when (call) { - "static" -> { - handleStaticMethod(methodName, params, result) - } - "AgoraRtmClient" -> { - handleClientMethod(methodName, params, result) - } - "AgoraRtmChannel" -> { - handleChannelMethod(methodName, params, result) - } - else -> { - result.notImplemented() - } + constructor(registrar: Registrar, channel: MethodChannel) { + this.registrar = registrar + this.methodChannel = channel + this.eventHandler = Handler(Looper.getMainLooper()) } - } - - private fun handleStaticMethod(methodName: String?, params: Map, result: MethodChannel.Result) { - when (methodName) { - "createInstance" -> { - val appId: String? = when { - params["appId"] is String -> params["appId"] as String - else -> null - } - - if (null == appId) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } - while (null != clients[nextClientIndex]) { - nextClientIndex++ + private fun getActiveContext(): Context { + return when { + (registrar.activity() == null) -> registrar.context() + else -> registrar.activity() } - - val rtmClient = RTMClient(getActiveContext(), appId, nextClientIndex, registrar.messenger(), eventHandler) - result.success(hashMapOf( - "errorCode" to 0, - "index" to nextClientIndex - )) - clients[nextClientIndex] = rtmClient - nextClientIndex++ - } - "getSdkVersion" -> { - result.success(hashMapOf( - "errorCode" to 0, - "version" to RtmClient.getSdkVersion() - )) - } - else -> { - result.notImplemented(); - } } - } - private fun handleClientMethod(methodName: String?, params: Map, result: Result) { - - val clientIndex = (params["clientIndex"] as Int).toLong() - var args: Map? = when { - (params.get("args") is Map<*,*>) -> (params["args"] as Map) - else -> null - } - val agoraClient = when { - clients[clientIndex] is RTMClient -> clients[clientIndex] as RTMClient - else -> null - } - if (null == agoraClient) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return + private fun runMainThread(f: () -> Unit) { + eventHandler.post(f) } - var client: RtmClient = agoraClient.client - - when (methodName) { - "destroy" -> { - agoraClient.channels.forEach{ - val pair = it.toPair() - pair.second.release() - } - agoraClient.channels.clear() - clients.remove(clientIndex) - runMainThread { - result.success(hashMapOf("errorCode" to 0)) + override fun onMethodCall(methodCall: MethodCall, result: Result) { + val methodName: String? = when { + methodCall.method is String -> methodCall.method as String + else -> null } - } - "setLog" -> { - val relativePath = "/sdcard/${getActiveContext().packageName}" - val size: Int = when { - args?.get("size") is Int -> args.get("size") as Int - else -> 524288 + val callArguments: Map? = when { + methodCall.arguments is Map<*, *> -> methodCall.arguments as Map + else -> null } - val path: String? = when { - args?.get("path") is String -> "${relativePath}/${(args.get("path") as String)}" - else -> null + val call: String? = when { + callArguments!!.get("call") is String -> callArguments.get("call") as String + else -> null } - val level: Int = when { - args?.get("level") is Int -> args.get("level") as Int - else -> 0 - } - - runMainThread { - result.success(hashMapOf( - "errorCode" to 0, - "results" to hashMapOf( - "setLogFileSize" to client.setLogFileSize(size), - "setLogLevel" to client.setLogFilter(level), - "setLogFile" to client.setLogFile(path) - ) - )) - } - } - "login" -> { - var token = args?.get("token") + var params: Map = callArguments["params"] as Map - token = when { - (token is String) -> token - else -> null + when (call) { + "static" -> { + handleStaticMethod(methodName, params, result) + } + "AgoraRtmClient" -> { + handleClientMethod(methodName, params, result) + } + "AgoraRtmChannel" -> { + handleChannelMethod(methodName, params, result) + } + else -> { + result.notImplemented() + } } + } - var userId = args?.get("userId") - - userId = when { - (userId is String) -> userId - else -> null - } + private fun handleStaticMethod(methodName: String?, params: Map, result: MethodChannel.Result) { + when (methodName) { + "createInstance" -> { + val appId: String? = when { + params["appId"] is String -> params["appId"] as String + else -> null + } - client.login( - token, - userId, - object: ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf("errorCode" to 0)) - } - } - override fun onFailure(code: ErrorInfo) { + if (null == appId) { runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + result.success(hashMapOf("errorCode" to -1)) } - } - } - ) - } - "logout" -> { - client.logout( - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf("errorCode" to 0)) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } + return } - ) - } - "renewToken" -> { - var token = args?.get("token") - token = when { - (token is String) -> token - else -> null - } - - client.renewToken( - token, - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf("errorCode" to 0)) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } + while (null != clients[nextClientIndex]) { + nextClientIndex++ } - ) - } - "queryPeersOnlineStatus" -> { - var peerIds: Set? = (args?.get("peerIds") as ArrayList).toSet() - client.queryPeersOnlineStatus(peerIds, - object : ResultCallback> { - override fun onSuccess(resp: MutableMap) { - runMainThread { + val rtmClient = RTMClient(getActiveContext(), appId, nextClientIndex, registrar.messenger(), eventHandler) result.success(hashMapOf( "errorCode" to 0, - "results" to resp + "index" to nextClientIndex )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - } - ) - } - "sendMessageToPeer" -> { - var peerId: String? = args?.get("peerId") as String - var text = args.get("message") as String - val message = client.createMessage() - message.text = text - val options = SendMessageOptions().apply { - (args["historical"] as? Boolean)?.let { - enableHistoricalMessaging = it - } - (args["offline"] as? Boolean)?.let { - enableOfflineMessaging = it - } - } - client.sendMessageToPeer(peerId, - message, - options, - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - } - ) - } - "setLocalUserAttributes" -> { - val attributes: List>? = args?.get("attributes") as List> - var localUserAttributes = ArrayList() - attributes!!.forEach { - var rtmAttribute = RtmAttribute() - rtmAttribute.key = it["key"] - rtmAttribute.value = it["value"] - localUserAttributes.add(rtmAttribute) - } - client.setLocalUserAttributes(localUserAttributes, - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - } - ) - } - "addOrUpdateLocalUserAttributes" -> { - val attributes: List>? = args?.get("attributes") as List> - var localUserAttributes = ArrayList() - attributes!!.forEach { - var rtmAttribute = RtmAttribute() - rtmAttribute.key = it["key"] - rtmAttribute.value = it["value"] - localUserAttributes.add(rtmAttribute) - } - client.addOrUpdateLocalUserAttributes(localUserAttributes, - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - } - ) - } - "deleteLocalUserAttributesByKeys" -> { - val keys: List? = args?.get("keys") as List - client.deleteLocalUserAttributesByKeys(keys, - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - } - ) - } - "clearLocalUserAttributes" -> { - client.clearLocalUserAttributes( - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - } - ) - } - "getUserAttributes" -> { - val userId: String? = when { - args?.get("userId") is String -> args.get("userId") as String - else -> null - } - client.getUserAttributes(userId, - object : ResultCallback> { - override fun onSuccess(resp: List) { - var attributes: MutableMap = HashMap() - resp.map { - attributes[it.key] = it.value - } - runMainThread { + clients[nextClientIndex] = rtmClient + nextClientIndex++ + } + "getSdkVersion" -> { result.success(hashMapOf( "errorCode" to 0, - "attributes" to attributes + "version" to RtmClient.getSdkVersion() )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "getUserAttributesByKeys" -> { - val userId: String? = when { - args?.get("userId") is String -> args.get("userId") as String - else -> null - } - var keys: List? = when { - args?.get("keys") is List<*> -> args.get("keys") as List - else -> null + } + else -> { + result.notImplemented(); + } } + } - client.getUserAttributesByKeys(userId, - keys, - object : ResultCallback> { - override fun onSuccess(resp: List) { - var attributes: MutableMap = HashMap() - resp.map { - attributes[it.key] = it.value - } - runMainThread { - result.success(hashMapOf( - "errorCode" to 0, - "attributes" to attributes - )) - } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "setChannelAttributes" -> { - val channelId: String? = when { - args?.get("channelId") is String -> args.get("channelId") as String - else -> null + private fun handleClientMethod(methodName: String?, params: Map, result: Result) { + + val clientIndex = (params["clientIndex"] as Int).toLong() + var args: Map? = when { + (params.get("args") is Map<*, *>) -> (params["args"] as Map) + else -> null } - val enableNotificationToChannelMembers: Boolean = when { - args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean - else -> false + val agoraClient = when { + clients[clientIndex] is RTMClient -> clients[clientIndex] as RTMClient + else -> null } - val attributes: List>? = args?.get("attributes") as List> - var channelAttributes = ArrayList() - attributes!!.forEach { - var rtmChannelAttribute = RtmChannelAttribute() - rtmChannelAttribute.key = it["key"] - rtmChannelAttribute.value = it["value"] - channelAttributes.add(rtmChannelAttribute) + if (null == agoraClient) { + runMainThread { + result.success(hashMapOf("errorCode" to -1)) + } + return } - client.setChannelAttributes(channelId, channelAttributes, - ChannelAttributeOptions(enableNotificationToChannelMembers), - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + var client: RtmClient = agoraClient.client + + when (methodName) { + "destroy" -> { + agoraClient.channels.forEach { + val pair = it.toPair() + pair.second.release() + } + agoraClient.channels.clear() + clients.remove(clientIndex) + runMainThread { + result.success(hashMapOf("errorCode" to 0)) + } + } + "setLog" -> { + val relativePath = "/sdcard/${getActiveContext().packageName}" + val size: Int = when { + args?.get("size") is Int -> args.get("size") as Int + else -> 524288 + } + val path: String? = when { + args?.get("path") is String -> "${relativePath}/${(args.get("path") as String)}" + else -> null + } + + val level: Int = when { + args?.get("level") is Int -> args.get("level") as Int + else -> 0 + } + + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "results" to hashMapOf( + "setLogFileSize" to client.setLogFileSize(size), + "setLogLevel" to client.setLogFilter(level), + "setLogFile" to client.setLogFile(path) + ) + )) + } + } + "login" -> { + var token = args?.get("token") + + token = when { + (token is String) -> token + else -> null + } + + var userId = args?.get("userId") + + userId = when { + (userId is String) -> userId + else -> null + } + + client.login( + token, + userId, + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf("errorCode" to 0)) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "logout" -> { + client.logout( + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf("errorCode" to 0)) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "renewToken" -> { + var token = args?.get("token") + + token = when { + (token is String) -> token + else -> null + } + + client.renewToken( + token, + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf("errorCode" to 0)) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "queryPeersOnlineStatus" -> { + var peerIds: Set? = (args?.get("peerIds") as ArrayList).toSet() + + client.queryPeersOnlineStatus(peerIds, + object : ResultCallback> { + override fun onSuccess(resp: MutableMap) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "results" to resp + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "sendMessageToPeer" -> { + var peerId: String? = args?.get("peerId") as String + var text = args.get("message") as String + val message = client.createMessage() + message.text = text + val options = SendMessageOptions().apply { + (args["historical"] as? Boolean)?.let { + enableHistoricalMessaging = it + } + (args["offline"] as? Boolean)?.let { + enableOfflineMessaging = it } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + client.sendMessageToPeer(peerId, + message, + options, + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "setLocalUserAttributes" -> { + val attributes: List>? = args?.get("attributes") as List> + var localUserAttributes = ArrayList() + attributes!!.forEach { + var rtmAttribute = RtmAttribute() + rtmAttribute.key = it["key"] + rtmAttribute.value = it["value"] + localUserAttributes.add(rtmAttribute) + } + client.setLocalUserAttributes(localUserAttributes, + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "addOrUpdateLocalUserAttributes" -> { + val attributes: List>? = args?.get("attributes") as List> + var localUserAttributes = ArrayList() + attributes!!.forEach { + var rtmAttribute = RtmAttribute() + rtmAttribute.key = it["key"] + rtmAttribute.value = it["value"] + localUserAttributes.add(rtmAttribute) + } + client.addOrUpdateLocalUserAttributes(localUserAttributes, + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "deleteLocalUserAttributesByKeys" -> { + val keys: List? = args?.get("keys") as List + client.deleteLocalUserAttributesByKeys(keys, + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "clearLocalUserAttributes" -> { + client.clearLocalUserAttributes( + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "getUserAttributes" -> { + val userId: String? = when { + args?.get("userId") is String -> args.get("userId") as String + else -> null + } + client.getUserAttributes(userId, + object : ResultCallback> { + override fun onSuccess(resp: List) { + var attributes: MutableMap = HashMap() + resp.map { + attributes[it.key] = it.value + } + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "attributes" to attributes + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) + } + "getUserAttributesByKeys" -> { + val userId: String? = when { + args?.get("userId") is String -> args.get("userId") as String + else -> null + } + var keys: List? = when { + args?.get("keys") is List<*> -> args.get("keys") as List + else -> null + } + + client.getUserAttributesByKeys(userId, + keys, + object : ResultCallback> { + override fun onSuccess(resp: List) { + var attributes: MutableMap = HashMap() + resp.map { + attributes[it.key] = it.value + } + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "attributes" to attributes + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) + } + "setChannelAttributes" -> { + val channelId: String? = when { + args?.get("channelId") is String -> args.get("channelId") as String + else -> null + } + val enableNotificationToChannelMembers: Boolean = when { + args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean + else -> false + } + val attributes: List>? = args?.get("attributes") as List> + var channelAttributes = ArrayList() + attributes!!.forEach { + var rtmChannelAttribute = RtmChannelAttribute() + rtmChannelAttribute.key = it["key"] + rtmChannelAttribute.value = it["value"] + channelAttributes.add(rtmChannelAttribute) + } + + client.setChannelAttributes(channelId, channelAttributes, + ChannelAttributeOptions(enableNotificationToChannelMembers), + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "addOrUpdateChannelAttributes" -> { + val channelId: String? = when { + args?.get("channelId") is String -> args.get("channelId") as String + else -> null + } + val enableNotificationToChannelMembers: Boolean = when { + args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean + else -> false + } + val attributes: List>? = args?.get("attributes") as List> + var channelAttributes = ArrayList() + attributes!!.forEach { + var rtmChannelAttribute = RtmChannelAttribute() + rtmChannelAttribute.key = it["key"] + rtmChannelAttribute.value = it["value"] + channelAttributes.add(rtmChannelAttribute) + } + client.addOrUpdateChannelAttributes(channelId, channelAttributes, + ChannelAttributeOptions(enableNotificationToChannelMembers), + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "deleteChannelAttributesByKeys" -> { + val channelId: String? = when { + args?.get("channelId") is String -> args.get("channelId") as String + else -> null + } + val enableNotificationToChannelMembers: Boolean = when { + args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean + else -> false + } + val keys: List? = args?.get("keys") as List + client.deleteChannelAttributesByKeys(channelId, keys, + ChannelAttributeOptions(enableNotificationToChannelMembers), + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "clearChannelAttributes" -> { + val channelId: String? = when { + args?.get("channelId") is String -> args.get("channelId") as String + else -> null + } + val enableNotificationToChannelMembers: Boolean = when { + args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean + else -> false + } + client.clearChannelAttributes(channelId, + ChannelAttributeOptions(enableNotificationToChannelMembers), + object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + } + ) + } + "getChannelAttributes" -> { + val channelId: String? = when { + args?.get("channelId") is String -> args.get("channelId") as String + else -> null + } + client.getChannelAttributes(channelId, + object : ResultCallback> { + override fun onSuccess(resp: List) { + var attributes = ArrayList>() + for (attribute in resp.orEmpty()) { + attributes.add(hashMapOf( + "key" to attribute.key, + "value" to attribute.value, + "userId" to attribute.getLastUpdateUserId(), + "updateTs" to attribute.getLastUpdateTs() + )) + } + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "attributes" to attributes + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) + } + "getChannelAttributesByKeys" -> { + val channelId: String? = when { + args?.get("channelId") is String -> args.get("channelId") as String + else -> null + } + var keys: List? = when { + args?.get("keys") is List<*> -> args.get("keys") as List + else -> null + } + + client.getChannelAttributesByKeys(channelId, + keys, + object : ResultCallback> { + override fun onSuccess(resp: List) { + var attributes = ArrayList>() + for (attribute in resp.orEmpty()) { + attributes.add(hashMapOf( + "key" to attribute.key, + "value" to attribute.value, + "userId" to attribute.getLastUpdateUserId(), + "updateTs" to attribute.getLastUpdateTs() + )) + } + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "attributes" to attributes + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) + } + "sendLocalInvitation" -> { + val calleeId = when { + args?.get("calleeId") is String -> args["calleeId"] as String + else -> null + } + val content = when { + args?.get("content") is String -> args["content"] as String + else -> null + } + val channelId = when { + args?.get("channelId") is String -> args["channelId"] as String + else -> null + } + val localInvitation = agoraClient.callKit.createLocalInvitation(calleeId) + if (null != content) { + localInvitation.content = content + } + if (null != channelId) { + localInvitation.channelId = channelId + } + agoraClient.callKit.sendLocalInvitation(localInvitation, object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + agoraClient.localInvitations[localInvitation.calleeId] = localInvitation + result.success(hashMapOf( + "errorCode" to 0 + )) + } } - } - } - ) - } - "addOrUpdateChannelAttributes" -> { - val channelId: String? = when { - args?.get("channelId") is String -> args.get("channelId") as String - else -> null - } - val enableNotificationToChannelMembers: Boolean = when { - args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean - else -> false - } - val attributes: List>? = args?.get("attributes") as List> - var channelAttributes = ArrayList() - attributes!!.forEach { - var rtmChannelAttribute = RtmChannelAttribute() - rtmChannelAttribute.key = it["key"] - rtmChannelAttribute.value = it["value"] - channelAttributes.add(rtmChannelAttribute) - } - client.addOrUpdateChannelAttributes(channelId, channelAttributes, - ChannelAttributeOptions(enableNotificationToChannelMembers), - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } } - } - override fun onFailure(code: ErrorInfo) { + }) + } + "cancelLocalInvitation" -> { + val calleeId = when { + args?.get("calleeId") is String -> args["calleeId"] as String + else -> null + } + val content = when { + args?.get("content") is String -> args["content"] as String + else -> null + } + val channelId = when { + args?.get("channelId") is String -> args["channelId"] as String + else -> null + } + val localInvitation = when { + agoraClient.localInvitations[calleeId] is LocalInvitation -> agoraClient.localInvitations[calleeId] + else -> null + } + + if (null == localInvitation) { runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + result.success(hashMapOf("errorCode" to -1)) } - } - } - ) - } - "deleteChannelAttributesByKeys" -> { - val channelId: String? = when { - args?.get("channelId") is String -> args.get("channelId") as String - else -> null - } - val enableNotificationToChannelMembers: Boolean = when { - args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean - else -> false - } - val keys: List? = args?.get("keys") as List - client.deleteChannelAttributesByKeys(channelId, keys, - ChannelAttributeOptions(enableNotificationToChannelMembers), - object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + return + } + + if (null != content) { + localInvitation.content = content + } + if (null != channelId) { + localInvitation.channelId = channelId + } + agoraClient.callKit.cancelLocalInvitation(localInvitation, object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + agoraClient.localInvitations.remove(localInvitation.calleeId) + result.success(hashMapOf( + "errorCode" to 0 + )) + } } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } } - } - } - ) - } - "clearChannelAttributes" -> { - val channelId: String? = when { - args?.get("channelId") is String -> args.get("channelId") as String - else -> null - } - val enableNotificationToChannelMembers: Boolean = when { - args?.get("enableNotificationToChannelMembers") is Boolean -> args.get("enableNotificationToChannelMembers") as Boolean - else -> false - } - client.clearChannelAttributes(channelId, - ChannelAttributeOptions(enableNotificationToChannelMembers), - object : ResultCallback { - override fun onSuccess(resp: Void?) { + }) + } + "acceptRemoteInvitation" -> { + val response = when { + args?.get("response") is String -> args.get("response") as String + else -> null + } + + val callerId = when { + args?.get("callerId") is String -> args.get("callerId") as String + else -> null + } + + var remoteInvitation: RemoteInvitation? = when { + agoraClient.remoteInvitations[callerId] is RemoteInvitation -> agoraClient.remoteInvitations[callerId] + else -> null + } + + if (null == remoteInvitation) { runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + result.success(hashMapOf("errorCode" to -1)) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + return + } + + if (null != response) { + remoteInvitation.response = response + } + agoraClient.callKit.acceptRemoteInvitation(remoteInvitation, object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + agoraClient.remoteInvitations.remove(remoteInvitation.callerId) + result.success(hashMapOf( + "errorCode" to 0 + )) + } } - } - } - ) - } - "getChannelAttributes" -> { - val channelId: String? = when { - args?.get("channelId") is String -> args.get("channelId") as String - else -> null - } - client.getChannelAttributes(channelId, - object : ResultCallback> { - override fun onSuccess(resp: List) { - var attributes = ArrayList>() - for(attribute in resp.orEmpty()){ - attributes.add(hashMapOf( - "key" to attribute.key, - "value" to attribute.value, - "userId" to attribute.getLastUpdateUserId(), - "updateTs" to attribute.getLastUpdateTs() - )) + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } } + }) + } + "refuseRemoteInvitation" -> { + val response = when { + args?.get("response") is String -> args.get("response") as String + else -> null + } + + val callerId = when { + args?.get("callerId") is String -> args.get("callerId") as String + else -> null + } + + var remoteInvitation: RemoteInvitation? = when { + agoraClient.remoteInvitations[callerId] is RemoteInvitation -> agoraClient.remoteInvitations[callerId] + else -> null + } + + if (null == remoteInvitation) { runMainThread { - result.success(hashMapOf( - "errorCode" to 0, - "attributes" to attributes - )) + result.success(hashMapOf("errorCode" to -1)) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + return + } + + if (null != response) { + remoteInvitation.response = response + } + + agoraClient.callKit.refuseRemoteInvitation(remoteInvitation, object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + agoraClient.remoteInvitations.remove(remoteInvitation.callerId) + result.success(hashMapOf( + "errorCode" to 0 + )) + } } - } - }) - } - "getChannelAttributesByKeys" -> { - val channelId: String? = when { - args?.get("channelId") is String -> args.get("channelId") as String - else -> null - } - var keys: List? = when { - args?.get("keys") is List<*> -> args.get("keys") as List - else -> null - } - client.getChannelAttributesByKeys(channelId, - keys, - object : ResultCallback> { - override fun onSuccess(resp: List) { - var attributes = ArrayList>() - for(attribute in resp.orEmpty()){ - attributes.add(hashMapOf( - "key" to attribute.key, - "value" to attribute.value, - "userId" to attribute.getLastUpdateUserId(), - "updateTs" to attribute.getLastUpdateTs() - )) + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } } + }) + } + "createChannel" -> { + val channelId = args?.get("channelId") as String + val agoraRtmChannel = RTMChannel(clientIndex, channelId, registrar.messenger(), eventHandler) + val channel: RtmChannel? = client.createChannel(channelId, agoraRtmChannel) + if (null == channel) { runMainThread { - result.success(hashMapOf( - "errorCode" to 0, - "attributes" to attributes - )) + result.success(hashMapOf("errorCode" to -1)) } - } - override fun onFailure(code: ErrorInfo) { + return + } + agoraClient.channels[channelId] = channel + runMainThread { + result.success(hashMapOf("errorCode" to 0)) + } + } + "releaseChannel" -> { + val channelId = args?.get("channelId") as String + val rtmChannel = agoraClient.channels[channelId] + if (null == rtmChannel) { runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) + result.success(hashMapOf("errorCode" to -1)) } - } - }) - } - "sendLocalInvitation" -> { - val calleeId = when { - args?.get("calleeId") is String -> args["calleeId"] as String - else -> null - } - val content = when { - args?.get("content") is String -> args["content"] as String - else -> null - } - val channelId = when { - args?.get("channelId") is String -> args["channelId"] as String - else -> null - } - val localInvitation = agoraClient.callKit.createLocalInvitation(calleeId) - if (null != content) { - localInvitation.content = content - } - if (null != channelId) { - localInvitation.channelId = channelId - } - agoraClient.callKit.sendLocalInvitation(localInvitation, object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - agoraClient.localInvitations[localInvitation.calleeId] = localInvitation - result.success(hashMapOf( - "errorCode" to 0 - )) + return + } + rtmChannel.release() + agoraClient.channels.remove(channelId) + runMainThread { + result.success(hashMapOf("errorCode" to 0)) + } } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "cancelLocalInvitation" -> { - val calleeId = when { - args?.get("calleeId") is String -> args["calleeId"] as String - else -> null - } - val content = when { - args?.get("content") is String -> args["content"] as String - else -> null - } - val channelId = when { - args?.get("channelId") is String -> args["channelId"] as String - else -> null - } - val localInvitation = when { - agoraClient.localInvitations[calleeId] is LocalInvitation -> agoraClient.localInvitations[calleeId] - else -> null - } - - if (null == localInvitation) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } - - if (null != content) { - localInvitation.content = content - } - if (null != channelId) { - localInvitation.channelId = channelId - } - agoraClient.callKit.cancelLocalInvitation(localInvitation, object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - agoraClient.localInvitations.remove(localInvitation.calleeId) - result.success(hashMapOf( - "errorCode" to 0 - )) + else -> { + result.notImplemented(); } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "acceptRemoteInvitation" -> { - val response = when { - args?.get("response") is String -> args.get("response") as String - else -> null } + } - val callerId = when { - args?.get("callerId") is String -> args.get("callerId") as String - else -> null - } + private fun handleChannelMethod(methodName: String?, params: Map, result: MethodChannel.Result) { - var remoteInvitation: RemoteInvitation? = when { - agoraClient.remoteInvitations[callerId] is RemoteInvitation -> agoraClient.remoteInvitations[callerId] - else -> null + val _clientIndex = (params["clientIndex"] as Int).toLong() + val _channelId = params["channelId"] as String + var args: Map? = when { + (params.get("args") is Map<*, *>) -> params["args"] as Map + else -> null } - if (null == remoteInvitation) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } + val agoraClient: RTMClient? = clients[_clientIndex] - if (null != response) { - remoteInvitation.response = response - } - agoraClient.callKit.acceptRemoteInvitation(remoteInvitation, object : ResultCallback { - override fun onSuccess(resp: Void?) { + if (null == agoraClient) { runMainThread { - agoraClient.remoteInvitations.remove(remoteInvitation.callerId) - result.success(hashMapOf( - "errorCode" to 0 - )) + result.success(hashMapOf("errorCode" to -1)) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "refuseRemoteInvitation" -> { - val response = when { - args?.get("response") is String -> args.get("response") as String - else -> null + return } - val callerId = when { - args?.get("callerId") is String -> args.get("callerId") as String - else -> null - } + val client: RtmClient? = agoraClient.client - var remoteInvitation: RemoteInvitation? = when { - agoraClient.remoteInvitations[callerId] is RemoteInvitation -> agoraClient.remoteInvitations[callerId] - else -> null - } - - if (null == remoteInvitation) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return + if (null == client) { + runMainThread { + result.success(hashMapOf("errorCode" to -1)) + } + return } - if (null != response) { - remoteInvitation.response = response - } + val rtmChannel = agoraClient.channels[_channelId] - agoraClient.callKit.refuseRemoteInvitation(remoteInvitation, object : ResultCallback { - override fun onSuccess(resp: Void?) { + if (null == rtmChannel) { runMainThread { - agoraClient.remoteInvitations.remove(remoteInvitation.callerId) - result.success(hashMapOf( - "errorCode" to 0 - )) + result.success(hashMapOf("errorCode" to -1)) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "createChannel" -> { - val channelId = args?.get("channelId") as String - val agoraRtmChannel = RTMChannel(clientIndex, channelId, registrar.messenger(), eventHandler) - val channel: RtmChannel? = client.createChannel(channelId, agoraRtmChannel) - if (null == channel) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return + return } - agoraClient.channels[channelId] = channel - runMainThread { - result.success(hashMapOf("errorCode" to 0)) - } - } - "releaseChannel" -> { - val channelId = args?.get("channelId") as String - val rtmChannel = agoraClient.channels[channelId] - if (null == rtmChannel) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } - rtmChannel.release() - agoraClient.channels.remove(channelId) - runMainThread { - result.success(hashMapOf("errorCode" to 0)) - } - } - else -> { - result.notImplemented(); - } - } - } - - private fun handleChannelMethod(methodName: String?, params: Map, result: MethodChannel.Result) { - - val _clientIndex = (params["clientIndex"] as Int).toLong() - val _channelId = params["channelId"] as String - var args: Map? = when { - (params.get("args") is Map<*,*>) -> params["args"] as Map - else -> null - } - val agoraClient: RTMClient? = clients[_clientIndex] - - if (null == agoraClient) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } - - val client: RtmClient? = agoraClient.client - - if (null == client) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } - - val rtmChannel = agoraClient.channels[_channelId] - - if (null == rtmChannel) { - runMainThread { - result.success(hashMapOf("errorCode" to -1)) - } - return - } + when (methodName) { + "join" -> { + rtmChannel.join(object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } - when (methodName) { - "join" -> { - rtmChannel.join(object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "sendMessage" -> { - val message = client.createMessage() - message.text = args?.get("message") as String - val options = SendMessageOptions().apply { - (args["historical"] as? Boolean)?.let { - enableHistoricalMessaging = it - } - (args["offline"] as? Boolean)?.let { - enableOfflineMessaging = it - } - } - rtmChannel.sendMessage(message, options, object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + "sendMessage" -> { + val message = client.createMessage() + message.text = args?.get("message") as String + val options = SendMessageOptions().apply { + (args["historical"] as? Boolean)?.let { + enableHistoricalMessaging = it + } + (args["offline"] as? Boolean)?.let { + enableOfflineMessaging = it + } + } + rtmChannel.sendMessage(message, options, object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "leave" -> { - rtmChannel.leave(object : ResultCallback { - override fun onSuccess(resp: Void?) { - runMainThread { - result.success(hashMapOf( - "errorCode" to 0 - )) + "leave" -> { + rtmChannel.leave(object : ResultCallback { + override fun onSuccess(resp: Void?) { + runMainThread { + result.success(hashMapOf( + "errorCode" to 0 + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - "getMembers" -> { - rtmChannel.getMembers(object : ResultCallback> { - override fun onSuccess(resp: List) { - val membersList = ArrayList>() - for (member in resp) { - membersList.add(hashMapOf("userId" to member.userId, "channelId" to member.channelId)) + "getMembers" -> { + rtmChannel.getMembers(object : ResultCallback> { + override fun onSuccess(resp: List) { + val membersList = ArrayList>() + for (member in resp) { + membersList.add(hashMapOf("userId" to member.userId, "channelId" to member.channelId)) + } + runMainThread { + result.success(hashMapOf( + "errorCode" to 0, + "members" to membersList + )) + } + } + + override fun onFailure(code: ErrorInfo) { + runMainThread { + result.success(hashMapOf("errorCode" to code.getErrorCode())) + } + } + }) } - runMainThread { - result.success(hashMapOf( - "errorCode" to 0, - "members" to membersList - )) + else -> { + result.notImplemented(); } - } - override fun onFailure(code: ErrorInfo) { - runMainThread { - result.success(hashMapOf("errorCode" to code.getErrorCode())) - } - } - }) - } - else -> { - result.notImplemented(); - } + } } - } } \ No newline at end of file diff --git a/android/src/main/kotlin/io/agora/agorartm/RTMChannel.kt b/android/src/main/kotlin/io/agora/agorartm/RTMChannel.kt index 294c64c..d8ee1e2 100644 --- a/android/src/main/kotlin/io/agora/agorartm/RTMChannel.kt +++ b/android/src/main/kotlin/io/agora/agorartm/RTMChannel.kt @@ -1,10 +1,7 @@ package io.agora.agorartm import android.os.Handler -import io.agora.rtm.RtmChannelAttribute -import io.agora.rtm.RtmChannelListener -import io.agora.rtm.RtmChannelMember -import io.agora.rtm.RtmMessage +import io.agora.rtm.* import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.EventChannel @@ -33,7 +30,7 @@ class RTMChannel : RtmChannelListener, EventChannel.StreamHandler { override fun onAttributesUpdated(attributes: MutableList?) { var attributeList = ArrayList>() - for(attribute in attributes.orEmpty()){ + for (attribute in attributes.orEmpty()) { attributeList.add(hashMapOf( "key" to attribute.key, "value" to attribute.value, @@ -59,6 +56,14 @@ class RTMChannel : RtmChannelListener, EventChannel.StreamHandler { )) } + override fun onImageMessageReceived(p0: RtmImageMessage?, p1: RtmChannelMember?) { + TODO("Not yet implemented") + } + + override fun onFileMessageReceived(p0: RtmFileMessage?, p1: RtmChannelMember?) { + TODO("Not yet implemented") + } + override fun onMemberJoined(member: RtmChannelMember) { sendChannelEvent("onMemberJoined", hashMapOf( diff --git a/android/src/main/kotlin/io/agora/agorartm/RTMClient.kt b/android/src/main/kotlin/io/agora/agorartm/RTMClient.kt index f0a65eb..6c15e79 100644 --- a/android/src/main/kotlin/io/agora/agorartm/RTMClient.kt +++ b/android/src/main/kotlin/io/agora/agorartm/RTMClient.kt @@ -206,6 +206,22 @@ class RTMClient : RtmClientListener, EventChannel.StreamHandler, RtmCallEventLis ))) } + override fun onImageMessageReceivedFromPeer(p0: RtmImageMessage?, p1: String?) { + TODO("Not yet implemented") + } + + override fun onFileMessageReceivedFromPeer(p0: RtmFileMessage?, p1: String?) { + TODO("Not yet implemented") + } + + override fun onMediaUploadingProgress(p0: RtmMediaOperationProgress?, p1: Long) { + TODO("Not yet implemented") + } + + override fun onMediaDownloadingProgress(p0: RtmMediaOperationProgress?, p1: Long) { + TODO("Not yet implemented") + } + override fun onTokenExpired() { sendClientEvent("onTokenExpired", hashMapOf()) diff --git a/example/ios/Podfile b/example/ios/Podfile index d077b08..f7d6a5e 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -10,60 +10,29 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - pods_ary.push({:name => podname, :path => podpath}); - else - puts "Invalid plugin specification: #{line}" - end - } - return pods_ary + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" end -target 'Runner' do - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - # Flutter Pods - generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') - if generated_xcode_build_settings.empty? - puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." - end - generated_xcode_build_settings.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join('.symlinks', 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) - end - } +flutter_ios_podfile_setup - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join('.symlinks', 'plugins', p[:name]) - File.symlink(p[:path], symlink) - pod p[:name], :path => File.join(symlink, 'ios') - } +target 'Runner' do + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end post_install do |installer| installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end + flutter_additional_ios_build_settings(target) end end diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 3b28da8..b249522 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,10 +9,6 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; @@ -29,8 +25,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -41,7 +35,6 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 3D8E8C95FD76FD7E17A35480 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 4973C34CC84918130B5084E3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -49,7 +42,6 @@ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -65,8 +57,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, F7591FF456923F6A63463D69 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -96,9 +86,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -234,7 +222,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 8CC0EBE5DBADE93D08C126A4 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -279,11 +267,11 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + "${PODS_ROOT}/AgoraRtm_iOS/AgoraRtmKit.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AgoraRtmKit.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -327,7 +315,6 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -399,7 +386,6 @@ }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -453,7 +439,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a1..919434a 100644 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index 949b678..0000000 --- a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - BuildSystemType - Original - - diff --git a/ios/agora_rtm.podspec b/ios/agora_rtm.podspec index 9e8143f..3ffe816 100644 --- a/ios/agora_rtm.podspec +++ b/ios/agora_rtm.podspec @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.dependency 'Flutter' s.static_framework = true - s.dependency 'AgoraRtm_iOS', '1.2.2' + s.dependency 'AgoraRtm_iOS', '1.4.8' s.ios.deployment_target = '8.0' end