diff --git a/gradle.properties b/gradle.properties index 5ab569f..4300a57 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,10 +3,10 @@ android.useAndroidX=true kotlin.code.style=official android.nonTransitiveRClass=true PUBLISH_VERSION=1.0.5 -SDK_CORE_VERSION=1.1.6-SNAPSHOT +SDK_CORE_VERSION=1.1.7-SNAPSHOT SDK_IM_VERSION=1.1.3 -SDK_PUSH_VERSION=1.1.3 +SDK_PUSH_VERSION=1.1.4-SNAPSHOT SDK_UPDATE_VERSION=1.1.8 -SDK_WEBVIEW_VERSION=1.1.9 +SDK_WEBVIEW_VERSION=1.1.10-SNAPSHOT SDK_LICENSE_VERSION=1.1.3 SDK_BUGCOLLECT_VERSION=1.0.11 diff --git a/sdk-core/src/main/java/com/xuqm/sdk/XuqmSDK.kt b/sdk-core/src/main/java/com/xuqm/sdk/XuqmSDK.kt index f5d1b3a..37c1cec 100644 --- a/sdk-core/src/main/java/com/xuqm/sdk/XuqmSDK.kt +++ b/sdk-core/src/main/java/com/xuqm/sdk/XuqmSDK.kt @@ -7,6 +7,9 @@ import com.xuqm.sdk.core.LogLevel import com.xuqm.sdk.core.ServiceEndpointRegistry import com.xuqm.sdk.core.ServiceEndpoints import com.xuqm.sdk.core.SDKConfig +import com.google.gson.Gson +import com.xuqm.sdk.internal.ConfigFile +import com.xuqm.sdk.internal.ConfigFileCrypto import com.xuqm.sdk.internal.ConfigFileReader import com.xuqm.sdk.network.ApiClient import com.xuqm.sdk.network.SdkPlatformConfig @@ -140,7 +143,7 @@ object XuqmSDK { * * 与 [autoInitializeAsync] 的区别: * - 原始字节由调用方传入(主线程只做文件读取,不做 PBKDF2) - * - 解密走 ConfigCache(内存→磁盘),后续启动跳过 PBKDF2 + * - 在 IO 线程直接解密,不使用磁盘缓存,signingKey 始终完整读取 * - 复用 sdkScope,不创建冗余 CoroutineScope * - 初始化完成后自动触发 BugCollect / License 等子 SDK 启动 */ @@ -148,10 +151,12 @@ object XuqmSDK { val ctx = context.applicationContext sdkScope.launch { runCatching { - // 1. 带缓存的解密(PBKDF2 只在首次或文件变更时执行) - val configFile = ConfigFileReader.readWithCache(ctx) - if (configFile == null) { - Log.w(TAG, "autoInitializeFromBytes: failed to read/decrypt config") + // 直接解密传入的字节(在 IO 线程执行 PBKDF2,不阻塞主线程,~100ms 可接受) + val configFile = runCatching { + val json = ConfigFileCrypto.decrypt(String(rawBytes, Charsets.UTF_8)) + Gson().fromJson(json, ConfigFile::class.java) + }.getOrElse { + Log.w(TAG, "autoInitializeFromBytes: failed to decrypt config: ${it.message}") return@launch } @@ -162,6 +167,7 @@ object XuqmSDK { } signingKey = configFile.signingKey + Log.i(TAG, "Config loaded: appKey=${configFile.appKey} signingKey=${if (configFile.signingKey.isNullOrBlank()) "null" else "[set]"}") // 2. 初始化 sdk-core initialize(ctx, configFile.appKey, configFile.serverUrl, logLevel) @@ -447,15 +453,20 @@ object XuqmSDK { } return } + // Set immediately so getUserId() returns correct value before init completes userInfoValue = info - val session = XuqmLoginSession( - appKey = appKey, - userId = info.userId, - userSig = info.userSig ?: loginSession?.userSig ?: "", - ) - loginSession = session - info.userSig?.takeIf { it.isNotBlank() }?.let { tokenStore.saveToken(it) } - notifyOptionalModules("onSdkLogin", session) + // Defer session creation and sub-SDK notification until SDK is fully initialized; + // if already initialized, afterInit runs synchronously + afterInit { + val session = XuqmLoginSession( + appKey = appKey, + userId = info.userId, + userSig = info.userSig ?: loginSession?.userSig ?: "", + ) + loginSession = session + info.userSig?.takeIf { it.isNotBlank() }?.let { tokenStore.saveToken(it) } + notifyOptionalModules("onSdkLogin", session) + } } @Deprecated(