diff --git a/app/build.gradle b/app/build.gradle index 53de7f8..5635f9c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,8 +29,8 @@ android { defaultConfig { applicationId "com.aoleyun.sn" - versionCode 208 - versionName "1.6.0317" + versionCode 210 + versionName "1.6.0403" //There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature. minSdkVersion 24 diff --git a/app/src/main/java/com/aoleyun/sn/bean/TimeControlApp.java b/app/src/main/java/com/aoleyun/sn/bean/TimeControlApp.java new file mode 100644 index 0000000..4d49727 --- /dev/null +++ b/app/src/main/java/com/aoleyun/sn/bean/TimeControlApp.java @@ -0,0 +1,26 @@ +package com.aoleyun.sn.bean; + +import java.io.Serializable; + +public class TimeControlApp implements Serializable { + private static final long serialVersionUID = 5184143240402181001L; + + String app_package; + String app_name; + + public String getApp_package() { + return app_package; + } + + public void setApp_package(String app_package) { + this.app_package = app_package; + } + + public String getApp_name() { + return app_name; + } + + public void setApp_name(String app_name) { + this.app_name = app_name; + } +} diff --git a/app/src/main/java/com/aoleyun/sn/bean/TimeControlData.java b/app/src/main/java/com/aoleyun/sn/bean/TimeControlData.java new file mode 100644 index 0000000..3b98060 --- /dev/null +++ b/app/src/main/java/com/aoleyun/sn/bean/TimeControlData.java @@ -0,0 +1,18 @@ +package com.aoleyun.sn.bean; + +import java.io.Serializable; +import java.util.List; + +public class TimeControlData implements Serializable { + private static final long serialVersionUID = 8902745668847718218L; + + List periods; + + public List getPeriods() { + return periods; + } + + public void setPeriods(List periods) { + this.periods = periods; + } +} diff --git a/app/src/main/java/com/aoleyun/sn/bean/TimeControlInfo.java b/app/src/main/java/com/aoleyun/sn/bean/TimeControlInfo.java new file mode 100644 index 0000000..bfd92db --- /dev/null +++ b/app/src/main/java/com/aoleyun/sn/bean/TimeControlInfo.java @@ -0,0 +1,36 @@ +package com.aoleyun.sn.bean; + +import java.io.Serializable; +import java.util.List; + +public class TimeControlInfo implements Serializable { + private static final long serialVersionUID = 4988631077105878200L; + + String start_time; + String end_time; + List app; + + public String getStart_time() { + return start_time; + } + + public void setStart_time(String start_time) { + this.start_time = start_time; + } + + public String getEnd_time() { + return end_time; + } + + public void setEnd_time(String end_time) { + this.end_time = end_time; + } + + public List getApp() { + return app; + } + + public void setApp(List app) { + this.app = app; + } +} diff --git a/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java b/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java index d6d0fb8..15fa2c2 100644 --- a/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java +++ b/app/src/main/java/com/aoleyun/sn/comm/CommonConfig.java @@ -91,6 +91,9 @@ public class CommonConfig { /*壁纸地址*/ public static final String WALLPAPER_URL_KEY = "wallpaper_url"; + /*时间管控json*/ + public static final String TIME_CONTROL_DATA_KEY = "time_dontrol_data_json_string"; + /** * 管控系统指令 diff --git a/app/src/main/java/com/aoleyun/sn/hook/AoleyunActivityController.java b/app/src/main/java/com/aoleyun/sn/hook/AoleyunActivityController.java index 4978098..35c06ae 100644 --- a/app/src/main/java/com/aoleyun/sn/hook/AoleyunActivityController.java +++ b/app/src/main/java/com/aoleyun/sn/hook/AoleyunActivityController.java @@ -6,6 +6,7 @@ import android.util.Log; import com.aoleyun.sn.comm.CommonConfig; import com.aoleyun.sn.utils.JgyUtils; +import com.hjq.toast.Toaster; import com.tencent.mmkv.MMKV; public class AoleyunActivityController extends IActivityController.Stub { @@ -20,10 +21,15 @@ public class AoleyunActivityController extends IActivityController.Stub { // return false; // } - //false 则不会启动,直接返回。 - if (JgyUtils.getInstance().isCloudLessonMod(pkg)) { - return true; + if (JgyUtils.getInstance().checkTimePeriod(pkg)) { + //false 则不会启动,直接返回。 + if (JgyUtils.getInstance().isCloudLessonMod(pkg)) { + return true; + } else { + return false; + } } else { + Toaster.show("专注模式只允许使用指定应用"); return false; } } diff --git a/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java b/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java index 38c1087..ba6de3b 100644 --- a/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java +++ b/app/src/main/java/com/aoleyun/sn/network/NetInterfaceManager.java @@ -55,6 +55,8 @@ import com.aoleyun.sn.bean.SnRunLog; import com.aoleyun.sn.bean.SnSetting; import com.aoleyun.sn.bean.SnTimeControl; import com.aoleyun.sn.bean.StudentsInfo; +import com.aoleyun.sn.bean.TimeControlData; +import com.aoleyun.sn.bean.TimeControlInfo; import com.aoleyun.sn.bean.TopApp; import com.aoleyun.sn.bean.Wallpaper; import com.aoleyun.sn.bean.WhitelistBean; @@ -623,6 +625,13 @@ public class NetInterfaceManager { .observeOn(AndroidSchedulers.mainThread()); } + public Observable> getTimeObservable() { + return mRetrofit.create(SnTimeControlApi.class) + .getTimeControl(Utils.getSerial(mContext)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + public Observable> getScreenLockObservable() { return mRetrofit.create(ScreenLockStateApi.class) .getScreenLockState(Utils.getSerial(mContext)) @@ -2027,6 +2036,8 @@ public class NetInterfaceManager { } catch (Exception e) { e.printStackTrace(); } + } else if ("G10".equals(Build.MODEL) || "D1".equals(Build.MODEL)) { + Settings.System.putString(mContext.getContentResolver(), CommonConfig.APP_VIEW_CLICK_DISABLED, "com.ttstd.utils:12345"); } else { Settings.System.putString(mContext.getContentResolver(), CommonConfig.APP_VIEW_CLICK_DISABLED, "com.arivoc.wordhd:2131624676,2131624689;com.ttstd.utils:12345"); } @@ -3609,7 +3620,7 @@ public class NetInterfaceManager { }; } - + @Deprecated public void getSnTimeControl(boolean refresh, BehaviorSubject lifecycle, onCompleteCallback callback) { ConnectMode connectMode = ConnectMode.ONE_MINUTE; if (refresh) { @@ -3630,13 +3641,14 @@ public class NetInterfaceManager { } } + @Deprecated public void getSnTimeControl(BehaviorSubject lifecycle, onCompleteCallback callback) { getSnTimeObservable() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getSnTimeObserver(callback)); } - + @Deprecated public void getSnTimeControl() { getSnTimeObservable() .subscribe(getSnTimeObserver(null)); @@ -3689,6 +3701,54 @@ public class NetInterfaceManager { }; } + public void getTimeControl(BehaviorSubject lifecycle, onCompleteCallback callback) { + getTimeObservable() + .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) + .subscribe(getTimeObserver(callback)); + } + + public void getTimeControl() { + getTimeObservable() + .subscribe(getTimeObserver(null)); + } + + private Observer> getTimeObserver(onCompleteCallback callback) { + return new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getTimeObserver", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse response) { + Log.e("getTimeObserver", "onNext: " + response); + if (response.code == OK) { + TimeControlData timeControlData = response.data; + List periods = timeControlData.getPeriods(); + mMMKV.encode(CommonConfig.TIME_CONTROL_DATA_KEY, GsonUtils.toJSONString(periods)); + } else { + mMMKV.remove(CommonConfig.TIME_CONTROL_DATA_KEY); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getTimeObserver", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getTimeObserver", "onComplete: "); + JgyUtils.getInstance().syncTimePeriod(); + if (callback != null) { + callback.onComplete(); + } + } + }; + } + + public interface GetAppinsideWebCallback { void onComplete(); } diff --git a/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java b/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java index f78f878..16b900d 100644 --- a/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java +++ b/app/src/main/java/com/aoleyun/sn/network/UrlAddress.java @@ -103,7 +103,9 @@ public class UrlAddress { /*获取系统设置*/ public static final String GET_FIRMWARE = "firmware/get"; /*获取时间管控*/ + @Deprecated public static final String GET_SN_TIME_CONTROL = "Sn/getSnTimeControl"; + public static final String GET_TIME_CONTROL = "android/control/time-control"; /*获取WiFi名和密码*/ public static final String GET_WIFI_ALIAS_PW = "And/SnControl/getWifi"; /*获取远程关机时间*/ diff --git a/app/src/main/java/com/aoleyun/sn/network/api/get/SnTimeControlApi.java b/app/src/main/java/com/aoleyun/sn/network/api/get/SnTimeControlApi.java index a7aeb01..da5375a 100644 --- a/app/src/main/java/com/aoleyun/sn/network/api/get/SnTimeControlApi.java +++ b/app/src/main/java/com/aoleyun/sn/network/api/get/SnTimeControlApi.java @@ -2,6 +2,7 @@ package com.aoleyun.sn.network.api.get; import com.aoleyun.sn.bean.BaseResponse; import com.aoleyun.sn.bean.SnTimeControl; +import com.aoleyun.sn.bean.TimeControlData; import com.aoleyun.sn.network.UrlAddress; import io.reactivex.rxjava3.core.Observable; @@ -13,4 +14,9 @@ public interface SnTimeControlApi { Observable> getSnTimeControl( @Query("sn") String sn ); + + @GET(UrlAddress.GET_TIME_CONTROL) + Observable> getTimeControl( + @Query("sn") String sn + ); } diff --git a/app/src/main/java/com/aoleyun/sn/push/PushManager.java b/app/src/main/java/com/aoleyun/sn/push/PushManager.java index 2a60e0b..4474d2d 100644 --- a/app/src/main/java/com/aoleyun/sn/push/PushManager.java +++ b/app/src/main/java/com/aoleyun/sn/push/PushManager.java @@ -1113,6 +1113,7 @@ public class PushManager { private void getTimeControl(String extras) { NetInterfaceManager.getInstance().getSnTimeControl(); + NetInterfaceManager.getInstance().getTimeControl(); } private void getTopApp(String extras) { diff --git a/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java b/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java index e720dc3..c40189d 100644 --- a/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java +++ b/app/src/main/java/com/aoleyun/sn/service/main/MainSPresenter.java @@ -556,7 +556,14 @@ public class MainSPresenter implements MainSContact.Presenter { mView.getSnTimeControlFinish(); } else { NetInterfaceManager.getInstance() - .getSnTimeControl(true, getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + .getSnTimeControl(getLifecycle(), new NetInterfaceManager.onCompleteCallback() { + @Override + public void onComplete() { + mView.getSnTimeControlFinish(); + } + }); + NetInterfaceManager.getInstance() + .getTimeControl(getLifecycle(), new NetInterfaceManager.onCompleteCallback() { @Override public void onComplete() { mView.getSnTimeControlFinish(); diff --git a/app/src/main/java/com/aoleyun/sn/service/main/MainService.java b/app/src/main/java/com/aoleyun/sn/service/main/MainService.java index 68bacb1..8e65cab 100644 --- a/app/src/main/java/com/aoleyun/sn/service/main/MainService.java +++ b/app/src/main/java/com/aoleyun/sn/service/main/MainService.java @@ -109,7 +109,7 @@ public class MainService extends Service implements MainSContact.MainView, Netwo String WiFiAlias = Utils.getWifiAlias(this); Log.e("OnNetworkStatusChanged", "onConnected: " + WiFiAlias); JgyUtils.getInstance().addNetworkConnectedTime(System.currentTimeMillis() / 1000); - mPresenter.sendNetwork(JgyUtils.getInstance().getNetworkConnectedTime()); +// mPresenter.sendNetwork(JgyUtils.getInstance().getNetworkConnectedTime()); if (JgyUtils.getInstance().isScreenOn()) { TimeTask task = new TimeTask(); task.execute("ntp.aliyun.com"); @@ -922,22 +922,21 @@ public class MainService extends Service implements MainSContact.MainView, Netwo @SuppressLint("NewApi") @Override public void onReceive(Context context, Intent intent) { - Log.e(TAG, "onReceive: " + intent.getAction()); - if (Intent.ACTION_DATE_CHANGED.equals(intent.getAction())) { - Log.e("TimeChangedReceiver", "onReceive:" + "data changed"); - } else if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) { - Log.e("TimeChangedReceiver", "onReceive:" + "time changed"); - } else if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { - Log.e("TimeChangedReceiver", "onReceive:" + "timezone changed"); - } else if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) { - Log.e("TimeChangedReceiver", "onReceive:" + "time tick"); - checkShutdownTime(); - checkUploadLogTime(); - setFloatingWindow(); - } else if (ACTION_UPDATE.equals(intent.getAction())) { - setFloatingWindow(); + Log.e("TimeChangedReceiver", "onReceive: " + intent.getAction()); + switch (intent.getAction()) { + case Intent.ACTION_DATE_CHANGED: + case Intent.ACTION_TIME_CHANGED: + case Intent.ACTION_TIMEZONE_CHANGED: + case Intent.ACTION_TIME_TICK: + checkShutdownTime(); + checkUploadLogTime(); + setFloatingWindow(); + JgyUtils.getInstance().checkTimePeriod(); + break; + case ACTION_UPDATE: + setFloatingWindow(); // mPresenter.getScreenLockState(); - Log.e("TimeChangedReceiver", "onReceive:" + "date update"); + break; } timeChangedStart.onstar(System.currentTimeMillis()); } @@ -1064,6 +1063,7 @@ public class MainService extends Service implements MainSContact.MainView, Netwo } } + private interface TopApp { void open(Long time); } diff --git a/app/src/main/java/com/aoleyun/sn/utils/JgyUtils.java b/app/src/main/java/com/aoleyun/sn/utils/JgyUtils.java index c870eb3..10993dc 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/JgyUtils.java +++ b/app/src/main/java/com/aoleyun/sn/utils/JgyUtils.java @@ -55,6 +55,8 @@ import com.aoleyun.sn.bean.LessonJson; import com.aoleyun.sn.bean.NetAndLaunchBean; import com.aoleyun.sn.bean.NetAndLaunchData; import com.aoleyun.sn.bean.TTAppground; +import com.aoleyun.sn.bean.TimeControlApp; +import com.aoleyun.sn.bean.TimeControlInfo; import com.aoleyun.sn.comm.CommonConfig; import com.aoleyun.sn.comm.JGYActions; import com.aoleyun.sn.comm.PackageNames; @@ -98,6 +100,9 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; @@ -143,6 +148,8 @@ public class JgyUtils { private LessonJson mLessonJson; private TimeUtils.ContralTime mContralTime; + private List mAppPeriods; + public static final int UnknowPlatform = 0; public static final int MTKPlatform = 1; @@ -230,6 +237,7 @@ public class JgyUtils { bindEbaifenService(); } refresh(); + syncTimePeriod(); } public static void init(Context context) { @@ -1028,17 +1036,13 @@ public class JgyUtils { return; } if (appIDList == null || appIDList.isEmpty()) { - if ("G10".equals(Build.MODEL) || "D1".equals(Build.MODEL)) { - Settings.System.putString(mContext.getContentResolver(), CommonConfig.APP_VIEW_CLICK_DISABLED, "com.arivoc.wordhd:2131624676,2131624689;com.ttstd.utils:12345"); - } else { - try { - Settings.System.putString(crv, CommonConfig.APP_VIEW_CLICK_DISABLED, null); - // TODO: 2024/9/11 修复1.4.0907版本数据为空系统报错 - CmdUtil.Result result = CmdUtil.execute(" settings delete system app_view_click_disabled"); - Log.e(TAG, "writeDeselectIDtoSystem: " + result); - } catch (Exception e) { - e.printStackTrace(); - } + try { + Settings.System.putString(crv, CommonConfig.APP_VIEW_CLICK_DISABLED, null); + // TODO: 2024/9/11 修复1.4.0907版本数据为空系统报错 + CmdUtil.Result result = CmdUtil.execute(" settings delete system app_view_click_disabled"); + Log.e(TAG, "writeDeselectIDtoSystem: " + result); + } catch (Exception e) { + e.printStackTrace(); } } else { String s = appIDList.stream().map(new Function() { @@ -3916,4 +3920,133 @@ public class JgyUtils { return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString(); } } + + private String getTopActivityInfo() { + ActivityManager manager = (ActivityManager) mContext.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); + List runningTaskInfos = manager.getRunningTasks(1); + if (runningTaskInfos != null && !runningTaskInfos.isEmpty()) { + ComponentName componentName = runningTaskInfos.get(0).topActivity; + if (componentName != null) { + String currentClassName = componentName.getPackageName(); + return currentClassName; + } + } + return ""; + } + + public boolean inOpenTimePeriod(TimeControlInfo timeControlInfo) { + String startTimeStr = timeControlInfo.getStart_time(); + String endTimeStr = timeControlInfo.getEnd_time(); + + // 获取当前日期和时间 + LocalDate currentDate = LocalDate.now(); + LocalTime currentTime = LocalTime.now(); + + // 解析时间并比较 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); + LocalTime startTime = LocalTime.parse(startTimeStr, formatter); + LocalTime endTime = LocalTime.parse(endTimeStr, formatter); + + boolean inTime = !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime); + return inTime; + } + + public void syncTimePeriod() { + String jsonString = mMMKV.decodeString(CommonConfig.TIME_CONTROL_DATA_KEY, ""); + if (TextUtils.isEmpty(jsonString)) { + mAppPeriods = null; + return; + } + Gson gson = new Gson(); + Type type = new TypeToken>() { + }.getType(); + try { + mAppPeriods = gson.fromJson(jsonString, type); + Log.e(TAG, "checkTimePeriod: periods = " + mAppPeriods); + checkTimePeriod(); + } catch (Exception e) { + Log.e(TAG, "checkTimePeriod: Exception = " + e.getMessage()); + } + } + + public void checkTimePeriod() { + if (mAppPeriods == null || mAppPeriods.isEmpty()) { + return; + } + String foregroundPackage = getTopActivityInfo(); + if (ApkUtils.isSystemApp(mContext, foregroundPackage)) { + Log.d(TAG, "checkTimePeriod: " + foregroundPackage + " is system app, skip"); + return; + } + Set packageNames = mAppPeriods.stream() + .filter(new Predicate() { + @Override + public boolean test(TimeControlInfo timeControlInfo) { + return inOpenTimePeriod(timeControlInfo); + } + }) + .map(new Function>() { + @Override + public List apply(TimeControlInfo timeControlInfo) { + return timeControlInfo.getApp().stream().map(new Function() { + @Override + public String apply(TimeControlApp timeControlApp) { + return timeControlApp.getApp_package(); + } + }).collect(Collectors.toList()); + } + }) + //使用 stream 和 flatMap 将所有元素合并 + .flatMap(List::stream) + .collect(Collectors.toSet()); + Log.d(TAG, "checkTimePeriod: " + packageNames); + if (packageNames.contains(foregroundPackage)) { + Log.e(TAG, "checkTimePeriod: " + foregroundPackage + " skip"); + } else { + gotoLauncher(); + } + } + + /** + * @param pkgName + * @return true为可以打开 + */ + public boolean checkTimePeriod(String pkgName) { + if (mAppPeriods == null || mAppPeriods.isEmpty()) { + return true; + } + if (ApkUtils.isSystemApp(mContext, pkgName)) { + Log.d(TAG, "checkTimePeriod: " + pkgName + " is system app, skip"); + return true; + } + Set packageNames = mAppPeriods.stream() + .filter(new Predicate() { + @Override + public boolean test(TimeControlInfo timeControlInfo) { + return inOpenTimePeriod(timeControlInfo); + } + }) + .map(new Function>() { + @Override + public List apply(TimeControlInfo timeControlInfo) { + return timeControlInfo.getApp().stream().map(new Function() { + @Override + public String apply(TimeControlApp timeControlApp) { + return timeControlApp.getApp_package(); + } + }).collect(Collectors.toList()); + } + }) + //使用 stream 和 flatMap 将所有元素合并 + .flatMap(List::stream) + .collect(Collectors.toSet()); + Log.d(TAG, "checkTimePeriod: " + packageNames); + if (packageNames.contains(pkgName)) { + return true; + } else { + return false; + } + } + + } diff --git a/app/src/main/java/com/aoleyun/sn/utils/Utils.java b/app/src/main/java/com/aoleyun/sn/utils/Utils.java index 5752be6..b80ec75 100644 --- a/app/src/main/java/com/aoleyun/sn/utils/Utils.java +++ b/app/src/main/java/com/aoleyun/sn/utils/Utils.java @@ -874,7 +874,7 @@ public class Utils { @SuppressLint({"MissingPermission", "HardwareIds"}) public static String getSn() { // if (BuildConfig.DEBUG) { -// return "GMG1096250930004"; +// return "LTPHR23040000006"; // } String serial = "unknow"; try {