Przeglądaj źródła

feat: 账号异地登录提示

DoggyZhang 1 miesiąc temu
rodzic
commit
08d3854056

+ 9 - 16
app/src/main/java/com/adealink/weparty/module/account/AccountModule.kt

@@ -3,6 +3,7 @@ package com.adealink.weparty.module.account
 import androidx.fragment.app.FragmentManager
 import com.adealink.frame.aab.BaseDynamicModule
 import com.adealink.weparty.R
+import com.adealink.weparty.module.account.data.UserKickReason
 
 object AccountModule : BaseDynamicModule<IAccountService>(IAccountService::class), IAccountService {
 
@@ -27,6 +28,11 @@ object AccountModule : BaseDynamicModule<IAccountService>(IAccountService::class
         getService().logout(toLogin)
     }
 
+    override fun onKickedOffline(reason: UserKickReason) {
+        performDownload()
+        getService().onKickedOffline(reason)
+    }
+
     override fun isLogin(): Boolean {
         return getService().isLogin()
     }
@@ -68,6 +74,9 @@ object AccountModule : BaseDynamicModule<IAccountService>(IAccountService::class
 
             }
 
+            override fun onKickedOffline(reason: UserKickReason) {
+            }
+
             override fun isLogin(): Boolean {
                 return false
             }
@@ -80,14 +89,6 @@ object AccountModule : BaseDynamicModule<IAccountService>(IAccountService::class
 
             }
 
-            override fun deleteAccount() {
-
-            }
-
-            override fun isNewRegister(): Boolean {
-                return false
-            }
-
             override fun refreshToken() {
 
             }
@@ -106,14 +107,6 @@ object AccountModule : BaseDynamicModule<IAccountService>(IAccountService::class
         }
     }
 
-    override fun deleteAccount() {
-        getService().deleteAccount()
-    }
-
-    override fun isNewRegister(): Boolean {
-        return getService().isNewRegister()
-    }
-
     override fun refreshToken() {
         getService().refreshToken()
     }

+ 3 - 7
app/src/main/java/com/adealink/weparty/module/account/IAccountService.kt

@@ -2,6 +2,7 @@ package com.adealink.weparty.module.account
 
 import androidx.fragment.app.FragmentManager
 import com.adealink.weparty.aab.IService
+import com.adealink.weparty.module.account.data.UserKickReason
 
 interface IAccountService : IService<IAccountService> {
     val uid: String
@@ -11,6 +12,8 @@ interface IAccountService : IService<IAccountService> {
 
     fun logout(toLogin: Boolean? = true)
 
+    fun onKickedOffline(reason: UserKickReason)
+
     fun onTokenExpire()
 
     fun isLogin(): Boolean
@@ -19,13 +22,6 @@ interface IAccountService : IService<IAccountService> {
 
     fun unregisterListener(l: ILoginListener)
 
-    fun deleteAccount()
-
-    /**
-     * 是否新注册用户
-     */
-    fun isNewRegister(): Boolean
-
     fun refreshToken()
 
     fun checkRemoteVirtualAppConfig()

+ 4 - 68
app/src/main/java/com/adealink/weparty/module/account/data/LoginData.kt

@@ -1,75 +1,11 @@
 package com.adealink.weparty.module.account.data
 
-import android.os.Parcelable
-import com.google.gson.annotations.SerializedName
-import kotlinx.parcelize.Parcelize
-import java.util.Locale
-
 enum class UserKickReason(val value: Long) {
-    //客户端自定义的
-    REASON_LOCAL_KICK_TOKEN_EXPIRE(-1),//token过期
-
-    //服务端定义的
-}
-
-data class BannerInfoRes(
-    @SerializedName("reason") val reason: String,
-    @SerializedName("expire") val expire: Long,
-)
-
+    //踢出原因
 
-@Parcelize
-data class SmsCountryInfo(
-    @SerializedName("areaCode") val areaCode: String,
-    @SerializedName("countryCode") val countryCode: String,
-    @SerializedName("countryName") var countryName: String,
-    @SerializedName("flag") val flag: String,
-    @SerializedName("supportSms") val supportSms: Boolean,
-    @SerializedName("supportWhatsapp") val supportWhatsapp: Boolean,
-    var localeName: String = ""
-) : Parcelable {
-    fun fill(): SmsCountryInfo {
-        localeName = countryName
-        val locale = Locale("", this.countryCode)
-        val lc = locale.displayCountry
-        if (lc.isNotEmpty()) {
-            localeName = lc
-        }
+    REASON_KICK_ONLINE_BY_MULTIPOINT_LOGIN(1),//多段登录
 
-        if (isChinaRegion(this.countryCode)) {
-            val cLocale = Locale("", "CN")
-            val clc = cLocale.displayCountry
-            if (clc.isNotEmpty()) {
-                localeName = "$clc/$localeName"
-            }
-            countryName = "China/$countryName"
-        }
-        return this
-    }
+    //客户端自定义踢出类型(负数)
+    REASON_LOCAL_KICK_TOKEN_EXPIRE(-1),//token过期
 
-    private fun isChinaRegion(cc: String): Boolean {
-        return "TW" == cc || "MO" == cc || "HK" == cc
-    }
 }
-
-
-data class GetSmsCountryReq(
-    @SerializedName("deviceId") val deviceId: String,
-    @SerializedName("newDeviceId") val newDeviceId: String,
-)
-
-
-enum class GetVerifyCodeReason(val value: Int) {
-    REGISTER(0), //注册
-    RESET_PASSWORD(1),  //设置密码或者重置密码
-    BIND_PHONE(2),  //绑定手机
-    CHANGE_BIND_PHONE(3),//修改绑定手机
-    FORGET_PASSWORD(4), //忘记密码
-    BIND_PHONE_FROM_CERTIFICATION(5);//来自认证中心
-
-    companion object {
-        fun map(value: Int?): GetVerifyCodeReason {
-            return GetVerifyCodeReason.values().firstOrNull { it.value == value } ?: REGISTER
-        }
-    }
-}

+ 5 - 8
module/account/src/main/java/com/adealink/weparty/account/AccountServiceImpl.kt

@@ -7,6 +7,7 @@ import com.adealink.weparty.account.login.manager.loginManager
 import com.adealink.weparty.module.account.Account
 import com.adealink.weparty.module.account.IAccountService
 import com.adealink.weparty.module.account.ILoginListener
+import com.adealink.weparty.module.account.data.UserKickReason
 
 @RegisterService(value = IAccountService::class)
 class AccountServiceImpl : IAccountService {
@@ -29,6 +30,10 @@ class AccountServiceImpl : IAccountService {
         loginManager.logout(toLogin)
     }
 
+    override fun onKickedOffline(reason: UserKickReason) {
+        loginManager.onKickedOffline(reason)
+    }
+
     override fun isLogin(): Boolean {
         return loginManager.isLogin
     }
@@ -41,14 +46,6 @@ class AccountServiceImpl : IAccountService {
         loginManager.removeListener(l)
     }
 
-    override fun deleteAccount() {
-        loginManager.deleteAccount()
-    }
-
-    override fun isNewRegister(): Boolean {
-        return loginManager.isNewRegister()
-    }
-
     override fun refreshToken() {
         loginManager.refreshToken()
     }

+ 14 - 0
module/account/src/main/java/com/adealink/weparty/account/login/LoginActivity.kt

@@ -15,6 +15,7 @@ import com.adealink.weparty.account.login.data.ThirdType
 import com.adealink.weparty.account.login.viewmodel.LoginViewModel
 import com.adealink.weparty.account.viewModel.AccountViewModelFactory
 import com.adealink.weparty.commonui.toast.util.showToast
+import com.adealink.weparty.commonui.widget.CommonDialog
 import com.adealink.weparty.module.account.Account
 import com.adealink.weparty.module.account.AccountModule
 import com.adealink.weparty.module.account.data.UserKickReason
@@ -81,6 +82,19 @@ class LoginActivity : BaseLoginActivity() {
             return
         }
         when (kickOutReason) {
+            UserKickReason.REASON_KICK_ONLINE_BY_MULTIPOINT_LOGIN.value -> {
+                val loginType = getDisplayLoginType(kickOutLoginType)
+                val message = getCompatString(
+                    com.adealink.weparty.account.R.string.account_kick_off,
+                    loginType,
+                    loginType
+                )
+                CommonDialog.Builder()
+                    .message(message)
+                    .setShowDefaultCancel(false)
+                    .build().show(supportFragmentManager)
+            }
+
             UserKickReason.REASON_LOCAL_KICK_TOKEN_EXPIRE.value -> {
                 showToast(getCompatString(com.adealink.weparty.account.R.string.account_token_expire))
             }

+ 2 - 3
module/account/src/main/java/com/adealink/weparty/account/login/manager/ILoginManager.kt

@@ -5,6 +5,7 @@ import com.adealink.frame.frame.IBaseFrame
 import com.adealink.frame.network.data.Res
 import com.adealink.weparty.account.login.data.LoginResult
 import com.adealink.weparty.module.account.ILoginListener
+import com.adealink.weparty.module.account.data.UserKickReason
 
 interface ILoginManager : IBaseFrame<ILoginListener> {
     var uid: String
@@ -19,13 +20,11 @@ interface ILoginManager : IBaseFrame<ILoginListener> {
     suspend fun testLogin(): Rlt<Res<LoginResult>>
 
     fun logout(toLogin: Boolean? = true)
+    fun onKickedOffline(reason: UserKickReason)
     fun onTokenExpire()
     fun notifyLogin()
     fun notifyLogout()
 
-    fun deleteAccount()
-    fun setIsNewRegister(isNew: Boolean)
-    fun isNewRegister(): Boolean
     fun refreshToken()
 
     fun checkRemoteVirtualAppConfig()

+ 6 - 45
module/account/src/main/java/com/adealink/weparty/account/login/manager/LoginManager.kt

@@ -16,18 +16,15 @@ import com.adealink.weparty.account.login.data.GoogleLoginReq
 import com.adealink.weparty.account.login.data.LoginResult
 import com.adealink.weparty.account.login.data.TestLoginReq
 import com.adealink.weparty.account.login.data.ThirdType
-import com.adealink.weparty.account.login.data.UserKickOutNotify
 import com.adealink.weparty.account.login.datasource.remote.LoginHttpService
 import com.adealink.weparty.account.login.phone.data.MobileData
 import com.adealink.weparty.account.login.phone.data.PhoneLoginReq
 import com.adealink.weparty.debug.DebugActivity
 import com.adealink.weparty.module.account.Account
 import com.adealink.weparty.module.account.AccountLocalService
-import com.adealink.weparty.module.account.AccountModule
 import com.adealink.weparty.module.account.ILoginListener
 import com.adealink.weparty.module.account.data.AccountErrorRefreshTokenEmpty
 import com.adealink.weparty.module.account.data.AccountErrorTokenRefreshing
-import com.adealink.weparty.module.account.data.SmsCountryInfo
 import com.adealink.weparty.module.account.data.UserKickReason
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.storage.AppPref
@@ -46,9 +43,6 @@ class LoginManager : BaseFrame<ILoginListener>(), ILoginManager {
     }
     private var isHandlingKickOut = false
     private val handlingRefreshToken = AtomicBoolean(false)
-    private var allSmsCountryList = mutableListOf<SmsCountryInfo>()
-
-    private var isNewRegister = false
 
     private var inviteUidCode: String? = null //邀请UID码
     private var inviteRoomIdCode: String? = null //邀请房间码
@@ -76,32 +70,6 @@ class LoginManager : BaseFrame<ILoginListener>(), ILoginManager {
         token = AppPref.token
     }
 
-    private fun handleKickOut(notify: UserKickOutNotify) {
-        launch(Dispatcher.UI) {
-            if (notify.kickUid == AccountModule.uid) {
-                if (isHandlingKickOut) {
-                    return@launch
-                }
-                val kickOutLoginType = AccountLocalService.loginType
-                isHandlingKickOut = true
-                logout(false)
-                if (isCurrentLoginActivity()) {
-                    isHandlingKickOut = false
-                    return@launch
-                }
-                isHandlingKickOut = false
-
-                if (isRunLogin()) return@launch
-                Router.build(AppUtil.appContext, Account.Login.PATH)
-                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
-                    .putExtra(Account.Common.EXTRA_KICK_OUT_REASON, notify.kickReason)
-                    .putExtra(Account.Common.EXTRA_KICK_OUT_LOGIN_TYPE, kickOutLoginType)
-                    .start()
-            }
-        }
-    }
-
-
     private fun isCurrentLoginActivity(): Boolean {
         return AppUtil.currentActivity is LoginActivity
     }
@@ -205,7 +173,6 @@ class LoginManager : BaseFrame<ILoginListener>(), ILoginManager {
         isLogin = false
         uid = ""
         token = ""
-        isNewRegister = false
         // 置空拉新/邀请相关的参数
         inviteUidCode = null
         inviteRoomIdCode = null
@@ -224,6 +191,12 @@ class LoginManager : BaseFrame<ILoginListener>(), ILoginManager {
         }
     }
 
+    override fun onKickedOffline(reason: UserKickReason) {
+        launch {
+            handleKickOut(reason)
+        }
+    }
+
     override fun notifyLogin() {
         dispatch { it.onLogin() }
     }
@@ -232,10 +205,6 @@ class LoginManager : BaseFrame<ILoginListener>(), ILoginManager {
         dispatch { it.onLogout() }
     }
 
-    override fun deleteAccount() {
-        // TODO: 删除账号
-    }
-
     override fun refreshToken() {
         launch {
             suspendRefreshToken()
@@ -309,14 +278,6 @@ class LoginManager : BaseFrame<ILoginListener>(), ILoginManager {
         }
     }
 
-    override fun setIsNewRegister(isNew: Boolean) {
-        isNewRegister = isNew
-    }
-
-    override fun isNewRegister(): Boolean {
-        return isNewRegister
-    }
-
     override fun checkRemoteVirtualAppConfig() {
         launch {
             val block = App.instance.securityService.checkRemoteVirtualAppConfig()

+ 0 - 5
module/account/src/main/java/com/adealink/weparty/account/register/RegisterProfileActivity.kt

@@ -1,7 +1,6 @@
 package com.adealink.weparty.account.register
 
 import android.content.Intent
-import android.view.KeyEvent
 import androidx.activity.viewModels
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
@@ -10,7 +9,6 @@ import com.adealink.frame.router.annotation.RouterUri
 import com.adealink.weparty.AppModule
 import com.adealink.weparty.account.R
 import com.adealink.weparty.account.databinding.ActivityRegisterProfileBinding
-import com.adealink.weparty.account.login.manager.loginManager
 import com.adealink.weparty.account.register.fragment.CompleteUserInfoFragment
 import com.adealink.weparty.account.register.fragment.SelectCategoryFragment
 import com.adealink.weparty.account.register.fragment.SelectGenderFragment
@@ -47,9 +45,6 @@ class RegisterProfileActivity : BaseActivity() {
     override fun onBeforeCreate() {
         super.onBeforeCreate()
         Router.bind(this)
-        if (from == "login") {
-            loginManager.setIsNewRegister(true)
-        }
     }
 
     override fun initViews() {

+ 7 - 4
module/im/src/main/java/com/adealink/weparty/im/manager/login/LoginManager.kt

@@ -10,12 +10,13 @@ import com.adealink.frame.util.AppUtil
 import com.adealink.weparty.App
 import com.adealink.weparty.commonui.ext.isFailure
 import com.adealink.weparty.im.constant.TAG_IM_LOGIN
+import com.adealink.weparty.im.data.UserInfo.Companion.loginUserInfo
 import com.adealink.weparty.im.datasource.remote.IMHttpService
 import com.adealink.weparty.im.manager.LoginWrapper
 import com.adealink.weparty.im.service.TIMAppService
 import com.adealink.weparty.im.util.TUIUtils
 import com.adealink.weparty.module.account.AccountModule
-import com.adealink.weparty.module.account.ILoginListener
+import com.adealink.weparty.module.account.data.UserKickReason
 import com.adealink.weparty.module.im.IMConfig
 import com.tencent.qcloud.tuicore.TUILogin
 import com.tencent.qcloud.tuicore.interfaces.TUICallback
@@ -25,9 +26,9 @@ import kotlinx.coroutines.launch
 
 val imLoginManager: ILoginManager by lazy { LoginManager() }
 
-class LoginManager : BaseFrame<com.adealink.weparty.im.manager.login.ILoginListener>(),
+class LoginManager : BaseFrame<ILoginListener>(),
     ILoginManager,
-    ILoginListener {
+    com.adealink.weparty.module.account.ILoginListener {
 
     private val imHttpService by fastLazy {
         App.instance.networkService.getHttpService(IMHttpService::class.java)
@@ -147,8 +148,10 @@ class LoginManager : BaseFrame<com.adealink.weparty.im.manager.login.ILoginListe
     private val mLoginListener: TUILoginListener = object : TUILoginListener() {
         override fun onKickedOffline() {
             super.onKickedOffline()
-            Log.i(TAG_IM_LOGIN, "You have been kicked off the line. Please login again!")
+            Log.i(TAG_IM_LOGIN, "You have been kicked off the line")
+            loginUserInfo.cleanUserInfo()
             logout()
+            AccountModule.onKickedOffline(UserKickReason.REASON_KICK_ONLINE_BY_MULTIPOINT_LOGIN)
         }
 
         override fun onUserSigExpired() {

+ 1 - 3
module/im/src/main/java/com/adealink/weparty/im/push/OfflineMessageDispatcher.java

@@ -6,13 +6,11 @@ import android.os.Bundle;
 import android.text.TextUtils;
 
 import com.adealink.frame.log.Log;
-import com.adealink.weparty.commonui.toast.util.ToastUtilKt;
 import com.adealink.weparty.commonui.util.BrandUtil;
 import com.adealink.weparty.im.service.TIMAppService;
 import com.google.gson.Gson;
 import com.tencent.qcloud.tuicore.push.OfflinePushExtBusinessInfo;
 import com.tencent.qcloud.tuicore.push.OfflinePushExtInfo;
-import com.tencent.qcloud.tuicore.util.ToastUtil;
 
 import java.util.Map;
 import java.util.Set;
@@ -152,7 +150,7 @@ public class OfflineMessageDispatcher {
             PackageManager packageManager = TIMAppService.getAppContext().getPackageManager();
             String label = String.valueOf(packageManager.getApplicationLabel(TIMAppService.getAppContext().getApplicationInfo()));
 
-            ToastUtilKt.showToast("测试: 你的应用" + label + "版本太低,不支持打开该离线消息");
+            //ToastUtilKt.showToast("测试: 你的应用" + label + "版本太低,不支持打开该离线消息");
             Log.e(TAG, "unknown version: " + version + " or action: " + action);
             return null;
         }

+ 0 - 43
module/im/src/main/java/com/adealink/weparty/im/service/TIMAppService.java

@@ -4,19 +4,13 @@ import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 
-import com.adealink.frame.log.Log;
-import com.adealink.weparty.commonui.toast.util.ToastUtilKt;
 import com.adealink.weparty.im.config.InitSetting;
-import com.adealink.weparty.im.data.UserInfo;
 import com.google.auto.service.AutoService;
 import com.tencent.qcloud.tuicore.ServiceInitializer;
-import com.tencent.qcloud.tuicore.TUILogin;
 import com.tencent.qcloud.tuicore.annotations.TUIInitializerDependency;
 import com.tencent.qcloud.tuicore.annotations.TUIInitializerID;
 import com.tencent.qcloud.tuicore.interfaces.ITUIService;
-import com.tencent.qcloud.tuicore.interfaces.TUICallback;
 import com.tencent.qcloud.tuicore.interfaces.TUIInitializer;
-import com.tencent.qcloud.tuicore.interfaces.TUILoginListener;
 
 @AutoService(TUIInitializer.class)
 @TUIInitializerDependency("TIMCommon")
@@ -42,43 +36,6 @@ public class TIMAppService implements TUIInitializer, ITUIService {
         initSetting = new InitSetting(mContext);
         initSetting.init();
         initThemeAndLanguageChangedReceiver();
-        initLoginStatusListener();
-    }
-
-    public void initLoginStatusListener() {
-        TUILogin.addLoginListener(loginStatusListener);
-    }
-
-    private final TUILoginListener loginStatusListener = new TUILoginListener() {
-        @Override
-        public void onKickedOffline() {
-            // TODO: 2025/11/16 测试
-            ToastUtilKt.showToast("测试: 您的账号已在其它终端登录");
-            logout();
-        }
-
-        @Override
-        public void onUserSigExpired() {
-            // TODO: 2025/11/16 触发重新登录
-            ToastUtilKt.showToast("测试: 账号已过期,请重新登录");
-            TUILogin.logout(new TUICallback() {
-                @Override
-                public void onSuccess() {
-                    logout();
-                }
-
-                @Override
-                public void onError(int errorCode, String errorMessage) {
-                    logout();
-                }
-            });
-        }
-    };
-
-    public void logout() {
-        Log.i(TAG, "logout");
-        UserInfo.getLoginUserInfo().cleanUserInfo();
-        // TODO: 2025/11/16 登出触发重新登录
     }
 
     private void initThemeAndLanguageChangedReceiver() {