feat: 简化登录模型,移除 nickname/avatar/expiresAt
- XuqmSDK.login() 只保留 userId + userSig - 移除 UserSigRefresher 续签逻辑 - XuqmLoginSession 移除 nickname/avatar/expiresAt - ImSDK.login() 同步简化 - AuthRepository 适配新登录方式,移除过期检查与定时刷新 - README 示例同步更新
这个提交包含在:
父节点
595a91ae3d
当前提交
553427d44e
@ -68,11 +68,10 @@ val userSig = api.getUserSig(userId)
|
||||
XuqmSDK.login(
|
||||
userId = userId,
|
||||
userSig = userSig,
|
||||
nickname = profile.nickname,
|
||||
avatar = profile.avatar,
|
||||
)
|
||||
|
||||
// 如果工程里集成了 sdk-im,SDK 会自动完成 IM 登录
|
||||
// 如果工程里集成了 sdk-im / sdk-push / sdk-update,
|
||||
// SDK 会自动完成对应模块的登录与初始化
|
||||
```
|
||||
|
||||
### 3. 切换联调环境
|
||||
|
||||
@ -30,9 +30,6 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
class AuthRepository(context: Context) {
|
||||
|
||||
private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
private var refreshJob: Job? = null
|
||||
private val refreshing = AtomicBoolean(false)
|
||||
|
||||
private val prefs = EncryptedSharedPreferences.create(
|
||||
"xuqm_demo_auth",
|
||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
||||
@ -52,21 +49,17 @@ class AuthRepository(context: Context) {
|
||||
fun getCurrentNickname(): String? = prefs.getString("nickname", null)
|
||||
fun getCurrentAvatar(): String? = prefs.getString("avatar", null)
|
||||
fun getCurrentUserSig(): String? = prefs.getString("user_sig", null)
|
||||
fun getCurrentUserSigExpiresAt(): Long = prefs.getLong("user_sig_expires_at", 0L)
|
||||
fun isLoggedIn(): Boolean = hasUsableSession()
|
||||
|
||||
private fun hasUsableSession(): Boolean {
|
||||
val now = System.currentTimeMillis()
|
||||
val demoToken = getDemoToken().orEmpty()
|
||||
val userId = getCurrentUserId().orEmpty()
|
||||
val userSig = getCurrentUserSig().orEmpty()
|
||||
val demoTokenExpiresAt = prefs.getLong("demo_token_expires_at", 0L)
|
||||
val userSigExpiresAt = getCurrentUserSigExpiresAt()
|
||||
return demoToken.isNotBlank() &&
|
||||
userId.isNotBlank() &&
|
||||
userSig.isNotBlank() &&
|
||||
demoTokenExpiresAt > now &&
|
||||
userSigExpiresAt > now
|
||||
demoTokenExpiresAt > System.currentTimeMillis()
|
||||
}
|
||||
|
||||
private fun saveSession(result: AuthResult) {
|
||||
@ -78,27 +71,7 @@ class AuthRepository(context: Context) {
|
||||
.putString("nickname", profile.nickname)
|
||||
.putString("avatar", profile.avatar)
|
||||
.putString("user_sig", result.userSig)
|
||||
.putLong("user_sig_expires_at", result.imTokenExpiresAt ?: 0L)
|
||||
.apply()
|
||||
scheduleImTokenRefresh(result.imTokenExpiresAt)
|
||||
}
|
||||
|
||||
private fun saveImCredential(result: ImRefreshResult) {
|
||||
prefs.edit()
|
||||
.putString("user_sig", result.userSig)
|
||||
.putLong("user_sig_expires_at", result.imTokenExpiresAt ?: 0L)
|
||||
.apply()
|
||||
}
|
||||
|
||||
private fun scheduleImTokenRefresh(expiresAt: Long?) {
|
||||
refreshJob?.cancel()
|
||||
val tokenExpiresAt = expiresAt ?: 0L
|
||||
if (tokenExpiresAt <= 0L) return
|
||||
val delayMs = (tokenExpiresAt - System.currentTimeMillis() - REFRESH_GRACE_MS).coerceAtLeast(0L)
|
||||
refreshJob = appScope.launch {
|
||||
delay(delayMs)
|
||||
refreshImToken()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun login(userId: String, password: String): Result<UserData> =
|
||||
@ -113,8 +86,6 @@ class AuthRepository(context: Context) {
|
||||
XuqmSDK.login(
|
||||
userId = data.profile.userId,
|
||||
userSig = userSig,
|
||||
nickname = data.profile.nickname,
|
||||
avatar = data.profile.avatar,
|
||||
)
|
||||
UserData(data.profile.userId, data.profile.nickname, data.profile.avatar, data.profile.gender)
|
||||
}
|
||||
@ -133,8 +104,6 @@ class AuthRepository(context: Context) {
|
||||
XuqmSDK.login(
|
||||
userId = data.profile.userId,
|
||||
userSig = userSig,
|
||||
nickname = data.profile.nickname,
|
||||
avatar = data.profile.avatar,
|
||||
)
|
||||
UserData(data.profile.userId, data.profile.nickname, data.profile.avatar, data.profile.gender)
|
||||
}
|
||||
@ -177,86 +146,22 @@ class AuthRepository(context: Context) {
|
||||
val userSig = getCurrentUserSig()
|
||||
val demoToken = getDemoToken()
|
||||
if (userId.isNullOrBlank() || userSig.isNullOrBlank() || demoToken.isNullOrBlank()) {
|
||||
clearSession()
|
||||
logout()
|
||||
throw IllegalStateException("No cached session")
|
||||
}
|
||||
val refreshed = if (shouldRefreshImToken()) {
|
||||
refreshImTokenInternal()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if (shouldRefreshImToken() && refreshed == null) {
|
||||
clearSession()
|
||||
throw IllegalStateException("Cached session expired")
|
||||
}
|
||||
XuqmSDK.login(
|
||||
userId = userId,
|
||||
userSig = refreshed?.userSig ?: userSig,
|
||||
nickname = getCurrentNickname(),
|
||||
avatar = getCurrentAvatar(),
|
||||
userSig = userSig,
|
||||
)
|
||||
if (refreshed != null) {
|
||||
saveImCredential(refreshed)
|
||||
scheduleImTokenRefresh(refreshed.imTokenExpiresAt)
|
||||
} else {
|
||||
scheduleImTokenRefresh(getCurrentUserSigExpiresAt().takeIf { it > 0L })
|
||||
}
|
||||
Unit
|
||||
}
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
refreshJob?.cancel()
|
||||
refreshJob = null
|
||||
XuqmSDK.logout()
|
||||
prefs.edit().clear().apply()
|
||||
}
|
||||
|
||||
private suspend fun refreshImToken() {
|
||||
if (!refreshing.compareAndSet(false, true)) return
|
||||
try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val refreshed = refreshImTokenInternal() ?: run {
|
||||
clearSession()
|
||||
return@withContext
|
||||
}
|
||||
saveImCredential(refreshed)
|
||||
XuqmSDK.login(
|
||||
userId = getCurrentUserId() ?: return@withContext,
|
||||
userSig = refreshed.userSig,
|
||||
nickname = getCurrentNickname(),
|
||||
avatar = getCurrentAvatar(),
|
||||
)
|
||||
scheduleImTokenRefresh(refreshed.imTokenExpiresAt)
|
||||
}
|
||||
} finally {
|
||||
refreshing.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearSession() {
|
||||
refreshJob?.cancel()
|
||||
refreshJob = null
|
||||
XuqmSDK.logout()
|
||||
prefs.edit().clear().apply()
|
||||
}
|
||||
|
||||
private suspend fun refreshImTokenInternal(): ImRefreshResult? {
|
||||
val appId = DEMO_APP_ID
|
||||
return runCatching {
|
||||
val response = api.refreshImToken(appId)
|
||||
requireNotNull(response.data) { response.message ?: "Refresh IM token failed" }
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
private fun shouldRefreshImToken(): Boolean {
|
||||
val expiresAt = getCurrentUserSigExpiresAt()
|
||||
return expiresAt <= 0L || expiresAt - System.currentTimeMillis() <= REFRESH_GRACE_MS
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val REFRESH_GRACE_MS = 5 * 60 * 1000L
|
||||
}
|
||||
|
||||
private fun <T> Result<T>.mapFailureMessage(transform: (Throwable) -> String): Result<T> =
|
||||
fold(
|
||||
onSuccess = { Result.success(it) },
|
||||
|
||||
@ -4,7 +4,4 @@ data class XuqmLoginSession(
|
||||
val appKey: String,
|
||||
val userId: String,
|
||||
val userSig: String,
|
||||
val nickname: String? = null,
|
||||
val avatar: String? = null,
|
||||
val expiresAt: Long? = null,
|
||||
)
|
||||
|
||||
@ -2,7 +2,6 @@ package com.xuqm.sdk
|
||||
|
||||
import android.content.Context
|
||||
import com.xuqm.sdk.auth.TokenStore
|
||||
import com.xuqm.sdk.auth.UserSigRefresher
|
||||
import com.xuqm.sdk.core.LogLevel
|
||||
import com.xuqm.sdk.core.ServiceEndpointRegistry
|
||||
import com.xuqm.sdk.core.ServiceEndpoints
|
||||
@ -26,8 +25,6 @@ object XuqmSDK {
|
||||
@Volatile
|
||||
private var loginSession: XuqmLoginSession? = null
|
||||
|
||||
private val userSigRefresher = UserSigRefresher()
|
||||
|
||||
fun initialize(
|
||||
context: Context,
|
||||
appKey: String,
|
||||
@ -63,31 +60,18 @@ object XuqmSDK {
|
||||
val currentLoginSession: XuqmLoginSession?
|
||||
get() = loginSession
|
||||
|
||||
fun setUserSigRefreshListener(listener: UserSigRefresher.UserSigRefreshListener?) {
|
||||
userSigRefresher.setRefreshListener(listener)
|
||||
}
|
||||
|
||||
suspend fun login(
|
||||
userId: String,
|
||||
userSig: String,
|
||||
nickname: String? = null,
|
||||
avatar: String? = null,
|
||||
userSigExpiresAt: Long? = null,
|
||||
): XuqmLoginSession = withContext(Dispatchers.IO) {
|
||||
requireInit()
|
||||
val session = XuqmLoginSession(
|
||||
appKey = appKey,
|
||||
userId = userId,
|
||||
userSig = userSig,
|
||||
nickname = nickname,
|
||||
avatar = avatar,
|
||||
expiresAt = userSigExpiresAt,
|
||||
)
|
||||
loginSession = session
|
||||
tokenStore.saveToken(userSig)
|
||||
userSigExpiresAt?.let {
|
||||
userSigRefresher.start(it)
|
||||
}
|
||||
notifyOptionalModules("onSdkLogin", session)
|
||||
session
|
||||
}
|
||||
@ -96,7 +80,6 @@ object XuqmSDK {
|
||||
val session = loginSession
|
||||
loginSession = null
|
||||
tokenStore.clear()
|
||||
userSigRefresher.stop()
|
||||
if (session != null) {
|
||||
notifyOptionalModulesSync("onSdkLogout")
|
||||
}
|
||||
|
||||
@ -85,28 +85,12 @@ object ImSDK {
|
||||
XuqmSDK.currentLoginSession?.let { onSdkLogin(it) }
|
||||
}
|
||||
|
||||
suspend fun login(
|
||||
userId: String,
|
||||
userSig: String,
|
||||
nickname: String? = null,
|
||||
avatar: String? = null,
|
||||
) = withContext(Dispatchers.IO) {
|
||||
suspend fun login(userId: String, userSig: String) = withContext(Dispatchers.IO) {
|
||||
XuqmSDK.requireInit()
|
||||
currentUserId = userId
|
||||
connectWithToken(userSig)
|
||||
}
|
||||
|
||||
suspend fun loginWithUserSig(userId: String, userSig: String) =
|
||||
withContext(Dispatchers.IO) {
|
||||
XuqmSDK.requireInit()
|
||||
currentUserId = userId
|
||||
connectWithToken(userSig)
|
||||
}
|
||||
|
||||
@Deprecated("Use loginWithUserSig(userId, userSig) instead.")
|
||||
suspend fun loginWithToken(userId: String, token: String) =
|
||||
loginWithUserSig(userId, token)
|
||||
|
||||
fun sendMessage(
|
||||
toId: String,
|
||||
chatType: String,
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户