feat(main): 增加设备服务到期检测与提醒

- 新增获取设备信息接口及过期时间解析
- 过期时弹出不可取消的提醒对话框
This commit is contained in:
2026-09-04 09:07:22 +08:00
parent b381678756
commit 3babc04942
6 changed files with 195 additions and 1 deletions

View File

@@ -28,6 +28,7 @@ import com.aoleyun.sn.activity.debug.DebugActivity;
import com.aoleyun.sn.activity.update.UpdateActivity;
import com.aoleyun.sn.base.mvvm.BaseMvvmActivity;
import com.aoleyun.sn.bean.AppSettings;
import com.aoleyun.sn.bean.SnInfo;
import com.aoleyun.sn.bean.StudentsInfo;
import com.aoleyun.sn.comm.CommonConfig;
import com.aoleyun.sn.comm.JGYActions;
@@ -41,6 +42,7 @@ import com.aoleyun.sn.utils.GlideLoadUtils;
import com.aoleyun.sn.utils.JgyUtils;
import com.aoleyun.sn.utils.SPUtils;
import com.aoleyun.sn.utils.SysSettingUtils;
import com.aoleyun.sn.utils.TimeUtils;
import com.aoleyun.sn.utils.Utils;
import com.blankj.utilcode.util.NetworkUtils;
import com.bumptech.glide.Glide;
@@ -48,6 +50,11 @@ import com.google.gson.JsonObject;
import com.hjq.toast.Toaster;
import com.tencent.mmkv.MMKV;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBinding> implements NetworkUtils.OnNetworkStatusChangedListener {
private static final String TAG = "MainActivity";
@@ -239,7 +246,7 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
// mViewDataBinding.tvImei.setText(Utils.getIMEI(this, 1));
// } else {
// if (!TextUtils.isEmpty(Utils.getIMEI(this, 1))) {
mViewDataBinding.tvImei.setText(Utils.getIMEI(this));
mViewDataBinding.tvImei.setText(Utils.getIMEI(this));
// }
// }
}
@@ -280,6 +287,75 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
}
}
private AlertDialog mExpireDialog;
private void showExpireDialog(String content) {
if (mExpireDialog != null && mExpireDialog.isShowing()) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.dialog);
builder.setMessage(content);
builder.setTitle("注意:");
builder.setIcon(R.mipmap.ic_launcher);
builder.setCancelable(false);
builder.setPositiveButton("确定", (dialog, which) -> dialog.dismiss());
mExpireDialog = builder.create();
if (!this.isFinishing() && !mExpireDialog.isShowing()) {
mExpireDialog.show();
}
}
/**
* 将服务端返回的过期时间字符串解析为毫秒时间戳
* 兼容:纯数字秒(10位)/毫秒(13位)时间戳,或 yyyy-MM-dd HH:mm:ss 等常见日期格式
* 解析失败返回0(表示无需处理)
*/
private long parseExpireAtToMillis(String expire_at) {
if (TextUtils.isEmpty(expire_at)) {
return 0;
}
String time = expire_at.trim();
//纯数字时间戳
if (TextUtils.isDigitsOnly(time)) {
try {
long value = Long.parseLong(time);
if (time.length() == 10) {
return value * 1000;//秒
} else if (time.length() == 13) {
return value;//毫秒
}
} catch (NumberFormatException e) {
Log.e(TAG, "parseExpireAtToMillis: " + e.getMessage());
}
return 0;
}
//日期格式
String[] patterns = {
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd",
"yyyy/MM/dd HH:mm:ss",
"yyyy/MM/dd HH:mm",
"yyyy/MM/dd",
"yyyy-MM-dd'T'HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ss.SSS"
};
for (String pattern : patterns) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.getDefault());
sdf.setLenient(false);
Date date = sdf.parse(time);
if (date != null) {
return date.getTime();
}
} catch (ParseException e) {
//尝试下一种格式
}
}
Log.e(TAG, "parseExpireAtToMillis: 无法解析的过期时间格式 = " + expire_at);
return 0;
}
@Override
public void initData() {
Log.e("getMacAddress", Utils.getAndroid10MAC(this));
@@ -296,6 +372,7 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
mViewModel.setBindInfoPanel();
mViewModel.getAppSettings();
mViewModel.getPushTags();
mViewModel.getSnInfo();
}
@@ -413,6 +490,22 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
mViewDataBinding.setAppSettings(appSettings);
}
});
mViewModel.mSnInfoData.observe(this, new Observer<SnInfo>() {
@Override
public void onChanged(SnInfo snInfo) {
if (snInfo == null) {
return;
}
String expire_at = snInfo.getExpire_at();
Log.e(TAG, "mSnInfoData onChanged: " + expire_at);
long expireTime = parseExpireAtToMillis(expire_at);
Log.e(TAG, "mSnInfoData onChanged: expireTime = " + expireTime + ", now = " + System.currentTimeMillis());
if (expireTime > 0 && expireTime <= System.currentTimeMillis()) {
Log.e(TAG, "mSnInfoData onChanged: 设备已过期");
showExpireDialog("设备服务已过期,过期时间:" + TimeUtils.transferLongToDate(expireTime) + ",请联系管理员处理!");
}
}
});
}
MainService.MainBinder mMainBinder;
@@ -509,6 +602,9 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
@Override
protected void onDestroy() {
if (mExpireDialog != null && mExpireDialog.isShowing()) {
mExpireDialog.dismiss();
}
super.onDestroy();
unregister();
JgyUtils.startServices(MainActivity.this);

View File

@@ -15,6 +15,7 @@ import com.aoleyun.sn.bean.AdminAppInfo;
import com.aoleyun.sn.bean.AppSettings;
import com.aoleyun.sn.bean.AppUpdateInfo;
import com.aoleyun.sn.bean.BaseResponse;
import com.aoleyun.sn.bean.SnInfo;
import com.aoleyun.sn.bean.StudentsInfo;
import com.aoleyun.sn.comm.CommonConfig;
import com.aoleyun.sn.comm.JGYActions;
@@ -353,4 +354,33 @@ public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEv
}
});
}
public MutableLiveData<SnInfo> mSnInfoData = new MutableLiveData<>();
public void getSnInfo() {
NetInterfaceManager.getInstance().getSnInfoControl()
.compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
.subscribe(new Observer<BaseResponse<SnInfo>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("getSnInfo", "onSubscribe: ");
}
@Override
public void onNext(BaseResponse<SnInfo> response) {
Log.e("getSnInfo", "onNext: " + response);
mSnInfoData.setValue(response.data);
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("getSnInfo", "onError: ");
}
@Override
public void onComplete() {
Log.e("getSnInfo", "onComplete: ");
}
});
}
}

View File

@@ -0,0 +1,55 @@
package com.aoleyun.sn.bean;
import java.io.Serializable;
public class SnInfo implements Serializable {
int control_status;
int is_log;
int is_log_type;
int is_screen_lock;
String expire_at;
public int getControl_status() {
return control_status;
}
public void setControl_status(int control_status) {
this.control_status = control_status;
}
public int getIs_log() {
return is_log;
}
public void setIs_log(int is_log) {
this.is_log = is_log;
}
public int getIs_log_type() {
return is_log_type;
}
public void setIs_log_type(int is_log_type) {
this.is_log_type = is_log_type;
}
public int getIs_screen_lock() {
return is_screen_lock;
}
public void setIs_screen_lock(int is_screen_lock) {
this.is_screen_lock = is_screen_lock;
}
public String getExpire_at() {
return expire_at;
}
public void setExpire_at(String expire_at) {
this.expire_at = expire_at;
}
}

View File

@@ -55,6 +55,7 @@ import com.aoleyun.sn.bean.NetAndLaunchData;
import com.aoleyun.sn.bean.PoweroffBean;
import com.aoleyun.sn.bean.PushTag;
import com.aoleyun.sn.bean.ScreenLockState;
import com.aoleyun.sn.bean.SnInfo;
import com.aoleyun.sn.bean.SnRunLog;
import com.aoleyun.sn.bean.SnSetting;
import com.aoleyun.sn.bean.SnTimeControl;
@@ -669,6 +670,10 @@ public class NetInterfaceManager {
1440 * CACHE_EXPIRE_ONE_MINUTE);
}
public Observable<BaseResponse<SnInfo>> getSnInfoControl() {
return schedule(getDevicesStatusApi().getSnInfo(Utils.getSerial(mContext)));
}
public Observable<BaseResponse<SnRunLog>> getSnRunLogControl() {
return schedule(getLogApi().getSnRunLog(Utils.getSerial(mContext)));
}

View File

@@ -25,6 +25,8 @@ public class UrlAddress {
public static final String GET_EBAG_CODE = "And/getEbagCode";
/*绑定设备*/
public static final String SN_CONFIRM_BIND = "And/sn/snConfirmBind";
/*获取设备信息设置*/
public static final String GET_SN_INFO = "And/sn/getSnInfo";
/*网课模式*/
public final static String GET_CLOUD_LESSON = "And/control/getCloudLessonSetting";

View File

@@ -6,6 +6,7 @@ import com.aoleyun.sn.bean.DeveloperBean;
import com.aoleyun.sn.bean.EBagCode;
import com.aoleyun.sn.bean.PushTag;
import com.aoleyun.sn.bean.ScreenLockState;
import com.aoleyun.sn.bean.SnInfo;
import com.aoleyun.sn.bean.StudentsInfo;
import com.aoleyun.sn.network.UrlAddress;
@@ -65,4 +66,9 @@ public interface DevicesStatusApi {
@Field("type") int type
);
@GET(UrlAddress.GET_SN_INFO)
Observable<BaseResponse<SnInfo>> getSnInfo(
@Query("sn") String sn
);
}