feat:同步Habu完成地区隔离功能

This commit is contained in:
Max
2023-12-01 16:10:22 +08:00
parent bdcfb21e6e
commit e37796286b
8 changed files with 238 additions and 14 deletions

View File

@@ -410,6 +410,7 @@ public class MainActivity extends BaseMvpActivity<IMainView, MainPresenter>
} }
onParseIntent(); onParseIntent();
handleNimIntent(); handleNimIntent();
InitialModel.get().regionCheck();
} }
private void onParseIntent() { private void onParseIntent() {
@@ -519,6 +520,7 @@ public class MainActivity extends BaseMvpActivity<IMainView, MainPresenter>
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onLoadLoginUserInfoEvent(LoadLoginUserInfoEvent event) { public void onLoadLoginUserInfoEvent(LoadLoginUserInfoEvent event) {
firstLoadedUserInfo(); firstLoadedUserInfo();
InitialModel.get().regionCheck();
} }
public void onLogout() { public void onLogout() {

View File

@@ -16,6 +16,7 @@ import android.util.Log;
import androidx.multidex.MultiDex; import androidx.multidex.MultiDex;
import com.bumptech.glide.request.target.ViewTarget; import com.bumptech.glide.request.target.ViewTarget;
import com.chuhai.utils.LanguageUtils;
import com.coorchice.library.utils.LogUtils; import com.coorchice.library.utils.LogUtils;
import com.facebook.stetho.Stetho; import com.facebook.stetho.Stetho;
import com.hjq.toast.ToastUtils; import com.hjq.toast.ToastUtils;
@@ -244,6 +245,10 @@ public class XChatApplication extends BaseApp {
SingleToastUtil.showToast(serviceResult.getMessage()); SingleToastUtil.showToast(serviceResult.getMessage());
EventBus.getDefault().post(new NeedCompleteInfoEvent()); EventBus.getDefault().post(new NeedCompleteInfoEvent());
throw new ServerException(serviceResult.getMessage(), serviceResult.getCode()); throw new ServerException(serviceResult.getMessage(), serviceResult.getCode());
} else if (serviceResult.getCode() == 401) {
SingleToastUtil.showToast(serviceResult.getMessage());
AuthModel.get().cleanLogInfo();
throw new ServerException(serviceResult.getMessage(), serviceResult.getCode());
} }
} }
return null; return null;
@@ -403,6 +408,7 @@ public class XChatApplication extends BaseApp {
httpParams.put("deviceId", DeviceUuidFactory.getDeviceId(context)); httpParams.put("deviceId", DeviceUuidFactory.getDeviceId(context));
httpParams.put("androidId", MD5Utils.getMD5String(Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID))); httpParams.put("androidId", MD5Utils.getMD5String(Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID)));
httpParams.put("channel", AppMetaDataUtil.getChannelID()); httpParams.put("channel", AppMetaDataUtil.getChannelID());
httpParams.put("lang", LanguageUtils.INSTANCE.getSystemLanguage().toLanguageTag());
RxNet.init(context) RxNet.init(context)
.debug(BuildConfig.DEBUG) .debug(BuildConfig.DEBUG)
.setBaseUrl(url) .setBaseUrl(url)

View File

@@ -219,20 +219,9 @@ public class AuthModel extends BaseModel implements IAuthModel {
if (currentAccountInfo == null || TextUtils.isEmpty(currentAccountInfo.getAccess_token())) { if (currentAccountInfo == null || TextUtils.isEmpty(currentAccountInfo.getAccess_token())) {
return Single.error(new Throwable(""));//没有账号信息 return Single.error(new Throwable(""));//没有账号信息
} }
return requestTicket().flatMap(ticketResult -> { return imLogin(currentAccountInfo)
if (!ticketResult.isSuccess()) {
return Single.error(new Throwable(ticketResult.getMessage()));
}
ticketInfo = ticketResult.getData();
DemoCache.saveTicketInfo(ticketInfo);
return Single.just(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_01));
})
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.flatMap((Function<String, SingleSource<String>>) s -> {
Log.i("IMLogin", "apply");
return imLogin(currentAccountInfo);
})
.doOnSuccess(s -> { .doOnSuccess(s -> {
EventBus.getDefault().post(new LoginEvent()); EventBus.getDefault().post(new LoginEvent());
}); });
@@ -781,7 +770,7 @@ public class AuthModel extends BaseModel implements IAuthModel {
}); });
} }
private void cleanLogInfo() { public void cleanLogInfo() {
reset();//这里先重置状态后调用IM登出因为这里观察了IM的在线状态 reset();//这里先重置状态后调用IM登出因为这里观察了IM的在线状态
NIMClient.getService(AuthService.class).logout(); NIMClient.getService(AuthService.class).logout();
EventBus.getDefault().post(new LogoutEvent()); EventBus.getDefault().post(new LogoutEvent());

View File

@@ -78,4 +78,5 @@ public interface IInitialModel extends IModel {
@Nullable @Nullable
FairyOpenInfo getFairyOpenInfo(); FairyOpenInfo getFairyOpenInfo();
void regionCheck();
} }

View File

@@ -1,5 +1,6 @@
package com.yizhuan.xchat_android_core.initial; package com.yizhuan.xchat_android_core.initial;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -14,6 +15,8 @@ import androidx.lifecycle.MutableLiveData;
import com.bumptech.glide.request.FutureTarget; import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.target.Target;
import com.chuhai.utils.LanguageUtils;
import com.chuhai.utils.TelephonyUtils;
import com.netease.nim.uikit.support.glide.GlideApp; import com.netease.nim.uikit.support.glide.GlideApp;
import com.yizhuan.xchat_android_core.R; import com.yizhuan.xchat_android_core.R;
import com.yizhuan.xchat_android_core.DemoCache; import com.yizhuan.xchat_android_core.DemoCache;
@@ -30,6 +33,8 @@ import com.yizhuan.xchat_android_core.manager.AvRoomDataManager;
import com.yizhuan.xchat_android_core.noble.NobleDataManager; import com.yizhuan.xchat_android_core.noble.NobleDataManager;
import com.yizhuan.xchat_android_core.public_chat_hall.manager.PublicChatHallDataManager; import com.yizhuan.xchat_android_core.public_chat_hall.manager.PublicChatHallDataManager;
import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel; import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel;
import com.yizhuan.xchat_android_core.user.UserModel;
import com.yizhuan.xchat_android_core.user.bean.UserInfo;
import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent; import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent;
import com.yizhuan.xchat_android_core.utils.CurrentTimeUtils; import com.yizhuan.xchat_android_core.utils.CurrentTimeUtils;
import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils;
@@ -49,11 +54,14 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.Single; import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe; import io.reactivex.SingleOnSubscribe;
import io.reactivex.SingleSource; import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action; import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer; import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function; import io.reactivex.functions.Function;
@@ -131,6 +139,8 @@ public class InitialModel extends BaseModel implements IInitialModel {
@Nullable @Nullable
private InitInfo cacheInitInfo; private InitInfo cacheInitInfo;
private Disposable regionCheckTimer;
private InitialModel() { private InitialModel() {
api = RxNet.create(Api.class); api = RxNet.create(Api.class);
loadMainTabInfoList(); loadMainTabInfoList();
@@ -514,6 +524,38 @@ public class InitialModel extends BaseModel implements IInitialModel {
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
/**
* 地区检测
*/
@Override
public void regionCheck() {
UserInfo userInfo = UserModel.get().getCacheLoginUserInfo();
if (userInfo == null) {
return;
}
if (TextUtils.isEmpty(userInfo.getNick()) || TextUtils.isEmpty(userInfo.getAvatar())) {
return;
}
String operatorCode;
if (TelephonyUtils.INSTANCE.isChinaOperator()) {
operatorCode = "460";
} else {
operatorCode = TelephonyUtils.INSTANCE.getOperatorFirstSim();
}
api.regionCheck(LanguageUtils.INSTANCE.getSystemLanguage().toLanguageTag(), operatorCode)
.compose(RxHelper.handleSchedulers())
.doOnSuccess(longServiceResult -> {
if (regionCheckTimer != null && !regionCheckTimer.isDisposed()) {
regionCheckTimer.dispose();
}
if (longServiceResult.isSuccess() && longServiceResult.getData() != null && longServiceResult.getData() > 0) {
regionCheckTimer = Observable.timer(Math.max(longServiceResult.getData(), 30 * 1000), TimeUnit.MILLISECONDS).subscribe(aLong -> {
regionCheck();
});
}
}).subscribe();
}
@Override @Override
public int getTeenagerMode() { public int getTeenagerMode() {
@@ -591,5 +633,16 @@ public class InitialModel extends BaseModel implements IInitialModel {
@GET("act/seize-treasure/status") @GET("act/seize-treasure/status")
Single<ServiceResult<FairyOpenInfo>> getFairyOpenInfo(); Single<ServiceResult<FairyOpenInfo>> getFairyOpenInfo();
/**
* 地区检测
*
* @param lang 语言
* @param mcc 运营商码
* @return
*/
@POST("/ipRegion/check")
@FormUrlEncoded
Single<ServiceResult<Long>> regionCheck(@Field("lang") String lang, @Field("mcc") String mcc);
} }
} }

View File

@@ -5,6 +5,7 @@ import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.chuhai.utils.TelephonyUtils;
import com.yizhuan.xchat_android_core.auth.AuthModel; import com.yizhuan.xchat_android_core.auth.AuthModel;
import com.yizhuan.xchat_android_core.utils.APIEncryptUtil; import com.yizhuan.xchat_android_core.utils.APIEncryptUtil;
import com.yizhuan.xchat_android_core.utils.OaidUtil; import com.yizhuan.xchat_android_core.utils.OaidUtil;
@@ -34,6 +35,12 @@ public class ParamsInterceptor implements Interceptor {
private Map<String, String> mHttpParams; private Map<String, String> mHttpParams;
// 运营商码
private String operatorCode;
// 运营商码的获取时间
private long operatorCodeTime;
public ParamsInterceptor(Map<String, String> params) { public ParamsInterceptor(Map<String, String> params) {
this.mHttpParams = params; this.mHttpParams = params;
} }
@@ -124,7 +131,6 @@ public class ParamsInterceptor implements Interceptor {
// Log.e("ParamsInterceptor", " url: " + oldRequest.url()+ " final params Map : " + paramsMap.toString()); // Log.e("ParamsInterceptor", " url: " + oldRequest.url()+ " final params Map : " + paramsMap.toString());
// Log.e("ParamsInterceptor", "timestamp:"+timestamp + " url: " + oldRequest.url()+ " sign : " + signStr); // Log.e("ParamsInterceptor", "timestamp:"+timestamp + " url: " + oldRequest.url()+ " sign : " + signStr);
Headers headers = oldRequest.headers().newBuilder() Headers headers = oldRequest.headers().newBuilder()
.add("pub_ticket", ticket) .add("pub_ticket", ticket)
.add("pub_uid", uid == 0 ? "" : String.valueOf(uid)) .add("pub_uid", uid == 0 ? "" : String.valueOf(uid))
@@ -137,6 +143,7 @@ public class ParamsInterceptor implements Interceptor {
} }
builder.addQueryParameter("pub_timestamp", timestamp); builder.addQueryParameter("pub_timestamp", timestamp);
builder.addQueryParameter("pub_sign", signStr); builder.addQueryParameter("pub_sign", signStr);
addHeaderWithOperator(builder);
Request newRequest = oldRequest.newBuilder() Request newRequest = oldRequest.newBuilder()
.method(oldRequest.method(), oldRequest.body()) .method(oldRequest.method(), oldRequest.body())
.headers(headers) .headers(headers)
@@ -146,5 +153,19 @@ public class ParamsInterceptor implements Interceptor {
} }
private void addHeaderWithOperator(HttpUrl.Builder builder) {
if ((System.currentTimeMillis() - operatorCodeTime) > (1000 * 60 * 10)) {
loadOperatorCode();
}
builder.addQueryParameter("mcc", operatorCode);
}
private void loadOperatorCode() {
if (TelephonyUtils.INSTANCE.isChinaOperator()) {
operatorCode = "460";
} else {
operatorCode = TelephonyUtils.INSTANCE.getOperatorFirstSim();
}
operatorCodeTime = System.currentTimeMillis();
}
} }

View File

@@ -0,0 +1,19 @@
package com.chuhai.utils
import android.os.Build
import android.os.LocaleList
import java.util.Locale
/**
* Created by Max on 2023/11/17 16:12
* Desc:
**/
object LanguageUtils {
fun getSystemLanguage(): Locale {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleList.getDefault()[0]
} else {
Locale.getDefault()
}
}
}

View File

@@ -0,0 +1,133 @@
package com.chuhai.utils
import android.content.Context
import android.telephony.TelephonyManager
import com.chuhai.utils.log.ILog
/**
* Created by Max on 2023/11/14 10:17
* Desc:TelephonyManager 相关工具
**/
object TelephonyUtils : ILog {
/**
* 是否为中国运营商任意卡属于中国就为true
*/
fun isChinaOperator(): Boolean {
val tm =
AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
?: return false
if (tm.simState == TelephonyManager.SIM_STATE_READY) {
if (!tm.simOperator.isNullOrEmpty() && tm.simOperator.startsWith("460")) {
return true
}
if (isChainOperator(tm.simOperatorName)) {
return true
}
}
if (!tm.networkOperator.isNullOrEmpty() && tm.networkOperator.startsWith("460")) {
return true
}
if (isChainOperator(tm.networkOperatorName)) {
return true
}
return false
}
/**
* 获取运营商优先SIM
*/
fun getOperatorFirstSim(): String? {
val operator = getSimOperator()
return if (operator.isNullOrEmpty()) {
getNetWorkOperator()
} else {
operator
}
}
/**
* 获取SIM运营商名称
*/
fun getSimOperator(): String? {
val tm =
AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
?: return null
if (tm.simState != TelephonyManager.SIM_STATE_READY) {
logD("SIM状态不对${tm.simState}")
return null
}
val simOperator = tm.simOperator
logD("getSimOperator()获取的MCC+MNC为$simOperator")
logD("getOperatorName()方法获取的运营商名称为:${tm.simOperatorName} ")
logD("通过getSimOperator()人为判断的运营商名称是: ${getOperatorName(simOperator)}")
return simOperator
}
/**
* 获取网络运营商
*/
fun getNetWorkOperator(): String? {
val tm = AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
?: return null
//用于判断拨号那张卡的运营商
val networkOperator = tm.networkOperator
logD("getNetWorkOperator() 获取的MCC+MNC为$networkOperator")
logD("getNetWorkOperator() phoneType${tm.phoneType}")
logD("getNetworkOperatorName()方法获取的网络类型名称是: ${tm.networkOperatorName}")
logD("通过getNetWorkOperator()人为判断的运营商名称是: ${getOperatorName(networkOperator)}")
return tm.networkOperator
}
/**
* 是否中国运营商
*/
private fun isChainOperator(operatorName: String?): Boolean {
if (operatorName == null) return false
if (operatorName == "CUCC"
|| operatorName == "CMCC"
|| operatorName == "CTCC"
|| operatorName == "CTT"
|| operatorName.contains("中国")
|| operatorName.contains("中國")
) {
return true
}
return false
}
/**
* 运营商类型
*/
private fun getOperatorName(simOperator: String?): String? {
if (simOperator == null) {
return null
}
return when (simOperator) {
"46001", "46006", "46009" -> {
// 联通
"CUCC"
}
"46000", "46002", "46004", "46007" -> {
// 移动
"CMCC"
}
"46003", "46005", "46011" -> {
// 电信
"CTCC"
}
"46020" -> {
// 铁通
"CTT"
}
else -> {
"OHTER"
}
}
}
}