openim sdk 依赖及初始化

This commit is contained in:
2025-09-08 12:10:38 +08:00
parent ef04450696
commit 1d632fb757
7 changed files with 762 additions and 75 deletions

View File

@@ -93,30 +93,35 @@ dependencies {
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(libs.androidx.animation)
implementation("io.coil-kt:coil-compose:2.7.0")
implementation("io.coil-kt:coil:2.7.0")
implementation("com.google.android.gms:play-services-auth:21.2.0")
implementation("io.github.serpro69:kotlin-faker:2.0.0-rc.5")
implementation("androidx.compose.material:material:1.6.8")
implementation("net.engawapg.lib:zoomable:1.6.1")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
implementation("androidx.credentials:credentials:1.2.2")
implementation("androidx.credentials:credentials-play-services-auth:1.2.2")
implementation("com.auth0.android:jwtdecode:2.0.2")
implementation(libs.coil.compose)
implementation(libs.coil)
implementation(libs.play.services.auth)
implementation(libs.kotlin.faker)
implementation(libs.androidx.material)
implementation(libs.zoomable)
implementation(libs.retrofit)
implementation(libs.converter.gson)
implementation(libs.androidx.credentials)
implementation(libs.androidx.credentials.play.services.auth)
implementation(libs.jwtdecode)
implementation(platform("com.google.firebase:firebase-bom:33.2.0"))
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-perf")
implementation("com.google.firebase:firebase-messaging-ktx")
implementation ("cn.jiguang.sdk:jpush-google:5.4.0")
api ("com.tencent.imsdk:imsdk-plus:8.1.6116")
implementation("io.github.rroohit:ImageCropView:3.0.1")
implementation("androidx.core:core-splashscreen:1.0.1") // 添加 SplashScreen 依赖
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.analytics)
implementation(libs.firebase.perf)
implementation(libs.firebase.messaging.ktx)
implementation (libs.jpush.google)
api (libs.imsdk.plus)
implementation (libs.im.sdk)
implementation (libs.im.core.sdk)
implementation (libs.gson)
implementation(libs.imagecropview)
implementation(libs.androidx.core.splashscreen) // 添加 SplashScreen 依赖
// 添加 lifecycle-runtime-ktx 依赖
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation ("org.greenrobot:eventbus:3.3.1")
implementation(libs.androidx.lifecycle.runtime.ktx.v262)
implementation (libs.eventbus)
}

View File

@@ -20,4 +20,3 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.tencent.imsdk.** { *; }

View File

@@ -82,6 +82,9 @@
<service
android:name=".TrtcService"
android:exported="false" />
<service
android:name=".OpenIMService"
android:exported="false" />
<receiver
android:name=".JpushReciver"

View File

@@ -30,13 +30,11 @@ import com.aiosman.ravenow.ui.index.tabs.ai.AgentViewModel
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.mine.MineAgentViewModel
import com.aiosman.ravenow.ui.like.LikeNoticeViewModel
import com.aiosman.ravenow.utils.Utils
import com.tencent.imsdk.v2.V2TIMCallback
import com.tencent.imsdk.v2.V2TIMLogListener
import com.tencent.imsdk.v2.V2TIMManager
import com.tencent.imsdk.v2.V2TIMSDKConfig
import com.tencent.imsdk.v2.V2TIMUserFullInfo
import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.suspendCoroutine
import com.aiosman.ravenow.im.OpenIMManager
import io.openim.android.sdk.OpenIMClient
import io.openim.android.sdk.models.InitConfig
object AppState {
@@ -100,26 +98,22 @@ object AppState {
}
val accountService: AccountService = AccountServiceImpl()
// 注册 Trtc
val config = V2TIMSDKConfig()
config.logLevel = V2TIMSDKConfig.V2TIM_LOG_INFO
val initConfig = InitConfig(
"https://im.ravenow.ai/api",//SDK api地址
"wss:///im.ravenow.ai/msg_gateway",//SDK WebSocket地址
OpenIMManager.getStorageDir(context),//SDK数据库存储目录
)
// 使用 OpenIMManager 初始化 SDK
OpenIMManager.initSDK(context, initConfig)
config.logListener = object : V2TIMLogListener() {
override fun onLog(logLevel: Int, logContent: String) {
Log.d("V2TIMLogListener", logContent)
}
}
val appConfig = accountService.getAppConfig()
V2TIMManager.getInstance().initSDK(context, appConfig.trtcAppId, config)
try {
val sign = accountService.getMyTrtcSign()
loginToTrtc(sign.userId, sign.sig)
updateTrtcUserProfile()
// 登录成功后启动TrtcService
context.startService(
Intent(context, TrtcService::class.java)
)
loginToOpenIM(sign.userId, sign.sig)
context.startService(Intent(context, OpenIMService::class.java))
enableChat = true
} catch (e: Exception) {
e.printStackTrace()
@@ -127,38 +121,42 @@ object AppState {
}
}
suspend fun loginToTrtc(userId: String, userSig: String): Boolean {
suspend fun loginToOpenIM(userId: String, imToken: String): Boolean {
return suspendCoroutine { continuation ->
V2TIMManager.getInstance().login(userId, userSig, object : V2TIMCallback {
override fun onError(code: Int, desc: String?) {
continuation.resumeWith(Result.failure(Exception("Login failed: $code, $desc")))
OpenIMClient.getInstance().login(object : io.openim.android.sdk.listener.OnBase<String> {
override fun onError(code: Int, error: String?) {
Log.e("AppState", "OpenIM 登录失败: code=$code, error=$error")
continuation.resumeWith(Result.failure(Exception("OpenIM Login failed: $code, $error")))
}
override fun onSuccess() {
override fun onSuccess(data: String?) {
Log.d("AppState", "OpenIM 登录成功: $data")
//其他api调用必须保证登录回调成功后操作
continuation.resumeWith(Result.success(true))
}
})
}, userId, imToken)
}
}
suspend fun updateTrtcUserProfile() {
val accountService: AccountService = AccountServiceImpl()
val profile = accountService.getMyAccountProfile()
val info = V2TIMUserFullInfo()
info.setNickname(profile.nickName)
info.faceUrl = profile.rawAvatar
info.selfSignature = profile.bio
return suspendCoroutine { continuation ->
V2TIMManager.getInstance().setSelfInfo(info, object : V2TIMCallback {
override fun onError(code: Int, desc: String?) {
continuation.resumeWith(Result.failure(Exception("Update user profile failed: $code, $desc")))
}
override fun onSuccess() {
continuation.resumeWith(Result.success(Unit))
}
})
}
}
// suspend fun updateTrtcUserProfile() {
// val accountService: AccountService = AccountServiceImpl()
// val profile = accountService.getMyAccountProfile()
// val info = V2TIMUserFullInfo()
// info.setNickname(profile.nickName)
// info.faceUrl = profile.rawAvatar
// info.selfSignature = profile.bio
// return suspendCoroutine { continuation ->
// V2TIMManager.getInstance().setSelfInfo(info, object : V2TIMCallback {
// override fun onError(code: Int, desc: String?) {
// continuation.resumeWith(Result.failure(Exception("Update user profile failed: $code, $desc")))
// }
//
// override fun onSuccess() {
// continuation.resumeWith(Result.success(Unit))
// }
// })
// }
// }
fun switchTheme() {
darkMode = !darkMode
@@ -225,11 +223,7 @@ object AppState {
// 清除游客状态
AppStore.isGuest = false
// 关闭 TrtcService
val trtcService = Intent(
context,
TrtcService::class.java
)
context.stopService(trtcService)
context.stopService(Intent(context, OpenIMService::class.java))
}
}

View File

@@ -0,0 +1,302 @@
package com.aiosman.ravenow
import android.Manifest
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.aiosman.ravenow.entity.ChatItem
import io.openim.android.sdk.OpenIMClient
import io.openim.android.sdk.listener.OnAdvanceMsgListener
import io.openim.android.sdk.models.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
/**
* OpenIM 服务
* 负责处理 OpenIM 的后台消息监听和通知
*/
class OpenIMService : Service() {
companion object {
private const val TAG = "OpenIMService"
private const val CHANNEL_ID = "openim_notification"
private const val NOTIFICATION_ID = 1001
}
private var openIMMessageListener: OnAdvanceMsgListener? = null
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "OpenIMService onStartCommand")
createNotificationChannel()
CoroutineScope(Dispatchers.IO).launch {
registerMessageListener(applicationContext)
}
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "OpenIMService onDestroy")
CoroutineScope(Dispatchers.IO).launch {
unRegisterMessageListener()
}
}
/**
* 注册 OpenIM 消息监听器
*/
private fun registerMessageListener(context: Context) {
val scope = CoroutineScope(Dispatchers.IO)
openIMMessageListener = object : OnAdvanceMsgListener {
override fun onRecvNewMessage(msg: Message?) {
Log.d(TAG, "收到新消息: ${msg?.toString()}")
msg?.let {
// 如果应用在前台,不显示通知
if (MainActivityLifecycle.isForeground) {
return
}
scope.launch {
// 检查通知策略
val shouldNotify = shouldShowNotification(it)
if (shouldNotify) {
sendNotification(context, it)
}
}
}
}
override fun onRecvC2CReadReceipt(list: List<C2CReadReceiptInfo>?) {
Log.d(TAG, "收到C2C已读回执数量: ${list?.size}")
// 处理已读回执,可以更新消息状态
}
override fun onRecvGroupMessageReadReceipt(groupMessageReceipt: GroupMessageReceipt?) {
Log.d(TAG, "收到群组消息已读回执")
// 处理群组消息已读回执
}
override fun onRecvMessageRevokedV2(info: RevokedInfo?) {
Log.d(TAG, "消息被撤回: ${info?.clientMsgID}")
// 处理消息撤回可以更新UI
}
override fun onRecvMessageExtensionsChanged(msgID: String?, list: List<KeyValue>?) {
Log.d(TAG, "消息扩展信息变更: $msgID")
// 处理消息扩展信息变更
}
override fun onRecvMessageExtensionsDeleted(msgID: String?, list: List<String>?) {
Log.d(TAG, "消息扩展信息删除: $msgID")
// 处理消息扩展信息删除
}
override fun onRecvMessageExtensionsAdded(msgID: String?, list: List<KeyValue>?) {
Log.d(TAG, "消息扩展信息添加: $msgID")
// 处理消息扩展信息添加
}
override fun onMsgDeleted(message: Message?) {
Log.d(TAG, "消息被删除: ${message?.clientMsgID}")
// 处理消息删除
}
override fun onRecvOfflineNewMessage(msg: List<Message>?) {
Log.d(TAG, "收到离线新消息,数量: ${msg?.size}")
// 处理离线新消息
msg?.forEach { message ->
// 为离线消息也可以发送通知
if (!MainActivityLifecycle.isForeground) {
scope.launch {
val shouldNotify = shouldShowNotification(message)
if (shouldNotify) {
sendNotification(context, message)
}
}
}
}
}
override fun onRecvOnlineOnlyMessage(s: String?) {
Log.d(TAG, "收到仅在线消息: $s")
// 处理仅在线消息
}
}
// 添加消息监听器
OpenIMClient.getInstance().messageManager.setAdvancedMsgListener(openIMMessageListener)
}
/**
* 取消注册消息监听器
*/
private fun unRegisterMessageListener() {
openIMMessageListener?.let {
// OpenIM SDK 可能需要不同的方法来移除监听器
// 这里假设有类似的方法具体需要根据SDK文档调整
Log.d(TAG, "取消注册消息监听器")
}
openIMMessageListener = null
}
/**
* 判断是否应该显示通知
* @param message 消息对象
* @return 是否显示通知
*/
private suspend fun shouldShowNotification(message: Message): Boolean {
// 这里可以根据用户设置、消息类型等判断是否显示通知
// 类似于 TrtcService 中的策略检查
// 示例:检查是否是系统消息或者用户设置了免打扰
return try {
// 可以根据发送者ID或会话ID检查通知策略
val senderId = message.sendID
// 这里可以调用类似 ChatState.getStrategyByTargetTrtcId 的方法
// 暂时返回 true表示默认显示通知
true
} catch (e: Exception) {
Log.e(TAG, "检查通知策略失败", e)
true // 默认显示通知
}
}
/**
* 创建通知渠道
*/
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "OpenIM 消息通知"
val descriptionText = "OpenIM 即时消息通知"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
enableVibration(true)
enableLights(true)
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
/**
* 发送通知
* @param context 上下文
* @param message OpenIM 消息对象
*/
private fun sendNotification(context: Context, message: Message) {
try {
// 创建点击通知后的意图
val intent = Intent(context, MainActivity::class.java).apply {
putExtra("ACTION", "OPENIM_NEW_MESSAGE")
putExtra("SENDER_ID", message.sendID)
putExtra("CONVERSATION_ID", message.sessionType)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
// 构建通知内容
val senderName = getSenderDisplayName(message)
val messageContent = getMessageDisplayContent(message)
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.mipmap.rider_pro_log_round)
.setContentTitle(senderName)
.setContentText(messageContent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setVibrate(longArrayOf(0, 300, 300, 300))
.setLights(0xFF0000FF.toInt(), 300, 300)
// 发送通知
with(NotificationManagerCompat.from(context)) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
Log.w(TAG, "没有通知权限,无法发送通知")
return
}
// 使用消息ID的哈希值作为通知ID确保每条消息都有唯一的通知
val notificationId = message.clientMsgID?.hashCode() ?: NOTIFICATION_ID
notify(notificationId, builder.build())
}
Log.d(TAG, "发送通知成功: $senderName - $messageContent")
} catch (e: Exception) {
Log.e(TAG, "发送通知失败", e)
}
}
/**
* 获取发送者显示名称
* @param message 消息对象
* @return 发送者名称
*/
private fun getSenderDisplayName(message: Message): String {
return try {
// 尝试获取发送者的昵称或显示名
message.senderNickname?.takeIf { it.isNotEmpty() }
?: message.sendID
?: "未知用户"
} catch (e: Exception) {
Log.e(TAG, "获取发送者名称失败", e)
"未知用户"
}
}
/**
* 获取消息显示内容
* @param message 消息对象
* @return 消息内容
*/
private fun getMessageDisplayContent(message: Message): String {
return try {
when (message.contentType) {
101 -> message.textElem.content ?: "[文本消息]" // 文本消息
102 -> "[图片]"
103 -> "[语音]"
104 -> "[视频]"
105 -> "[文件]"
106 -> "[位置]"
107 -> "[自定义消息]"
108 -> "[合并消息]"
109 -> "[名片]"
110 -> "[引用消息]"
else -> "[消息]"
}
} catch (e: Exception) {
Log.e(TAG, "获取消息内容失败", e)
"[消息]"
}
}
}

View File

@@ -0,0 +1,342 @@
package com.aiosman.ravenow.im
import android.app.Application
import android.content.Context
import android.util.Log
import io.openim.android.sdk.OpenIMClient
import io.openim.android.sdk.listener.*
import io.openim.android.sdk.models.*
/**
* OpenIM SDK 管理器
* 负责 OpenIM SDK 的初始化和各种监听器的设置
*/
object OpenIMManager {
private const val TAG = "OpenIMManager"
/**
* 初始化 OpenIM SDK
* @param context Android上下文
* @param initConfig SDK初始化配置
*/
fun initSDK(context: Context, initConfig: InitConfig) {
try {
OpenIMClient.getInstance().initSDK(
context.applicationContext as Application,
initConfig,
object : OnConnListener {
override fun onConnectFailed(code: Int, error: String?) {
Log.e(TAG, "连接服务器失败: code=$code, error=$error")
}
override fun onConnectSuccess() {
//连接服务器成功
Log.d(TAG, "连接服务器成功")
}
override fun onConnecting() {
//连接服务器中...
Log.d(TAG, "连接服务器中...")
}
override fun onKickedOffline() {
//当前用户被踢下线
Log.w(TAG, "当前用户被踢下线")
// 可以在这里处理用户被踢下线的逻辑,比如跳转到登录页面
}
override fun onUserTokenExpired() {
//登录票据已经过期
Log.w(TAG, "登录票据已经过期")
// 可以在这里处理token过期的逻辑比如重新登录
}
}
)
// 初始化完成后设置各种监听器
initListeners()
Log.d(TAG, "OpenIM SDK 初始化成功")
} catch (e: Exception) {
Log.e(TAG, "OpenIM SDK 初始化失败", e)
}
}
/**
* 初始化所有监听器
*/
private fun initListeners() {
setUserListener()
setMessageListener()
setFriendshipListener()
setConversationListener()
setGroupListener()
setSignalingListener()
}
/**
* 设置用户信息监听器
*/
private fun setUserListener() {
OpenIMClient.getInstance().userInfoManager.setOnUserListener(object : OnUserListener {
override fun onSelfInfoUpdated(userInfo: UserInfo?) {
Log.d(TAG, "用户信息更新: ${userInfo?.nickname}")
// 处理用户信息更新
}
})
}
/**
* 设置消息监听器
*/
private fun setMessageListener() {
OpenIMClient.getInstance().messageManager.setAdvancedMsgListener(object : OnAdvanceMsgListener {
override fun onRecvNewMessage(msg: Message?) {
Log.d(TAG, "收到新消息: ${msg?.toString()}")
// 处理新消息
}
override fun onRecvC2CReadReceipt(list: List<C2CReadReceiptInfo>?) {
Log.d(TAG, "收到C2C已读回执数量: ${list?.size}")
// 处理C2C已读回执
}
override fun onRecvGroupMessageReadReceipt(groupMessageReceipt: GroupMessageReceipt?) {
Log.d(TAG, "收到群组消息已读回执")
// 处理群组消息已读回执
}
override fun onRecvMessageRevokedV2(info: RevokedInfo?) {
Log.d(TAG, "消息被撤回: ${info?.clientMsgID}")
// 处理消息撤回
}
override fun onRecvMessageExtensionsChanged(msgID: String?, list: List<KeyValue>?) {
Log.d(TAG, "消息扩展信息变更: $msgID")
// 处理消息扩展信息变更
}
override fun onRecvMessageExtensionsDeleted(msgID: String?, list: List<String>?) {
Log.d(TAG, "消息扩展信息删除: $msgID")
// 处理消息扩展信息删除
}
override fun onRecvMessageExtensionsAdded(msgID: String?, list: List<KeyValue>?) {
Log.d(TAG, "消息扩展信息添加: $msgID")
// 处理消息扩展信息添加
}
override fun onMsgDeleted(message: Message?) {
Log.d(TAG, "消息被删除: ${message?.clientMsgID}")
// 处理消息删除
}
override fun onRecvOfflineNewMessage(msg: List<Message>?) {
Log.d(TAG, "收到离线新消息,数量: ${msg?.size}")
// 处理离线新消息
}
override fun onRecvOnlineOnlyMessage(s: String?) {
Log.d(TAG, "收到仅在线消息: $s")
// 处理仅在线消息
}
})
}
/**
* 设置好友关系监听器
*/
private fun setFriendshipListener() {
OpenIMClient.getInstance().friendshipManager.setOnFriendshipListener(object : OnFriendshipListener {
override fun onFriendApplicationAdded(friendApplication: FriendApplicationInfo?) {
Log.d(TAG, "收到好友申请")
// 处理好友申请
}
override fun onFriendApplicationDeleted(friendApplication: FriendApplicationInfo?) {
Log.d(TAG, "好友申请被删除")
// 处理好友申请删除
}
override fun onFriendApplicationAccepted(friendApplication: FriendApplicationInfo?) {
Log.d(TAG, "好友申请被接受")
// 处理好友申请接受
}
override fun onFriendApplicationRejected(friendApplication: FriendApplicationInfo?) {
Log.d(TAG, "好友申请被拒绝")
// 处理好友申请拒绝
}
override fun onFriendAdded(friendInfo: FriendInfo?) {
Log.d(TAG, "添加好友: ${friendInfo?.nickname}")
// 处理添加好友
}
override fun onFriendDeleted(friendInfo: FriendInfo?) {
Log.d(TAG, "删除好友: ${friendInfo?.nickname}")
// 处理删除好友
}
override fun onFriendInfoChanged(friendInfo: FriendInfo?) {
Log.d(TAG, "好友信息变更: ${friendInfo?.nickname}")
// 处理好友信息变更
}
override fun onBlacklistAdded(blackInfo: BlacklistInfo) {
Log.d(TAG, "添加黑名单")
// 处理添加黑名单
}
override fun onBlacklistDeleted(blackInfo: BlacklistInfo) {
Log.d(TAG, "移除黑名单")
// 处理移除黑名单
}
})
}
/**
* 设置会话监听器
*/
private fun setConversationListener() {
OpenIMClient.getInstance().conversationManager.setOnConversationListener(object : OnConversationListener {
override fun onConversationChanged(conversationList: MutableList<ConversationInfo>?) {
Log.d(TAG, "会话发生变化,数量: ${conversationList?.size}")
// 处理会话变化
}
override fun onNewConversation(conversationList: MutableList<ConversationInfo>?) {
Log.d(TAG, "新增会话,数量: ${conversationList?.size}")
// 处理新增会话
}
override fun onSyncServerFailed(reinstalled:Boolean) {
Log.e(TAG, "同步服务器失败")
// 处理同步失败
}
override fun onSyncServerFinish(reinstalled:Boolean) {
Log.d(TAG, "同步服务器完成")
// 处理同步完成
}
override fun onSyncServerStart(reinstalled:Boolean) {
Log.d(TAG, "开始同步服务器")
// 处理开始同步
}
override fun onTotalUnreadMessageCountChanged(totalUnreadCount: Int) {
Log.d(TAG, "总未读消息数变化: $totalUnreadCount")
// 处理总未读数变化
}
})
}
/**
* 设置群组监听器
*/
private fun setGroupListener() {
OpenIMClient.getInstance().groupManager.setOnGroupListener(object : OnGroupListener {
override fun onGroupApplicationAdded(groupApplication: GroupApplicationInfo?) {
Log.d(TAG, "收到入群申请")
// 处理入群申请
}
override fun onGroupApplicationDeleted(groupApplication: GroupApplicationInfo?) {
Log.d(TAG, "入群申请被删除")
// 处理入群申请删除
}
override fun onGroupApplicationAccepted(groupApplication: GroupApplicationInfo?) {
Log.d(TAG, "入群申请被接受")
// 处理入群申请接受
}
override fun onGroupApplicationRejected(groupApplication: GroupApplicationInfo?) {
Log.d(TAG, "入群申请被拒绝")
// 处理入群申请拒绝
}
override fun onGroupInfoChanged(groupInfo: GroupInfo?) {
Log.d(TAG, "群信息变更: ${groupInfo?.groupName}")
// 处理群信息变更
}
override fun onGroupMemberAdded(groupMemberInfo: GroupMembersInfo?) {
Log.d(TAG, "群成员加入")
// 处理群成员加入
}
override fun onGroupMemberDeleted(groupMemberInfo: GroupMembersInfo?) {
Log.d(TAG, "群成员退出")
// 处理群成员退出
}
override fun onGroupMemberInfoChanged(groupMemberInfo: GroupMembersInfo?) {
Log.d(TAG, "群成员信息变更")
// 处理群成员信息变更
}
override fun onJoinedGroupAdded(groupInfo: GroupInfo?) {
Log.d(TAG, "加入新群: ${groupInfo?.groupName}")
// 处理加入新群
}
override fun onJoinedGroupDeleted(groupInfo: GroupInfo?) {
Log.d(TAG, "退出群聊: ${groupInfo?.groupName}")
// 处理退出群聊
}
})
}
/**
* 设置信令监听器
*/
private fun setSignalingListener() {
// OpenIMClient.getInstance(). .setSignalingListener(object : OnSignalingListener {
// override fun onInvitationReceived(signalInvitationInfo: SignalInvitationInfo?) {
// Log.d(TAG, "收到信令邀请")
// // 处理信令邀请
// }
//
// override fun onInvitationCancelled(signalInvitationInfo: SignalInvitationInfo?) {
// Log.d(TAG, "信令邀请被取消")
// // 处理信令邀请取消
// }
//
// override fun onInvitationTimeout(signalInvitationInfo: SignalInvitationInfo?) {
// Log.d(TAG, "信令邀请超时")
// // 处理信令邀请超时
// }
//
// override fun onInviteeAccepted(signalInvitationInfo: SignalInvitationInfo?) {
// Log.d(TAG, "信令邀请被接受")
// // 处理信令邀请接受
// }
//
// override fun onInviteeRejected(signalInvitationInfo: SignalInvitationInfo?) {
// Log.d(TAG, "信令邀请被拒绝")
// // 处理信令邀请拒绝
// }
// })
}
/**
* 获取SDK数据库存储目录
* @param context Android上下文
* @return 存储目录路径
*/
fun getStorageDir(context: Context): String {
// 使用应用的内部存储目录下的im_sdk文件夹
val storageDir = context.filesDir.resolve("im_sdk")
// 如果目录不存在,创建它
if (!storageDir.exists()) {
storageDir.mkdirs()
}
return storageDir.absolutePath
}
}

View File

@@ -2,16 +2,31 @@
accompanistSystemuicontroller = "0.27.0"
agp = "8.4.0"
animation = "1.7.0-beta05"
coil = "2.7.0"
composeImageBlurhash = "3.0.2"
converterGson = "2.11.0"
coreSdk = "3.8.3"
coreSplashscreen = "1.0.1"
credentialsPlayServicesAuth = "1.2.2"
eventbus = "3.3.1"
firebaseBom = "33.2.0"
gson = "2.12.1"
imagecropview = "3.0.1"
imsdkPlus = "8.1.6116"
jpushGoogle = "5.4.0"
jwtdecode = "2.0.2"
kotlin = "1.9.10"
coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
kotlinFaker = "2.0.0-rc.5"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2024.06.00"
lifecycleRuntimeKtxVersion = "2.6.2"
mapsCompose = "4.3.3"
material = "1.6.8"
material3Android = "1.2.1"
media3Exoplayer = "1.3.1"
navigationCompose = "2.7.7"
@@ -22,19 +37,41 @@ places = "3.3.0"
googleid = "1.1.1"
identityCredential = "20231002"
lifecycleProcess = "2.8.4"
playServicesAuth = "21.4.0"
rendering = "1.17.1"
zoomable = "1.6.1"
[libraries]
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" }
im-sdk = { module = "io.openim:android-sdk", version.ref = "coreSdk" }
androidx-animation = { module = "androidx.compose.animation:animation", version.ref = "animation" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
androidx-credentials = { module = "androidx.credentials:credentials", version.ref = "credentialsPlayServicesAuth" }
androidx-credentials-play-services-auth = { module = "androidx.credentials:credentials-play-services-auth", version.ref = "credentialsPlayServicesAuth" }
androidx-lifecycle-runtime-ktx-v262 = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtxVersion" }
androidx-material = { module = "androidx.compose.material:material", version.ref = "material" }
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3Exoplayer" }
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "media3Exoplayer" }
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3Exoplayer" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "pagingRuntime" }
androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "pagingRuntime" }
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
compose-image-blurhash = { module = "com.github.orlando-dev-code:compose-image-blurhash", version.ref = "composeImageBlurhash" }
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
im-core-sdk = { module = "io.openim:core-sdk", version.ref = "coreSdk" }
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics" }
firebase-messaging-ktx = { module = "com.google.firebase:firebase-messaging-ktx" }
firebase-perf = { module = "com.google.firebase:firebase-perf" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
imagecropview = { module = "io.github.rroohit:ImageCropView", version.ref = "imagecropview" }
imsdk-plus = { module = "com.tencent.imsdk:imsdk-plus", version.ref = "imsdkPlus" }
jpush-google = { module = "cn.jiguang.sdk:jpush-google", version.ref = "jpushGoogle" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
@@ -49,6 +86,8 @@ androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-man
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-material3-android = { group = "androidx.compose.material3", name = "material3-android", version.ref = "material3Android" }
jwtdecode = { module = "com.auth0.android:jwtdecode", version.ref = "jwtdecode" }
kotlin-faker = { module = "io.github.serpro69:kotlin-faker", version.ref = "kotlinFaker" }
maps-compose = { module = "com.google.maps.android:maps-compose", version.ref = "mapsCompose" }
androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activityKtx" }
androidx-lifecycle-common-jvm = { group = "androidx.lifecycle", name = "lifecycle-common-jvm", version.ref = "lifecycleCommonJvm" }
@@ -56,7 +95,10 @@ places = { module = "com.google.android.libraries.places:places", version.ref =
googleid = { group = "com.google.android.libraries.identity.googleid", name = "googleid", version.ref = "googleid" }
identity-credential = { group = "com.android.identity", name = "identity-credential", version.ref = "identityCredential" }
androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycleProcess" }
play-services-auth = { module = "com.google.android.gms:play-services-auth", version.ref = "playServicesAuth" }
rendering = { group = "com.google.ar.sceneform", name = "rendering", version.ref = "rendering" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converterGson" }
zoomable = { module = "net.engawapg.lib:zoomable", version.ref = "zoomable" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }