新增APP更新功能

This commit is contained in:
zhanglei
2025-10-29 15:08:05 +08:00
parent b602a61636
commit b38ea562ba
6 changed files with 80 additions and 90 deletions
@@ -9,7 +9,9 @@ import com.tencent.qcloud.tuicore.util.ToastUtil
import com.tencent.qcloud.tuikit.tuichat.classicui.page.TUIGroupChatActivity import com.tencent.qcloud.tuikit.tuichat.classicui.page.TUIGroupChatActivity
import com.xjjk.healthyclients.MyApplication.Companion.appContext import com.xjjk.healthyclients.MyApplication.Companion.appContext
import com.xjjk.healthyclients.base.viewmodel.BaseViewModel import com.xjjk.healthyclients.base.viewmodel.BaseViewModel
import com.xjjk.healthyclients.bean.AppUpdateBean
import com.xjjk.healthyclients.bean.im.IMInfoBean import com.xjjk.healthyclients.bean.im.IMInfoBean
import com.xjjk.healthyclients.data.repository.CommonRepository
import com.xjjk.healthyclients.data.repository.GuidanceRepository import com.xjjk.healthyclients.data.repository.GuidanceRepository
import com.xjjk.healthyclients.data.repository.IMRepository import com.xjjk.healthyclients.data.repository.IMRepository
import com.xjjk.healthyclients.event.AppraiseFinishEvent import com.xjjk.healthyclients.event.AppraiseFinishEvent
@@ -33,6 +35,8 @@ class AppViewModel: BaseViewModel() {
var imUserId = MutableStateFlow("") var imUserId = MutableStateFlow("")
var imAppId = MutableStateFlow("") var imAppId = MutableStateFlow("")
var userHaveWatch = MutableSharedFlow<Boolean?>() var userHaveWatch = MutableSharedFlow<Boolean?>()
var mAppUpdateBean = MutableStateFlow<AppUpdateBean?>(null)
override fun init() { override fun init() {
} }
fun getIMSig(successCall: (IMInfoBean) -> Unit = {}){ fun getIMSig(successCall: (IMInfoBean) -> Unit = {}){
@@ -114,5 +118,17 @@ class AppViewModel: BaseViewModel() {
}) })
} }
fun getAppVersionInfo() {
launch(
{
handleRequest(
CommonRepository.getAppUpdateInfo(),
successBlock = {
mAppUpdateBean.emit(it.result)
})
}
)
}
} }
@@ -35,7 +35,6 @@ import com.xjjk.healthyclients.superfuntion.startLoginActivity
import com.xjjk.healthyclients.ui.viewmodel.MainViewModel import com.xjjk.healthyclients.ui.viewmodel.MainViewModel
import com.xjjk.healthyclients.utils.ConstantUtils import com.xjjk.healthyclients.utils.ConstantUtils
import com.xjjk.healthyclients.utils.LocationManager import com.xjjk.healthyclients.utils.LocationManager
import com.xjjk.healthyclients.utils.SystemUtils
import com.xjjk.healthyclients.view.PrivacyDialog import com.xjjk.healthyclients.view.PrivacyDialog
import com.xjjk.healthyclients.view.TextViewDialog import com.xjjk.healthyclients.view.TextViewDialog
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@@ -67,12 +66,7 @@ class MainActivity : BaseVMBActivity<MainViewModel, ActivityMainBinding>(R.layou
override fun initView(savedInstanceState: Bundle?) { override fun initView(savedInstanceState: Bundle?) {
if (!SystemUtils.isSignedWithReleaseCert(mContext)) { UpdateBuilder.create().check()// 启动更新任务
UpdateBuilder.create()
.check()// 启动更新任务
} else {
// mViewModel.getAppVersionInfo()
}
mBinding.apply { mBinding.apply {
//设置回调 //设置回调
mainTabLayout.setHomeBottomTabLayoutCallback(this@MainActivity) mainTabLayout.setHomeBottomTabLayoutCallback(this@MainActivity)
@@ -8,16 +8,17 @@ object UrlConfig {
// private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://192.168.1.23/" // 开发环境 // private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://192.168.1.23/" // 开发环境
private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://cqyt.dev.yg.dt.io/" // 开发环境 private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://cqyt.dev.yg.dt.io/" // 开发环境
private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xjgateway.mcrm.vip:8888" // 测试环境 private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xjgateway.mcrm.vip:8888" // 测试环境
// private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api.xjygjk.com" // 正式环境 private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api.xjygjk.com" // 正式环境
private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api-jkglpt.iosp.ydpt.tech" // 正式环境 // private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api-jkglpt.iosp.ydpt.tech" // 正式环境
private const val DEBUG_H5_ADDRESS_REMOTE = "http://cms.dev.yg.dt.io" // 开发环境 private const val DEBUG_H5_ADDRESS_REMOTE = "http://cms.dev.yg.dt.io" // 开发环境
private const val TEST_H5_ADDRESS_REMOTE = "https://xjconsole.mcrm.vip:8888" // 测试环境 private const val TEST_H5_ADDRESS_REMOTE = "https://xjconsole.mcrm.vip:8888" // 测试环境
// private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console.xjygjk.com" // 正式环境 private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console.xjygjk.com" // 正式环境
private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console-jkglpt.iosp.ydpt.tech" // 正式环境 // private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console-jkglpt.iosp.ydpt.tech" // 正式环境
//2025年10月23日 14:37 冯普说改为之前的地址,给油田部署的正式地址还没有启用
val baseUrlType: BaseUrlType = BaseUrlType.PRODUCT val baseUrlType: BaseUrlType = BaseUrlType.TEST
var testDeviceList = mutableListOf("7e8e7e49a26340b1","bb2d17cc138d109f")//测试设备列表 荣耀 oppo vivo var testDeviceList = mutableListOf("7e8e7e49a26340b1","bb2d17cc138d109f")//测试设备列表 荣耀 oppo vivo
var isTestDevice: Boolean = false var isTestDevice: Boolean = false
@@ -93,15 +94,15 @@ object UrlConfig {
* @param type 0,健康风险 1,心理评估 * @param type 0,健康风险 1,心理评估
*/ */
fun getEvaluationReportUrl(type: Int): String { // fun getEvaluationReportUrl(type: Int): String {
var httpUrl = getDefaultBaseUrl().toHttpUrl() // var httpUrl = getDefaultBaseUrl().toHttpUrl()
return getH5Url() + // return getH5Url() +
"/?scheme=" + httpUrl.scheme + // "/?scheme=" + httpUrl.scheme +
"&host=" + httpUrl.host + // "&host=" + httpUrl.host +
"&mobile=0" + // "&mobile=0" +
"&tokenF=" + DataStoreManager.getToken() + // "&tokenF=" + DataStoreManager.getToken() +
"&type=" + type // "&type=" + type
} // }
fun getKnowledgeDetailUrl(@UrlH5RouteUtils.RouteType routeType: String, map: MutableMap<String, Any?> = mutableMapOf()):String{ fun getKnowledgeDetailUrl(@UrlH5RouteUtils.RouteType routeType: String, map: MutableMap<String, Any?> = mutableMapOf()):String{
// return "http://192.168.1.22:9000/#/rich-text?id=sacsacasc&value=123132132" // return "http://192.168.1.22:9000/#/rich-text?id=sacsacasc&value=123132132"
var params="" var params=""
@@ -2,6 +2,9 @@ package com.xjjk.healthyclients.ui.activity
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.sw.healthyclients.data.local.DataStoreManager import com.sw.healthyclients.data.local.DataStoreManager
import com.xjjk.healthyclients.AppViewModel import com.xjjk.healthyclients.AppViewModel
import com.xjjk.healthyclients.BuildConfig import com.xjjk.healthyclients.BuildConfig
@@ -10,6 +13,9 @@ import com.xjjk.healthyclients.base.BaseVMBActivity
import com.xjjk.healthyclients.databinding.ActivitySettingBinding import com.xjjk.healthyclients.databinding.ActivitySettingBinding
import com.xjjk.healthyclients.superfuntion.startRetrievePassWordActivity import com.xjjk.healthyclients.superfuntion.startRetrievePassWordActivity
import com.xjjk.healthyclients.superfuntion.startWebActivity import com.xjjk.healthyclients.superfuntion.startWebActivity
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.lzh.framework.updatepluginlib.UpdateBuilder
/** /**
* 个人信息设置页面 * 个人信息设置页面
@@ -17,6 +23,7 @@ import com.xjjk.healthyclients.superfuntion.startWebActivity
class UserSettingActivity : class UserSettingActivity :
BaseVMBActivity<AppViewModel, ActivitySettingBinding>(R.layout.activity_setting) { BaseVMBActivity<AppViewModel, ActivitySettingBinding>(R.layout.activity_setting) {
var newVersion: Boolean = false//是否有新版本
override fun initView(savedInstanceState: Bundle?) { override fun initView(savedInstanceState: Bundle?) {
mBinding?.apply { mBinding?.apply {
@@ -24,6 +31,7 @@ class UserSettingActivity :
settingUserAgreement.setOrderStateInfo("用户协议",0,View.VISIBLE) settingUserAgreement.setOrderStateInfo("用户协议",0,View.VISIBLE)
settingUserPrivacyPolicy.setOrderStateInfo("隐私政策",0,View.VISIBLE) settingUserPrivacyPolicy.setOrderStateInfo("隐私政策",0,View.VISIBLE)
settingVersion.setOrderStateInfo("当前版本",0,View.VISIBLE,false, "v"+BuildConfig.VERSION_NAME) settingVersion.setOrderStateInfo("当前版本",0,View.VISIBLE,false, "v"+BuildConfig.VERSION_NAME)
settingCheckVersion.setOrderStateInfo("检查更新", 0, View.VISIBLE, false, "")
} }
@@ -34,13 +42,12 @@ class UserSettingActivity :
} }
override fun initData() { override fun initData() {
mViewModel.getAppVersionInfo()
} }
override fun bindEvent() { override fun bindEvent() {
mBinding?.apply { mBinding?.apply {
addClickViews(settingEditPassword,settingUserAgreement,settingUserPrivacyPolicy) addClickViews(settingEditPassword,settingUserAgreement,settingUserPrivacyPolicy,settingCheckVersion)
} }
} }
@@ -64,8 +71,40 @@ class UserSettingActivity :
} }
} }
} }
R.id.setting_check_version -> {
if (newVersion) {
UpdateBuilder.create().check()
} else {
showToast("已是最新版本了")
}
}
} }
} }
override fun createObserve() {
super.createObserve()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
mViewModel.mAppUpdateBean.collectLatest { bean ->
if (bean==null) {
mBinding?.settingCheckVersion?.setOrderStateInfo("检查更新", 0, View.VISIBLE, false, "已是最新版本")
}
bean?.let {
if (it.versionNo > BuildConfig.VERSION_CODE) {
newVersion = true
mBinding?.settingCheckVersion?.setOrderStateInfo("检查更新", 0, View.VISIBLE, false, "有新版本待更新")
} else {
mBinding?.settingCheckVersion?.setOrderStateInfo("检查更新", 0, View.VISIBLE, false, "已是最新版本")
}
}
}
}
}
}
} }
@@ -1,66 +0,0 @@
package com.xjjk.healthyclients.utils;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.widget.Toast;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SystemUtils {
public static boolean isSignedWithReleaseCert(Context context) {
// TODO: 2024/7/9 应要求,正式签名包不做应用内检查更新,故做此签名判断
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
// 通常正式签名的SHA1值是已知的,可以将其与应用的签名进行比对。
// 这里假设已知的正式签名SHA1值是 "YOUR_RELEASE_CERT_SHA1_HASH"
String knownReleaseSignatureSha1 = "CD:5D:30:3C:B7:D0:1A:D2:E6:0D:DE:96:71:5B:59:AB:C5:3C:C5:92";
for (Signature signature : signatures) {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(signature.toByteArray());
String currentSignatureSha1 = SystemUtils.byte2HexFormatted(md.digest());
System.out.println("计算出的签名--" + currentSignatureSha1);
// String currentSignatureSha1 = android.util.Base64.encodeToString(md.digest(), android.util.Base64.DEFAULT).trim();
if (knownReleaseSignatureSha1.equals(currentSignatureSha1)) {
return true;
}
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
return false;
}
private static String byte2HexFormatted(byte[] arr) {
StringBuilder str = new StringBuilder(arr.length * 2);
for (int i = 0; i < arr.length; i++) {
String h = Integer.toHexString(arr[i]);
int l = h.length();
if (l == 1)
h = "0" + h;
if (l > 2)
h = h.substring(l - 2, l);
str.append(h.toUpperCase());
if (i < (arr.length - 1))
str.append(':');
}
return str.toString();
}
public static void copyTextToClipboard(Context context, String string) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", string);
clipboard.setPrimaryClip(clip);
Toast.makeText(context, "已复制", Toast.LENGTH_SHORT).show();
}
}
@@ -48,6 +48,12 @@
android:layout_marginLeft="@dimen/dp_12" android:layout_marginLeft="@dimen/dp_12"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<com.xjjk.healthyclients.view.CustomUserInfoMenu
android:id="@+id/setting_check_version"
android:layout_marginLeft="@dimen/dp_12"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
</layout> </layout>