From fb7c1138df9797a4874f1184e8aa2fed63c15201 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Mon, 19 Jan 2026 09:52:39 +0800 Subject: [PATCH] =?UTF-8?q?version:1.0.6=20fix:=20update:mdm=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=AF=B9=E6=8E=A5=EF=BC=8C=E5=A2=9E=E5=8A=A0gradle?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=B5=8C=E5=85=A5=E8=AF=81=E4=B9=A6=E5=B9=B6?= =?UTF-8?q?=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 84 +- app/src/main/AndroidManifest.xml | 87 +- .../aidl/com/uiui/zy/IGetInfoInterface.aidl | 29 - .../aidl/com/uiui/zy/KeepAliveConnection.aidl | 13 + .../assets/honor_permission_statement.html | 43 + .../main/assets/honor_software_license.html | 24 + .../com/xwad/os/activity/ExitActivity.java | 33 +- .../xwad/os/activity/PasswordActivity.java | 3 +- .../xwad/os/activity/debug/DebugActivity.java | 219 +++++ .../os/activity/debug/DebugViewModel.java | 18 + .../xwad/os/activity/edit/EditActivity.java | 3 +- .../xwad/os/activity/home/HomeActivity.java | 595 +++++++++++-- .../xwad/os/activity/home/HomeViewModel.java | 67 +- .../os/activity/login/LoginViewModel.java | 3 +- .../xwad/os/activity/main/MainActivity.java | 2 +- .../xwad/os/activity/main/MainViewModel.java | 18 +- .../selectegrade/SelecteGradeActivity.java | 3 +- .../os/activity/update/UpdateActivity.java | 9 +- .../xwad/os/activity/user/UserActivity.java | 82 +- .../xwad/os/activity/user/UserViewModel.java | 15 +- .../java/com/xwad/os/adapter/AppAdapter.java | 7 +- .../xwad/os/base/BaseAlertDialogBuilder.java | 50 ++ .../com/xwad/os/base/BaseApplication.java | 10 +- .../java/com/xwad/os/bean/AppUploadInfo.java | 91 ++ .../com/xwad/os/bean/IsActivationBean.java | 78 ++ .../main/java/com/xwad/os/bean/SnPackage.java | 71 ++ .../java/com/xwad/os/bean/SnPackageApp.java | 26 + .../java/com/xwad/os/bean/TimeControl.java | 53 ++ .../main/java/com/xwad/os/bean/WhoisBean.java | 109 +++ .../java/com/xwad/os/config/CommonConfig.java | 45 + .../com/xwad/os/dialog/UserDebugDialog.java | 248 ++++++ .../java/com/xwad/os/eula/EulaDialog.java | 150 ++++ .../main/java/com/xwad/os/eula/EulaUtils.java | 63 ++ .../com/xwad/os/eula/LicenseActivity.java | 36 + app/src/main/java/com/xwad/os/eula/Utils.java | 65 ++ .../com/xwad/os/fragment/app/AppFragment.java | 8 +- .../xwad/os/fragment/app/AppViewModel.java | 211 ++++- .../xwad/os/fragment/mine/MineFragment.java | 14 +- .../xwad/os/fragment/user/UserViewModel.java | 3 +- .../usercenter/device/DeviceFragment.java | 8 +- .../usercenter/device/DeviceViewModel.java | 15 +- .../usercenter/info/InfoFragment.java | 5 +- .../com/xwad/os/jxw/base/BaseActivity.java | 110 +++ .../os/jxw/base/BaseNewThemeActivity.java | 207 +++++ .../xwad/os/jxw/base/BaseThemeActivity.java | 76 ++ .../java/com/xwad/os/manager/AmapManager.java | 69 +- .../java/com/xwad/os/manager/AppManager.java | 46 +- .../com/xwad/os/manager/ControlManager.java | 832 ++++++++++++++++++ .../com/xwad/os/manager/DeviceSNManager.java | 1 + .../java/com/xwad/os/mdm/AdminManager.java | 75 +- .../xwad/os/network/NetInterfaceManager.java | 672 +++++++++++++- .../com/xwad/os/network/RetryCallback.java | 92 ++ .../java/com/xwad/os/network/UrlAddress.java | 30 + .../java/com/xwad/os/network/api/AppApi.java | 23 + .../com/xwad/os/network/api/GetWhoisApi.java | 22 + .../com/xwad/os/network/api/SnInfoApi.java | 27 + .../xwad/os/network/api/UploadAppImgApi.java | 25 + .../xwad/os/network/api/UploadScreenshot.java | 35 + .../xwad/os/permission/PermissionUtils.java | 20 + .../java/com/xwad/os/push/PushManager.java | 567 +++++++++++- .../com/xwad/os/service/DownloadService.java | 3 +- .../com/xwad/os/service/ManagerService.java | 808 +++++++++++++++++ .../com/xwad/os/service/SocketService.java | 21 +- .../xwad/os/service/main/MainSContact.java | 86 ++ .../xwad/os/service/main/MainSPresenter.java | 212 ++++- .../com/xwad/os/service/main/MainService.java | 130 ++- .../main/java/com/xwad/os/utils/ApkUtils.java | 108 ++- .../java/com/xwad/os/utils/BitmapUtils.java | 70 ++ .../com/xwad/os/utils/BrightnessUtils.java | 140 +++ .../main/java/com/xwad/os/utils/FileUtil.java | 3 +- .../com/xwad/os/utils/GlideLoadUtils.java | 8 + .../main/java/com/xwad/os/utils/JgyUtils.java | 42 +- .../java/com/xwad/os/utils/MathUtils.java | 196 +++++ .../java/com/xwad/os/utils/ScreenUtils.java | 53 ++ .../java/com/xwad/os/utils/TimeUtils.java | 684 +++++++++++++- .../main/java/com/xwad/os/utils/Utils.java | 379 ++++++++ .../main/res/drawable-hdpi/icon_homework.png | Bin 0 -> 33934 bytes app/src/main/res/drawable/bt_disable.xml | 15 + .../main/res/drawable/bt_main_background.xml | 9 + app/src/main/res/drawable/bt_pressed.xml | 13 + .../res/drawable/debug_edit_background.xml | 18 + app/src/main/res/drawable/home_card_bg.xml | 19 + app/src/main/res/layout/activity_debug.xml | 514 +++++++++++ app/src/main/res/layout/activity_home.xml | 28 +- .../main/res/layout/activity_screen_lock.xml | 401 +++++++++ app/src/main/res/layout/activity_update.xml | 2 +- app/src/main/res/layout/activity_user.xml | 1 + app/src/main/res/layout/dialog_userdebug.xml | 121 +++ app/src/main/res/layout/eula_layout.xml | 50 ++ app/src/main/res/layout/license_layout.xml | 41 + app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/strings.xml | 5 +- app/src/main/res/values/styles.xml | 32 +- app/src/main/res/xml/file_paths.xml | 37 +- build.gradle | 6 +- 95 files changed, 9463 insertions(+), 442 deletions(-) create mode 100644 app/src/main/aidl/com/uiui/zy/KeepAliveConnection.aidl create mode 100644 app/src/main/assets/honor_permission_statement.html create mode 100644 app/src/main/assets/honor_software_license.html create mode 100644 app/src/main/java/com/xwad/os/activity/debug/DebugActivity.java create mode 100644 app/src/main/java/com/xwad/os/activity/debug/DebugViewModel.java create mode 100644 app/src/main/java/com/xwad/os/base/BaseAlertDialogBuilder.java create mode 100644 app/src/main/java/com/xwad/os/bean/AppUploadInfo.java create mode 100644 app/src/main/java/com/xwad/os/bean/IsActivationBean.java create mode 100644 app/src/main/java/com/xwad/os/bean/SnPackage.java create mode 100644 app/src/main/java/com/xwad/os/bean/SnPackageApp.java create mode 100644 app/src/main/java/com/xwad/os/bean/TimeControl.java create mode 100644 app/src/main/java/com/xwad/os/bean/WhoisBean.java create mode 100644 app/src/main/java/com/xwad/os/dialog/UserDebugDialog.java create mode 100644 app/src/main/java/com/xwad/os/eula/EulaDialog.java create mode 100644 app/src/main/java/com/xwad/os/eula/EulaUtils.java create mode 100644 app/src/main/java/com/xwad/os/eula/LicenseActivity.java create mode 100644 app/src/main/java/com/xwad/os/eula/Utils.java create mode 100644 app/src/main/java/com/xwad/os/jxw/base/BaseActivity.java create mode 100644 app/src/main/java/com/xwad/os/jxw/base/BaseNewThemeActivity.java create mode 100644 app/src/main/java/com/xwad/os/jxw/base/BaseThemeActivity.java create mode 100644 app/src/main/java/com/xwad/os/manager/ControlManager.java create mode 100644 app/src/main/java/com/xwad/os/network/RetryCallback.java create mode 100644 app/src/main/java/com/xwad/os/network/api/GetWhoisApi.java create mode 100644 app/src/main/java/com/xwad/os/network/api/UploadAppImgApi.java create mode 100644 app/src/main/java/com/xwad/os/network/api/UploadScreenshot.java create mode 100644 app/src/main/java/com/xwad/os/permission/PermissionUtils.java create mode 100644 app/src/main/java/com/xwad/os/service/ManagerService.java create mode 100644 app/src/main/java/com/xwad/os/utils/BrightnessUtils.java create mode 100644 app/src/main/java/com/xwad/os/utils/MathUtils.java create mode 100644 app/src/main/res/drawable-hdpi/icon_homework.png create mode 100644 app/src/main/res/drawable/bt_disable.xml create mode 100644 app/src/main/res/drawable/bt_main_background.xml create mode 100644 app/src/main/res/drawable/bt_pressed.xml create mode 100644 app/src/main/res/drawable/debug_edit_background.xml create mode 100644 app/src/main/res/drawable/home_card_bg.xml create mode 100644 app/src/main/res/layout/activity_debug.xml create mode 100644 app/src/main/res/layout/activity_screen_lock.xml create mode 100644 app/src/main/res/layout/dialog_userdebug.xml create mode 100644 app/src/main/res/layout/eula_layout.xml create mode 100644 app/src/main/res/layout/license_layout.xml diff --git a/app/build.gradle b/app/build.gradle index 36a5121..b53923d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.application' def appName() { - return "XwadOS" + return "XwadOSHonor" } def releaseTime() { @@ -17,8 +17,8 @@ android { minSdkVersion 23 targetSdkVersion 29 - versionCode 1 - versionName "1.0.0" + versionCode 7 + versionName "1.0.6" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -83,6 +83,79 @@ android { } +// def cerFile = file("E:\\Xuewang365\\HonorCer\\HONOR.CER") + + applicationVariants.all { variant -> + def variantName = variant.name.capitalize() + // 建议使用 packageApplication 任务,它更明确指向 APK 生成 + def packageTask = tasks.findByName("package${variantName}") + + if (packageTask) { + packageTask.doLast { + // 1. 配置路径优化:尽量使用 project 属性,避免写死 E:\ 盘符 + def cerFile = file("E:\\Xuewang365\\HonorCer\\HONOR.CER") + if (!cerFile.exists()) { + println "⚠️ 未找到证书文件: ${cerFile.path}" + return + } + + def sdkDir = android.sdkDirectory.path +// def buildToolsVersion = android.buildToolsVersion // 建议动态获取,除非有特定版本要求 + def buildToolsVersion = "33.0.0" + def buildToolsPath = "${sdkDir}/build-tools/${buildToolsVersion}" + def aaptPath = "${buildToolsPath}/aapt${org.gradle.internal.os.OperatingSystem.current().isWindows() ? '.exe' : ''}" + def apksignerPath = "${buildToolsPath}/apksigner${org.gradle.internal.os.OperatingSystem.current().isWindows() ? '.bat' : ''}" + + // 2. 关键优化:精准定位当前 Variant 的输出文件 + // 使用 variant.outputs 获取当前构建生成的特定文件 + variant.outputs.all { output -> + def apkFile = output.outputFile + println "APK地址:${apkFile.absolutePath}" + + if (apkFile != null && apkFile.name.endsWith(".apk")) { + println "🛠️ 开始对当前 APK 注入: ${apkFile.name}" + + // 3. 准备 META-INF 临时结构 + def tempBaseDir = new File(project.buildDir, "intermediates/honor_cer_temp/${variant.name}") + def metaInfDir = new File(tempBaseDir, "META-INF") + metaInfDir.deleteDir() // 清理旧数据 + metaInfDir.mkdirs() + + def targetFile = new File(metaInfDir, cerFile.name) + ant.copy(file: cerFile, tofile: targetFile) + + // 4. 调用 aapt 注入 + exec { + workingDir tempBaseDir + commandLine aaptPath, "add", apkFile.absolutePath, "META-INF/${cerFile.name}" + } + + // 5. 重新签名 (Apksigner) + def signingConfig = variant.signingConfig + if (signingConfig != null && signingConfig.storeFile.exists()) { + exec { + commandLine apksignerPath, "sign", + "--ks", signingConfig.storeFile.absolutePath, + "--ks-pass", "pass:${signingConfig.storePassword}", + "--ks-key-alias", signingConfig.keyAlias, + "--key-pass", "pass:${signingConfig.keyPassword}", + "--v2-signing-enabled", "true", + "--v3-signing-enabled", "true", + apkFile.path + } + println "✅ [${variant.name}] 注入并修复签名成功!" + } else { + println "❌ [${variant.name}] 签名失败:SigningConfig 配置无效" + } + + // 清理临时目录 + tempBaseDir.deleteDir() + } + } + } + } + } + buildTypes { debug { @@ -90,7 +163,7 @@ android { minifyEnabled false //Zipalign优化 zipAlignEnabled true - buildConfigField "String", "platform", '"tuixin"' + buildConfigField "String", "platform", '"HONOR"' signingConfig signingConfigs.tuixin applicationVariants.all { variant -> variant.outputs.each { output -> @@ -111,7 +184,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //签名 signingConfig signingConfigs.tuixin - buildConfigField "String", "platform", '"tuixin"' + buildConfigField "String", "platform", '"HONOR"' // 将release版本的包名重命名,加上版本及日期 applicationVariants.all { variant -> variant.outputs.each { output -> @@ -126,6 +199,7 @@ android { } } + } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 94b8c86..8cdd981 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,6 +8,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38,9 +65,12 @@ - + + + + @@ -127,7 +157,7 @@ android:resumeWhilePausing="true" android:screenOrientation="landscape" android:stateNotNeeded="true" - android:theme="@style/AppThemeWithoutFitsSystemWindows" + android:theme="@style/HomeThemeWithoutFitsSystemWindows" android:windowSoftInputMode="adjustPan"> @@ -241,6 +271,14 @@ android:launchMode="singleTask" android:screenOrientation="landscape" android:theme="@style/AppWhiteTheme" /> + + - - - - - - + + + + + + + + + - + + + + + + + + + + + getAdminApp(); - //写入系统数据 - boolean putSecureInt(String key, int value); - //写入系统数据 - boolean putSystemInt(String key, int value); - //写入系统数据 - boolean putSystemFloat(String key, float value); } diff --git a/app/src/main/aidl/com/uiui/zy/KeepAliveConnection.aidl b/app/src/main/aidl/com/uiui/zy/KeepAliveConnection.aidl new file mode 100644 index 0000000..8dd7ed1 --- /dev/null +++ b/app/src/main/aidl/com/uiui/zy/KeepAliveConnection.aidl @@ -0,0 +1,13 @@ +// KeepAliveConnection.aidl +package com.uiui.zy; + +// Declare any non-default types here with import statements + +interface KeepAliveConnection { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ +// void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, +// double aDouble, String aString); +} diff --git a/app/src/main/assets/honor_permission_statement.html b/app/src/main/assets/honor_permission_statement.html new file mode 100644 index 0000000..0af5abb --- /dev/null +++ b/app/src/main/assets/honor_permission_statement.html @@ -0,0 +1,43 @@ + + + + + + + + +

+ 本软件在使用过程中,为了更好的提供客户服务,基于技术必要性将会使用到如下的权限和功能: +
+
设备管理功能: +
1. 启用/禁用WLAN; +
2. 启用/禁用WLAN热点; +
3. 启用/禁用USB调试模式、数据传输; +
4. 启用/禁用存储访问(MicroSD卡); +
5. 启用/禁用NFC; +
6. 启用/禁用数据连接; +
7. 启用/禁用状态栏下拉菜单; +
8. 启用/禁用通话; +
9. 启用/禁用短信; +
10. 重启、关机; +
11. 获取root状态; +
12. 挂断当前通话; +
13. 静默安装/卸载某应用; +
14. 删除某应用数据; +
15. 停止某应用进程; +
16. 开启/关闭仅以指定某应用商店安装应用功能,开启时屏蔽其他应用商店安装,同时屏蔽其他安装方式,如屏蔽adb和SD卡安装方式; +
17. 保持某应用始终运行; +
18. 阻止某应用启动运行; +
19. 仅允许某应用被安装,屏蔽其他应用安装; +
20. 阻止某应用被卸载; +
21. 配置荣耀邮箱的Exchange参数; + + diff --git a/app/src/main/assets/honor_software_license.html b/app/src/main/assets/honor_software_license.html new file mode 100644 index 0000000..723ec86 --- /dev/null +++ b/app/src/main/assets/honor_software_license.html @@ -0,0 +1,24 @@ + + + + + + + + + + +

+您可以根据软件的具体业务场景声明您的免责协议,本协议与荣耀公司无关。 + + + \ No newline at end of file diff --git a/app/src/main/java/com/xwad/os/activity/ExitActivity.java b/app/src/main/java/com/xwad/os/activity/ExitActivity.java index e021054..099a5dd 100644 --- a/app/src/main/java/com/xwad/os/activity/ExitActivity.java +++ b/app/src/main/java/com/xwad/os/activity/ExitActivity.java @@ -9,6 +9,7 @@ import android.media.AudioAttributes; import android.media.SoundPool; import android.os.Build; import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -24,6 +25,7 @@ import com.xwad.os.R; import com.xwad.os.base.BaseDataBindingActivity; import com.xwad.os.config.CommonConfig; import com.xwad.os.databinding.ActivityExitBinding; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.utils.Utils; import java.util.List; @@ -163,32 +165,35 @@ public class ExitActivity extends BaseDataBindingActivity { } private void exitDesktop() { - List componentNames = getAllLauncherApps(); - Log.e(TAG, "exitDesktop: " + componentNames); - if (componentNames != null && componentNames.size() != 0) { - ComponentName componentName = componentNames.get(0); - Intent intent = new Intent(); - intent.setComponent(componentName); - try { - startActivity(intent); - } catch (Exception e) { - Log.e(TAG, "exitDesktop: " + e.getMessage()); - } - } +// List componentNames = getAllLauncherApps(); +// Log.e(TAG, "exitDesktop: " + componentNames); +// if (componentNames != null && componentNames.size() != 0) { +// ComponentName componentName = componentNames.get(0); +// Intent intent = new Intent(); +// intent.setComponent(componentName); +// try { +// startActivity(intent); +// } catch (Exception e) { +// Log.e(TAG, "exitDesktop: " + e.getMessage()); +// } +// } +// +// startActivity(new Intent(Settings.ACTION_HOME_SETTINGS)); - startActivity(new Intent(Settings.ACTION_HOME_SETTINGS)); + AdminManager.getInstance().setDefaultLauncher("com.hihonor.android.launcher", "com.hihonor.android.launcher.unihome.UniHomeLauncher"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAndRemoveTask(); } else { finishAffinity(); } + android.os.Process.killProcess(android.os.Process.myPid()); System.exit(0); } private void setEmpty() { - Handler.getMain().postDelayed(new Runnable() { + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { mBinding.icv.clearInputContent(); diff --git a/app/src/main/java/com/xwad/os/activity/PasswordActivity.java b/app/src/main/java/com/xwad/os/activity/PasswordActivity.java index 34d04c5..59ed6cc 100644 --- a/app/src/main/java/com/xwad/os/activity/PasswordActivity.java +++ b/app/src/main/java/com/xwad/os/activity/PasswordActivity.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -155,7 +156,7 @@ public class PasswordActivity extends BaseDataBindingActivity { } private void setEmpty() { - Handler.getMain().postDelayed(new Runnable() { + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { mBinding.icv.clearInputContent(); diff --git a/app/src/main/java/com/xwad/os/activity/debug/DebugActivity.java b/app/src/main/java/com/xwad/os/activity/debug/DebugActivity.java new file mode 100644 index 0000000..ccda3d9 --- /dev/null +++ b/app/src/main/java/com/xwad/os/activity/debug/DebugActivity.java @@ -0,0 +1,219 @@ +package com.xwad.os.activity.debug; + +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.util.Log; +import android.view.View; +import android.widget.CompoundButton; + +import com.hihonor.android.app.admin.DeviceApplicationManager; +import com.hihonor.android.app.admin.DeviceControlManager; +import com.hihonor.android.app.admin.DeviceHwSystemManager; +import com.hihonor.android.app.admin.DevicePackageManager; +import com.hihonor.android.app.admin.DevicePasswordManager; +import com.hihonor.android.app.admin.DeviceRestrictionManager; +import com.hihonor.android.app.admin.DeviceSettingsManager; +import com.xwad.os.R; +import com.xwad.os.base.mvvm.BaseMvvmActivity; +import com.xwad.os.databinding.ActivityDebugBinding; +import com.xwad.os.mdm.AdminManager; +import com.xwad.os.receiver.AoleDeviceAdminReceiver; +import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX; + +public class DebugActivity extends BaseMvvmActivity { + private static final String TAG = "DebugActivity"; + + private DevicePolicyManager mDevicePolicyManager; + private DeviceRestrictionManager mDeviceRestrictionManager; + private DeviceControlManager mDeviceControlManager; + private DeviceApplicationManager mDeviceApplicationManager; + private DeviceHwSystemManager mDeviceHwSystemManager; + private DeviceSettingsManager mDeviceSettingsManager; + private DevicePasswordManager mDevicePasswordManager; + + /*设备包管理类*/ + private DevicePackageManager mDevicePackageManager; + + private ComponentName mAdminName; + + @Override + public boolean setNightMode() { + return true; + } + +// @Override +// public boolean setfitWindow() { +// return true; +// } + + @Override + protected int getLayoutId() { + return R.layout.activity_debug; + } + + @Override + protected void initDataBinding() { + mViewModel.setCtx(this); + mViewModel.setLifecycle(getLifecycleSubject()); + mViewModel.setVDBinding(mViewDataBinding); + mViewDataBinding.setClick(new BtnClick()); + } + + @Override + protected void initView() { + UltimateBarX.addStatusBarTopPadding(mViewDataBinding.bannerLayout); + addNavigationBarBottomPadding(mViewDataBinding.clBottom); + + mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); + mDeviceRestrictionManager = new DeviceRestrictionManager(); + mDeviceControlManager = new DeviceControlManager(); + mDeviceApplicationManager = new DeviceApplicationManager(); + mDeviceHwSystemManager = new DeviceHwSystemManager(); + mDeviceSettingsManager = new DeviceSettingsManager(); + mDevicePackageManager = new DevicePackageManager(); + mDevicePasswordManager = new DevicePasswordManager(); + mAdminName = new ComponentName(this, AoleDeviceAdminReceiver.class); + + mViewDataBinding.swWindow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mDeviceRestrictionManager.setMultiWindowDisabled(mAdminName, isChecked); + } + }); + mViewDataBinding.swYoyo.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mDeviceRestrictionManager.setVoiceAssistantButtonDisabled(mAdminName, isChecked); + if (isChecked) { + AdminManager.getInstance().removeDisallowedRunningApp("com.hihonor.servicecenter"); + AdminManager.getInstance().addDisallowedRunningApp("com.hihonor.magicvoice"); + } else { + AdminManager.getInstance().addDisallowedRunningApp("com.hihonor.servicecenter"); + AdminManager.getInstance().removeDisallowedRunningApp("com.hihonor.magicvoice"); + } + } + }); + mViewDataBinding.swRestore.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mDeviceSettingsManager.setRestoreFactoryDisabled(mAdminName, isChecked); + } + }); + mViewDataBinding.swUsbDebug.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mDeviceRestrictionManager.setUSBDataDisabled(mAdminName, isChecked); + mDeviceControlManager.turnOnUsbDebugMode(mAdminName, !isChecked); + } + }); + mViewDataBinding.swRemoveAdmin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + mDeviceControlManager.setForcedActiveDeviceAdmin(mAdminName, DebugActivity.this); + } else { + mDeviceControlManager.removeActiveDeviceAdmin(mAdminName); + mDeviceControlManager.clearDeviceOwnerApp(); + } + } + }); + mViewDataBinding.swExpandPanel.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + try { + mDeviceRestrictionManager.setStatusBarExpandPanelDisabled(mAdminName, isChecked); + } catch (Exception e) { + Log.e(TAG, "onCheckedChanged: " + e.getMessage()); + } + } + }); + mViewDataBinding.swQuickTools.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + try { + mDevicePasswordManager.setQuickToolsDisabled(mAdminName, isChecked); + } catch (Exception e) { + Log.e(TAG, "onCheckedChanged: " + e.getMessage()); + } + } + }); + mViewDataBinding.swPowerOff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + try { + mDeviceRestrictionManager.setPowerDisabled(mAdminName, isChecked); + } catch (Exception e) { + Log.e(TAG, "onCheckedChanged: " + e.getMessage()); + } + } + }); + mViewDataBinding.swMultiWindow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + try { + mDeviceRestrictionManager.setMultiWindowDisabled(mAdminName, isChecked); + } catch (Exception e) { + Log.e(TAG, "onCheckedChanged: " + e.getMessage()); + } + } + }); + } + + @Override + protected void initData() { + + } + + @Override + protected void onResume() { + super.onResume(); + getAdminStatus(); + } + + private void getAdminStatus() { + if (isActiveMe()) { + mViewDataBinding.tvAdmin.setText("已激活"); + mViewDataBinding.swWindow.setChecked(mDeviceRestrictionManager.isMultiWindowDisabled(mAdminName)); + mViewDataBinding.swYoyo.setChecked(mDeviceRestrictionManager.isVoiceAssistantButtonDisabled(mAdminName)); + mViewDataBinding.swRestore.setChecked(mDeviceSettingsManager.isRestoreFactoryDisabled(mAdminName)); + mViewDataBinding.swUsbDebug.setChecked(mDeviceRestrictionManager.isUSBDataDisabled(mAdminName)); + mViewDataBinding.swRemoveAdmin.setChecked(mDeviceControlManager.isForcedActiveDeviceAdmin(mAdminName)); + mViewDataBinding.swExpandPanel.setChecked(mDeviceRestrictionManager.isStatusBarExpandPanelDisabled(mAdminName)); + mViewDataBinding.swQuickTools.setChecked(mDevicePasswordManager.isQuickToolsDisabled(mAdminName)); + mViewDataBinding.swPowerOff.setChecked(mDeviceRestrictionManager.isPowerDisabled(mAdminName)); + mViewDataBinding.swMultiWindow.setChecked(mDeviceRestrictionManager.isMultiWindowDisabled(mAdminName)); + + } else { + mViewDataBinding.tvAdmin.setText("未激活"); + } + } + + /** + * 判断是否激活 + * + * @return + */ + private boolean isActiveMe() { + boolean active; + if (mDevicePolicyManager == null) { + active = false; + } else { + active = mDevicePolicyManager.isAdminActive(mAdminName); + } + Log.e(TAG, "isActiveMe: active = " + active); + return active; + } + + public class BtnClick { + public void exit(View view) { + finish(); + } + + public void refresh(View view) { + getAdminStatus(); + } + } + + +} diff --git a/app/src/main/java/com/xwad/os/activity/debug/DebugViewModel.java b/app/src/main/java/com/xwad/os/activity/debug/DebugViewModel.java new file mode 100644 index 0000000..e751014 --- /dev/null +++ b/app/src/main/java/com/xwad/os/activity/debug/DebugViewModel.java @@ -0,0 +1,18 @@ +package com.xwad.os.activity.debug; + +import com.trello.rxlifecycle4.android.ActivityEvent; +import com.xwad.os.base.mvvm.BaseViewModel; +import com.xwad.os.databinding.ActivityDebugBinding; + +public class DebugViewModel extends BaseViewModel { + + @Override + public ActivityDebugBinding getVDBinding() { + return binding; + } + + @Override + public void onDestroy() { + + } +} diff --git a/app/src/main/java/com/xwad/os/activity/edit/EditActivity.java b/app/src/main/java/com/xwad/os/activity/edit/EditActivity.java index df8214e..e18a223 100644 --- a/app/src/main/java/com/xwad/os/activity/edit/EditActivity.java +++ b/app/src/main/java/com/xwad/os/activity/edit/EditActivity.java @@ -14,6 +14,7 @@ import com.xwad.os.base.mvvm.BaseMvvmActivity; import com.xwad.os.config.CommonConfig; import com.xwad.os.databinding.ActivityEditBinding; import com.xwad.os.manager.DeviceSNManager; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.utils.ActivationUtil; import java.util.HashMap; @@ -102,7 +103,7 @@ public class EditActivity extends BaseMvvmActivity params = new HashMap<>(); - params.put("sn", DeviceSNManager.getDeviceSN()); + params.put("sn", AdminManager.getInstance().getSerial()); params.put(mKey, mViewDataBinding.editText.getText().toString()); mViewModel.updateInfo(params); } else { diff --git a/app/src/main/java/com/xwad/os/activity/home/HomeActivity.java b/app/src/main/java/com/xwad/os/activity/home/HomeActivity.java index 662a8bf..f7717b3 100644 --- a/app/src/main/java/com/xwad/os/activity/home/HomeActivity.java +++ b/app/src/main/java/com/xwad/os/activity/home/HomeActivity.java @@ -1,5 +1,6 @@ package com.xwad.os.activity.home; +import android.app.admin.DevicePolicyManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -11,6 +12,7 @@ import android.content.res.Resources; import android.os.BatteryManager; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -21,6 +23,7 @@ import android.view.animation.TranslateAnimation; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; @@ -28,6 +31,7 @@ import androidx.lifecycle.Observer; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.viewpager.widget.ViewPager; +import com.hihonor.android.app.admin.DeviceControlManager; import com.hjq.permissions.OnPermissionCallback; import com.hjq.permissions.XXPermissions; import com.hjq.toast.Toaster; @@ -39,13 +43,17 @@ import com.xwad.os.activity.login.LoginActivity; import com.xwad.os.activity.permission.PermissionActivity; import com.xwad.os.activity.update.UpdateActivity; import com.xwad.os.base.mvvm.BaseMvvmActivity; +import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.AppUpdateInfo; +import com.xwad.os.bean.PhraseContent; import com.xwad.os.bean.UserInfo; import com.xwad.os.bean.jxw.TabBean; import com.xwad.os.config.CommonConfig; import com.xwad.os.databinding.ActivityHomeBinding; import com.xwad.os.dialog.PermissionsDialog; import com.xwad.os.dialog.PrivacyPolicyDialog; +import com.xwad.os.eula.EulaDialog; +import com.xwad.os.eula.EulaUtils; import com.xwad.os.fragment.ai.AiFragment; import com.xwad.os.fragment.app.AppFragment; import com.xwad.os.fragment.chinese.ChineseFragment; @@ -64,10 +72,13 @@ import com.xwad.os.jxw.fragment.SztzFragment; import com.xwad.os.jxw.util.Util; import com.xwad.os.manager.DeviceSNManager; import com.xwad.os.mdm.AdminManager; +import com.xwad.os.permission.PermissionUtils; +import com.xwad.os.receiver.AoleDeviceAdminReceiver; import com.xwad.os.service.main.MainService; import com.xwad.os.utils.ActivationUtil; import com.xwad.os.utils.ApkUtils; import com.xwad.os.utils.DataUtil; +import com.xwad.os.utils.JgyUtils; import com.xwad.os.utils.OpenApkUtils; import com.xwad.os.utils.Utils; import com.xwad.os.view.jxw.widget.DefaultAppsDialog; @@ -76,17 +87,48 @@ import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableOnSubscribe; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; import me.jessyan.autosize.AutoSizeCompat; import me.jessyan.autosize.AutoSizeConfig; -public class HomeActivity extends BaseMvvmActivity { +public class HomeActivity extends BaseMvvmActivity { private static final String TAG = "HomeActivity"; private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + private static final int REQUEST_ENABLE = 4321; + + private ArrayList forceAppList = new ArrayList() {{ + this.add(BuildConfig.APPLICATION_ID); + }}; + + private ArrayList mPersistentApp=new ArrayList(){{ + this.add(BuildConfig.APPLICATION_ID); + this.add("com.jxw.launcher"); + this.add("com.jxw.zncd"); + this.add("com.jxw.tbdd"); + this.add("com.jxw.tbfd"); + this.add("com.jxw.qkxx"); + this.add("com.jxw.jpkc"); + this.add("com.jxw.download"); + this.add("com.jxw.jxw"); + this.add("com.study.flashplayer"); + this.add("com.jxw.question"); + }}; + + private DevicePolicyManager mDevicePolicyManager; + private DeviceControlManager mDeviceControlManager; + private ComponentName mAdminName; + private EulaDialog mEulaDialog; + private List tabBeanLists = new ArrayList<>(); private List fragments = new ArrayList<>(); @@ -118,30 +160,30 @@ public class HomeActivity extends BaseMvvmActivity= Build.VERSION_CODES.O) { +// startForegroundService(intent); +// } else { +// startService(intent); +// } if (Build.VERSION.SDK_INT >= 33) { hideSystemUI(); @@ -163,49 +205,20 @@ public class HomeActivity extends BaseMvvmActivity() { + mViewModel.mAppUpdateInfoData.observe(this, new Observer() { @Override - public void onChanged(AppUpdateInfo appUpdateInfo) { + public void onChanged(AppInfo appUpdateInfo) { if (appUpdateInfo == null) { // Toaster.show("已是最新版本"); } else { @@ -220,7 +233,7 @@ public class HomeActivity extends BaseMvvmActivity() { @Override public void onChanged(Boolean aBoolean) { @@ -240,13 +253,395 @@ public class HomeActivity extends BaseMvvmActivity() { + @Override + public void onChanged(PhraseContent phraseContent) { + String text = phraseContent.getContent(); + mViewDataBinding.tvNotification.setText(text); + mViewDataBinding.tvNotification.requestFocus(); + } + }); + mViewModel.getPhrase(); + mViewModel.getSystemSettings(); mViewModel.getOauthToken(); mViewModel.getAnswerControlStatus(); + mViewModel.getPublicIp(); + } + + private void initViews() { + Log.e(TAG, "initViews: " ); + long time = System.currentTimeMillis(); + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + mViewDataBinding.rlTab.setLayoutManager(linearLayoutManager); + + tabAdapter = new TabAdapter(tabBeanLists); + tabAdapter.setOnItemClickListener(new TabAdapter.RadiaoOnItemClickListener() { + @Override + public void onSelectClick(int i) { + tabAdapter.setChoosePosition(i); + mViewDataBinding.subjectViewPager.setCurrentItem(i); + } + }); + mViewDataBinding.rlTab.setAdapter(tabAdapter); + + mViewDataBinding.subjectViewPager.setOffscreenPageLimit(12); + mViewDataBinding.subjectViewPager.setScrollAnim(true); + mViewDataBinding.subjectViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrollStateChanged(int i) { + + } + + @Override + public void onPageScrolled(int i, float f, int i2) { + + } + + @Override + public void onPageSelected(int i) { + tabAdapter.setChoosePosition(i); + mViewDataBinding.rlTab.scrollToPosition(i); + } + }); initDatas(); + Log.e(TAG, "initViews: time = " + (System.currentTimeMillis() - time) + "ms"); + } + /** + * 先判断用户协议,再判断mdm授权,然后判断应用权限 + */ + private void checkEula() { + EulaUtils eulaUtils = new EulaUtils(); + boolean hasUserAccepted = eulaUtils.hasUserAccepted(); + if (hasUserAccepted) { + checkActiveAdmin(); + } else { + if (mEulaDialog == null) { + mEulaDialog = new EulaDialog(this, mDevicePolicyManager, mAdminName, new EulaDialog.EulaCallback() { + @Override + public void onGranted() { + checkActiveAdmin(); + } + + @Override + public void onDenied() { + finish(); + } + }); + } + mEulaDialog.show(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == REQUEST_ENABLE) { + Log.e(TAG, "onActivityResult: " + REQUEST_ENABLE); + checkActiveAdmin(); + } + } + } + + private void checkActiveAdmin() { +// Debug.waitForDebugger(); + int controlMode = 0; + try { + controlMode = mDeviceControlManager.getControlMode(mAdminName); + } catch (Exception e) { + Log.e(TAG, "checkActiveAdmin: getControlMode Exception: " + e.getMessage()); + } + Log.e(TAG, "checkActiveAdmin: controlMode = " + controlMode); + //判断管控模式 + if (controlMode == 0) { + //0:普通模式走原生激活 + if (!isActiveMe()) { + userActiveAdmin(); + Log.e(TAG, "checkActiveAdmin: userActiveAdmin0"); + } else { + userActiveAdmin(); + setDefault(); + Log.e(TAG, "checkActiveAdmin: setDefault0"); + } + } else if (controlMode == 1) { + //1:管控模式静默激活 + if (!isActiveMe()) { + forceActiveAdmin(); + Log.e(TAG, "checkActiveAdmin: forceActiveAdmin1"); + } else { + setDefault(); + Log.e(TAG, "checkActiveAdmin: setDefault1"); + } + } +// Log.e(TAG, "checkActiveAdmin: removeActiveDeviceAdmin = " + mDeviceControlManager.removeActiveDeviceAdmin(mAdminName)); +// mDeviceControlManager.clearDeviceOwnerApp(); + } + + private void forceActiveAdmin() { + Toaster.show("请先激活设备"); + try { +// if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + //No virtual method setForcedActiveDeviceAdmin(Landroid/content/ComponentName;Landroid/content/Context;) + // Z in class Lcom/huawei/android/app/admin/DeviceControlManager; + // or its super classes (declaration of 'com.huawei.android.app.admin.DeviceControlManager' appears in /system/framework/hwframework.jar); + + //先强制激活,如果不能则手动激活 + boolean active = mDeviceControlManager.setForcedActiveDeviceAdmin(mAdminName, this); + Log.e(TAG, "forceActiveAdmin: " + "setForcedActiveDeviceAdmin = " + active); + if (!active) { + userActiveAdmin(); + } else { + + } +// } else { +// mDeviceControlManager.setForcedActiveDeviceAdmin(mAdminName, this); +// Log.e(TAG, "forceActiveAdmin: " + "setForcedActiveDeviceAdmin = " + mDevicePolicyManager.isAdminActive(mAdminName)); +// if (!mDevicePolicyManager.isAdminActive(mAdminName)) { +// userActiveAdmin(); +// } +// } + } catch (NoSuchMethodError error) { + Log.e(TAG, "forceActiveAdmin: " + error.getMessage()); + Toast.makeText(this, getString(R.string.not_support), Toast.LENGTH_SHORT).show(); + userActiveAdmin(); + } catch (SecurityException | IllegalArgumentException e) { + Log.e(TAG, "forceActiveAdmin: " + e.getMessage()); + Toast.makeText(this, getString(R.string.force_active_error), Toast.LENGTH_LONG).show(); + } + } + + private void userActiveAdmin() { + Log.e(TAG, "userActiveAdmin: "); + //如果当前APK没有被设备管理激活,则先进行激活 + if (mDevicePolicyManager != null && !mDevicePolicyManager.isAdminActive(mAdminName)) { + Log.e(TAG, "userActiveAdmin: " + "not Admin Active"); + Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName); + startActivityForResult(intent, REQUEST_ENABLE); + } else { + Log.e(TAG, "userActiveAdmin: " + "Admin Active"); +// try { +// //为1时获取不了sn +// mDeviceControlManager.setControlMode(mAdminName, 1); +// } catch (Exception e) { +// Log.e(TAG, "userActiveAdmin: setControlMode: " + e.getMessage()); +// } + try { + mDeviceControlManager.setForcedActiveDeviceAdmin(mAdminName, this); + Log.e(TAG, "userActiveAdmin: " + "setForcedActiveDeviceAdmin"); + } catch (Exception e) { + Log.e(TAG, "userActiveAdmin: setForcedActiveDeviceAdmin: " + e.getMessage()); + } + } + } + + /** + * https://developer.honor.com/cn/docs/11015/guides/faq + * setDeviceOwnerApp不能登录账户 + */ + private void setDeviceOwnerApp() { + int sdk_int = Utils.getMagicOsVersion(); + Log.e(TAG, "setDeviceOwnerApp: MagicOS Version = " + sdk_int); + if (sdk_int >= 26) { + //Magic UI 4.0 及以上 + try { + mDeviceControlManager.setDeviceOwnerApp(mAdminName, getPackageName()); + Log.e(TAG, "setDeviceOwnerApp: " + Utils.getSerial(HomeActivity.this)); + Log.e(TAG, "setDeviceOwnerApp: successful1"); + } catch (Exception e) { + if (e.getMessage().contains("accounts")) { + Toaster.showLong("设备激活失败,请退出账号"); + Toaster.debugShow(e.getMessage()); + } + Log.e(TAG, "setDeviceOwnerApp: " + e.getMessage()); + } + } else { + // 反射调用setDeviceOwnerApp,激活Device Owner,MagicOS 7.0以上可以直接调用SDK里的对应方法 + DeviceControlManager dcm = new DeviceControlManager(); + try { + Method m = dcm.getClass().getDeclaredMethod("setDeviceOwnerApp", ComponentName.class, String.class); + if (m != null) { + m.invoke(dcm, mAdminName, getPackageName()); // componentName为APK的设备管理器组件 + Log.e(TAG, "setDeviceOwnerApp successful2"); + } + } catch (Exception e) { + Toaster.show("设备激活失败,请退出账号"); + Log.e(TAG, "setDeviceOwnerApp error: " + e.toString()); + e.printStackTrace(); + } + } + } + + private void setDefault() { + Log.e(TAG, "setDefault: "); + AdminManager.init(this); + getPermission(); + debugTest(); + setDeviceOwnerApp(); + setDisallowUninstall(); + JgyUtils.getInstance().startServices(); + + long time = System.currentTimeMillis(); + + if (BuildConfig.DEBUG) { + boolean onUsb = AdminManager.getInstance().turnOnUsbDebugMode(true); +// Toaster.show("打开usb: " + onUsb); + } + AdminManager.getInstance().setCustomSettingsMenu(mMenuList); + AdminManager.getInstance().setTimeAndDateSetDisabled(false); + AdminManager.getInstance().setPowerSaveModeDisabled(true); + AdminManager.getInstance().setSearchIndexDisabled(true); + AdminManager.getInstance().setSystemBrowserDisabled(false); + AdminManager.getInstance().setMultiWindowDisabled(true); + AdminManager.getInstance().setVoiceAssistantButtonDisabled(true); + AdminManager.getInstance().addAlertWindowApps(forceAppList); + +// AdminManager.getInstance().setRestoreFactoryDisabled(true); + AdminManager.getInstance().setDefaultLauncher("com.xwad.os"); + AdminManager.getInstance().addIgnoreFrequentRelaunchAppList("com.xwad.os"); + AdminManager.getInstance().addDisallowedRunningApp("com.hihonor.servicecenter"); +// AdminManager.getInstance().setStatusBarExpandPanelDisabled(true); + AdminManager.getInstance().setQuickToolsDisabled(true); + + Log.e(TAG, "setDefault: time = " + (System.currentTimeMillis() - time) + "ms"); + } + + private static final List mMenuList = new ArrayList() {{ + this.add("digital_balance"); + this.add("smart_assistant"); + this.add("users_accounts"); + this.add("google"); + this.add("backup_settings"); + this.add("apps_honor_tips"); + this.add("pengine_settings"); + }}; + + private void getPermission() { + Log.e(TAG, "getPermission: "); + if (XXPermissions.isGranted(HomeActivity.this, PermissionUtils.PERMISSIONS)) { + initViews(); + Log.e(TAG, "getPermission: " + "isGranted"); + } else { + XXPermissions.with(this) + // 申请单个权限 + .permission(PermissionUtils.PERMISSIONS) + // 申请多个权限 +// .permission(group) + // 设置权限请求拦截器(局部设置) + //.interceptor(new PermissionInterceptor()) + // 设置不触发错误检测机制(局部设置) + //.unchecked() + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (!all) { + Toaster.show("请授予所有权限确保正常使用"); + } else { + initViews(); + Log.e(TAG, "onGranted: " + "获取权限成功"); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + Toaster.show("被永久拒绝授权,请手动授予权限"); + // 如果是被永久拒绝就跳转到应用权限系统设置页面 + XXPermissions.startPermissionActivity(HomeActivity.this, permissions); + } else { + Toaster.show("获取权限失败"); + } + } + }); + } + } + + private void setDisallowUninstall() { + Observable.create((ObservableOnSubscribe) emitter -> { + Log.e("setDisallowUninstall", "subscribe: "); +// //强制激活设备管理器 +// AdminManager.getInstance().setForcedActiveDeviceAdmin(); + // 添加阻止某应用被卸载名单 + AdminManager.getInstance().addDisallowedUninstallPackages(forceAppList); + Log.e(TAG, "setDisallowUninstall: getDisallowedUninstallPackageList: " + AdminManager.getInstance().getDisallowedUninstallPackageList()); + // 添加保持某应用始终运行名单 + AdminManager.getInstance().addPersistentApp(mPersistentApp); + Log.e(TAG, "setDisallowUninstall: getPersistentApp: " + AdminManager.getInstance().getPersistentApp()); + //设置可信任应用列表 + AdminManager.getInstance().removeSuperTrustListForHwSystemManger(AdminManager.getInstance().getSuperTrustListForHwSystemManger()); + // TODO: 2026/1/13 有闪退但是没有报错信息 +// AdminManager.getInstance().setSuperTrustListForHwSystemManger(forceAppList); + Log.e(TAG, "setDisallowUninstall: getSuperTrustListForHwSystemManger = " + AdminManager.getInstance().getSuperTrustListForHwSystemManger()); +// AdminManager.getInstance().addDisabledDeactivateMdmPackages(forceAppList); + Log.e(TAG, "setDisallowUninstall: getSerial: " + Utils.getSerial(this)); + AdminManager.getInstance().addInstallPackageDefaultTrustList(ApkUtils.mJxwApps); + emitter.onNext(1); + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new io.reactivex.rxjava3.core.Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("setDisallowUninstall", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull Integer integer) { + Log.e("setDisallowUninstall", "onNext: "); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("setDisallowUninstall", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("setDisallowUninstall", "onComplete: "); + } + }); + } + + private void debugTest() { + if (BuildConfig.DEBUG) { + Log.e(TAG, "debugTest: " + AdminManager.getInstance().getSerial()); + Log.e(TAG, "debugTest: " + Utils.getSerial(this)); + Log.e(TAG, "debugTest: " + Utils.getAndroid10MAC(this)); + } + } + + // 激活 + private void activeLicense() { +// hemInstance.activeLicense(); + } + + // 去激活 + private void deActiveLicense() { +// hemInstance.deActiveLicense(); + } + + /** + * 判断是否激活 + * + * @return + */ + private boolean isActiveMe() { + boolean active; + if (mDevicePolicyManager == null) { + active = false; + } else { + active = mDevicePolicyManager.isAdminActive(mAdminName); + } + Log.e(TAG, "isActiveMe: active = " + active); + return active; + } + + @Subscribe(threadMode = ThreadMode.MAIN) public void onGkNoticeEvent(UpdateGradeEvent updateGradeEvent) { Log.e(TAG, "onGkNoticeEvent: "); @@ -407,19 +802,17 @@ public class HomeActivity extends BaseMvvmActivity>() { @Override public void onSubscribe(@NonNull Disposable d) { @@ -126,22 +130,22 @@ public class HomeViewModel extends BaseViewModel mAppUpdateInfoData = new MutableLiveData<>(); + public MutableLiveData mAppUpdateInfoData = new MutableLiveData<>(); public void checkUpdate() { - NetInterfaceManager.getInstance().getCheckUpdateObservable(BuildConfig.APPLICATION_ID) + NetInterfaceManager.getInstance().getUpdateObservable(BuildConfig.APPLICATION_ID) .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) - .subscribe(new Observer>() { + .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { Log.e("checkUpdate", "onSubscribe: "); } @Override - public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { + public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { Log.e("checkUpdate", "onNext: " + appUpdateInfoBaseResponse); if (appUpdateInfoBaseResponse.code == 200) { - AppUpdateInfo appUpdateInfo = appUpdateInfoBaseResponse.data; + AppInfo appUpdateInfo = appUpdateInfoBaseResponse.data; mAppUpdateInfoData.setValue(appUpdateInfo); } else { mAppUpdateInfoData.setValue(null); @@ -150,8 +154,8 @@ public class HomeViewModel extends BaseViewModel() { @Override public void onSubscribe(@NonNull Disposable d) { @@ -357,4 +362,50 @@ public class HomeViewModel extends BaseViewModel mPhraseData = new MutableLiveData<>(); + + public void getPhrase() { + boolean activation = ActivationUtil.getInstance().isActivation(); + if (!activation) { + return; + } + NetInterfaceManager.getInstance().getPhraseObservable() + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getPhrase", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse phraseContentBaseResponse) { + Log.e("getPhrase", "onNext: " + phraseContentBaseResponse); + if (phraseContentBaseResponse.code == 200) { + PhraseContent phraseContent = phraseContentBaseResponse.data; + mPhraseData.setValue(phraseContent); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getPhrase", "onError: "); + } + + @Override + public void onComplete() { + Log.e("getPhrase", "onComplete: "); + } + }); + } + } diff --git a/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java b/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java index fe89b12..2a9bfed 100644 --- a/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java +++ b/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java @@ -93,7 +93,8 @@ public class LoginViewModel extends BaseViewModel appUpdateInfoBaseResponse) { + public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { Log.e("checkUpdate", "onNext: " + appUpdateInfoBaseResponse); if (appUpdateInfoBaseResponse.code == 200) { - AppUpdateInfo appUpdateInfo = appUpdateInfoBaseResponse.data; + AppInfo appUpdateInfo = appUpdateInfoBaseResponse.data; mAppUpdateInfoData.setValue(appUpdateInfo); } else { mAppUpdateInfoData.setValue(null); @@ -145,8 +147,8 @@ public class MainViewModel extends BaseViewModel params = new HashMap<>(); - params.put("sn", DeviceSNManager.getDeviceSN()); + params.put("sn", AdminManager.getInstance().getSerial()); params.put("sn_grade", grade); mViewModel.updateInfo(params); } else { diff --git a/app/src/main/java/com/xwad/os/activity/update/UpdateActivity.java b/app/src/main/java/com/xwad/os/activity/update/UpdateActivity.java index d866447..eb1c25f 100644 --- a/app/src/main/java/com/xwad/os/activity/update/UpdateActivity.java +++ b/app/src/main/java/com/xwad/os/activity/update/UpdateActivity.java @@ -9,6 +9,7 @@ import com.arialyy.aria.core.download.DownloadEntity; import com.hjq.toast.Toaster; import com.xwad.os.R; import com.xwad.os.base.mvvm.BaseMvvmActivity; +import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.AppUpdateInfo; import com.xwad.os.databinding.ActivityUpdateBinding; import com.xwad.os.service.DownloadService; @@ -18,7 +19,7 @@ import static com.arialyy.aria.core.inf.IEntity.STATE_RUNNING; public class UpdateActivity extends BaseMvvmActivity { - private AppUpdateInfo mAppInfoData; + private AppInfo mAppInfoData; @Override @@ -42,14 +43,14 @@ public class UpdateActivity extends BaseMvvmActivity() { + mViewModel.mAppUpdateInfoData.observe(this, new Observer() { @Override - public void onChanged(AppUpdateInfo appUpdateInfo) { + public void onChanged(AppInfo appUpdateInfo) { if (appUpdateInfo == null) { // Toaster.show("已是最新版本"); } else { @@ -193,6 +203,68 @@ public class UserActivity extends BaseMvvmActivity= SystemClock.uptimeMillis() - DEBUGDURATION) { + mDEBUGHits = new long[DEBUGCOUNTS]; //重新初始化数组 +// if (mMMKV.decodeBool(CommonConfig.EnableDebug, false)) { +// Toaster.show("已关闭Debug模式"); +// mMMKV.encode(CommonConfig.EnableDebug, false); +// } else { + showDebugDialog(); +// } + } + } + + private UserDebugDialog mUserDebugDialog; + + private void showDebugDialog() { + if (mUserDebugDialog != null) { + mUserDebugDialog.dismiss(); + mUserDebugDialog = null; + } + mUserDebugDialog = new UserDebugDialog(this); + mUserDebugDialog.setOnClickBottomListener(new UserDebugDialog.OnClickBottomListener() { + @Override + public void onPositiveClick() { + String pwd = mMMKV.decodeString(CommonConfig.SCREEN_LOCK_PWD, CommonConfig.SUPER_PASSWORD); + if (CommonConfig.SUPER_PASSWORD.equals(mUserDebugDialog.getEdittext()) || pwd.equals(mUserDebugDialog.getEdittext())) { +// mMMKV.encode(CommonConfig.EnableDebug, true); + Toaster.show("进入用户Debug模式"); + startActivity(new Intent(UserActivity.this, DebugActivity.class)); +// AdminManager.getInstance().setRestoreFactoryDisabled(1); +// AdminManager.getInstance().removeActiveDeviceAdmin(); + } else { + Toaster.show("密码错误"); + } + mUserDebugDialog.dismiss(); + } + + @Override + public void onNegtiveClick() { + mUserDebugDialog.dismiss(); + } + }); + if (ScreenUtils.isTablet(UserActivity.this)) { + AutoSizeCompat.autoConvertDensityBaseOnWidth(getResources(), BaseAlertDialogBuilder.ALERT_BASE_WIDTH_TABLE); + } else { + AutoSizeCompat.autoConvertDensityBaseOnWidth(getResources(), BaseAlertDialogBuilder.ALERT_BASE_WIDTH); + } + mUserDebugDialog.setCanceledOnTouchOutside(false); + mUserDebugDialog.show(); + mUserDebugDialog.getWindow().setGravity(Gravity.CENTER); + mUserDebugDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + mUserDebugDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + mUserDebugDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + private void setLocalData() { String avatarFilePath = mMMKV.decodeString(CommonConfig.UIUI_USER_AVATAR_KEY); GlideLoadUtils.getInstance().glideLoad(UserActivity.this, avatarFilePath, mViewDataBinding.nvAvatar, R.drawable.default_avatar); @@ -286,7 +358,7 @@ public class UserActivity extends BaseMvvmActivity params = new HashMap<>(); - params.put("sn", NetInterfaceManager.convertToJsonRequestBody(DeviceSNManager.getDeviceSN())); + params.put("sn", NetInterfaceManager.convertToJsonRequestBody(AdminManager.getInstance().getSerial())); mViewModel.updateAvatar(params, body); } else { mMMKV.encode(CommonConfig.UIUI_USER_AVATAR_KEY, avatarFilePath); @@ -341,6 +413,10 @@ public class UserActivity extends BaseMvvmActivity mAppUpdateInfoData = new MutableLiveData<>(); + public MutableLiveData mAppUpdateInfoData = new MutableLiveData<>(); public void checkUpdate() { - NetInterfaceManager.getInstance().getCheckUpdateObservable(BuildConfig.APPLICATION_ID) + NetInterfaceManager.getInstance().getUpdateObservable(BuildConfig.APPLICATION_ID) .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) - .subscribe(new Observer>() { + .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { Log.e("checkUpdate", "onSubscribe: "); } @Override - public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { + public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { Log.e("checkUpdate", "onNext: " + appUpdateInfoBaseResponse); if (appUpdateInfoBaseResponse.code == 200) { - AppUpdateInfo appUpdateInfo = appUpdateInfoBaseResponse.data; + AppInfo appUpdateInfo = appUpdateInfoBaseResponse.data; mAppUpdateInfoData.setValue(appUpdateInfo); } else { mAppUpdateInfoData.setValue(null); @@ -92,8 +93,8 @@ public class UserViewModel extends BaseViewModel { holder.iv_icon.setImageDrawable(desktopIcon.getIcon()); String pkg = desktopIcon.getPackageName(); Log.e(TAG, "getView: " + pkg); - holder.iv_icon.setImageDrawable(desktopIcon.getIcon()); // int i = IconUtils.appClassNameList.indexOf(pkg); // if (i != -1) { @@ -104,6 +104,11 @@ public class AppAdapter extends RecyclerView.Adapter { return; } + if (AppManager.APP_HOMEWORK.equals(pkg)) { + mContext.startActivity(new Intent(mContext, HomeworkActivity.class)); + return; + } + if (!ApkUtils.isAvailable(mContext, pkg)) { OpenApkUtils.getInstance().showDownloadDialog(mContext, pkg, lable); return; diff --git a/app/src/main/java/com/xwad/os/base/BaseAlertDialogBuilder.java b/app/src/main/java/com/xwad/os/base/BaseAlertDialogBuilder.java new file mode 100644 index 0000000..60268f6 --- /dev/null +++ b/app/src/main/java/com/xwad/os/base/BaseAlertDialogBuilder.java @@ -0,0 +1,50 @@ +package com.xwad.os.base; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.res.Resources; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; + +import com.xwad.os.utils.ScreenUtils; + +import me.jessyan.autosize.AutoSizeCompat; + +public class BaseAlertDialogBuilder extends AlertDialog.Builder { + + /** + * + */ + public static final float ALERT_BASE_WIDTH = 480f; + public static final float ALERT_BASE_WIDTH_TABLE = 640f; + + public BaseAlertDialogBuilder(@NonNull Context context) { + super(adjustAutoSize(context)); + } + + public BaseAlertDialogBuilder(@NonNull Context context, int themeResId) { + super(adjustAutoSize(context), themeResId); + } + + private static Context adjustAutoSize(Context context) { + return new ContextWrapper(context) { + private Resources mResources; + + { + Resources oldResources = super.getResources(); + mResources = new Resources(oldResources.getAssets(), oldResources.getDisplayMetrics(), oldResources.getConfiguration()); + } + + @Override + public Resources getResources() { + if (ScreenUtils.isTablet(context)) { + AutoSizeCompat.autoConvertDensityBaseOnWidth(mResources, ALERT_BASE_WIDTH_TABLE); + } else { + AutoSizeCompat.autoConvertDensityBaseOnWidth(mResources, ALERT_BASE_WIDTH); + } + return mResources; + } + }; + } +} diff --git a/app/src/main/java/com/xwad/os/base/BaseApplication.java b/app/src/main/java/com/xwad/os/base/BaseApplication.java index 1976e2c..51104a3 100644 --- a/app/src/main/java/com/xwad/os/base/BaseApplication.java +++ b/app/src/main/java/com/xwad/os/base/BaseApplication.java @@ -20,10 +20,11 @@ import com.tencent.bugly.crashreport.CrashReport; import com.tencent.mmkv.MMKV; import com.xwad.os.BuildConfig; import com.xwad.os.alarm.AlarmUtils; +import com.xwad.os.config.CommonConfig; import com.xwad.os.manager.AmapManager; import com.xwad.os.manager.AppManager; import com.xwad.os.manager.ConnectManager; -import com.xwad.os.manager.DeviceSNManager; +import com.xwad.os.manager.ControlManager; import com.xwad.os.mdm.AdminManager; import com.xwad.os.network.NetInterfaceManager; import com.xwad.os.push.PushManager; @@ -37,6 +38,7 @@ import com.xwad.os.utils.SystemUtils; public class BaseApplication extends Application { private static final String TAG = "BaseApplication"; + /** * ViewModel中因为经常旋转导致弱引用为空 */ @@ -86,7 +88,7 @@ public class BaseApplication extends Application { AdminManager.init(this); CrashReport.initCrashReport(getApplicationContext(), "4efcaad4c9", false); - CrashReport.setDeviceId(BaseApplication.this, DeviceSNManager.getDeviceSN()); + CrashReport.setDeviceId(BaseApplication.this, AdminManager.getInstance().getSerial()); // 初始化 Toast 框架 Toaster.init(this); @@ -98,6 +100,7 @@ public class BaseApplication extends Application { AppUsedTimeUtils.init(this); OpenApkUtils.init(this); ConnectManager.init(this); + ControlManager.init(this); NetInterfaceManager.init(this); // startService(new Intent(this, MainService.class)); registAppReceive(); @@ -114,12 +117,13 @@ public class BaseApplication extends Application { public void aliyunPushInit() { PushServiceFactory.init(this); final CloudPushService pushService = PushServiceFactory.getCloudPushService(); - pushService.setLogLevel(CloudPushService.LOG_DEBUG); + pushService.setLogLevel(CloudPushService.LOG_OFF); pushService.register(this, new CommonCallback() { @Override public void onSuccess(String response) { Log.e("AliyunPush", "init cloudchannel success"); Log.e("AliyunPush", "init cloudchannel success " + pushService.getDeviceId()); + MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE).encode(CommonConfig.ALIYUN_PUSH_ID, pushService.getDeviceId()); } @Override diff --git a/app/src/main/java/com/xwad/os/bean/AppUploadInfo.java b/app/src/main/java/com/xwad/os/bean/AppUploadInfo.java new file mode 100644 index 0000000..fe23619 --- /dev/null +++ b/app/src/main/java/com/xwad/os/bean/AppUploadInfo.java @@ -0,0 +1,91 @@ +package com.xwad.os.bean; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; + +import java.io.Serializable; + +public class AppUploadInfo implements Serializable { + private static final long serialVersionUID = -6920148363520647811L; + + String app_name; + String app_package; + String app_version_name; + long app_version_code; + long firstInstallTime; + long lastUpdateTime; + long app_size; + int source; + + public String getApp_name() { + return app_name; + } + + public void setApp_name(String app_name) { + this.app_name = app_name; + } + + public String getApp_package() { + return app_package; + } + + public void setApp_package(String app_package) { + this.app_package = app_package; + } + + public String getApp_version_name() { + return app_version_name; + } + + public void setApp_version_name(String app_version_name) { + this.app_version_name = app_version_name; + } + + public long getApp_version_code() { + return app_version_code; + } + + public void setApp_version_code(long app_version_code) { + this.app_version_code = app_version_code; + } + + public long getFirstInstallTime() { + return firstInstallTime; + } + + public void setFirstInstallTime(long firstInstallTime) { + this.firstInstallTime = firstInstallTime; + } + + public long getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(long lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public long getApp_size() { + return app_size; + } + + public void setApp_size(long app_size) { + this.app_size = app_size; + } + + public int getSource() { + return source; + } + + public void setSource(int source) { + this.source = source; + } + + @NonNull + @Override + public String toString() { + return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString(); + } +} diff --git a/app/src/main/java/com/xwad/os/bean/IsActivationBean.java b/app/src/main/java/com/xwad/os/bean/IsActivationBean.java new file mode 100644 index 0000000..d5c6f82 --- /dev/null +++ b/app/src/main/java/com/xwad/os/bean/IsActivationBean.java @@ -0,0 +1,78 @@ +package com.xwad.os.bean; + +import java.io.Serializable; +import java.util.List; + +public class IsActivationBean implements Serializable { + private static final long serialVersionUID = 930211633376920464L; + + //是否激活 0否1是 + int is_activation; + // + String code; + //激活码类型 0体验卡 1正式 + int code_type; + //体验到期时间戳 单位秒 0代表没有时间限制 + long expire_time; + //激活时间 + long activation_time; + + List sn_package; + int sn_package_id; + + public int getIs_activation() { + return is_activation; + } + + public void setIs_activation(int is_activation) { + this.is_activation = is_activation; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public int getCode_type() { + return code_type; + } + + public void setCode_type(int code_type) { + this.code_type = code_type; + } + + public long getExpire_time() { + return expire_time; + } + + public void setExpire_time(long expire_time) { + this.expire_time = expire_time; + } + + public long getActivation_time() { + return activation_time; + } + + public void setActivation_time(long activation_time) { + this.activation_time = activation_time; + } + + public List getSn_package() { + return sn_package; + } + + public void setSn_package(List sn_package) { + this.sn_package = sn_package; + } + + public int getSn_package_id() { + return sn_package_id; + } + + public void setSn_package_id(int sn_package_id) { + this.sn_package_id = sn_package_id; + } +} diff --git a/app/src/main/java/com/xwad/os/bean/SnPackage.java b/app/src/main/java/com/xwad/os/bean/SnPackage.java new file mode 100644 index 0000000..fceaae1 --- /dev/null +++ b/app/src/main/java/com/xwad/os/bean/SnPackage.java @@ -0,0 +1,71 @@ +package com.xwad.os.bean; + +import java.io.Serializable; + +public class SnPackage implements Serializable { + private static final long serialVersionUID = -2350603364822310416L; + + int id; + String sn_id; + String sn; + String app_package; + String code; + String sn_package_app_id; + SnPackageApp sn_package_app; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getSn_id() { + return sn_id; + } + + public void setSn_id(String sn_id) { + this.sn_id = sn_id; + } + + public String getSn() { + return sn; + } + + public void setSn(String sn) { + this.sn = sn; + } + + public String getApp_package() { + return app_package; + } + + public void setApp_package(String app_package) { + this.app_package = app_package; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getSn_package_app_id() { + return sn_package_app_id; + } + + public void setSn_package_app_id(String sn_package_app_id) { + this.sn_package_app_id = sn_package_app_id; + } + + public SnPackageApp getSn_package_app() { + return sn_package_app; + } + + public void setSn_package_app(SnPackageApp sn_package_app) { + this.sn_package_app = sn_package_app; + } +} diff --git a/app/src/main/java/com/xwad/os/bean/SnPackageApp.java b/app/src/main/java/com/xwad/os/bean/SnPackageApp.java new file mode 100644 index 0000000..b2c9a2f --- /dev/null +++ b/app/src/main/java/com/xwad/os/bean/SnPackageApp.java @@ -0,0 +1,26 @@ +package com.xwad.os.bean; + +import java.io.Serializable; + +public class SnPackageApp implements Serializable { + private static final long serialVersionUID = 3704612310075489816L; + + int id; + String app_name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + 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/xwad/os/bean/TimeControl.java b/app/src/main/java/com/xwad/os/bean/TimeControl.java new file mode 100644 index 0000000..f318bb0 --- /dev/null +++ b/app/src/main/java/com/xwad/os/bean/TimeControl.java @@ -0,0 +1,53 @@ +package com.xwad.os.bean; + +import java.io.Serializable; + +public class TimeControl implements Serializable { + private static final long serialVersionUID = 8400702243953866327L; + + int id; + int user_id; + String sn; + String start_time; + String end_time; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUser_id() { + return user_id; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } + + public String getSn() { + return sn; + } + + public void setSn(String sn) { + this.sn = sn; + } + + 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; + } +} diff --git a/app/src/main/java/com/xwad/os/bean/WhoisBean.java b/app/src/main/java/com/xwad/os/bean/WhoisBean.java new file mode 100644 index 0000000..016dd6e --- /dev/null +++ b/app/src/main/java/com/xwad/os/bean/WhoisBean.java @@ -0,0 +1,109 @@ +package com.xwad.os.bean; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; + +import java.io.Serializable; + +public class WhoisBean implements Serializable { + private static final long serialVersionUID = -6537021620041268080L; + + String ip; + String pro; + String proCode; + String city; + String cityCode; + String region; + String regionCode; + String addr; + String regionNames; + String err; + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getPro() { + return pro; + } + + public void setPro(String pro) { + this.pro = pro; + } + + public String getProCode() { + return proCode; + } + + public void setProCode(String proCode) { + this.proCode = proCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCityCode() { + return cityCode; + } + + public void setCityCode(String cityCode) { + this.cityCode = cityCode; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getRegionCode() { + return regionCode; + } + + public void setRegionCode(String regionCode) { + this.regionCode = regionCode; + } + + public String getAddr() { + return addr; + } + + public void setAddr(String addr) { + this.addr = addr; + } + + public String getRegionNames() { + return regionNames; + } + + public void setRegionNames(String regionNames) { + this.regionNames = regionNames; + } + + public String getErr() { + return err; + } + + public void setErr(String err) { + this.err = err; + } + + @NonNull + @Override + public String toString() { + return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString(); + } +} diff --git a/app/src/main/java/com/xwad/os/config/CommonConfig.java b/app/src/main/java/com/xwad/os/config/CommonConfig.java index efb691d..715c9fd 100644 --- a/app/src/main/java/com/xwad/os/config/CommonConfig.java +++ b/app/src/main/java/com/xwad/os/config/CommonConfig.java @@ -5,6 +5,8 @@ public class CommonConfig { public static final String CLOUD_LESSON_SETTINGS_KEY = "cloud_lesson_settings_key"; + public static final String ALIYUN_PUSH_ID = "aliyun_push_id_key"; + @Deprecated public static final String isLogined = "isLogined"; public static final String AES_KEY = "xqdep8exnafpef3d"; @@ -12,6 +14,9 @@ public class CommonConfig { public static final String LOCK_SCREEN_PASSWORD ="Iflytek_lockScreenPasswordKey"; public static final String DEFAULT_PASSWORD = "666666"; + public static final String SCREEN_LOCK_PWD = "screen_lock_passwd"; + public static final String SUPER_PASSWORD = "0728"; + /*保存个人基本信息*/ /*性别*/ public static final String UIUI_USER_GENDER_KEY = "USER_INFO_GENDER"; @@ -42,6 +47,8 @@ public class CommonConfig { public static final String ACTIVATIONBEAN_CODE_KEY = "UIUI_ACTIVATIONBEAN_CODE"; public static final String INSTALL_SD_APKS = "install_sd_apks"; + /*是否显示通知栏,以及增强模式*/ + public static final String NOTIFY_BAR_SHOW_KEY = "is_notify_bar_show_key"; /*是否显示返回Android按钮*/ public static final String UIUI_RETURN_ANDROID_KEY = "iflytek_uiui_is_return_android"; @@ -53,8 +60,18 @@ public class CommonConfig { public static final String MAP_LONGITUDE_KEY = "map_longitude_key"; public static final String MAP_LATITUDE_KEY = "map_latitude_key"; public static final String MAP_ADDRESS_KEY = "map_address_key"; + public static final String MAP_PROVINCE_KEY = "map_province_key"; + public static final String MAP_CITY_KEY = "map_city_key"; + public static final String MAP_DISTRICT_KEY = "map_district_key"; + public static final String MAP_STREET_KEY = "map_street_key"; + public static final String MAP_LOCATION_DESCRIBE_KEY = "map_locationDescribe_key"; public static final String MAP_ERROR_KEY = "map_error_key"; + public static final String MAP_onLocationChanged_time_KEY = "map_onLocationChanged_time_key"; + + public static final String MAP_BEAN = "MapBean"; + + public static final String SETTING_OTHER_APPINSTALLER_KEY = "iflytek_setting_other_appInstaller"; /*应用市场的app列表*/ public final static String ADMIN_APP_LIST = "only_admin_app_list"; @@ -100,4 +117,32 @@ public class CommonConfig { public static final String NOTI_BAR_PERMANENT_ACTION = "notification_bar_permanent_action"; /*是否允许通知*/ public static final String ALLOW_NOTIFICATION = "allow_notification"; + + /*默认桌面key*/ + public final static String DESKTOP_APP_KEY = "desktop_app_key"; + public final static String BROWSER_APP_KEY = "browser_app_key"; + public final static String TYPEWRITING_APP_KEY = "typewriting_app_key"; + + /** + * 管控系统指令 + */ + + /*USB模式-充电*/ + public final static String AOLE_ACTION_USB_USB_CHARGE = "aole_action_usb_usb_charge"; + /*USB模式-MTP*/ + public final static String AOLE_ACTION_USB_USB_MTP = "aole_action_usb_usb_mtp"; + /*USB模式-MIDI*/ + public final static String AOLE_ACTION_USB_USB_MIDI = "aole_action_usb_usb_midi"; + + /*应用安装白名单总开关*/ + public final static String AOLE_APP_ALLOW_INSTALL = "aole_app_allow_install"; + /*应用安装白名单*/ + public final static String AOLE_ACTION_APP_FORBID = "aole_app_forbid"; + /*强制安装应用,禁止卸载*/ + public final static String AOLE_ACTION_FORCE_APP = "aole_force_app"; + + /*应用ID管控*/ + public final static String AOLE_ACTION_APP_FORBID_ID = "aole_app_forbid_id"; + /*应用ID管控*/ + public final static String AOLE_ACTION_APP_FORBID_ARRAY = "DeselectViewArray"; } diff --git a/app/src/main/java/com/xwad/os/dialog/UserDebugDialog.java b/app/src/main/java/com/xwad/os/dialog/UserDebugDialog.java new file mode 100644 index 0000000..e3a606f --- /dev/null +++ b/app/src/main/java/com/xwad/os/dialog/UserDebugDialog.java @@ -0,0 +1,248 @@ +package com.xwad.os.dialog; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; + +import com.xwad.os.R; + + +/** + * description:自定义dialog + */ + +public class UserDebugDialog extends AlertDialog { + + /** + * 显示的标题 + */ + private TextView titleTv; + + /** + * 确认和取消按钮 + */ + private TextView negtiveBn, positiveBn; + + private EditText editText; + + + private Context mContext; + + public UserDebugDialog(Context context) { + super(context, R.style.UserDebugDialog); + this.mContext = context; + } + + /** + * 都是内容数据 + */ + private String message; + private String title; + private String positive, negtive; + private int imageResId = -1; + + /** + * 底部是否只有一个按钮 + */ + private boolean isSingle = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_userdebug); + //按空白处不能取消动画 +// setCanceledOnTouchOutside(false); + //初始化界面控件 + initView(); + //初始化界面数据 + refreshView(); + //初始化界面控件的事件 + initEvent(); + } + + /** + * 初始化界面的确定和取消监听器 + */ + private void initEvent() { + //设置确定按钮被点击后,向外界提供监听 + positiveBn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onClickBottomListener != null) { + onClickBottomListener.onPositiveClick(); + } + } + }); + //设置取消按钮被点击后,向外界提供监听 + negtiveBn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onClickBottomListener != null) { + onClickBottomListener.onNegtiveClick(); + } + } + }); + } + + /** + * 初始化界面控件的显示数据 + */ + private void refreshView() { + //如果用户自定了title和message +// if (!TextUtils.isEmpty(title)) { +// titleTv.setText(title); +// titleTv.setVisibility(View.VISIBLE); +// } else { +// titleTv.setVisibility(View.GONE); +// } + //如果设置按钮的文字 + if (!TextUtils.isEmpty(positive)) { + positiveBn.setText(positive); + } else { + positiveBn.setText("确定"); + } + if (!TextUtils.isEmpty(negtive)) { + negtiveBn.setText(negtive); + } else { + negtiveBn.setText("取消"); + } + + /** + * 只显示一个按钮的时候隐藏取消按钮,回掉只执行确定的事件 + */ + if (isSingle) { + negtiveBn.setVisibility(View.GONE); + } else { + negtiveBn.setVisibility(View.VISIBLE); + } + } + + @Override + public void show() { + super.show(); + refreshView(); + } + + /** + * 初始化界面控件 + */ + private void initView() { + negtiveBn = findViewById(R.id.bt_cancel); + positiveBn = findViewById(R.id.bt_confirm); + titleTv = findViewById(R.id.tv_title); + editText = findViewById(R.id.editText); + } + + /** + * 设置确定取消按钮的回调 + */ + private OnClickBottomListener onClickBottomListener; + + public void setOnClickBottomListener(OnClickBottomListener onClickBottomListener) { + this.onClickBottomListener = onClickBottomListener; + } + + public interface OnClickBottomListener { + /** + * 点击确定按钮事件 + */ + void onPositiveClick(); + + /** + * 点击取消按钮事件 + */ + void onNegtiveClick(); + } + + public String getMessage() { + return message; + } + + public UserDebugDialog setMessage(String message) { + this.message = message; + return this; + } + + public String getTitle() { + return title; + } + + public UserDebugDialog setTitle(String title) { + this.title = title; + return this; + } + + public String getPositive() { + return positive; + } + + public UserDebugDialog setPositive(String positive) { + this.positive = positive; + return this; + } + + public String getNegtive() { + return negtive; + } + + public UserDebugDialog setNegtive(String negtive) { + this.negtive = negtive; + return this; + } + + public UserDebugDialog setNegtiveText(String negtive) { + negtiveBn.setText(negtive); + return this; + } + + public int getImageResId() { + return imageResId; + } + + public boolean isSingle() { + return isSingle; + } + + public UserDebugDialog setSingle(boolean single) { + isSingle = single; + return this; + } + + public UserDebugDialog setImageResId(int imageResId) { + this.imageResId = imageResId; + return this; + } + + public void showKeyboard() { + if (editText != null) { + //设置可获得焦点 + editText.setFocusable(true); + editText.setFocusableInTouchMode(true); + //请求获得焦点 + editText.requestFocus(); + //调用系统输入法 + InputMethodManager inputManager = (InputMethodManager) editText + .getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInput(editText, 0); + } + } + + @Override + public void dismiss() { + super.dismiss(); + + } + + public String getEdittext() { + if (!TextUtils.isEmpty(editText.getText().toString())) { + return editText.getText().toString().trim(); + } else { + return ""; + } + } +} diff --git a/app/src/main/java/com/xwad/os/eula/EulaDialog.java b/app/src/main/java/com/xwad/os/eula/EulaDialog.java new file mode 100644 index 0000000..35b6287 --- /dev/null +++ b/app/src/main/java/com/xwad/os/eula/EulaDialog.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) Honor Technologies Co., Ltd. 2019-2020. All rights reserved. + */ + +package com.xwad.os.eula; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.Color; +import android.text.Html; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; + +import com.xwad.os.R; +import com.xwad.os.base.BaseAlertDialogBuilder; + + +/** + * The EulaDialog for this Sample + * + * @author honor mdm + * @since 2019-10-23 + */ +public class EulaDialog { + private static final int REQUEST_ENABLE = 1; + private static final String PERMISSION_STATEMENT_FILE = "honor_permission_statement.html"; + + private Activity mActivity = null; + private DevicePolicyManager mDevicePolicyManager = null; + private ComponentName mAdminName = null; + private boolean hasUserAccepted = false; + private boolean onlyShowOnce = false; + private AlertDialog eulaDialog; + private EulaCallback mEulaCallback; + + public EulaDialog(Activity context, DevicePolicyManager devicePolicyManager, ComponentName adminName, EulaCallback callback) { + mActivity = context; + mDevicePolicyManager = devicePolicyManager; + mAdminName = adminName; + mEulaCallback = callback; + } + + public interface EulaCallback { + void onGranted(); + + void onDenied(); + } + + /** + * Show permission usage statement + */ + @SuppressLint("InflateParams") + public void show() { + EulaUtils eulaUtils = new EulaUtils(); + hasUserAccepted = eulaUtils.hasUserAccepted(); + if (!hasUserAccepted) { + /* Show the Eula */ + if (eulaDialog == null) { + BaseAlertDialogBuilder builder = new BaseAlertDialogBuilder(mActivity); + builder.setPositiveButton(mActivity.getString(R.string.accept_btn), + (dialog, which) -> { + eulaUtils.saveUserOnlyShowOnce(onlyShowOnce); + eulaUtils.saveUserChoice(true); + dialog.dismiss(); + mEulaCallback.onGranted(); + }); + builder.setNegativeButton(mActivity.getString(R.string.exit_btn), + (dialog, which) -> { + mEulaCallback.onDenied(); + mActivity.finish(); + }); + eulaDialog = builder.create(); + builder.setCancelable(false); + LayoutInflater inflater = LayoutInflater.from(mActivity); + View layout = inflater.inflate(R.layout.eula_layout, null); + TextView permissionText = layout.findViewById(R.id.content_permissions); + String content = Utils.getStringFromHtmlFile(mActivity, PERMISSION_STATEMENT_FILE); + permissionText.setText(Html.fromHtml(content)); + + initStatementView(layout); + + CheckBox checkbox = layout.findViewById(R.id.not_show_check); + checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> { + onlyShowOnce = isChecked; + }); + eulaDialog.setView(layout); + eulaDialog.show(); + eulaDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + } else { + mEulaCallback.onGranted(); + } + } + + private void initStatementView(View layout) { + if (layout == null) { + return; + } + TextView statementText = layout.findViewById(R.id.read_statement); + statementText.setMovementMethod(LinkMovementMethod.getInstance()); + CharSequence text = statementText.getText(); + if (text instanceof Spannable) { + int end = text.length(); + Spannable sp = (Spannable) text; + URLSpan[] urls = sp.getSpans(0, end, URLSpan.class); + SpannableStringBuilder style = new SpannableStringBuilder(text); + style.clearSpans(); // should clear old spans + for (URLSpan url : urls) { + MyURLSpan myURLSpan = new MyURLSpan(); + style.setSpan(myURLSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spanned.SPAN_EXCLUSIVE_INCLUSIVE); + } + statementText.setText(style); + } + } + + private class MyURLSpan extends ClickableSpan { + @Override + public void onClick(View widget) { + widget.setBackgroundColor(Color.parseColor("#00000000")); + + Intent intent = new Intent(mActivity, LicenseActivity.class); + mActivity.startActivity(intent); + } + } + + private void activeProcess() { +// if (mDevicePolicyManager != null +// && !mDevicePolicyManager.isAdminActive(mAdminName)) { +// Intent intent = new Intent(mActivity, SplashActivity.class); +// mActivity.startActivityForResult(intent, REQUEST_ENABLE); +// } + + } + + +} diff --git a/app/src/main/java/com/xwad/os/eula/EulaUtils.java b/app/src/main/java/com/xwad/os/eula/EulaUtils.java new file mode 100644 index 0000000..0c15d4e --- /dev/null +++ b/app/src/main/java/com/xwad/os/eula/EulaUtils.java @@ -0,0 +1,63 @@ +package com.xwad.os.eula; + +import com.tencent.mmkv.MMKV; + +/** + * 只要当用户选中“不再提醒”,同时点击“同意”后,此对话框就不用再显示;但是如果应用有了重大功能更新(开发者自行判断),此对话框还要再次弹出。 + */ +public class EulaUtils { + private static final String TAG = "EulaUtils"; + + /*重大功能更新版本号*/ + private static final int DEFAULT_VERSION_CODE = 1; + private static final String MMKV_EULA_ID = "eula"; + private static final String EULA_PREFIX = "eula_useraccepted_"; + private static final String ONLY_SHOW_ONCE_KEY = "eula_useraccepted_onlyShowOnce"; + private int mVersionCode; + + private String mEulaKey; + + private MMKV mMMKV = MMKV.mmkvWithID(MMKV_EULA_ID, MMKV.MULTI_PROCESS_MODE); + + public EulaUtils() { +// mVersionCode = getVersionCodeInner(); + mVersionCode = DEFAULT_VERSION_CODE; + mEulaKey = EULA_PREFIX + mVersionCode; + } + + public void saveUserOnlyShowOnce(boolean onlyShowOnce) { + mMMKV.encode(mEulaKey, onlyShowOnce); + } + + /** + * Whether the user select not show again + * + * @return boolean true if selected otherwise false. + */ + public boolean hasUserAccepted() { + if (mMMKV.decodeBool(ONLY_SHOW_ONCE_KEY, false)) { + return true; + } else { + return mMMKV.decodeBool(mEulaKey, false); + } + } + + /** + * Save user's choice to SharedPreferences. + * + * @param accepted Whether the user select not show again. + */ + public void saveUserChoice(boolean accepted) { + mMMKV.encode(mEulaKey, accepted); + } + +// private int getVersionCodeInner() { +// PackageInfo pi = null; +// try { +// pi = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); +// } catch (PackageManager.NameNotFoundException e) { +// Log.e(TAG, "Name not found exception"); +// } +// return pi == null ? DEFAULT_VERSION_CODE : pi.versionCode; +// } +} diff --git a/app/src/main/java/com/xwad/os/eula/LicenseActivity.java b/app/src/main/java/com/xwad/os/eula/LicenseActivity.java new file mode 100644 index 0000000..9b7b93b --- /dev/null +++ b/app/src/main/java/com/xwad/os/eula/LicenseActivity.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) Honor Technologies Co., Ltd. 2019-2020. All rights reserved. + */ + +package com.xwad.os.eula; + +import android.app.Activity; +import android.os.Bundle; +import android.text.Html; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.xwad.os.R; + +/** + * The LicenseActivity for this Sample + * + * @author honor mdm + * @since 2019-10-23 + */ +public class LicenseActivity extends Activity { + private static final String LICENSE_FILE = "honor_software_license.html"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.license_layout); + Button acceptBtn = findViewById(R.id.cancelBtn); + acceptBtn.setOnClickListener(view -> finish()); + TextView licenseText = findViewById(R.id.license_content); + String content = Utils.getStringFromHtmlFile(this, LICENSE_FILE); + licenseText.setText(Html.fromHtml(content)); + } +} diff --git a/app/src/main/java/com/xwad/os/eula/Utils.java b/app/src/main/java/com/xwad/os/eula/Utils.java new file mode 100644 index 0000000..1eb25b4 --- /dev/null +++ b/app/src/main/java/com/xwad/os/eula/Utils.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) Honor Technologies Co., Ltd. 2019-2020. All rights reserved. + */ + +package com.xwad.os.eula; + +import android.content.Context; +import android.util.Log; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * The Utils for this Sample + * + * @author honor mdm + * @since 2019-10-23 + */ +public class Utils { + private static final String TAG = "SampleUtils"; + private static final int EXPECTED_BUFFER_DATA = 2048; + private static final int MAX_LENGTH = 1024; + private static final int MAX_LINE_LENGTH = 128; + + /** + * Get help string from html file + * + * @param context Context object + * @param filePath html file path + * @return string in html + */ + public static String getStringFromHtmlFile(Context context, String filePath) { + String result = ""; + if (context == null || filePath == null) { + return result; + } + try (InputStreamReader streamReader = + new InputStreamReader(context.getAssets().open(filePath), "utf-8"); + BufferedReader reader = new BufferedReader(streamReader)) { + StringBuilder builder = new StringBuilder(EXPECTED_BUFFER_DATA); + String line = null; + + boolean readCurrentLine = true; + + // Read each line of the html file, and build a string. + while ((line = reader.readLine()) != null && line.length() < MAX_LINE_LENGTH) { + // Don't read the Head tags when CSS styling is not supporeted. + if (line.contains(" { + private static final String TAG = "AppViewModel"; + @Override public FragmentAppBinding getVDBinding() { return binding; @@ -33,15 +44,15 @@ public class AppViewModel extends BaseViewModel desktopIcons = AppManager.getInstance().getFilterAppList(); // DesktopIcon appstoreDesktopIcon = new DesktopIcon(); -// appstoreDesktopIcon.setLable(ApkUtils.getAppName(getCtx(), "com.uiui.zyappstore")); +// appstoreDesktopIcon.setLable(ApkUtils.getAppName(BaseApplication.getInstance(), "com.uiui.zyappstore")); // appstoreDesktopIcon.setPackageName(AppManager.APPSTORE_PACKAGE_NAME); // appstoreDesktopIcon.setClassName(AppManager.APPSTORE_CLASS_NAME); // appstoreDesktopIcon.setLable("应用市场"); // Drawable appstoreDrawable; -// if (ApkUtils.isAvailable(getCtx(), AppManager.APPSTORE_PACKAGE_NAME)) { -// appstoreDrawable = ApkUtils.getAppDrawable(getCtx(), "com.uiui.zyappstore"); +// if (ApkUtils.isAvailable(BaseApplication.getInstance(), AppManager.APPSTORE_PACKAGE_NAME)) { +// appstoreDrawable = ApkUtils.getAppDrawable(BaseApplication.getInstance(), "com.uiui.zyappstore"); // } else { -// appstoreDrawable = getCtx().getDrawable(R.drawable.com_android_appstore); +// appstoreDrawable = BaseApplication.getInstance().getDrawable(R.drawable.com_android_appstore); // } // appstoreDesktopIcon.setIcon(appstoreDrawable); // desktopIcons.add(desktopIcons.size(), appstoreDesktopIcon); @@ -49,47 +60,47 @@ public class AppViewModel extends BaseViewModel>() { + @Override + public ArrayList call() throws Exception { + ArrayList desktopIcons = AppManager.getInstance().getFilterAppList(); + +// DesktopIcon appstoreDesktopIcon = new DesktopIcon(); +// appstoreDesktopIcon.setLable(ApkUtils.getAppName(BaseApplication.getInstance(), "com.uiui.zyappstore")); +// appstoreDesktopIcon.setPackageName(AppManager.APPSTORE_PACKAGE_NAME); +// appstoreDesktopIcon.setClassName(AppManager.APPSTORE_CLASS_NAME); +// appstoreDesktopIcon.setLable("应用市场"); +// Drawable appstoreDrawable; +// if (ApkUtils.isAvailable(BaseApplication.getInstance(), AppManager.APPSTORE_PACKAGE_NAME)) { +// appstoreDrawable = ApkUtils.getAppDrawable(BaseApplication.getInstance(), "com.uiui.zyappstore"); +// } else { +// appstoreDrawable = BaseApplication.getInstance().getDrawable(R.drawable.com_android_appstore); +// } +// appstoreDesktopIcon.setIcon(appstoreDrawable); +// desktopIcons.add(desktopIcons.size(), appstoreDesktopIcon); + +// DesktopIcon updateDesktopIcon = new DesktopIcon(); +// updateDesktopIcon.setLable("应用更新"); +// updateDesktopIcon.setPackageName(AppManager.UPDATE_NAME); +// updateDesktopIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.icon_update)); +// desktopIcons.add(desktopIcons.size(), updateDesktopIcon); + +// DesktopIcon manualIcon = new DesktopIcon(); +// manualIcon.setLable("使用手册"); +// manualIcon.setPackageName(AppManager.MANUAL_NAME); +// manualIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.icon_manual)); +// desktopIcons.add(desktopIcons.size(), manualIcon); + +// DesktopIcon browserIcon = new DesktopIcon(); +// browserIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.uiui_zybrowser)); +// browserIcon.setLable("浏览器"); +// browserIcon.setPackageName(AppManager.BROWSER_PACKAGE_NAME); +// browserIcon.setClassName(AppManager.BROWSER_CLASS_NAME); +// desktopIcons.add(browserIcon); + +// DesktopIcon serviceIcon = new DesktopIcon(); +// serviceIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.service_icon)); +// serviceIcon.setLable("联系客服"); +// serviceIcon.setPackageName(AppManager.SERVICE_NAME); +// desktopIcons.add(serviceIcon); + +// if (ApkUtils.isAvailable(BaseApplication.getInstance(), "com.jxw.zwpg")) { +// DesktopIcon zwpgIcon = new DesktopIcon(); +// zwpgIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.zwpg_icon)); +// zwpgIcon.setLable("作文批改"); +// zwpgIcon.setPackageName("com.jxw.zwpg"); +// desktopIcons.add(zwpgIcon); +// } + +// if (ApkUtils.isAvailable(BaseApplication.getInstance(), "com.jxw.gb.zwpg")) { +// DesktopIcon zwpgIcon = new DesktopIcon(); +// zwpgIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.zwpg_icon)); +// zwpgIcon.setLable("作文批改"); +// zwpgIcon.setPackageName("com.jxw.gb.zwpg"); +// desktopIcons.add(zwpgIcon); +// } + +// if (ApkUtils.isAvailable(BaseApplication.getInstance(), "com.jxw.huiben")) { +// DesktopIcon zwpgIcon = new DesktopIcon(); +// zwpgIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.zhidu_icon)); +// zwpgIcon.setLable("AR指读"); +// zwpgIcon.setPackageName("com.jxw.huiben"); +// desktopIcons.add(zwpgIcon); +// } + +// DesktopIcon exitIcon = new DesktopIcon(); +// exitIcon.setLable("退出桌面"); +// exitIcon.setPackageName(AppManager.DESKTOP_EXIT); +// exitIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.exit_icon)); +// desktopIcons.add(desktopIcons.size(), exitIcon); + + DesktopIcon homeworkDesktopIcon = new DesktopIcon(); + homeworkDesktopIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.icon_homework)); + homeworkDesktopIcon.setLable("作业"); + homeworkDesktopIcon.setPackageName(AppManager.APP_HOMEWORK); + desktopIcons.add(homeworkDesktopIcon); + + DesktopIcon clockIcon = new DesktopIcon(); + clockIcon.setLable("时钟"); + clockIcon.setPackageName(OpenApkUtils.getInstance().getDeskClockPackageName()); + //使用getCtx()会报错 + clockIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.com_android_deskclock)); + desktopIcons.add(clockIcon); + + DesktopIcon calcIcon = new DesktopIcon(); + calcIcon.setLable("计算器"); + calcIcon.setPackageName(OpenApkUtils.getInstance().getCalculatorPackageName()); + calcIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.com_android_calculator2)); + desktopIcons.add(calcIcon); + + DesktopIcon cameraIcon = new DesktopIcon(); + cameraIcon.setLable("相机"); + cameraIcon.setPackageName(OpenApkUtils.getInstance().getCameraPackageName()); + cameraIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.com_android_camera)); + desktopIcons.add(cameraIcon); + + DesktopIcon galleryIcon = new DesktopIcon(); + galleryIcon.setLable("图库"); + galleryIcon.setPackageName(OpenApkUtils.getInstance().getGalleryPackageName()); + galleryIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.com_android_gallery3d_app)); + desktopIcons.add(galleryIcon); + + DesktopIcon AiAppIcon = new DesktopIcon(); + AiAppIcon.setLable("AI答疑(测试)"); + AiAppIcon.setPackageName("com.jxw.aizndy"); + AiAppIcon.setClassName("com.jxw.aizndy.ui.activity.MainCameraActivity"); + AiAppIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.icon_jxw_aizndy)); + desktopIcons.add(desktopIcons.size(), AiAppIcon); + + DesktopIcon AddAppIcon = new DesktopIcon(); + AddAppIcon.setLable("添加应用"); + AddAppIcon.setPackageName(AppManager.ADD_NAME); + AddAppIcon.setIcon(BaseApplication.getInstance().getDrawable(R.drawable.icon_add)); + desktopIcons.add(desktopIcons.size(), AddAppIcon); + + return desktopIcons; + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + + } + + @Override + public void onNext(@NonNull ArrayList desktopIcons) { + Log.e("getInstalledApp", "onNext: " + desktopIcons); + mDesktopIconListData.postValue(desktopIcons); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getInstalledApp", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + + } + }); + } } diff --git a/app/src/main/java/com/xwad/os/fragment/mine/MineFragment.java b/app/src/main/java/com/xwad/os/fragment/mine/MineFragment.java index 688408a..70a6f88 100644 --- a/app/src/main/java/com/xwad/os/fragment/mine/MineFragment.java +++ b/app/src/main/java/com/xwad/os/fragment/mine/MineFragment.java @@ -12,10 +12,10 @@ import android.view.View; import androidx.fragment.app.Fragment; import androidx.lifecycle.Observer; +import com.hjq.toast.Toaster; import com.tencent.mmkv.MMKV; import com.xwad.os.R; import com.xwad.os.activity.ExitActivity; -import com.xwad.os.activity.login.result.LoginSuccessfulActivity; import com.xwad.os.activity.user.UserActivity; import com.xwad.os.base.mvvm.fragment.BaseMvvmFragment; import com.xwad.os.bean.UserAvatarInfo; @@ -24,7 +24,6 @@ import com.xwad.os.databinding.FragmentMineBinding; import com.xwad.os.jxw.StudyRecordMng; import com.xwad.os.jxw.ToastUtil; import com.xwad.os.jxw.event.UpdateColorEvent; -import com.xwad.os.service.main.MainService; import com.xwad.os.utils.OpenApkUtils; import com.xwad.os.view.jxw.view.dialog.QhbzDialog; import com.xwad.os.view.jxw.widget.DefaultAppsDialog; @@ -43,7 +42,7 @@ import java.io.IOException; * create an instance of this fragment. */ public class MineFragment extends BaseMvvmFragment { - private static final String TAG = "PrecisionFragment"; + private static final String TAG = "MineFragment"; private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); private Activity mContext; @@ -356,7 +355,12 @@ public class MineFragment extends BaseMvvmFragment mQrCodeData = new MutableLiveData<>(); public void getQrCode() { - String encryptString = CXAESUtil.encrypt(CommonConfig.AES_KEY, DeviceSNManager.getDeviceSN()); + String encryptString = CXAESUtil.encrypt(CommonConfig.AES_KEY, AdminManager.getInstance().getSerial()); Log.e("getQRCode", "setImageAndText: " + encryptString); Bitmap bitmap = Utils.createQRImage(encryptString, 400, 400); mQrCodeData.setValue(bitmap); diff --git a/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceFragment.java b/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceFragment.java index 95ee0d0..e89b46c 100644 --- a/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceFragment.java +++ b/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceFragment.java @@ -15,9 +15,11 @@ import com.xwad.os.activity.permission.PermissionActivity; import com.xwad.os.activity.service.ServiceActivity; import com.xwad.os.activity.update.UpdateActivity; import com.xwad.os.base.mvvm.fragment.BaseMvvmFragment; +import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.AppUpdateInfo; import com.xwad.os.databinding.FragmentDeviceBinding; import com.xwad.os.manager.DeviceSNManager; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.utils.ApkUtils; public class DeviceFragment extends BaseMvvmFragment { @@ -46,14 +48,14 @@ public class DeviceFragment extends BaseMvvmFragment() { + mViewModel.mAppUpdateInfoData.observe(this, new Observer() { @Override - public void onChanged(AppUpdateInfo appUpdateInfo) { + public void onChanged(AppInfo appUpdateInfo) { if (appUpdateInfo == null) { Toaster.show("已是最新版本"); } else { diff --git a/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceViewModel.java b/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceViewModel.java index 76bceee..c6501b8 100644 --- a/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceViewModel.java +++ b/app/src/main/java/com/xwad/os/fragment/usercenter/device/DeviceViewModel.java @@ -10,6 +10,7 @@ import com.trello.rxlifecycle4.android.ActivityEvent; import com.trello.rxlifecycle4.android.FragmentEvent; import com.xwad.os.BuildConfig; import com.xwad.os.base.mvvm.BaseViewModel; +import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.AppUpdateInfo; import com.xwad.os.bean.BaseResponse; import com.xwad.os.databinding.FragmentDeviceBinding; @@ -31,22 +32,22 @@ public class DeviceViewModel extends BaseViewModel mAppUpdateInfoData = new MutableLiveData<>(); + public MutableLiveData mAppUpdateInfoData = new MutableLiveData<>(); public void checkUpdate() { - NetInterfaceManager.getInstance().getCheckUpdateObservable(BuildConfig.APPLICATION_ID) + NetInterfaceManager.getInstance().getUpdateObservable(BuildConfig.APPLICATION_ID) .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) - .subscribe(new Observer>() { + .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { Log.e("checkUpdate", "onSubscribe: "); } @Override - public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { + public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { Log.e("checkUpdate", "onNext: " + appUpdateInfoBaseResponse); if (appUpdateInfoBaseResponse.code == 200) { - AppUpdateInfo appUpdateInfo = appUpdateInfoBaseResponse.data; + AppInfo appUpdateInfo = appUpdateInfoBaseResponse.data; mAppUpdateInfoData.setValue(appUpdateInfo); } else { mAppUpdateInfoData.setValue(null); @@ -55,8 +56,8 @@ public class DeviceViewModel extends BaseViewModel params = new HashMap<>(); - params.put("sn", DeviceSNManager.getDeviceSN()); + params.put("sn", AdminManager.getInstance().getSerial()); params.put("sex", "1"); mViewModel.updateInfo(params); } else { @@ -77,7 +78,7 @@ public class InfoFragment extends BaseMvvmFragment params = new HashMap<>(); - params.put("sn", DeviceSNManager.getDeviceSN()); + params.put("sn", AdminManager.getInstance().getSerial()); params.put("sex", "2"); mViewModel.updateInfo(params); } else { diff --git a/app/src/main/java/com/xwad/os/jxw/base/BaseActivity.java b/app/src/main/java/com/xwad/os/jxw/base/BaseActivity.java new file mode 100644 index 0000000..a825da6 --- /dev/null +++ b/app/src/main/java/com/xwad/os/jxw/base/BaseActivity.java @@ -0,0 +1,110 @@ +package com.xwad.os.jxw.base; + +//import android.content.Intent; +//import android.os.Build; +//import android.os.Bundle; +//import android.os.Handler; +//import android.os.Looper; +//import android.os.Message; +//import android.view.View; +//import android.view.Window; +//import androidx.fragment.app.FragmentActivity; +//import com.jxw.launcher.netInterface.NetConnectionObserver; +// +//public class BaseActivity extends FragmentActivity implements NetConnectionObserver { +// Handler handler = new Handler(Looper.getMainLooper()) { +// @Override +// public void handleMessage(Message message) { +// super.handleMessage(message); +// BaseActivity.this.startMediaService(); +// } +// }; +// private Handler mRestoreImmersiveModeHandler = new Handler(); +// private Runnable restoreImmersiveModeRunnable = new Runnable() { +// @Override +// public void run() { +// BaseActivity.this.restoreTransparentBars(); +// } +// }; +// +// public void restoreTransparentBars() { +// } +// +// public void onNetworkChanged(boolean z) { +// } +// +// @Override +// public void onCreate(Bundle bundle) { +// super.onCreate(bundle); +// requestWindowFeature(1); +// View decorView = getWindow().getDecorView(); +// if (Build.VERSION.SDK_INT >= 21) { +// Window window = getWindow(); +// window.clearFlags(201326592); +// window.getDecorView().setSystemUiVisibility(1792); +// window.addFlags(Integer.MIN_VALUE); +// window.setStatusBarColor(0); +// window.setNavigationBarColor(0); +// } else if (Build.VERSION.SDK_INT >= 19) { +// getWindow().addFlags(67108864); +// getWindow().addFlags(134217728); +// } +// decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { +// @Override +// public void onSystemUiVisibilityChange(int i) { +// BaseActivity.this.restoreTransparentBars(); +// } +// }); +// decorView.setOnFocusChangeListener(new View.OnFocusChangeListener() { +// @Override +// public void onFocusChange(View view, boolean z) { +// BaseActivity.this.restoreTransparentBars(); +// } +// }); +// this.handler.sendEmptyMessageDelayed(1, 3000L); +// } +// +// @Override +// public void onPause() { +// super.onPause(); +// MyApp.getInstance().removeNetObserver(this); +// } +// +// @Override +// public void onResume() { +// restoreTranslucentBarsDelayed(); +// MyApp.getInstance().mBottomBtnOnClickListener.setContext(this); +// super.onResume(); +// MyApp.getInstance().addNetObserver(this); +// } +// +// @Override +// public void onWindowFocusChanged(boolean z) { +// super.onWindowFocusChanged(z); +// restoreTranslucentBarsDelayed(); +// } +// +// public void restoreTranslucentBarsDelayed() { +// restoreTransparentBars(); +// this.mRestoreImmersiveModeHandler.postDelayed(this.restoreImmersiveModeRunnable, 500L); +// } +// +// public void startMediaService() { +// try { +// Intent intent = new Intent(); +// intent.setClassName("com.jxw.launcher", "com.jxw.system.mediaserver.JhtMediaService"); +// if (Build.VERSION.SDK_INT >= 26) { +// startForegroundService(intent); +// } else { +// startService(intent); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// +// @Override +// public void updateNetStatus(int i) { +// onNetworkChanged(MyApp.getInstance().isNetConnection()); +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/xwad/os/jxw/base/BaseNewThemeActivity.java b/app/src/main/java/com/xwad/os/jxw/base/BaseNewThemeActivity.java new file mode 100644 index 0000000..ddefa1a --- /dev/null +++ b/app/src/main/java/com/xwad/os/jxw/base/BaseNewThemeActivity.java @@ -0,0 +1,207 @@ +package com.xwad.os.jxw.base; + +//import android.content.SharedPreferences; +//import android.content.pm.PackageManager; +//import android.os.Bundle; +//import android.text.TextUtils; +//import android.util.Log; +//import com.google.gson.Gson; +//import com.jxw.api.RegisterApi; +//import com.jxw.api.util.SPUtils; +//import com.jxw.constant.Constant; +//import com.jxw.httputil.OkhtttpUtils; +//import com.jxw.launcher.view.dialog.DialogUpdate; +//import com.jxw.update.Otabean; +//import com.jxw.utils.AppUtil; +//import java.io.IOException; +//import java.util.ArrayList; +//import java.util.List; +//import okhttp3.Call; +//import okhttp3.Callback; +//import okhttp3.OkHttpClient; +//import okhttp3.Request; +//import okhttp3.Response; +//import org.json.JSONArray; +//import org.json.JSONException; +//import org.json.JSONObject; +// +//public abstract class BaseNewThemeActivity extends BaseThemeActivity { +// public static List packages = new ArrayList(); +// +// @Override +// public void onCreate(Bundle bundle) { +// super.onCreate(bundle); +// getPackageList(); +// } +// +// @Override +// public void onDestroy() { +// super.onDestroy(); +// } +// +// @Override +// public void onResume() { +// super.onResume(); +// } +// +// @Override +// protected void onPause() { +// super.onPause(); +// } +// +// private void basecheckUpdate() { +// String deviceSerial; +// SharedPreferences sharedPreferences = getSharedPreferences(Constant.PREFERENCE, 0); +// if (!TextUtils.isEmpty(sharedPreferences.getString("series", ""))) { +// deviceSerial = sharedPreferences.getString("series", ""); +// } else { +// deviceSerial = RegisterApi.getInstance().getDeviceSerial(); +// if ("unknown".equals(deviceSerial) || TextUtils.isEmpty(deviceSerial)) { +// deviceSerial = RegisterApi.getInstance().getDeviceSerialx(); +// } +// } +// new OkHttpClient().newCall(new Request.Builder().url(Constant.PLATFORM_URL_HEADER + "/api/jxwota/apk/checkBySn?apkIsbn=znpbxgbv6&series=" + deviceSerial + "&deviceType=OTHER").build()).enqueue(new Callback() { +// @Override +// public void onFailure(Call call, IOException iOException) { +// Log.d("zzj", "onFailure=" + iOException.getMessage()); +// } +// +// @Override +// public void onResponse(Call call, Response response) throws IOException { +// BaseNewThemeActivity.this.getOtaData(response); +// } +// }); +// } +// +// public synchronized void getOtaData(Response response) throws IOException { +// Log.d("zzj", "onResponse=" + response); +// if (response.isSuccessful()) { +// String string = response.body().string(); +// PackageManager packageManager = MyApp.getInstance().getPackageManager(); +// Log.d("zzj", "获取数据成功了:" + string); +// try { +// JSONArray jSONArray = new JSONObject(string).getJSONArray("data"); +// packages.clear(); +// final int i = 0; +// for (int i2 = 0; i2 < jSONArray.length(); i2++) { +// JSONObject optJSONObject = jSONArray.optJSONObject(i2); +// int optInt = optJSONObject.optInt("versionCode"); +// String optString = optJSONObject.optString("packageName"); +// String optString2 = optJSONObject.optString("forceUpdate"); +// try { +// if (optInt > packageManager.getPackageInfo(optString, 0).versionCode) { +// i++; +// if (optString2.equals("1")) { +// packages.add(optString); +// } +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// runOnUiThread(new Runnable() { +// @Override +// public void run() { +// if (i > 0) { +// BaseNewThemeActivity baseNewThemeActivity = BaseNewThemeActivity.this; +// new DialogUpdate(baseNewThemeActivity, "" + i).show(); +// } +// } +// }); +// } catch (JSONException e2) { +// e2.printStackTrace(); +// } +// } +// } +// +// private void getPackageList() { +// OkhtttpUtils.getInstance().doGet(this, Constant.PLATFORM_URL_HEADER + "/api/jxwota/apk/sign/packageList?apkIsbn=znpbxgbv6", false, new OkhtttpUtils.OkCallback() { +// @Override +// public void onResponse(String str) { +// Log.e("zsj", str); +// try { +// JSONObject jSONObject = new JSONObject(str); +// if ("0".equals(jSONObject.optString("code"))) { +// JSONArray jSONArray = jSONObject.getJSONArray("data"); +// ArrayList arrayList = new ArrayList(); +// for (int i = 0; i < jSONArray.length(); i++) { +// Otabean otabean = new Otabean(); +// otabean.setPackageName(jSONArray.getString(i)); +// otabean.setSign(AppUtil.getApplicationPackage(BaseNewThemeActivity.this, jSONArray.getString(i))); +// Log.e("BaseNewThemeActivity:", "MD5:===" + otabean.getSign()); +// arrayList.add(otabean); +// } +// if (arrayList.size() > 0) { +// BaseNewThemeActivity.this.getApkList(arrayList); +// } +// } +// } catch (Exception unused) { +// } +// } +// +// @Override +// public void onFailure(Exception exc) { +// Log.e("zsj", exc.getMessage()); +// } +// }); +// } +// +// public void getApkList(List list) { +// try { +// String json = new Gson().toJson(list); +// OkhtttpUtils.getInstance().doPostOrGet(this, "POST", Constant.PLATFORM_URL_HEADER + "/api/jxwota/apk/sign/checkBySn?apkIsbn=znpbxgbv6&series=" + SPUtils.getSeries(), json, false, new OkhtttpUtils.OkCallback() { +// @Override +// public void onFailure(Exception exc) { +// } +// +// @Override +// public void onResponse(String str) { +// Log.e("zsj", str); +// try { +// PackageManager packageManager = MyApp.getInstance().getPackageManager(); +// Log.d("zzj", "获取数据成功了:" + str); +// try { +// JSONArray jSONArray = new JSONObject(str).getJSONArray("data"); +// BaseNewThemeActivity.packages.clear(); +// final int i = 0; +// for (int i2 = 0; i2 < jSONArray.length(); i2++) { +// JSONObject optJSONObject = jSONArray.optJSONObject(i2); +// int optInt = optJSONObject.optInt("versionCode"); +// String optString = optJSONObject.optString("packageName"); +// String optString2 = optJSONObject.optString("forceUpdate"); +// try { +// if (optInt > packageManager.getPackageInfo(optString, 0).versionCode) { +// i++; +// if (optString2.equals("1")) { +// BaseNewThemeActivity.packages.add(optString); +// } +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// BaseNewThemeActivity.this.runOnUiThread(new Runnable() { +// @Override +// public void run() { +// if (i > 0) { +// try { +// BaseNewThemeActivity baseNewThemeActivity = BaseNewThemeActivity.this; +// new DialogUpdate(baseNewThemeActivity, "" + i).show(); +// } catch (Exception unused) { +// } +// } +// } +// }); +// } catch (JSONException e2) { +// e2.printStackTrace(); +// } +// } catch (Exception e3) { +// e3.printStackTrace(); +// } +// } +// }); +// } catch (Exception e) { +// e.getMessage(); +// } +// } +//} diff --git a/app/src/main/java/com/xwad/os/jxw/base/BaseThemeActivity.java b/app/src/main/java/com/xwad/os/jxw/base/BaseThemeActivity.java new file mode 100644 index 0000000..6d3cba0 --- /dev/null +++ b/app/src/main/java/com/xwad/os/jxw/base/BaseThemeActivity.java @@ -0,0 +1,76 @@ +package com.xwad.os.jxw.base; + +//import android.os.Build; +//import android.os.Bundle; +//import android.os.Environment; +//import android.view.Window; +//import com.jxw.studyrecord.StudyRecordMng; +//import java.io.File; +//import net.lingala.zip4j.util.InternalZipConstants; +// +//public abstract class BaseThemeActivity extends BaseActivity { +// @Override +// public void onCreate(Bundle bundle) { +// super.onCreate(bundle); +// if (Build.VERSION.SDK_INT >= 21) { +// Window window = getWindow(); +// window.clearFlags(201326592); +// window.getDecorView().setSystemUiVisibility(1792); +// window.addFlags(Integer.MIN_VALUE); +// window.setStatusBarColor(0); +// window.setNavigationBarColor(0); +// } +// createDefDirs(); +// ActivityManager.getScreenManager().pushActivity(this); +// } +// +// @Override +// public void onDestroy() { +// clearCurrentActivity(); +// super.onDestroy(); +// } +// +// @Override +// public void onResume() { +// MyApp.getInstance(); +// MyApp.setCurrentActivity(this); +// super.onResume(); +// getWindow().getDecorView().setSystemUiVisibility(13058); +// } +// +// @Override +// public void onPause() { +// super.onPause(); +// } +// +// @Override +// public void onWindowFocusChanged(boolean z) { +// super.onWindowFocusChanged(z); +// if (z) { +// StudyRecordMng.stopCount(this); +// } +// } +// +// private void createDefDirs() { +// String[] stringArray = getResources().getStringArray(C1224R.array.default_directories); +// if (stringArray == null) { +// return; +// } +// String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath(); +// for (String str : stringArray) { +// File file = new File(absolutePath + InternalZipConstants.ZIP_FILE_SEPARATOR + str); +// if (!file.exists()) { +// file.mkdirs(); +// } +// file.setReadable(true, false); +// } +// } +// +// private void clearCurrentActivity() { +// MyApp.getInstance(); +// if (MyApp.getCurrentActivity() == this) { +// MyApp.getInstance(); +// MyApp.setCurrentActivity(null); +// } +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/xwad/os/manager/AmapManager.java b/app/src/main/java/com/xwad/os/manager/AmapManager.java index d88e327..f26df0b 100644 --- a/app/src/main/java/com/xwad/os/manager/AmapManager.java +++ b/app/src/main/java/com/xwad/os/manager/AmapManager.java @@ -11,8 +11,11 @@ import com.amap.api.location.AMapLocationClientOption; import com.amap.api.location.AMapLocationListener; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import com.hjq.permissions.Permission; +import com.hjq.permissions.XXPermissions; import com.jeremyliao.liveeventbus.LiveEventBus; import com.tencent.mmkv.MMKV; +import com.xwad.os.BuildConfig; import com.xwad.os.bean.BaseResponse; import com.xwad.os.bean.MapBean; import com.xwad.os.config.CommonConfig; @@ -40,7 +43,7 @@ public class AmapManager { private MapBean mMapBean; private AmapManager(Context context) { - this.mContext = context; + this.mContext = context.getApplicationContext(); initAmap(); } @@ -96,21 +99,33 @@ public class AmapManager { Gson gson = new Gson(); Type type = new TypeToken() { }.getType(); - try { - mMapBean = gson.fromJson(jsonString, type); - } catch (Exception e) { - Log.e(TAG, "initAmap: "); - mMMKV.remove(CommonConfig.MAP_LOCATION_JSON_KEY); - } + mMapBean = gson.fromJson(jsonString, type); } else { Log.e(TAG, "initAmap: jsonString is empty"); } } + public static final String[] PERMISSION_LOCATION = new String[]{ + Permission.ACCESS_COARSE_LOCATION, + Permission.ACCESS_FINE_LOCATION, +// Permission.ACCESS_BACKGROUND_LOCATION, + }; + + private boolean checkPermission() { + return XXPermissions.isGranted(mContext, PERMISSION_LOCATION); + } + public void startLocation() { boolean activation = ActivationUtil.getInstance().isActivation(); - if (!activation) { + if (!BuildConfig.DEBUG) { + if (!activation) { + Log.e(TAG, "startLocation: 未激活"); + return; + } + } + if (!checkPermission()) { + Log.e(TAG, "startLocation: 没有定位权限"); return; } mAMapLocationClient.stopLocation(); @@ -128,15 +143,18 @@ public class AmapManager { updateAddress(aMapLocation); mMapBean = getMapBean(aMapLocation); saveMapResult(mMapBean); - LiveEventBus.get("MapBean") + LiveEventBus.get(CommonConfig.MAP_BEAN) .post(mMapBean); + LiveEventBus.get(CommonConfig.MAP_ADDRESS_KEY) + .post(mMapBean.getAddress()); Log.e(TAG, "onLocationChanged: " + aMapLocation.getAddress()); sb.append(aMapLocation.getAddress()).append("\n"); - + mMMKV.encode(CommonConfig.MAP_onLocationChanged_time_KEY, System.currentTimeMillis()); } else { //定位失败 sb.append("定位失败" + "\n"); sb.append(aMapLocation.getErrorInfo()); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, aMapLocation.getErrorInfo()); Log.e(TAG, "onLocationChanged: " + "定位失败"); } Log.e(TAG, "amap: " + sb.toString()); @@ -145,9 +163,10 @@ public class AmapManager { private void updateAddress(AMapLocation aMapLocation) { boolean activation = ActivationUtil.getInstance().isActivation(); - if (!activation) { - return; - } +// if (!activation) { +// Log.e(TAG, "updateAddress: not activation" ); +// return; +// } NetInterfaceManager.getInstance().getUpdateAddressObservable(aMapLocation.getAddress() , aMapLocation.getLongitude(), aMapLocation.getLatitude() ) @@ -174,14 +193,14 @@ public class AmapManager { }); } - public String getLocationTude() { - if (mMapBean != null) { - return mMapBean.getLongitude() + "," + mMapBean.getLatitude(); - } else { - startLocation(); - return CommonConfig.DEFAULT_LOCATION_TUDE; - } - } +// public String getLocationTude() { +// if (mMapBean != null) { +// return mMapBean.getLongitude() + "," + mMapBean.getLatitude(); +// } else { +// startLocation(); +// return CommonConfig.DEFAULT_LOCATION_TUDE; +// } +// } public String getDistrict() { if (mMapBean != null) { @@ -216,6 +235,14 @@ public class AmapManager { private void saveMapResult(MapBean mapBean) { Log.e(TAG, "saveMapResult: " + GsonUtils.toJSONString(mapBean)); mMMKV.encode(CommonConfig.MAP_LOCATION_JSON_KEY, GsonUtils.toJSONString(mapBean)); + mMMKV.encode(CommonConfig.MAP_LONGITUDE_KEY, mapBean.getLongitude()); + mMMKV.encode(CommonConfig.MAP_LATITUDE_KEY, mapBean.getLatitude()); + mMMKV.encode(CommonConfig.MAP_ADDRESS_KEY, mapBean.getAddress()); + mMMKV.encode(CommonConfig.MAP_PROVINCE_KEY, mapBean.getProvince()); + mMMKV.encode(CommonConfig.MAP_CITY_KEY, mapBean.getCity()); + mMMKV.encode(CommonConfig.MAP_DISTRICT_KEY, mapBean.getDistrict()); + mMMKV.encode(CommonConfig.MAP_STREET_KEY, mapBean.getStreet()); + mMMKV.encode(CommonConfig.MAP_LOCATION_DESCRIBE_KEY, mapBean.getLocationDescribe()); } } diff --git a/app/src/main/java/com/xwad/os/manager/AppManager.java b/app/src/main/java/com/xwad/os/manager/AppManager.java index c2a245d..0564b6d 100644 --- a/app/src/main/java/com/xwad/os/manager/AppManager.java +++ b/app/src/main/java/com/xwad/os/manager/AppManager.java @@ -14,7 +14,6 @@ import com.tencent.mmkv.MMKV; import com.xwad.os.R; import com.xwad.os.bean.DesktopIcon; import com.xwad.os.config.CommonConfig; -import com.xwad.os.mdm.AdminManager; import com.xwad.os.utils.ApkUtils; import java.text.Collator; @@ -29,16 +28,17 @@ import java.util.stream.Collectors; public class AppManager { private static final String TAG = "AppManager"; - public static final String ADD_NAME = "com.zyos.add"; + public static final String ADD_NAME = "com.xwad.add"; public static final String APPSTORE_PACKAGE_NAME = "com.uiui.zyappstore"; public static final String APPSTORE_CLASS_NAME = "com.uiui.zyappstore.activity.MainActivity"; - public static final String UPDATE_NAME = "com.zyos.update"; - public static final String MANUAL_NAME = "com.zyos.manual"; - public static final String SERVICE_NAME = "com.zyos.service"; + public static final String UPDATE_NAME = "com.xwad.update"; + public static final String MANUAL_NAME = "com.xwad.manual"; + public static final String SERVICE_NAME = "com.xwad.service"; private static final String SHOW_PACKAGE_KEY = "SHOW_PACKAGE_KEY"; public static final String BROWSER_PACKAGE_NAME = "com.uiui.zybrowser"; public static final String BROWSER_CLASS_NAME = "com.uiui.zybrowser.activity.main.MainActivity"; - public static final String DESKTOP_EXIT = "com.zyos.exit"; + public static final String DESKTOP_EXIT = "com.xwad.exit"; + public static final String APP_HOMEWORK = "com.xwad.homework"; @SuppressLint("StaticFieldLeak") @@ -62,7 +62,7 @@ public class AppManager { throw new RuntimeException("Context is NULL"); } this.mContext = context; - this.showPackages = mMMKV.decodeStringSet(SHOW_PACKAGE_KEY, new HashSet(){{ + this.showPackages = mMMKV.decodeStringSet(SHOW_PACKAGE_KEY, new HashSet() {{ this.add("com.jxw.yyhb"); this.add("com.jxw.souti"); }}); @@ -98,8 +98,10 @@ public class AppManager { List resolveinfoList = pm.queryIntentActivities(resolveIntent, 0); Set allowPackages = resolveinfoList.stream().map(resolveInfo -> resolveInfo.activityInfo.packageName).collect(Collectors.toSet()); -// List adminApp = AdminManager.getInstance().getAdminApp(); -// Log.i(TAG, "queryFilterAppInfo: adminapp = " + adminApp); + Log.e(TAG, "getFilterAppset: " + showPackages); + + List adminApp = getAdminApp(); + Log.i(TAG, "queryFilterAppInfo: adminapp = " + adminApp); for (ResolveInfo resolveInfo : resolveinfoList) { String pkg = resolveInfo.activityInfo.packageName; if (ApkUtils.appIsDisable(mContext, pkg)) { @@ -116,11 +118,11 @@ public class AppManager { } } else { if (allowPackages.contains(pkg) && !ApkUtils.excludePackageName.contains(pkg)) { -// if (adminApp.contains(pkg)) { -// resolveInfos.add(resolveInfo); -// } else if (ApkUtils.showPackageName.contains(pkg)) { + if (adminApp.contains(pkg)) { resolveInfos.add(resolveInfo); -// } + } else if (ApkUtils.showPackageName.contains(pkg)) { + resolveInfos.add(resolveInfo); + } } } } @@ -148,8 +150,9 @@ public class AppManager { List resolveinfoList = pm.queryIntentActivities(resolveIntent, 0); Set allowPackages = resolveinfoList.stream().map(resolveInfo -> resolveInfo.activityInfo.packageName).collect(Collectors.toSet()); + Log.e(TAG, "getFilterAppList: " + showPackages); -// List adminApp = AdminManager.getInstance().getAdminApp(); + List adminApp = getAdminApp(); // Log.i(TAG, "queryFilterAppInfo: adminapp = " + adminApp); for (ResolveInfo resolveInfo : resolveinfoList) { String pkg = resolveInfo.activityInfo.packageName; @@ -167,11 +170,11 @@ public class AppManager { } } else { if (allowPackages.contains(pkg) && !ApkUtils.excludePackageName.contains(pkg)) { -// if (adminApp.contains(pkg)) { -// resolveInfos.add(resolveInfo); -// } else if (ApkUtils.showPackageName.contains(pkg)) { + if (adminApp.contains(pkg)) { resolveInfos.add(resolveInfo); -// } + } else if (ApkUtils.showPackageName.contains(pkg)) { + resolveInfos.add(resolveInfo); + } } } } @@ -213,7 +216,6 @@ public class AppManager { } - for (ResolveInfo applicationInfo : resolveInfos) { if (!ApkUtils.excludeClassName.contains(applicationInfo.activityInfo.name)) { desktopIcons.add(DesktopIcon.creatDesktopIcon(mContext, applicationInfo)); @@ -234,6 +236,7 @@ public class AppManager { List resolveinfoList = pm.queryIntentActivities(resolveIntent, 0); Set allowPackages = resolveinfoList.stream().map(resolveInfo -> resolveInfo.activityInfo.packageName).collect(Collectors.toSet()); + Log.e(TAG, "getAllAppList: " + showPackages); // List adminApp = AdminManager.getInstance().getAdminApp(); // Log.i(TAG, "queryFilterAppInfo: adminapp = " + adminApp); @@ -289,4 +292,9 @@ public class AppManager { return desktopIcons; } + public List getAdminApp() { + Set adminAppSet = mMMKV.decodeStringSet(CommonConfig.ADMIN_APP_LIST, new HashSet<>()); + Log.e(TAG, "getAdminApp: " + adminAppSet); + return new ArrayList<>(adminAppSet); + } } diff --git a/app/src/main/java/com/xwad/os/manager/ControlManager.java b/app/src/main/java/com/xwad/os/manager/ControlManager.java new file mode 100644 index 0000000..d3ec027 --- /dev/null +++ b/app/src/main/java/com/xwad/os/manager/ControlManager.java @@ -0,0 +1,832 @@ +package com.xwad.os.manager; + +import android.annotation.SuppressLint; +import android.bluetooth.BluetoothAdapter; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; + +import com.google.gson.JsonObject; +import com.hjq.toast.Toaster; +import com.tencent.mmkv.MMKV; +import com.xwad.os.BuildConfig; +import com.xwad.os.bean.SystemSettings; +import com.xwad.os.config.CommonConfig; +import com.xwad.os.gson.GsonUtils; +import com.xwad.os.mdm.AdminManager; +import com.xwad.os.utils.ApkUtils; +import com.xwad.os.utils.JgyUtils; +import com.xwad.os.utils.TimeUtils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.function.Predicate; + +/** + * 系统管理处理 + * 所有数据 后台1是0否,底层0是1否 + * + * @author jgy02 + */ +public class ControlManager { + private static final String TAG = "ControlManager"; + + @SuppressLint("StaticFieldLeak") + private static ControlManager sInstance; + private Context mContext; + private ContentResolver mResolver; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + private ControlManager(Context context) { + if (context == null) { + throw new RuntimeException("Context is NULL"); + } + this.mContext = context; + this.mResolver = context.getContentResolver(); + } + + public static void init(Context context) { + if (sInstance == null) { + sInstance = new ControlManager(context); + } + } + + public static ControlManager getInstance() { + if (sInstance == null) { + throw new IllegalStateException("You must be init ControlManager first"); + } + return sInstance; + } + +// private int changeNum(int status) { +// return status == 0 ? 1 : 0; +// } + + private boolean isDebugMode() { + return BuildConfig.DEBUG; + } + + public void setSystemSetting(String jsonString) { + if (TextUtils.isEmpty(jsonString)) { + return; + } + SystemSettings systemSettings = GsonUtils.toJavaObject(jsonString, SystemSettings.class); + if (null != systemSettings) { + setUSBstate(systemSettings); +// setPhoneList(systemSettings); +// setBluetooth(systemSettings); +// setHotspot(systemSettings); + setBar(systemSettings); + setCamera(systemSettings); +// setTF(systemSettings); + setIcon(systemSettings); + setCanReset(systemSettings); + setDeveloperOptions(systemSettings); +// setSearchTopic(systemSettings); + setSOSNumber(systemSettings); + setAppstoreAdmin(systemSettings); + setDefaultApp(systemSettings); + setIsControl(systemSettings); + setOtherAppInstaller(systemSettings); + setQuickApp(systemSettings); + setTimeControl(systemSettings); + setBrowserInput(systemSettings); + + setZhuangyuanSetting(systemSettings); + } + } + + /** + * 关闭所有功能 + */ + public void setDisableSetting() { + Log.e("setDisableSetting", "Close all settings: "); +// setUSBstate(1); +// setPhoneList(1); +// setBluetooth(0); +// setHotspot(0); + setCamera(1); +// setTF(1); + setIcon(1); + setWallpaper(0); + setCanReset(1); + setBrowserInput(1); + if (!isDebugMode()) { +// setDeveloperOptions(1); + } +// setSearchTopic(0); + setTimeControlClose(); + } + + /** + * usb连接模式管控 + * + * @param settings + */ + private void setUSBstate(SystemSettings settings) { + //USB数据功能管控 + //仅充电:usb_charge + //MTP模式:usb_mtp + //Midi模式:usb_midi + String setting_usb = settings.getSetting_usb(); + Log.e("SystemSetting", "setting_usb:" + setting_usb); + AdminManager.getInstance().setUSBDataDisabled(!"usb_mtp".equals(setting_usb)); + } + + + /** + * usb连接模式管控 + * + * @param state + */ + public void setUSBstate(int state) { + //USB数据功能管控 + //仅充电:usb_charge + //MTP模式:usb_mtp + //Midi模式:usb_midi + if (!isDebugMode()) { + try { +// boolean qch_usb_choose = Settings.System.putString(mResolver, "qch_usb_choose", "usb_charge"); +// Log.e(TAG, "qch_usb_choose:" + qch_usb_choose); + String usbStatus = CommonConfig.AOLE_ACTION_USB_USB_CHARGE; + Intent usbIntent = new Intent(usbStatus).setPackage("com.android.settings"); + mContext.sendBroadcast(usbIntent); + } catch (Exception e) { + Log.e(TAG, "setUSBstate: " + e.getMessage()); + } + } + } + + /** + * usb连接模式管控 + */ + public void setUSBstate(String action) { + //USB数据功能管控 + //仅充电:usb_charge + //MTP模式:usb_mtp + //Midi模式:usb_midi + if (!isDebugMode()) { + Log.e(TAG, "qch_usb_choose:" + action); + AdminManager.getInstance().setUSBDataDisabled(!"usb_mtp".equals(action)); + } + } + + private void setPhoneList(SystemSettings settings) { + //设置电话功能,电话白名单 +// int setting_call = changeNum(settings.getSetting_call()); +// boolean qch_call_forbid = Settings.System.putInt(mResolver, "qch_call_forbid", setting_call); +// Log.e("SystemSetting", "qch_call_forbid: " + setting_call); + +// int setting_phone = changeNum(settings.getSetting_phone()); +// boolean aole_white_list_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_WHITE_LIST_ON, setting_phone); +// Log.e("SystemSetting", "aole_white_list_on: " + setting_phone); + +// String setting_phones = settings.getSetting_phones(); +// boolean aole_white_list_Array = Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_WHITE_LIST_ARRAY, setting_phones); +// Log.e("SystemSetting", "aole_white_list_Array: " + aole_white_list_Array + "=" + setting_phones); + +// int setting_memory = changeNum(settings.getSetting_memory()); +// boolean aole_sdcard_forbid_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_SDCARD_FORBID_ON, setting_memory); +// Log.e("SystemSetting", "aole_sdcard_forbid_on: " + setting_memory); + } + + private void setPhoneList(int state) { + try { + //设置电话功能,电话白名单 +// boolean qch_call_forbid = Settings.System.putInt(mResolver, "qch_call_forbid", state); +// Log.e(TAG, "qch_call_forbid:" + qch_call_forbid); + +// boolean aole_white_list_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_WHITE_LIST_ON, state); +// Log.e(TAG, "aole_white_list_on:" + aole_white_list_on); + +// boolean aole_white_list_Array = Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_WHITE_LIST_ARRAY, ""); + // ToastTool.show("qch_call_forbid::"+setting_call+"----setting_phones::"+setting_phones+"----"+aole_white_list_Array+"---"+qch_call_forbid); +// Log.e(TAG, "aole_white_list_Array:" + aole_white_list_Array + "---" + aole_white_list_Array); + +// boolean aole_sdcard_forbid_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_SDCARD_FORBID_ON, state); +// Log.e(TAG, "aole_sdcard_forbid_on:" + aole_sdcard_forbid_on); + } catch (Exception e) { + Log.e(TAG, "setPhoneList: " + e.getMessage()); + } + } + + private void setBluetooth(SystemSettings settings) { + try { + //蓝牙开关 +// int setting_bht = changeNum(settings.getSetting_bht()); + //总开关 +// int setting_bhtvideo = changeNum(settings.getSetting_bhtvideo()); + //蓝牙音频开关 +// int setting_bluetooth = changeNum(settings.getSetting_bluetooth()); + //蓝牙传输开关 +// boolean aole_bht_forbid_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_BHT_FORBID_ON, setting_bht); + //写入系统数据库 +// Log.e("SystemSetting", "aole_bht_forbid_on:" + aole_bht_forbid_on); + BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); +// if (aole_bht_forbid_on) { +// //成功 +// if (null == mBluetoothAdapter) { +// mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); +// //获取默认蓝牙适配器 +// } +// if (setting_bht == 0) { +// //蓝牙总开关开启 +// String setting_context = settings.getSetting_context(); +// if (setting_bhtvideo == 0) { +// if (null != setting_context && !"".equals(setting_context) && !" ".equals(setting_context) && !"null".equals(setting_context)) { +// Log.e("SystemSetting", "setting_context:" + setting_context); +//// Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, setting_context); +// } else { +//// Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, "Empty"); +// } +// } else if (setting_bhtvideo == 1) { +//// Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, "Empty"); +// } +//// Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_BT_FORBID_ON, setting_bluetooth); +// } else { +// mBluetoothAdapter.disable(); +// //设置关闭时关闭蓝牙 +// } +// } + } catch (Exception e) { + Log.e(TAG, "setBluetooth: " + e.getMessage()); + } + } + + private void setBluetooth(int state) { + try { +// boolean aole_bht_forbid_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_BHT_FORBID_ON, state); + //写入系统数据库 +// Log.e(TAG, "aole_bht_forbid_on:" + aole_bht_forbid_on); + BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); +// if (aole_bht_forbid_on) { +// //成功 +// if (null == mBluetoothAdapter) { +// mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); +// //获取默认蓝牙适配器 +// } +// //蓝牙总开关开启 +//// Settings.System.putString(mResolver, CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, "Empty"); +//// Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_BT_FORBID_ON, state); +// mBluetoothAdapter.disable(); +// //设置关闭时关闭蓝牙 +// } + } catch (Exception e) { + Log.e(TAG, "setBluetooth: " + e.getMessage()); + } + } + + private void setHotspot(SystemSettings settings) { + try { +// int setting_hotspot = changeNum(settings.getSetting_hotspot());//热点 +// if (setting_hotspot == 1) { +// Intent intent = new Intent(); +// intent.setAction("qch_hotspot_close"); +// intent.setPackage("com.android.settings"); +// mContext.sendStickyBroadcast(intent); +// } +// boolean aole_hotspot_forbid_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_HOTSPOT_FORBID_ON, setting_hotspot);//写入系统数据库 +// Log.e("SystemSetting", "aole_hotspot_forbid_on:" + setting_hotspot); +// Log.e("SystemSetting", "aole_hotspot_forbid_on:" + aole_hotspot_forbid_on); + } catch (Exception e) { + Log.e(TAG, "setHotspot: " + e.getMessage()); + } + } + + private void setHotspot(int state) { + try { + Intent intent = new Intent(); + intent.setAction("qch_hotspot_close"); + intent.setPackage("com.android.settings"); + mContext.sendStickyBroadcast(intent); +// boolean aole_hotspot_forbid_on = Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_HOTSPOT_FORBID_ON, state); +// Log.e(TAG, "aole_hotspot_forbid_on:" + aole_hotspot_forbid_on); + } catch (Exception e) { + Log.e(TAG, "setHotspot: " + e.getMessage()); + } + } + + private void setBar(SystemSettings settings) { + //系统导航条显示开关 + int setting_navigation = settings.getSetting_navigation(); + Log.e(TAG, "setBar: setting_navigation = " + setting_navigation); + AdminManager.getInstance().setStatusBarExpandPanelDisabled(setting_navigation); + + //状态栏显示开关 + int setting_statusbar = settings.getSetting_statusbar(); + Log.e(TAG, "setBar: setting_statusbar = " + setting_statusbar); + AdminManager.getInstance().setNavigationBarDisabled(setting_statusbar); + } + + @Deprecated + private void setCamera(SystemSettings settings) { + try { + //摄像头开关 + int setting_camera = (settings.getSetting_camera()); +// Settings.System.putInt(mResolver, "qch_app_camera", setting_camera); +// ApkUtils.hideSystemSettingAPP(mContext, "com.mediatek.camera"); + Log.e("SystemSetting", "setting_camera:" + setting_camera); + String cameraStatus = ""; + switch (setting_camera) { + case 0: + cameraStatus = "qch_camera_open"; + break; + case 1: + cameraStatus = "qch_camera_forbid"; + break; + } + } catch (Exception e) { + Log.e(TAG, "setCamera: " + e.getMessage()); + } + } + + @Deprecated + private void setCamera(int state) { + try { + //摄像头开关 +// boolean qch_app_camera = Settings.System.putInt(mResolver, "qch_app_camera", state); + Log.e(TAG, "qch_app_camera1:" + state); +// ApkUtils.hideSystemSettingAPP(mContext, "com.mediatek.camera"); +// Log.e(TAG, "setting_camera---------" + qch_app_camera); + String cameraStatus = "qch_camera_forbid"; + switch (state) { + case 0: + cameraStatus = "qch_camera_open"; + break; + case 1: + cameraStatus = "qch_camera_forbid"; + break; + } + Intent cameraIntent = new Intent(cameraStatus).setPackage("com.android.settings"); + mContext.sendBroadcast(cameraIntent); + } catch (Exception e) { + Log.e(TAG, "setCamera: " + e.getMessage()); + } + } + + @SuppressLint("NewApi") + private void setTF(SystemSettings settings) { + //tfmedia开关 + int setting_tfmedia = (settings.getSetting_tfmedia()); +// boolean qch_tfmedia_forbid = Settings.System.putInt(mResolver, "qch_tfmedia_forbid", setting_tfmedia); +// Log.e("SystemSetting", "setting_tfmedia:" + qch_tfmedia_forbid); + String tfmediaStatus = ""; + switch (setting_tfmedia) { + case 0: + tfmediaStatus = "qch_tfmedia_open"; + break; + case 1: + tfmediaStatus = "qch_tfmedia_forbid"; + break; + default: + break; + } + Intent tfmediaIntent = new Intent(tfmediaStatus).setPackage("com.android.settings"); + mContext.sendBroadcast(tfmediaIntent); + if (setting_tfmedia == 1) { + String qch_tfmedia_filetypes = settings.getSetting_tfmedia_format(); + if (TextUtils.isEmpty(qch_tfmedia_filetypes)) { +// Settings.System.putString(mResolver, "qch_tfmedia_filetypes", "");//影音管控 + } else { + HashSet types = new HashSet<>(Arrays.asList(qch_tfmedia_filetypes.split(","))); + types.removeIf(new Predicate() { + @Override + public boolean test(String s) { + return TextUtils.isEmpty(s); + } + }); + String typesString = String.join(",", types); +// Settings.System.putString(mResolver, "qch_tfmedia_filetypes", typesString);//影音管控 + Log.e("SystemSetting", "qch_tfmedia_filetypes :" + typesString); + } + } else { +// Settings.System.putInt(mResolver, "qch_tfmedia_forbid", 0); + } + } + + private void setTF(int state) { + try { + //tfmedia开关 +// int setting_tfmedia = 1; +// boolean qch_tfmedia_forbid = Settings.System.putInt(mResolver, "qch_tfmedia_forbid", state); +// Log.e(TAG, "setting_tfmedia---------" + qch_tfmedia_forbid); + String tfmediaStatus = ""; + switch (state) { + case 0: + tfmediaStatus = "qch_tfmedia_open"; + break; + case 1: + tfmediaStatus = "qch_tfmedia_forbid"; + break; + } + Intent tfmediaIntent = new Intent(tfmediaStatus).setPackage("com.android.settings"); + mContext.sendBroadcast(tfmediaIntent); + if (state == 1) { +// boolean qch_tfmedia_filetypes = Settings.System.putString(mResolver, "qch_tfmedia_filetypes", "Empty");//影音管控 +// Log.e(TAG, "qch_tfmedia_filetypes:" + qch_tfmedia_filetypes); + } else { +// Settings.System.putInt(mResolver, "qch_tfmedia_forbid", 0); + } + } catch (Exception e) { + Log.e(TAG, "setTF: " + e.getMessage()); + } + } + + @Deprecated + private void setIcon(SystemSettings settings) { + try { + int deskclock = (settings.getSetting_clock()); + Log.e("SystemSetting", "qch_app_deskclock:" + deskclock); + //录音机 + int soundrecorder = (settings.getSetting_recording()); + Log.e("SystemSetting", "qch_app_soundrecorder:" + soundrecorder); + //音乐 + int music = (settings.getSetting_music()); + Log.e("SystemSetting", "qch_app_music:" + music); + //图库 + int gallery = (settings.getSetting_picture()); + Log.e("SystemSetting", "qch_app_gallery:" + gallery); + //壁纸 + int wallpaper = (settings.getSetting_wallpaper()); + Log.e("SystemSetting", "qch_app_wallpaper:" + wallpaper); + //文件管理器 + int filemanager = (settings.getSetting_file()); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { +// ApkUtils.hideSystemSettingAPP(mContext, "com.mediatek.filemanager"); + } else { +// ApkUtils.hideSystemSettingAPP(mContext, "com.android.documentsui"); + } + Log.e("SystemSetting", "qch_app_filemanager:" + filemanager); + //浏览器 + int browser = (settings.getSetting_browser()); + Log.e(TAG, "qch_app_browser" + browser); + } catch (Exception e) { + Log.e(TAG, "setIcon: " + e.getMessage()); + } + } + + @Deprecated + private void setIcon(int state) { + try { + + //时钟 +// int deskclock = 1; +// ApkUtils.hideSystemSettingAPP(mContext, "com.android.deskclock"); + Log.e(TAG, "qch_app_deskclock" + state); + //录音机 +// int soundrecorder = 1; +// ApkUtils.hideSystemSettingAPP(mContext, "com.android.soundrecorder"); + Log.e(TAG, "qch_app_soundrecorder" + state); + //音乐 +// int music = 1; +// ApkUtils.hideSystemSettingAPP(mContext, "com.android.music"); + Log.e(TAG, "qch_app_music" + state); + //图库 +// int gallery = 1; +// ApkUtils.hideSystemSettingAPP(mContext, "com.android.gallery3d"); + Log.e(TAG, "qch_app_gallery" + state); + //文件管理器 +// int filemanager = 1; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { +// ApkUtils.hideSystemSettingAPP(mContext, "com.mediatek.filemanager"); + } else { +// ApkUtils.hideSystemSettingAPP(mContext, "com.android.documentsui"); + } + Log.e(TAG, "qch_app_filemanager" + state); + //浏览器 + Log.e(TAG, "qch_app_browser" + state); + } catch (Exception e) { + Log.e(TAG, "setIcon: " + e.getMessage()); + } + } + + private void setWallpaper(int state) { + //壁纸 +// int wallpaper = 1; +// Settings.System.putInt(mResolver, "qch_app_wallpaper", state); + Log.e(TAG, "qch_app_wallpaper" + state); + } + + private void setCanReset(SystemSettings settings) { + int qch_restore = settings.getQch_restore(); + Log.e(TAG, "setCanReset: qch_restore = " + qch_restore); + AdminManager.getInstance().setRestoreFactoryDisabled(qch_restore); + } + + private void setCanReset(int state) { + Log.e(TAG, "setCanReset: state = " + state); + AdminManager.getInstance().setRestoreFactoryDisabled(state); + } + + /** + * 置浏览器禁止输入,默认打开 + * + * @param state + */ + @Deprecated + private void setBrowserInput(int state) { +// Settings.System.putInt(mResolver, "qch_Browser_input", 0); + } + + @Deprecated + private void setBrowserInput(SystemSettings systemSettings) { + int setting_browserInput = (systemSettings.getSetting_browserInput()); +// Settings.System.putInt(mResolver, "qch_Browser_input", setting_browserInput); + } + + public void setDeveloperOptions(SystemSettings systemSettings) { + int dev_mode = systemSettings.getDev_mode(); + Log.e(TAG, "setDeveloperOptions: " + dev_mode); + if (!isDebugMode()) { + setDeveloperMode(dev_mode); + } + } + + public void setDeveloperOptions(String jsonString) { + JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); + int dev_mode = (jsonObject.get("dev_mode").getAsInt()); + Log.e(TAG, "setDeveloperOptions: " + dev_mode); + if (!isDebugMode()) { +// Settings.System.putInt(mResolver, "qch_Developeroptions", dev_mode); + int old_dev_enabled = Settings.Global.getInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0); + Log.e(TAG, "setDeveloperOptions: " + old_dev_enabled); + int new_state = (dev_mode == 1 ? 0 : 1); + if (old_dev_enabled != new_state) { +// Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, new_state); +// Settings.Global.putInt(mResolver, Settings.Global.ADB_ENABLED, new_state); + } +// Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_DEVELOPER_OPTIONS, dev_mode); + if (dev_mode == 1) { + Intent intent = new Intent(); + intent.setAction("qch_developeroptions_close"); + intent.setPackage("com.android.settings"); + mContext.sendBroadcast(intent); + Log.e(TAG, "setDeveloperOptions: " + "关闭开发者模式"); + Toaster.debugShow("关闭开发者模式"); + } else { + Log.e(TAG, "setDeveloperOptions: " + "打开开发者模式"); + Toaster.debugShow("打开开发者模式"); + } + } + } + + public void setDeveloperOptions(int state) { + Log.e(TAG, "setDeveloperOptions: " + state); + if (!isDebugMode()) { +// Settings.System.putInt(mResolver, "qch_Developeroptions", state); + int old_dev_enabled = Settings.Global.getInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0); + Log.e(TAG, "setDeveloperOptions: " + old_dev_enabled); + int new_state = (state == 1 ? 0 : 1); + if (old_dev_enabled != new_state) { +// Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, new_state); +// Settings.Global.putInt(mResolver, Settings.Global.ADB_ENABLED, new_state); + } +// Settings.System.putInt(mResolver, CommonConfig.AOLE_ACTION_DEVELOPER_OPTIONS, state); + if (state == 1) { + Intent intent = new Intent(); + intent.setAction("qch_developeroptions_close"); + intent.setPackage("com.android.settings"); + mContext.sendBroadcast(intent); + Log.e(TAG, "setDeveloperOptions: " + "关闭开发者模式"); + } else { + Log.e(TAG, "setDeveloperOptions: " + "打开开发者模式"); +// Toaster.show("打开开发者模式"); + } + } + } + + public void setSearchTopic(String jsonString) { + JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); + if (jsonObject.get("search_topic") == null) return; + int mode = jsonObject.get("search_topic").getAsInt(); + mMMKV.encode("search_topic", mode); + Log.e(TAG, "setSearchTopic:" + mode); + } + + public void setSearchTopic(int state) { + mMMKV.encode("search_topic", state); + Log.e(TAG, "setSearchTopic:" + state); + } + + /** + * 开机管控usb + */ + public void setDefaultUSBstate() { + //USB数据功能管控 + //仅充电:usb_charge + //MTP模式:usb_mtp + //Midi模式:usb_midi + String setting_usb = Settings.System.getString(mResolver, "qch_usb_choose"); + Log.e("SystemSetting", "setting_usb:" + setting_usb); + String usbStatus = ""; + if (TextUtils.isEmpty(setting_usb)) { + usbStatus = CommonConfig.AOLE_ACTION_USB_USB_CHARGE; + } else { + if (!isDebugMode()) { + switch (setting_usb) { + case "usb_charge": + usbStatus = CommonConfig.AOLE_ACTION_USB_USB_CHARGE; + break; + case "usb_mtp": + usbStatus = CommonConfig.AOLE_ACTION_USB_USB_MTP; + break; +// case "usb_midi": +// usbStatus = CommonConfig.AOLE_ACTION_USB_USB_MIDI; +// break; + default: + usbStatus = CommonConfig.AOLE_ACTION_USB_USB_CHARGE; + break; + } + } + } + Intent usbIntent = new Intent(usbStatus).setPackage("com.android.settings"); + mContext.sendBroadcast(usbIntent); + } + + @Deprecated + private void setSOSNumber(SystemSettings settings) { + String setting_sos = settings.getSetting_sos(); + Log.e(TAG, "setSOSNumber: setting_sos = " + setting_sos); + } + + @Deprecated + private void setAppstoreAdmin(SystemSettings settings) { + int setting_admin_app = settings.getSetting_admin_app(); + mMMKV.encode(CommonConfig.APP_ADMIN, setting_admin_app); + int isReturnAndroid = settings.getIs_return_android(); + mMMKV.encode(CommonConfig.UIUI_RETURN_ANDROID_KEY, isReturnAndroid); + } + + private void setSetting(SystemSettings settings) { + String setting_volume = settings.getSetting_volume(); + String setting_luminance = settings.getSetting_luminance(); + String setting_typeface = settings.getSetting_typeface(); + } + + private void setScreenShared(SystemSettings settings) { + int projection_screen = settings.getProjection_screen(); + setScreenShared(projection_screen); + } + + private void setScreenShared(int state) { +// Settings.System.putInt(mResolver, "projection_screen", state); + } + + private void setHotPoint(SystemSettings settings) { + int hot_point = settings.getHot_point(); + setScreenShared(hot_point); + } + + private void setHotPoint(int state) { +// Settings.System.putInt(mResolver, "hot_point", state); + } + + private void setDefaultApp(SystemSettings settings) { + String desktop_app = settings.getDesktop_app(); + Log.e(TAG, "setDefaultApp: desktop_app = " + desktop_app); + if (!TextUtils.isEmpty(desktop_app)) { + mMMKV.encode(CommonConfig.DESKTOP_APP_KEY, desktop_app); + JgyUtils.getInstance().setDefaultDesktop(desktop_app); + } else { + mMMKV.encode(CommonConfig.DESKTOP_APP_KEY, ""); + } + String browser_app = settings.getBrowser_app(); + Log.e(TAG, "setDefaultApp: browser_app = " + browser_app); + if (!TextUtils.isEmpty(browser_app)) { + mMMKV.encode(CommonConfig.BROWSER_APP_KEY, browser_app); + JgyUtils.getInstance().setDefaultBrowser(browser_app); + } else { + mMMKV.encode(CommonConfig.BROWSER_APP_KEY, ""); + } + String typewriting_app = settings.getTypewriting_app(); + Log.e(TAG, "setDefaultApp: typewriting_app = " + typewriting_app); + if (!TextUtils.isEmpty(typewriting_app)) { + mMMKV.encode(CommonConfig.TYPEWRITING_APP_KEY, typewriting_app); + JgyUtils.getInstance().setDefaultInputMethod(typewriting_app); + } else { + mMMKV.encode(CommonConfig.TYPEWRITING_APP_KEY, ""); + } + } + + /** + * 应用安装之后重新设置 + */ + public void setDefaultApp() { + String desktop_app = mMMKV.decodeString(CommonConfig.DESKTOP_APP_KEY, ""); + Log.e(TAG, "setDefaultApp: desktop_app = " + desktop_app); + if (!TextUtils.isEmpty(desktop_app)) { + JgyUtils.getInstance().setDefaultDesktop(desktop_app); + } + String browser_app = mMMKV.decodeString(CommonConfig.BROWSER_APP_KEY, ""); + Log.e(TAG, "setDefaultApp: browser_app = " + browser_app); + if (!TextUtils.isEmpty(browser_app)) { + JgyUtils.getInstance().setDefaultBrowser(browser_app); + } + String typewriting_app = mMMKV.decodeString(CommonConfig.TYPEWRITING_APP_KEY, ""); + Log.e(TAG, "setDefaultApp: typewriting_app = " + typewriting_app); + if (!TextUtils.isEmpty(typewriting_app)) { + JgyUtils.getInstance().setDefaultInputMethod(typewriting_app); + } + } + + private void setIsControl(SystemSettings settings) { + int is_control = settings.getIs_control(); + setIsControl(is_control); + } + + private void setIsControl(int state) { +// Settings.System.putInt(mResolver, CommonConfig.KEY_IS_CONTROL, state); + //关闭 + if (state == 0) { +// setBluetooth(0); +// setHotspot(0); + setUSBstate(CommonConfig.AOLE_ACTION_USB_USB_MTP); + } + } + + @Deprecated + private void setOtherAppInstaller(SystemSettings settings) { + int is_storeinstall = settings.getIs_storeinstall(); + mMMKV.encode(CommonConfig.APP_STORE_INSTALL, is_storeinstall); + int setting_other_appInstaller = settings.getSetting_other_appInstaller(); + mMMKV.encode(CommonConfig.APP_INSTALLATION, setting_other_appInstaller); + } + + @Deprecated + public void setOtherAppInstaller(int status) { + mMMKV.encode(CommonConfig.APP_STORE_INSTALL, status); + mMMKV.encode(CommonConfig.APP_INSTALLATION, status); + mMMKV.encode(CommonConfig.AOLE_APP_ALLOW_INSTALL, status); + } + + + public static final String QUICK_APP_KEY = "QuickAppPackageKey"; + public static final String QUICK_APP_REFRESH_KEY = "QuickAppRefreshKey"; + public static final String QUICK_APP_ENABLED_KEY = "QuickAppEnabledKey"; + + @Deprecated + private void setQuickApp(SystemSettings settings) { + if (settings.getIs_quickapp() == 1) { + String pkg = settings.getQuickapp(); +// Settings.Global.putString(mContext.getContentResolver(), QUICK_APP_KEY, pkg); +// Settings.Global.putInt(mContext.getContentResolver(), QUICK_APP_ENABLED_KEY, 1); + } else { +// Settings.Global.putInt(mContext.getContentResolver(), QUICK_APP_ENABLED_KEY, 0); + } + } + + private void setTimeControl(SystemSettings settings) { + int is_timecontrol = settings.getIs_timecontrol(); + mMMKV.encode(TimeUtils.AOLELEARN_TIME_CONTROL_KEY, is_timecontrol); + +// String timecontrol_start = settings.getTimecontrol_start(); +// mMMKV.encode(TimeUtils.AOLELEARN_TTIMECONTROL_START_KEY, timecontrol_start); +// String timecontrol_end = settings.getTimecontrol_start(); +// mMMKV.encode(TimeUtils.AOLELEARN_TTIMECONTROL_END_KEY, timecontrol_end); + } + + private void setTimeControlClose() { + mMMKV.encode(TimeUtils.AOLELEARN_TIME_CONTROL_KEY, 0); +// mMMKV.encode(TimeUtils.AOLELEARN_TTIMECONTROL_START_KEY, ""); +// mMMKV.encode(TimeUtils.AOLELEARN_TTIMECONTROL_END_KEY, ""); + } + + private void setZhuangyuanSetting(SystemSettings setting) { + setBluetoothShare((setting.getIs_bluetooth_share())); + setDeveloperMode((setting.getIs_developer_mode())); + setDeviceRecover((setting.getIs_device_recover())); + setTopNotify(setting.getIs_top_notify()); + setBottomBar(setting.getIs_bottom_bar()); + } + + public void setBluetoothShare(int status) { + Log.e(TAG, "setBluetoothShare: " + status); + AdminManager.getInstance().setBluetoothDataTransferDisable(status == 0); + } + + public void setDeveloperMode(int status) { + Log.e(TAG, "setDeveloperMode: " + status); + AdminManager.getInstance().turnOnUsbDebugMode(status); + } + + public void setDeviceRecover(int status) { + Log.e(TAG, "setDeviceRecover: " + status); + AdminManager.getInstance().setRestoreFactoryDisabled(status); + } + + public void setTopNotify(int status) { + Log.e(TAG, "setTopNotify: " + status); + AdminManager.getInstance().setStatusBarExpandPanelDisabled(status); + } + + public void setBottomBar(int status) { + Log.e(TAG, "setBottomBar: " + status); + AdminManager.getInstance().setNavigationBarDisabled(status); + } + + +} diff --git a/app/src/main/java/com/xwad/os/manager/DeviceSNManager.java b/app/src/main/java/com/xwad/os/manager/DeviceSNManager.java index d171bc6..1c4e2f7 100644 --- a/app/src/main/java/com/xwad/os/manager/DeviceSNManager.java +++ b/app/src/main/java/com/xwad/os/manager/DeviceSNManager.java @@ -24,6 +24,7 @@ public class DeviceSNManager { /** * 获取设备SN,如果不存在则创建新的 */ + @Deprecated public static String getDeviceSN() { String existingSN = mMMKV.decodeString(SN_KEY, ""); diff --git a/app/src/main/java/com/xwad/os/mdm/AdminManager.java b/app/src/main/java/com/xwad/os/mdm/AdminManager.java index 34af8bb..74a8fe9 100644 --- a/app/src/main/java/com/xwad/os/mdm/AdminManager.java +++ b/app/src/main/java/com/xwad/os/mdm/AdminManager.java @@ -119,27 +119,33 @@ public class AdminManager { this.mContext = context; this.mAdminName = new ComponentName(context, AoleDeviceAdminReceiver.class); this.mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - this.mDeviceApplicationManager = new DeviceApplicationManager(); - this.mDeviceBluetoothManager = new DeviceBluetoothManager(); - this.mDeviceCameraManager = new DeviceCameraManager(); - this.mDeviceControlManager = new DeviceControlManager(); - this.mDeviceEmailManager = new DeviceEmailManager(); - this.mDeviceFirewallManager = new DeviceFirewallManager(); - this.mDeviceHwSystemManager = new DeviceHwSystemManager(); - this.mDeviceInfraredManager = new DeviceInfraredManager(); - this.mDeviceLocationManager = new DeviceLocationManager(); - this.mDeviceNetworkManager = new DeviceNetworkManager(); - this.mDeviceP2PManager = new DeviceP2PManager(); - this.mDevicePackageManager = new DevicePackageManager(); - this.mDevicePasswordManager = new DevicePasswordManager(); - this.mDevicePhoneManager = new DevicePhoneManager(); - this.mDeviceRestrictionManager = new DeviceRestrictionManager(); - this.mDeviceSettingsManager = new DeviceSettingsManager(); - this.mDeviceStorageManagerEx = new DeviceStorageManagerEx(); - this.mDeviceTelephonyManager = new DeviceTelephonyManager(); + try { + this.mDeviceApplicationManager = new DeviceApplicationManager(); + this.mDeviceBluetoothManager = new DeviceBluetoothManager(); + this.mDeviceCameraManager = new DeviceCameraManager(); + this.mDeviceControlManager = new DeviceControlManager(); + this.mDeviceEmailManager = new DeviceEmailManager(); + this.mDeviceFirewallManager = new DeviceFirewallManager(); + this.mDeviceHwSystemManager = new DeviceHwSystemManager(); + this.mDeviceInfraredManager = new DeviceInfraredManager(); + this.mDeviceLocationManager = new DeviceLocationManager(); + this.mDeviceNetworkManager = new DeviceNetworkManager(); + this.mDeviceP2PManager = new DeviceP2PManager(); + this.mDevicePackageManager = new DevicePackageManager(); + this.mDevicePasswordManager = new DevicePasswordManager(); + this.mDevicePhoneManager = new DevicePhoneManager(); + this.mDeviceRestrictionManager = new DeviceRestrictionManager(); + this.mDeviceSettingsManager = new DeviceSettingsManager(); + this.mDeviceStorageManagerEx = new DeviceStorageManagerEx(); + this.mDeviceTelephonyManager = new DeviceTelephonyManager(); // this.mDeviceTelevisionManager = new DeviceTelevisionManager(); - this.mDeviceVpnManager = new DeviceVpnManager(); - this.mDeviceWifiPolicyManager = new DeviceWifiPolicyManager(); + this.mDeviceVpnManager = new DeviceVpnManager(); + this.mDeviceWifiPolicyManager = new DeviceWifiPolicyManager(); + } catch (Exception e) { + Log.e(TAG, "AdminManager: " + e.getMessage()); + } + + removeAllInstallPackageTrustList(); Log.e(TAG, "AdminManager: setCallStatusNotificationApp = " + setCallStatusNotificationApp(BuildConfig.APPLICATION_ID)); getCallStatusNotificationApp(); @@ -543,10 +549,12 @@ public class AdminManager { /** * 设置可信任应用列表 - * + * 3.11.9 ~ 3.11.23 接口为拆分了以上功能的各个接口,该接口和 3.11.9 ~ 3.11.23 接 + * 口不可同时使用。 * @param packageNames */ public void setSuperTrustListForHwSystemManger(ArrayList packageNames) { + Log.e(TAG, "setSuperTrustListForHwSystemManger: " + packageNames); try { mDeviceHwSystemManager.setSuperTrustListForHwSystemManger(mAdminName, packageNames); } catch (Exception e) { @@ -564,6 +572,7 @@ public class AdminManager { } public void removeSuperTrustListForHwSystemManger(ArrayList packageNames) { + Log.e(TAG, "removeSuperTrustListForHwSystemManger: " + packageNames); try { mDeviceHwSystemManager.removeSuperTrustListForHwSystemManger(mAdminName, packageNames); } catch (Exception e) { @@ -666,17 +675,27 @@ public class AdminManager { public static Uri toUri(Context context, String filePath) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // return FileProvider.getUriForFile(context, context.getApplicationInfo().packageName + ".fileprovider", new File(filePath)); - return FileProvider.getUriForFile(context, "com.uiui.sn.fileprovider", new File(filePath)); + return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".FileProvider", new File(filePath)); } return Uri.fromFile(new File(filePath)); } private Set defaultAllowInstallPackages = new HashSet() {{ this.add(BuildConfig.APPLICATION_ID); + this.add("com.xwad.store"); this.add("com.uiui.aios"); this.add("com.uiui.appstore"); }}; + public void setInstallPackageDefaultTrustList(List packages) { + Log.e(TAG, "setInstallPackageDefaultTrustList: " + packages); + List trustList = new ArrayList<>(defaultAllowInstallPackages); + if (packages != null && !packages.isEmpty()) { + trustList.addAll(packages); + } + addInstallPackageTrustList(trustList); + } + public void addInstallPackageDefaultTrustList(List packages) { Log.e(TAG, "addInstallPackageDefaultTrustList: " + packages); removeAllInstallPackageTrustList(); @@ -755,11 +774,12 @@ public class AdminManager { * @param filePath */ public void installPackage(String filePath) { - try { - mDevicePackageManager.installPackage(mAdminName, filePath); - } catch (Exception e) { - Log.e(TAG, "installPackage: " + e.getMessage()); - } + Log.e(TAG, "installPackage: " + filePath); +// try { +// mDevicePackageManager.installPackage(mAdminName, filePath); +// } catch (Exception e) { +// Log.e(TAG, "installPackage: " + e.getMessage()); +// } Uri contentUri = toUri(mContext, filePath); mContext.grantUriPermission("android", contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); String uriPath = contentUri.toString(); @@ -1718,6 +1738,7 @@ public class AdminManager { } } + @Deprecated public void addAlertWindowApps(ArrayList appList) { try { int sdk_int = Utils.getMagicOsVersion(); diff --git a/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java b/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java index a0fb998..28c8b0d 100644 --- a/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java +++ b/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java @@ -2,9 +2,20 @@ package com.xwad.os.network; import android.annotation.SuppressLint; import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Environment; +import android.text.TextUtils; import android.util.Log; +import androidx.core.content.ContextCompat; + import com.google.gson.Gson; +import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.tencent.mmkv.MMKV; import com.trello.rxlifecycle4.RxLifecycle; @@ -15,6 +26,7 @@ import com.xwad.os.alarm.AlarmUtils; import com.xwad.os.bean.AlarmClockData; import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.AppUpdateInfo; +import com.xwad.os.bean.AppUploadInfo; import com.xwad.os.bean.BaseResponse; import com.xwad.os.bean.CodeBean; import com.xwad.os.bean.GuideBean; @@ -26,40 +38,54 @@ import com.xwad.os.bean.LoginInfo; import com.xwad.os.bean.OrderInfo; import com.xwad.os.bean.PayInfo; import com.xwad.os.bean.PhraseContent; +import com.xwad.os.bean.ScreenPassword; import com.xwad.os.bean.SnInfo; import com.xwad.os.bean.StudyStatBean; import com.xwad.os.bean.SystemSettings; import com.xwad.os.bean.UserAvatarInfo; import com.xwad.os.bean.UserInfo; import com.xwad.os.bean.VipInfo; +import com.xwad.os.bean.WhoisBean; import com.xwad.os.config.CommonConfig; import com.xwad.os.disklrucache.CacheHelper; import com.xwad.os.gson.GsonUtils; -import com.xwad.os.manager.DeviceSNManager; +import com.xwad.os.manager.ControlManager; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.network.api.AlarmClockApi; import com.xwad.os.network.api.AppApi; import com.xwad.os.network.api.AppUsageRecordApi; import com.xwad.os.network.api.FilesApi; +import com.xwad.os.network.api.GetWhoisApi; import com.xwad.os.network.api.HomeworkApi; import com.xwad.os.network.api.LoginApi; import com.xwad.os.network.api.PhraseApi; import com.xwad.os.network.api.SettingApi; import com.xwad.os.network.api.SnInfoApi; +import com.xwad.os.network.api.UploadAppImgApi; +import com.xwad.os.network.api.UploadScreenshot; import com.xwad.os.network.api.UserApi; import com.xwad.os.network.api.jxw.JxwApi; import com.xwad.os.network.api.uiuios.CheckUpdateApi; import com.xwad.os.network.interceptor.RepeatRequestInterceptor; +import com.xwad.os.service.ManagerService; import com.xwad.os.utils.ActivationUtil; +import com.xwad.os.utils.ApkUtils; +import com.xwad.os.utils.BitmapUtils; +import com.xwad.os.utils.CmdUtil; +import com.xwad.os.utils.JgyUtils; import com.xwad.os.utils.JxwUtils; import com.xwad.os.utils.OpenApkUtils; import com.xwad.os.utils.Utils; import java.io.File; +import java.io.FileNotFoundException; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -67,8 +93,12 @@ import java.util.stream.Collectors; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableEmitter; +import io.reactivex.rxjava3.core.ObservableOnSubscribe; +import io.reactivex.rxjava3.core.ObservableSource; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.BehaviorSubject; import okhttp3.Cache; @@ -78,11 +108,14 @@ import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; +import retrofit2.Call; import retrofit2.Retrofit; import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; public class NetInterfaceManager { + private static final String TAG = "NetInterfaceManager"; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); @SuppressLint("StaticFieldLeak") @@ -97,6 +130,9 @@ public class NetInterfaceManager { private Retrofit mJxwRetrofit; private OkHttpClient mJxwOkHttpClient; + private Set mUploadIconPkgs; + private static final String uploadIconPkgsKey = "UPLOAD_ICON_PACKAGE_KEY"; + private final ConcurrentHashMap requestIdsMap = new ConcurrentHashMap<>(); //超时时间 private static final int TIME_OUT = 30; @@ -180,6 +216,9 @@ public class NetInterfaceManager { .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .build(); } + + mUploadIconPkgs = mMMKV.decodeStringSet(uploadIconPkgsKey, new HashSet<>()); + Log.e("init", "NetInterfaceManager: mUploadIconPkgs = " + mUploadIconPkgs); } /** @@ -243,6 +282,7 @@ public class NetInterfaceManager { * @param pkg * @return */ + @Deprecated public Observable> getCheckUpdateObservable(String pkg) { return mUiuiosRetrofit.create(CheckUpdateApi.class) .checkUpdate(pkg) @@ -259,6 +299,22 @@ public class NetInterfaceManager { return mRetrofit.create(AppUsageRecordApi.class); } + public UploadScreenshot getUploadScreenshotControl() { + return mRetrofit.create(UploadScreenshot.class); + } + + public SnInfoApi getSnInfoApi() { + return mRetrofit.create(SnInfoApi.class); + } + + public AppApi getAppApi() { + return mRetrofit.create(AppApi.class); + } + + public UploadAppImgApi getUploadAppImgApi() { + return mRetrofit.create(UploadAppImgApi.class); + } + /* * * Observable @@ -266,15 +322,15 @@ public class NetInterfaceManager { * */ public Observable> getSnInfoControl() { - return mRetrofit.create(SnInfoApi.class) - .getSninfo(DeviceSNManager.getDeviceSN()) + return getSnInfoApi() + .getSninfo(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getUserAvatarInfoControl() { - return mRetrofit.create(SnInfoApi.class) - .getUserAvatarInfo(DeviceSNManager.getDeviceSN()) + return getSnInfoApi() + .getUserAvatarInfo(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -282,21 +338,21 @@ public class NetInterfaceManager { public Observable getUpdateInfoObservable(Map params) { String json = GsonUtils.toJSONString(params); RequestBody body = convertToJsonRequestBody(json); - return mRetrofit.create(SnInfoApi.class) + return getSnInfoApi() .updateUserInfo(getToken(), body) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getUpdateInfoObservable(Map params, MultipartBody.Part multipartBody) { - return mRetrofit.create(SnInfoApi.class) + return getSnInfoApi() .updateUserInfo(getToken(), params, multipartBody) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getupdateAvatarObservable(Map params, MultipartBody.Part multipartBody) { - return mRetrofit.create(SnInfoApi.class) + return getSnInfoApi() .updateAvatar(getToken(), params, multipartBody) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); @@ -304,21 +360,21 @@ public class NetInterfaceManager { public Observable getRunningAppObservable(String json) { return mRetrofit.create(AppUsageRecordApi.class) - .sendRunningInfo(DeviceSNManager.getDeviceSN(), json) + .sendRunningInfo(AdminManager.getInstance().getSerial(), json) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getCloudLessonObservable() { return mRetrofit.create(SettingApi.class) - .getCloudLessonSetting(DeviceSNManager.getDeviceSN()) + .getCloudLessonSetting(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getCloudLessonAppObservable() { return mRetrofit.create(SettingApi.class) - .getCloudLessonApp(DeviceSNManager.getDeviceSN()) + .getCloudLessonApp(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -326,28 +382,28 @@ public class NetInterfaceManager { public Observable>> getAlarmClockObservable() { return mRetrofit .create(AlarmClockApi.class) - .getAlarmClock(DeviceSNManager.getDeviceSN()) + .getAlarmClock(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getUpdateAlarmObservable(int id) { return mRetrofit.create(AlarmClockApi.class) - .updateAlarm(DeviceSNManager.getDeviceSN(), id) + .updateAlarm(AdminManager.getInstance().getSerial(), id) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getStudyStatObservable() { - return mRetrofit.create(SnInfoApi.class) - .getStudyStat(DeviceSNManager.getDeviceSN()) + return getSnInfoApi() + .getStudyStat(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getUpdateAddressObservable(String address, double longitude, double latitude) { - return mRetrofit.create(SnInfoApi.class) - .updateAddress(getToken(), DeviceSNManager.getDeviceSN(), address, longitude, latitude) + return getSnInfoApi() + .updateAddress(getToken(), AdminManager.getInstance().getSerial(), address, longitude, latitude) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -361,46 +417,53 @@ public class NetInterfaceManager { public Observable>> getHomeworkObservable() { return mRetrofit.create(HomeworkApi.class) - .getHomeworks(DeviceSNManager.getDeviceSN()) + .getHomeworks(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getHomeworkDetailObservable(int id) { return mRetrofit.create(HomeworkApi.class) - .getHomeworkDetail(DeviceSNManager.getDeviceSN(), id) + .getHomeworkDetail(AdminManager.getInstance().getSerial(), id) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getHomeworkUpdateObservable(int id) { return mRetrofit.create(HomeworkApi.class) - .updateHomework(DeviceSNManager.getDeviceSN(), id) + .updateHomework(AdminManager.getInstance().getSerial(), id) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getPhraseObservable() { return mRetrofit.create(PhraseApi.class) - .getPhrase(DeviceSNManager.getDeviceSN()) + .getPhrase(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getSettingControl() { return mRetrofit.create(SettingApi.class) - .getSetting(DeviceSNManager.getDeviceSN()) + .getSetting(AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getAdminAppObservable(String app_package) { - return mRetrofit.create(AppApi.class) + return getAppApi() .getAdminApp(BuildConfig.APPLICATION_ID, app_package) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } + public Observable> getUpdateObservable(String packageName) { + return getAppApi() + .getAppUpdate(packageName, "0", JgyUtils.getInstance().checkAppPlatform()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + public Observable getPhoneCodeObservable(String mobile) { return mRetrofit.create(LoginApi.class) .getCode(mobile) @@ -410,21 +473,21 @@ public class NetInterfaceManager { public Observable> getCodeLoginObservable(String mobile, String code) { return mRetrofit.create(LoginApi.class) - .codeLogin(mobile, code, DeviceSNManager.getDeviceSN()) + .codeLogin(mobile, code, AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getNewCodeLoginObservable(String mobile, String code) { return mRetrofit.create(LoginApi.class) - .newCodeLogin(mobile, code, "", BuildConfig.APPLICATION_ID) + .newCodeLogin(mobile, code, AdminManager.getInstance().getSerial(), BuildConfig.APPLICATION_ID) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getUserLoginObservable(String mobile, String password) { return mRetrofit.create(LoginApi.class) - .userLogin(mobile, password, DeviceSNManager.getDeviceSN()) + .userLogin(mobile, password, AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -445,32 +508,55 @@ public class NetInterfaceManager { public Observable> getBuyVipControl(String vipId) { return mRetrofit.create(UserApi.class) - .buyVip(getToken(), DeviceSNManager.getDeviceSN(), vipId) + .buyVip(getToken(), AdminManager.getInstance().getSerial(), vipId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getCodeActivationControl(String code) { return mRetrofit.create(UserApi.class) - .codeActivation(getToken(), DeviceSNManager.getDeviceSN(), code) + .codeActivation(getToken(), AdminManager.getInstance().getSerial(), code) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getActivationCodeControl() { return mRetrofit.create(UserApi.class) - .getActivationCode(getToken(), DeviceSNManager.getDeviceSN()) + .getActivationCode(getToken(), AdminManager.getInstance().getSerial()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable> getPayQrcodeControl(String orderSn) { return mRetrofit.create(UserApi.class) - .payQrcode(getToken(), DeviceSNManager.getDeviceSN(), orderSn) + .payQrcode(getToken(), AdminManager.getInstance().getSerial(), orderSn) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } + public Observable> getLockScreenPwdObservable() { + return getSnInfoApi() + .getLockScreenPwd(Utils.getSerial()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Observable getUpdateLockScreenObservable() { + return mRetrofit.create(SnInfoApi.class) + .updateLockScreen(Utils.getSerial()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Observable>> getAdminAppObservable() { + return mRetrofit.create(AppApi.class) + .getAdminApp(Utils.getSerial()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + + public Observable getOauthTokenObservable() { Map params = new HashMap<>(); params.put("appId", JxwUtils.getAppId()); @@ -510,7 +596,7 @@ public class NetInterfaceManager { void onComplete(); } - public interface onCompleteCallback { + public interface OnCompleteCallback { void onComplete(); } @@ -646,12 +732,12 @@ public class NetInterfaceManager { return new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { - Log.e("getUserAvatarInfoControl", "onSubscribe: "); + Log.e("getUserAvatarInfo", "onSubscribe: "); } @Override public void onNext(@NonNull BaseResponse userAvatarInfoBaseResponse) { - Log.e("getUserAvatarInfoControl", "onNext: " + userAvatarInfoBaseResponse); + Log.e("getUserAvatarInfo", "onNext: " + userAvatarInfoBaseResponse); if (callback != null) { callback.setUserAvatarInfo(userAvatarInfoBaseResponse.data); } @@ -659,7 +745,7 @@ public class NetInterfaceManager { @Override public void onError(@NonNull Throwable e) { - Log.e("getUserAvatarInfoControl", "onError: " + e.getMessage()); + Log.e("getUserAvatarInfo", "onError: " + e.getMessage()); if (callback != null) { callback.setUserAvatarInfo(null); } @@ -668,17 +754,17 @@ public class NetInterfaceManager { @Override public void onComplete() { - Log.e("getUserAvatarInfoControl", "onComplete: "); + Log.e("getUserAvatarInfo", "onComplete: "); } }; } - public void getCloudLessonSettings(BehaviorSubject lifecycle, onCompleteCallback callback) { + public void getCloudLessonSettings(BehaviorSubject lifecycle, OnCompleteCallback callback) { Observable.zip(getCloudLessonObservable(), getCloudLessonAppObservable(), this::getLessonJson).compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getCloudLessonSettingsObserver(callback)); } - public void getCloudLessonSettings(onCompleteCallback callback) { + public void getCloudLessonSettings(OnCompleteCallback callback) { Observable.zip(getCloudLessonObservable(), getCloudLessonAppObservable(), this::getLessonJson).subscribe(getCloudLessonSettingsObserver(callback)); } @@ -715,7 +801,7 @@ public class NetInterfaceManager { return lessonJson; } - public Observer getCloudLessonSettingsObserver(onCompleteCallback callback) { + public Observer getCloudLessonSettingsObserver(OnCompleteCallback callback) { return new Observer() { @Override public void onSubscribe(@NonNull Disposable d) { @@ -746,13 +832,13 @@ public class NetInterfaceManager { } - public void getCloudLessonSetting(BehaviorSubject lifecycle, onCompleteCallback callback) { + public void getCloudLessonSetting(BehaviorSubject lifecycle, OnCompleteCallback callback) { getCloudLessonObservable() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getCloudLessonObserver(callback)); } - public void getCloudLessonSetting(onCompleteCallback callback) { + public void getCloudLessonSetting(OnCompleteCallback callback) { getCloudLessonObservable() .subscribe(getCloudLessonObserver(callback)); } @@ -762,7 +848,7 @@ public class NetInterfaceManager { .subscribe(getCloudLessonObserver(null)); } - private Observer> getCloudLessonObserver(onCompleteCallback callback) { + private Observer> getCloudLessonObserver(OnCompleteCallback callback) { return new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { @@ -788,13 +874,13 @@ public class NetInterfaceManager { }; } - public void getCloudLessonApp(BehaviorSubject lifecycle, onCompleteCallback callback) { + public void getCloudLessonApp(BehaviorSubject lifecycle, OnCompleteCallback callback) { getCloudLessonAppObservable() .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) .subscribe(getCloudLessonAppObserver(callback)); } - public void getCloudLessonApp(onCompleteCallback callback) { + public void getCloudLessonApp(OnCompleteCallback callback) { getCloudLessonAppObservable() .subscribe(getCloudLessonAppObserver(callback)); } @@ -804,7 +890,7 @@ public class NetInterfaceManager { .subscribe(getCloudLessonAppObserver(null)); } - private Observer> getCloudLessonAppObserver(onCompleteCallback callback) { + private Observer> getCloudLessonAppObserver(OnCompleteCallback callback) { return new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { @@ -942,4 +1028,502 @@ public class NetInterfaceManager { } }; } + + public void updateAdminInfo() { + String address = String.valueOf(mMMKV.decodeString(CommonConfig.MAP_ADDRESS_KEY, "-")); + String longitude = String.valueOf(mMMKV.decodeString(CommonConfig.MAP_LONGITUDE_KEY, "0")); + String latitude = String.valueOf(mMMKV.decodeString(CommonConfig.MAP_LATITUDE_KEY, "0")); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("address", address); + jsonObject.addProperty("longitude", longitude); + jsonObject.addProperty("latitude", latitude); + JsonObject softwareJson = new JsonObject(); + // TODO: 2022/6/29 + softwareJson.addProperty("jpush_id", ""); + softwareJson.addProperty("updatetools_version", ApkUtils.getAPPVersionName(mContext, JgyUtils.PACKAGE_UPDATETOOLS)); + softwareJson.addProperty("jiaoguanyi_version", ApkUtils.getAPPVersionName(mContext, "com.jiaoguanyi.os")); + softwareJson.addProperty("gankao_version", ApkUtils.getAPPVersionName(mContext, "com.gankao.gkwxhd")); + softwareJson.addProperty("learning_version", ApkUtils.getAPPVersionName(mContext, "com.info.learning")); + softwareJson.addProperty("chat_version", ApkUtils.getAPPVersionName(mContext, "com.info.chat")); + + softwareJson.addProperty("appstore_version", ApkUtils.getAPPVersionName(mContext, JgyUtils.PACKAGE_APPSTORE)); + softwareJson.addProperty("info_version", ApkUtils.getAPPVersionName(mContext, JgyUtils.PACKAGE_DEVICEINFO)); + softwareJson.addProperty("browser_version", ApkUtils.getAPPVersionName(mContext, JgyUtils.PACKAGE_BROWSER)); + softwareJson.addProperty("notice_version", ApkUtils.getAPPVersionName(mContext, "com.uiui.info")); + softwareJson.addProperty("desktop_version", ApkUtils.getAPPVersionName(mContext,BuildConfig.APPLICATION_ID)); + + softwareJson.addProperty("appstore_install_time", ApkUtils.getAppLastUpdateTime(mContext, JgyUtils.PACKAGE_APPSTORE)); + softwareJson.addProperty("info_install_time", ApkUtils.getAppLastUpdateTime(mContext, JgyUtils.PACKAGE_DEVICEINFO)); + softwareJson.addProperty("browser_install_time", ApkUtils.getAppLastUpdateTime(mContext, JgyUtils.PACKAGE_BROWSER)); + softwareJson.addProperty("notice_install_time", ApkUtils.getAppLastUpdateTime(mContext, "com.uiui.info")); + softwareJson.addProperty("desktop_install_time", ApkUtils.getAppLastUpdateTime(mContext, BuildConfig.APPLICATION_ID)); + + String addr = jsonObject.toString(); + String machine = Utils.getMachine(mContext); + String hardware = Utils.getHardware(mContext); + String software = softwareJson.toString(); + if (BuildConfig.DEBUG) { + Log.e(TAG, "updateAdminInfo: address = " + jsonObject.toString()); + Log.e(TAG, "updateAdminInfo: machine = " + machine); + Log.e(TAG, "updateAdminInfo: getHardware = " + hardware); + Log.e(TAG, "updateAdminInfo: software = " + software); + } + getSnInfoApi().sendAdminSn( + Utils.getSerial(), + "", + machine, + hardware, + software + ).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("updateAdminInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("updateAdminInfo", "onNext: " + baseResponse); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("updateAdminInfo", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("updateAdminInfo", "onComplete: "); + } + }); + } + + + Set showPackages = new HashSet() {{ + this.add("com.uiui.os"); + this.add("com.uiui.info"); + this.add("com.uiui.health"); + this.add("com.uiui.city"); + this.add("com.uiui.videoplayer"); + + this.add("com.uiui.aios"); + this.add("com.uiui.sn"); + this.add("com.uiui.appstore"); + this.add("com.uiui.browser"); + + this.add("com.uiui.zyos"); + this.add("com.uiui.zy"); + this.add("com.uiui.zyappstore"); + this.add("com.uiui.zybrowser"); + this.add("com.uiui.zysn"); + +// this.add("com.jxw.launcher"); + //扶小鹰 +// this.add(JgyUtils.gkwxhd); +// this.add(JgyUtils.fuxiaoying); +// this.add(JgyUtils.moshujia); +// this.add(JgyUtils.english); +// this.add(JgyUtils.zhiduoke); +// this.add(JgyUtils.aobama); +// this.add(JgyUtils.growthspace); + this.add("com.tencent.android.qqdownloader"); + this.add("org.chromium.browser"); + }}; + + Set hidePackages = new HashSet() {{ + this.add("com.android.quicksearchbox"); + this.add("com.oirsdfg89.flg"); + }}; + + Set showSystemApps = new HashSet() {{ + this.add("com.android.gallery3d"); + this.add("com.android.documentsui"); + this.add("org.chromium.browser"); + + }}; + + public static long getPackageSize(Context context, String filePath) { + long size = new File(filePath).length(); + return size; + } + + /** + * 发送app安装情况 + */ + public void SendAppInstallInfo() { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(@NonNull ObservableEmitter emitter) throws Throwable { + Set adminAppSet = mMMKV.decodeStringSet(CommonConfig.ADMIN_APP_LIST, new HashSet<>()); + PackageManager pm = mContext.getPackageManager(); + List installedPackages = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES); + List uploadInfos = new ArrayList<>(); + Intent intent = new Intent(Intent.ACTION_MAIN, null); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + List appsWithLauncher = pm.queryIntentActivities(intent, 0); + Log.e("SendAppInstallInfo", "appsWithLauncher: " + appsWithLauncher); + List pkgs = new ArrayList<>(); + for (PackageInfo packageInfo : installedPackages) { + if (pm.getApplicationEnabledSetting(packageInfo.packageName) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { + pkgs.add(packageInfo.packageName); + } + } + for (ResolveInfo info : appsWithLauncher) { + pkgs.add(info.activityInfo.packageName); + } + Log.e("SendAppInstallInfo", "pkgs: " + pkgs); + + for (PackageInfo info : installedPackages) { + Log.i("SendAppInstallInfo", "info: " + info.packageName); + //排除掉部分系统应用 + if (ApkUtils.isSystemApp(mContext, info.packageName)) { + if (!showSystemApps.contains(info.packageName)) { + continue; + } + } + //排除掉没有图标的应用 + if (!pkgs.contains(info.packageName) && !showPackages.contains(info.packageName)) { + continue; + } + if (hidePackages.contains(info.packageName)) { + continue; + } + Log.e("SendAppInstallInfo", "info: " + info.packageName); + AppUploadInfo uploadInfo = new AppUploadInfo(); + uploadInfo.setApp_name(info.applicationInfo.loadLabel(pm).toString()); + uploadInfo.setApp_package(info.packageName); + uploadInfo.setApp_version_name(info.versionName); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + uploadInfo.setApp_version_code(info.getLongVersionCode()); + } else { + uploadInfo.setApp_version_code(info.versionCode); + } + uploadInfo.setFirstInstallTime(info.firstInstallTime / 1000); + uploadInfo.setLastUpdateTime(info.lastUpdateTime / 1000); + uploadInfo.setApp_size(getPackageSize(mContext, info.applicationInfo.publicSourceDir)); + uploadInfo.setSource(adminAppSet.contains(info.packageName) ? 1 : 0); + uploadInfos.add(uploadInfo); + } + String json = GsonUtils.toJSONString(uploadInfos); + emitter.onNext(json); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .concatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Throwable { + Log.e("SendAppInstallInfo", "apply: " + s); + return getAppApi() + .installorRemove(Utils.getSerial(), s); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("SendAppInstallInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("SendAppInstallInfo", "onNext: " + baseResponse); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("SendAppInstallInfo", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("SendAppInstallInfo", "onComplete: "); + } + }); + uploadAppIcon(); + } + + private List zyApp = new ArrayList() {{ + this.add("com.uiui.browser"); + this.add("com.uiui.zyappstore"); + this.add("com.uiui.zybrowser"); + }}; + + private void uploadAppIcon() { + PackageManager pm = mContext.getPackageManager(); + List packageInfos = pm.getInstalledPackages(0); + Log.e(TAG, "uploadAppIcon: packageInfos = " + packageInfos); + Intent intent = new Intent(Intent.ACTION_MAIN, null); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + List appsWithLauncher = pm.queryIntentActivities(intent, 0); + List allLauncherPkgs = appsWithLauncher.stream().map(resolveInfo -> resolveInfo.activityInfo.packageName).collect(Collectors.toList()); + allLauncherPkgs.addAll(zyApp); + Log.e(TAG, "uploadAppIcon: allLauncherPkgs = " + allLauncherPkgs); + List filter = packageInfos.stream().filter(packageInfo -> allLauncherPkgs.contains(packageInfo.packageName)).collect(Collectors.toList()); + Log.e(TAG, "uploadAppIcon: filter = " + filter); + for (PackageInfo packageInfo : filter) { + if (!mUploadIconPkgs.contains(packageInfo.packageName)) { + Drawable drawable = packageInfo.applicationInfo.loadIcon(pm); + File file = BitmapUtils.drawableToFile(mContext, drawable, packageInfo.packageName); + //File转RequestBody + MediaType mediaType = MediaType.Companion.parse("image/png"); + RequestBody fileBody = RequestBody.Companion.create(file, mediaType); + //设置一个file文件 + MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), fileBody); + Map params = new HashMap<>(); + params.put("package", NetInterfaceManager.convertToRequestBody(packageInfo.packageName)); + Call call = getUploadAppImgApi().uploadAppImg(Utils.getSerial(), params, body); + call.enqueue(new RetryCallback(call, 1, 30 * 1000) { + @Override + public void onRequestResponse(Call call, retrofit2.Response response) { + BaseResponse baseResponse = (BaseResponse) response.body(); + Log.e("addIcon", "onRequestResponse: " + baseResponse); + if (baseResponse.code == 200 || baseResponse.code == 401) { + addIcon(packageInfo.packageName); + } + } + + @Override + public void onRequestFail(Call call, Throwable t) { + Log.e("addIcon", "onRequestFail: "); + } + + @Override + public void onStartRetry() { + Log.e("addIcon", "onStartRetry: "); + } + }); + } else { + Log.e("addIcon", "updateAppInstall: upload " + packageInfo.packageName); + } + } + } + + public void addIcon(String pkg) { + mUploadIconPkgs.add(pkg); + mMMKV.encode(uploadIconPkgsKey, mUploadIconPkgs); + Log.e("addIcon", "addIcon: " + mMMKV.decodeString(uploadIconPkgsKey)); + } + + public void screenshot() { +// String path = mContext.getExternalFilesDir("db").getAbsolutePath(); + String path = ContextCompat.getExternalFilesDirs(mContext, Environment.DIRECTORY_DOWNLOADS)[0].getAbsolutePath(); + String filePath = path + File.separator + Utils.getSerial() + ".png"; + getScreenshot(filePath).concatMap(new Function>() { + @Override + public ObservableSource apply(Integer integer) throws Exception { + if (integer != 0) { + throw new FileNotFoundException(); + } + File file = new File(filePath); + if (!file.exists()) { + throw new FileNotFoundException(filePath); + } +// Bitmap bitmap = BitmapFactory.decodeFile(filePath); +// if (bitmap.getWidth() < bitmap.getHeight()) { +// bitmap = ImageUtils.rotate(bitmap, -90, bitmap.getWidth(), bitmap.getHeight()); +// } +// ByteArrayOutputStream baos = new ByteArrayOutputStream(); +// bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); +// file.createNewFile(); +// FileOutputStream fos = new FileOutputStream(file); +// InputStream is = new ByteArrayInputStream(baos.toByteArray()); +// int x; +// byte[] b = new byte[1024 * 100]; +// while ((x = is.read(b)) != -1) { +// fos.write(b, 0, x); +// } +// fos.close(); + MediaType mediaType = MediaType.Companion.parse("image/png"); + RequestBody requestBody = RequestBody.Companion.create(file, mediaType); + MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestBody); + return getSendFile(filePath, body); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + Log.e("screenshot", "onSubscribe: "); + } + + @Override + public void onNext(BaseResponse baseResponse) { + Log.e("screenshot", "onNext: " + baseResponse); + } + + @Override + public void onError(Throwable e) { + Log.e("screenshot", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("screenshot", "onComplete: "); + } + }); + } + + private Observable getScreenshot(String filePath) { + Observable screenshotObservable = Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) { + int code = CmdUtil.execute("screencap -p " + filePath).code; + e.onNext(code); + e.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + return screenshotObservable; + } + + private Observable getSendFile(String path, MultipartBody.Part body) { + return getUploadScreenshotControl() + .getControlScreenshot(Utils.getSerial(), body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public static final String WHOIS_IP = "whois_ip_addr"; + + public interface PublicIpCallbak { + void getPublicIp(String ip); + } + + public void getPublicIp(BehaviorSubject lifecycle, PublicIpCallbak callbak) { + Retrofit retrofit = new Retrofit.Builder() + .client(NetInterfaceManager.getInstance().getOkHttpClient()) + .baseUrl(UrlAddress.PCONLINE_WHOIS) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + .build(); + retrofit.create(GetWhoisApi.class) + .getWhois(true) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getPublicIp", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull WhoisBean whoisBean) { + Log.e("getPublicIp", "onNext: " + whoisBean); + if (whoisBean != null && !TextUtils.isEmpty(whoisBean.getIp())) { + callbak.getPublicIp(whoisBean.getIp()); + mMMKV.encode(NetInterfaceManager.WHOIS_IP, whoisBean.getIp()); + } else { + callbak.getPublicIp("unknown"); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getPublicIp", "onError: "); + callbak.getPublicIp("unknown"); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getPublicIp", "onComplete: "); + } + }); + } + + + public void getLockScreenPwd(BehaviorSubject lifecycle, OnCompleteCallback callback) { + getLockScreenPwdObservable() + .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY)) + .subscribe(getLockScreenPwdObserver(callback)); + } + + public void getLockScreenPwd(OnCompleteCallback callback) { + getLockScreenPwdObservable() + .subscribe(getLockScreenPwdObserver(callback)); + } + + public void getLockScreenPwd() { + getLockScreenPwdObservable() + .subscribe(getLockScreenPwdObserver(null)); + } + + private Observer> getLockScreenPwdObserver(OnCompleteCallback callback) { + return new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getLockScreenPwdObserver", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse screenPasswordBaseResponse) { + Log.e("getLockScreenPwdObserver", "onNext: " + screenPasswordBaseResponse); + if (screenPasswordBaseResponse.code == 200) { + ScreenPassword screenPassword = screenPasswordBaseResponse.data; + if (screenPassword == null || TextUtils.isEmpty(screenPassword.getPwd())) { + mCacheHelper.put(UrlAddress.LOCK_SCREEN_PWD, ""); + } else { + mCacheHelper.put(UrlAddress.LOCK_SCREEN_PWD, GsonUtils.toJSONString(screenPassword)); + mMMKV.encode(ManagerService.LOCK_SCREEN_PASSWORD, screenPassword.getPwd()); + } + } else { + mCacheHelper.put(UrlAddress.LOCK_SCREEN_PWD, ""); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getLockScreenPwdObserver", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getLockScreenPwdObserver", "onComplete: "); + if (callback != null) { + callback.onComplete(); + } + } + }; + } + + public void getSystemSettings() { + getSettingControl() + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getSystemSettings", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseresponse) { + Log.e("getSystemSettings", "onNext: " + baseresponse); + int code = baseresponse.code; + if (code == 200) { + String data = new Gson().toJson(baseresponse.data); + ControlManager.getInstance().setSystemSetting(data); + mCacheHelper.put(UrlAddress.GET_SETTINGS, GsonUtils.toJSONString(baseresponse.data)); + } else { + ControlManager.getInstance().setDisableSetting(); + mCacheHelper.put(UrlAddress.GET_SETTINGS, ""); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getSystemSettings", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getSystemSettings", "onComplete: "); + } + }); + } + } diff --git a/app/src/main/java/com/xwad/os/network/RetryCallback.java b/app/src/main/java/com/xwad/os/network/RetryCallback.java new file mode 100644 index 0000000..a7f47f3 --- /dev/null +++ b/app/src/main/java/com/xwad/os/network/RetryCallback.java @@ -0,0 +1,92 @@ +package com.xwad.os.network; + +import android.util.Log; + +import java.util.Timer; +import java.util.TimerTask; + +import io.reactivex.rxjava3.annotations.NonNull; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public abstract class RetryCallback implements Callback { + + private static final String TAG = "RetryCallback"; + + private int mRetryCount; + private long mRetryInterval; + + private int mCurrentRetryCount; + + private boolean isExecuting; + + private Call mCall; + + private Timer timer = new Timer(); + + public RetryCallback(Call call, int retryCount, long retryInterval) { + isExecuting = true; + mCall = call; + mRetryCount = retryCount; + mRetryInterval = retryInterval; + } + + @Override + public final void onResponse(@NonNull Call call, @NonNull Response response) { + Log.e(TAG, "onResponse"); + isExecuting = false; + if (!response.isSuccessful() && mCurrentRetryCount < mRetryCount) { + mCurrentRetryCount++; + retryRequest(call); + } else { + onRequestResponse(call, response); + } + } + + @Override + public final void onFailure(@NonNull Call call, @NonNull Throwable t) { + Log.e(TAG, "onFailure"); + isExecuting = false; + if (mCurrentRetryCount < mRetryCount) { + mCurrentRetryCount++; + Log.e(TAG, "onFailure: " + "RetryCount: " + mCurrentRetryCount); + Log.e(TAG, "onFailure: " + "RetryResponse: " + call.request()); + retryRequest(call); + } else { + onRequestFail(call, t); + } + } + + private void retryRequest(final Call call) { + Log.e(TAG, "retryRequest"); + onStartRetry(); + TimerTask timerTask = new TimerTask() { + @Override + public void run() { + synchronized (RetryCallback.this) { + mCall = call.clone(); + mCall.enqueue(RetryCallback.this); + isExecuting = true; + } + } + }; + timer.schedule(timerTask, mRetryInterval); + } + + public void cancelCall() { + synchronized (this) { + if (!isExecuting) { + timer.cancel(); + } else { + mCall.cancel(); + } + } + } + + public abstract void onRequestResponse(Call call, Response response); + + public abstract void onRequestFail(Call call, Throwable t); + + public abstract void onStartRetry(); +} \ No newline at end of file diff --git a/app/src/main/java/com/xwad/os/network/UrlAddress.java b/app/src/main/java/com/xwad/os/network/UrlAddress.java index 75bdd63..a5922c5 100644 --- a/app/src/main/java/com/xwad/os/network/UrlAddress.java +++ b/app/src/main/java/com/xwad/os/network/UrlAddress.java @@ -37,7 +37,15 @@ public class UrlAddress { /*获取管理员所有应用*/ public final static String GET_ADMIN_APP = "getAdminApp"; public final static String APP_FORCE_INSTALL = "app/force-install"; + /*根据包名获取更新*/ + public final static String GET_NEWEST_APPUPDATE = "app/newestAppUpdate"; + /*发送卸载或者安装信息*/ + public final static String SEND_INSTALLEDORREMOVED = "app/addAppInstall"; + /*上传应用图标*/ + public static final String UPLOAD_APP_IMG = "collectData/uploadAppImg"; + /*获取应用库是否有图标*/ + public static final String GET_IS_APP_IMG = "collectData/getIsAppImg"; /*设备信息接口*/ public static final String SNINFO = "sn/getSnInfo"; @@ -47,6 +55,22 @@ public class UrlAddress { public static final String UPDATE_INFO = "sn/update-info"; /*更新头像*/ public static final String UPDATE_avatar = "sn/avatar"; + /*发送设备基本信息*/ + public final static String UPDATE_SNINFO = "sn/updateAdminSn"; + /*获取屏幕管控*/ + public final static String GET_SCREEN_LOCK = "sn/getScreenshot"; + /*获取锁屏密码*/ + public static final String LOCK_SCREEN_PWD = "sn/getLockScreenPwd"; + /*解除锁屏*/ + public static final String UPDATE_LOCK_SCREEN = "sn/updateLockScreen"; + + /*上传屏幕截图*/ + public final static String UPLOAD_SCREEN_SNAPSHOT = "sn/uploadScreenshot"; + /*上传控制面版截图*/ + public static final String UPLOAD_CONTROL_SCREENSHOT = "sn/uploadControlScreenshot"; + + + /*获取统计*/ public static final String GET_STUDY_STAT = "Sn/getStudyStat"; @@ -57,6 +81,7 @@ public class UrlAddress { public static final String APP_USAGE_RECORD = "appUsageRecord"; /*正在运行的应用*/ public static final String RUN_NEW_APP = "app/runNewApp"; + /*获取闹钟*/ public static final String GET_ALARM_CLOCK = "getAlarmClock"; /*爱心提醒通知成功*/ @@ -84,6 +109,7 @@ public class UrlAddress { public static final String UIUIOS_ROOT_URL = "https://map.uiuios.com/android/"; /*获取应用更新*/ + @Deprecated public static final String CHECK_UPDATE = "app/check-update"; public static final String JXW_BASE_URL = "https://openapi.jxwxxkj.com/"; @@ -92,5 +118,9 @@ public class UrlAddress { /*控制/设备端-查看答疑管控状态*/ public static final String answer_Control_status = "api/jxwdevice/answerControl/status"; + /*通过ip获取信息*/ + public static final String PCONLINE_WHOIS = "http://whois.pconline.com.cn/"; + public static final String WHOIS = "ipJson.jsp"; + } diff --git a/app/src/main/java/com/xwad/os/network/api/AppApi.java b/app/src/main/java/com/xwad/os/network/api/AppApi.java index 38a6b9e..51e8c1e 100644 --- a/app/src/main/java/com/xwad/os/network/api/AppApi.java +++ b/app/src/main/java/com/xwad/os/network/api/AppApi.java @@ -4,8 +4,13 @@ import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.BaseResponse; import com.xwad.os.network.UrlAddress; +import java.util.List; + import io.reactivex.rxjava3.core.Observable; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; +import retrofit2.http.POST; import retrofit2.http.Query; public interface AppApi { @@ -15,4 +20,22 @@ public interface AppApi { @Query("app_package") String app_package ); + @GET(UrlAddress.GET_NEWEST_APPUPDATE) + Observable> getAppUpdate( + @Query("packageName") String packageName, + @Query("versionCode") String versionCode, + @Query("type") int type + ); + + @FormUrlEncoded + @POST(UrlAddress.SEND_INSTALLEDORREMOVED) + Observable installorRemove( + @Field("sn") String sn, + @Field("app") String jsonString + ); + + @GET(UrlAddress.GET_ADMIN_APP) + Observable>> getAdminApp( + @Query("sn") String sn + ); } diff --git a/app/src/main/java/com/xwad/os/network/api/GetWhoisApi.java b/app/src/main/java/com/xwad/os/network/api/GetWhoisApi.java new file mode 100644 index 0000000..8a1a373 --- /dev/null +++ b/app/src/main/java/com/xwad/os/network/api/GetWhoisApi.java @@ -0,0 +1,22 @@ +package com.xwad.os.network.api; + +import com.xwad.os.bean.WhoisBean; +import com.xwad.os.network.UrlAddress; + +import io.reactivex.rxjava3.core.Observable; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * @author : fanhuitong + * e-mail : + * @date : 2021/10/1814:39 + * desc : + * version: 1.0 + */ +public interface GetWhoisApi { + @GET(UrlAddress.WHOIS) + Observable getWhois( + @Query("json") boolean json + ); +} diff --git a/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java b/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java index 77e48fe..f61e25e 100644 --- a/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java +++ b/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java @@ -1,6 +1,7 @@ package com.xwad.os.network.api; import com.xwad.os.bean.BaseResponse; +import com.xwad.os.bean.ScreenPassword; import com.xwad.os.bean.SnInfo; import com.xwad.os.bean.StudyStatBean; import com.xwad.os.bean.UserAvatarInfo; @@ -71,4 +72,30 @@ public interface SnInfoApi { @Field("latitude") double latitude ); + @FormUrlEncoded + @POST(UrlAddress.UPDATE_SNINFO) + Observable sendAdminSn( + @Field("sn") String sn, + @Field("address") String address, + @Field("machine") String machine, + @Field("hardware") String hardware, + @Field("software") String software + ); + + @GET(UrlAddress.GET_SCREEN_LOCK) + Observable getScreenshot( + @Query("sn")String sn + ); + + @GET(UrlAddress.LOCK_SCREEN_PWD) + Observable> getLockScreenPwd( + @Query("sn") String sn + ); + + @FormUrlEncoded + @POST(UrlAddress.UPDATE_LOCK_SCREEN) + Observable updateLockScreen( + @Field("sn") String sn + ); + } diff --git a/app/src/main/java/com/xwad/os/network/api/UploadAppImgApi.java b/app/src/main/java/com/xwad/os/network/api/UploadAppImgApi.java new file mode 100644 index 0000000..abb5da2 --- /dev/null +++ b/app/src/main/java/com/xwad/os/network/api/UploadAppImgApi.java @@ -0,0 +1,25 @@ +package com.xwad.os.network.api; + +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.network.UrlAddress; + +import java.util.Map; + +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.http.Multipart; +import retrofit2.http.POST; +import retrofit2.http.Part; +import retrofit2.http.PartMap; +import retrofit2.http.Query; + +public interface UploadAppImgApi { + @Multipart + @POST(UrlAddress.UPLOAD_APP_IMG) + Call uploadAppImg( + @Query("sn") String sn, + @PartMap Map params, + @Part MultipartBody.Part file + ); +} diff --git a/app/src/main/java/com/xwad/os/network/api/UploadScreenshot.java b/app/src/main/java/com/xwad/os/network/api/UploadScreenshot.java new file mode 100644 index 0000000..42bd5c6 --- /dev/null +++ b/app/src/main/java/com/xwad/os/network/api/UploadScreenshot.java @@ -0,0 +1,35 @@ +package com.xwad.os.network.api; + +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.network.UrlAddress; + +import io.reactivex.rxjava3.core.Observable; +import okhttp3.MultipartBody; +import retrofit2.Call; +import retrofit2.http.Multipart; +import retrofit2.http.POST; +import retrofit2.http.Part; +import retrofit2.http.Query; + +public interface UploadScreenshot { + @Multipart + @POST(UrlAddress.UPLOAD_SCREEN_SNAPSHOT) + Observable uploadScreenshot( + @Query("sn") String sn, + @Part MultipartBody.Part file + ); + + @Multipart + @POST(UrlAddress.UPLOAD_SCREEN_SNAPSHOT) + Call uploadScreenshotCall( + @Query("sn") String sn, + @Part MultipartBody.Part file + ); + + @Multipart + @POST(UrlAddress.UPLOAD_CONTROL_SCREENSHOT) + Observable getControlScreenshot( + @Query("sn") String sn, + @Part MultipartBody.Part body + ); +} diff --git a/app/src/main/java/com/xwad/os/permission/PermissionUtils.java b/app/src/main/java/com/xwad/os/permission/PermissionUtils.java new file mode 100644 index 0000000..3b4fecd --- /dev/null +++ b/app/src/main/java/com/xwad/os/permission/PermissionUtils.java @@ -0,0 +1,20 @@ +package com.xwad.os.permission; + +import com.hjq.permissions.Permission; + +public class PermissionUtils { + public static final String[] PERMISSIONS = new String[]{ + Permission.CAMERA, + Permission.READ_PHONE_STATE, +// Permission.READ_SMS, + Permission.READ_PHONE_NUMBERS, + Permission.WRITE_EXTERNAL_STORAGE, + Permission.READ_EXTERNAL_STORAGE, + Permission.WRITE_SETTINGS, +// Permission.SYSTEM_ALERT_WINDOW, + Permission.ACCESS_FINE_LOCATION, + Permission.ACCESS_COARSE_LOCATION, +// Permission.ACCESS_BACKGROUND_LOCATION, +// Permission.REQUEST_INSTALL_PACKAGES + }; +} diff --git a/app/src/main/java/com/xwad/os/push/PushManager.java b/app/src/main/java/com/xwad/os/push/PushManager.java index be2a6ee..4d97f78 100644 --- a/app/src/main/java/com/xwad/os/push/PushManager.java +++ b/app/src/main/java/com/xwad/os/push/PushManager.java @@ -4,17 +4,61 @@ import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.graphics.Bitmap; +import android.os.PowerManager; +import android.text.TextUtils; +import android.util.Log; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.tencent.mmkv.MMKV; +import com.xwad.os.BuildConfig; import com.xwad.os.activity.home.HomeActivity; +import com.xwad.os.activity.homework.HomeworkDetailsActivity; +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.config.CommonConfig; import com.xwad.os.disklrucache.CacheHelper; import com.xwad.os.fragment.user.UserFragment; +import com.xwad.os.gson.GsonUtils; +import com.xwad.os.manager.ControlManager; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.network.NetInterfaceManager; import com.hjq.toast.Toaster; +import com.xwad.os.network.RetryCallback; +import com.xwad.os.service.ManagerService; +import com.xwad.os.service.main.MainService; +import com.xwad.os.utils.ApkUtils; +import com.xwad.os.utils.BitmapUtils; +import com.xwad.os.utils.JgyUtils; +import com.xwad.os.utils.ServiceAliveUtils; +import com.xwad.os.utils.Utils; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableEmitter; +import io.reactivex.rxjava3.core.ObservableOnSubscribe; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.Response; public class PushManager { private static final String TAG = "PushManager"; public static final String SET_ALARMCLOCK = "zuoyeos.action.change.alarmclaock"; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); @SuppressLint("StaticFieldLeak") @@ -45,10 +89,186 @@ public class PushManager { return sInstance; } + + //1.获取设备在线信息 + private static final String GET_DRIVELINE = "1"; + // 2.获取当前正在运行得应用和电量 + private static final String GET_STARTTIME = "2"; + // 3.数据线传输管控 + private static final String USB_STATE = "3"; + // 4.TF卡管控 + private static final String TFCARD_STATE = "4"; + // 5.蓝牙管控 + private static final String BLUETOOTH_STATE = "5"; + // 6.浏览器上网管控 + private static final String BROWSER_URLPATH = "6"; + // 7.应用联网管控 + private static final String APP_NETWORKSTATE = "7"; + // 8.应用锁管控 + private static final String APP_LOCKEDSTATE = "8"; + // 9.强制安装应用 + private static final String FORCE_INSTALLAPK = "9"; + // 10.强制卸载应用 + private static final String FORCE_UNINSTALLAPK = "10"; + // 11.绑定设备 + private static final String BIND_DEVIVES = "11"; + //12.影音格式管控 + private static final String TFMEDIA = "12"; + //13.摄像头管控 + private static final String CAMRERA = "13"; + //14.电话管控管控 + private static final String PHONE = "14"; + //15.禁止升级 + private static final String DISABLE_UPDATAE = "15"; + //16.app内部网址管控 + private static final String APP_WEBSITE = "16"; + //设备恢复出厂设置 + private static final String RESET_DEVICES = "17"; + //浏览器书签 + private static final String BROWSER_LABEL = "18"; + //APP联网自启管控 + private static final String APP_NET_AUTO = "19"; + //系统管控 + private static final String SYSTEM_SETTING = "21"; + //重启 + private static final String REBOOT_DEVICES = "22"; + //获取app管控设置 + private static final String APP_SETTING = "23"; + //强制停止应用 + private static final String FORCE_KILL = "24"; + //锁屏 + private static final String LOCK_SCREEN = "25"; + //截图 + private static final String SNAPSHOT = "26"; + //时间管控 + private static final String JIGUANG_TIME_CONTROL = "27"; + //热点管控 + private static final String HOTSPOT_CONTROL = "29"; + //禁止恢复出厂设置 + private static final String RESTORE_CONTROL = "30"; + //浏览器禁止输入 + private static final String BROWSER_CONTROL = "32"; + //开发人员选项 + private static final String DEVELOPER_CONTROL = "33"; + //清除应用缓存 + private static final String CLEAN_APP_CACHE = "34"; + //几个桌面图标 + private static final String APP_RECORDER = "35"; + private static final String APP_FILE_MANAGER = "36"; + private static final String APP_GALLERY = "37"; + private static final String APP_MUSIC = "38"; + private static final String APP_BROWSER = "43"; + //搜题开关 + private static final String SEARCH_TOPIC = "39"; + //电话白名单推送 + private static final String PHONE_LIST = "40"; + //调整套餐 + private static final String CHANGE_COMBO = "41"; + //取消所有套餐 + private static final String CANCEL_COMBO = "42"; + //升级套餐 + private static final String UPGRADE_COMBO = "44"; + //设备授权和解除 + private static final String BIND_UNBIND = "45"; + //飞行模式 + private static final String FLIGHT_MODE = "47"; + //勿扰模式 + private static final String NOTDISTURB_MODE = "48"; + //定位 + private static final String LOCATION = "49"; + //充电提醒 + private static final String CHARGING_REMINDER = "50"; + //显示用户下载的应用 + private static final String SHOW_THIRD_APP = "51"; + //音量调节 + private static final String VOLUME = "52"; + //亮度调节 + private static final String LUMINANCE = "53"; + //字体大小调节 + private static final String TYPEFACE = "54"; + //自动旋转 + private static final String SCREEN_ROTATION = "55"; + //WiFi设置 + private static final String WIFI_SET = "56"; //闹钟 - private static final String JIGUANG_ALARM_CLOCK = "57"; + private static final String ALARM_CLOCK = "57"; + //应用白名单 + private static final String APP_WHITELIST = "58"; + //隐藏图标 + private static final String HIDE_APPICON = "59"; + //优化内存 + private static final String KILL_APP = "60"; + //SOS联系人 + private static final String SOS_PHONENUM = "61"; + //重新安装应用 + private static final String REINSTALL_APP = "62"; + //显示所有的admin应用 + private static final String ADMIN_APP = "63"; /*网课模式*/ private static final String ONLINE_COURSE_MODE = "71"; + /*投屏开关*/ + private static final String SCRENN_SHARED = "74"; + /*移动热点开关*/ + private static final String HOT_SPOT = "75"; + /*桌面默认应用*/ + private static final String ACTION_DEFAULT_DESKTOP = "76"; + /*浏览器默认应用*/ + private static final String ACTION_DEFAULT_BRPWSER = "77"; + /*输入法默认应用*/ + private static final String ACTION_DEFAULT_INPUT_METHOD = "78"; + /*家长管控开关*/ + private static final String ACTION_PARENTAL_CONTROL = "79"; + /*更新白名单*/ + private static final String UPDATE_WHITE_LIST = "83"; + /*应用市场下载管控*/ + private static final String STORE_INSTALL = "85"; + /*管理员设置*/ + private static final String ADMIN_SN_SETTING = "87"; + /*安装小程序上传应用*/ + private static final String FORCE_INSTALL_WECHAT_RUL = "88"; + + private static final String UNBIND_DEVICES = "90"; + /*快捷应用*/ + private static final String SET_QUICKAPP = "91"; + /*应用市场安装开关*/ + private static final String APP_INSTALL_SWITCH = "93"; + /*时间控制*/ + private static final String TIME_CONTROL = "94"; + //浏览器禁止输入 + private static final String BROWSER_CONTROL2 = "98"; + /*更新设备信息*/ + private static final String UPDATE_INFO = "99"; + /*清除激活推送*/ + private static final String UNBIND_DEVICE = "100"; + /*返回安卓界面*/ + private static final String GO_ANDROID = "101"; + /*九学王激活*/ + private static final String ACTIVATION_JXW = "102"; + /*更新锁屏密码*/ + private static final String UPGRADE_PASSWD = "103"; + /*前置拍照*/ + private static final String TAKE_FRONT_PICTURE = "104"; + /*同意申请安装*/ + private static final String ALLOW_APP_INSTALL = "107"; + /*USB文件传输开关*/ + private static final String USB_TRANSFER = "108"; + /*蓝牙文件传输开关*/ + private static final String BLUETOOTH_TRANSFER = "109"; + /*开发者模式开关*/ + private static final String DEVELOPER_MODE = "110"; + /*设备恢复出厂开关*/ + private static final String RESTORE_FACTORY_MODE = "111"; + /*顶部通知栏开关*/ + private static final String ACTION_BAR_MODE = "112"; + /*底部导航条开关*/ + private static final String NAVIGATION_BAR_MODE = "113"; + /*顶部通知栏开关 */ + private static final String NOTIFY_BAR_SHOW = "114"; + /*上传截图并刷新接口*/ + private static final String REFRESH_NETWORK = "116"; + /*禁止联网APP设置*/ + private static final String DISALLOW_APP_NETWORK = "117"; + /*付款成功*/ private static final String WECHAT_PAY_COMPLETE = "97"; /*作业提醒*/ @@ -59,10 +279,40 @@ public class PushManager { public void setPushContent(String title, String extras) { switch (title) { - case JIGUANG_ALARM_CLOCK: + case GET_DRIVELINE: + Toaster.debugShow("收到推送消息: 获取在线信息"); +// NetInterfaceManager.getInstance().getDriveState(member_id, sn_id); + break; + case GET_STARTTIME: + Toaster.debugShow("收到推送消息: 获取运行应用"); + sendStartTime(extras); + break; + case USB_STATE: + Toaster.debugShow("收到推送消息: USB连接模式管控"); + setUsbStatus(extras); + break; + case REBOOT_DEVICES: + Toaster.debugShow("收到推送消息: 重启"); + AdminManager.getInstance().rebootDevice(); + break; + case LOCK_SCREEN: + Toaster.debugShow("收到推送消息: 锁屏"); + setLockScreen(extras); + Log.e(TAG, extras); + break; + case SNAPSHOT: + Toaster.debugShow("收到推送消息: 截图"); + screenshot(extras); + Log.e(TAG, extras); + break; + case ALARM_CLOCK: Toaster.debugShow("收到推送消息: 设置闹钟"); sendAlarmClock(extras); break; + case KILL_APP: + Toaster.debugShow("收到推送消息: 内存优化"); + killBackgroundApp(); + break; case ONLINE_COURSE_MODE: Toaster.debugShow("收到推送消息: 网课模式"); NetInterfaceManager.getInstance().getCloudLessonSettings(); @@ -71,8 +321,39 @@ public class PushManager { startHome(); break; case HOMEWORK_REMINDERS: + Toaster.debugShow("收到推送消息: 作业提醒"); sendHomework(extras); break; + case UNBIND_DEVICE: + cleanCache(); + break; + case GO_ANDROID: + setReturnAndrdoid(extras); + break; + case BLUETOOTH_TRANSFER: + setBluetoothTransfer(extras); + break; + case DEVELOPER_MODE: + setDeveloperMode(extras); + break; + case RESTORE_FACTORY_MODE: + setResetMode(extras); + break; + case ACTION_BAR_MODE: + setActionBarMode(extras); + break; + case NAVIGATION_BAR_MODE: + setNavigationBarMode(extras); + break; + case NOTIFY_BAR_SHOW: + setNotification(extras); + break; + case REFRESH_NETWORK: + Toaster.debugShow("收到推送消息: 刷新并截图"); + screenshot(extras); + sendStartTime(extras); +// sendRefreshSeeting(); + break; case LOVE_ENCOURAGEMENT: Toaster.debugShow("收到推送消息: 爱的鼓励"); sendEncouragement(extras); @@ -80,6 +361,179 @@ public class PushManager { } } + private void setNotification(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_notify_bar_show"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setNotification: jsonElement is null"); + return; + } + int is_notify_bar_show = jsonElement.getAsInt(); + mMMKV.encode(CommonConfig.NOTIFY_BAR_SHOW_KEY, is_notify_bar_show); + mContext.startService(new Intent(mContext, MainService.class)); + } + + private void setNavigationBarMode(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_bottom_bar"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setNavigationBarMode: jsonElement is null"); + return; + } + int is_bottom_bar = jsonElement.getAsInt(); + ControlManager.getInstance().setBottomBar(is_bottom_bar); + } + + private void setActionBarMode(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_top_notify"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setActionBarMode: jsonElement is null"); + return; + } + int is_top_notify = jsonElement.getAsInt(); + ControlManager.getInstance().setTopNotify(is_top_notify); + } + + private void setResetMode(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_device_recover"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setDeveloperMode: jsonElement is null"); + return; + } + int is_device_recover = jsonElement.getAsInt(); + ControlManager.getInstance().setDeviceRecover(is_device_recover); + } + + private void setDeveloperMode(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_developer_mode"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setDeveloperMode: jsonElement is null"); + return; + } + int is_developer_mode = jsonElement.getAsInt(); + ControlManager.getInstance().setDeveloperMode(is_developer_mode); + } + + private void setBluetoothTransfer(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_bluetooth_share"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setBluetoothTransfer: jsonElement is null"); + return; + } + int is_bluetooth_share = jsonElement.getAsInt(); + ControlManager.getInstance().setBluetoothShare(is_bluetooth_share); + } + + private void setUsbTransfer(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + JsonElement jsonElement = jsonObject.get("is_usb_share"); + if (jsonElement == null || jsonElement.isJsonNull()) { + Log.e(TAG, "setUsbTransfer: jsonElement is null"); + return; + } + int is_usb_share = jsonElement.getAsInt(); + Intent usbIntent = new Intent(); + if (is_usb_share == 0) { + usbIntent.setAction(CommonConfig.AOLE_ACTION_USB_USB_CHARGE); + } else { + usbIntent.setAction(CommonConfig.AOLE_ACTION_USB_USB_MTP); + } + mContext.sendBroadcast(usbIntent); + } + + private void cleanCache() { + mMMKV.remove(CommonConfig.isLogined); + mMMKV.remove(CommonConfig.UIUI_ACTIVATION_KEY); + mMMKV.remove(CommonConfig.UIUI_CODE_TYPE_KEY); + mMMKV.remove(CommonConfig.UIUI_EXPIRE_TIME_KEY); + mMMKV.remove(CommonConfig.ACTIVATIONBEAN_CODE_KEY); + + mMMKV.remove(CommonConfig.ACCOUNT_LOGIN_STATU); + mMMKV.remove(CommonConfig.ACCOUNT_LOGIN_TOKEN); + mMMKV.remove(CommonConfig.ACCOUNT_LOGIN_MOBILE); + mMMKV.remove(CommonConfig.ACCOUNT_LOGIN_ID); + + mMMKV.clearAll(); + + Utils.triggerRebirth(mContext); + } + + private void setLockScreen(String jsonString) { + int type = 0; + JsonObject jSONObject = GsonUtils.getJsonObject(jsonString); + type = jSONObject.get("type").getAsInt(); + + if (!ServiceAliveUtils.isServiceAlive(mContext, ManagerService.class.getName())) { + mContext.startService(new Intent(mContext, ManagerService.class)); + } + Intent intent = new Intent(); +// intent.putExtra("name", name); + mMMKV.encode(ManagerService.LOCK_STATE, type); + if (1 == type) { + intent.setAction(ManagerService.ACTION_LOCK); + } else if (0 == type) { + intent.setAction(ManagerService.ACTION_UNLOCK); + } + mContext.sendBroadcast(intent); + NetInterfaceManager.getInstance().getLockScreenPwd(); + } + + private void killBackgroundApp() { + List pkgList = ApkUtils.queryFilterAppList(mContext); + for (String pkg : pkgList) { + if (runningAppWhitelist.contains(pkg)) continue; + AdminManager.getInstance().killApplicationProcess(pkg); + Log.e(TAG, "killBackgroundApp: " + pkg); + } + } + + public static Set runningAppWhitelist = new HashSet() {{ + this.add(BuildConfig.APPLICATION_ID); + this.add("com.android.launcher3"); + this.add("com.uiui.info"); + this.add("com.uiui.os"); + this.add("com.uiui.health"); + this.add("com.uiui.videoplayer"); + this.add("com.uiui.aios"); + this.add("com.uiui.sn"); + this.add("com.uiui.appstore"); + this.add("com.uiui.browser"); + this.add("com.uiui.zyos"); + this.add("com.uiui.zy"); + this.add("com.uiui.zyappstore"); + this.add("com.uiui.zybrowser"); + this.add("com.uiui.zysn"); + this.add("com.sohu.inputmethod.sogou"); + }}; + + private void sendStartTime(String jsonString) { +// MapManager.getInstance().startPositioning(); + Intent intent = new Intent(CommonConfig.IFLYTEK_UPDATE_ADDRESS_ACTION); +// intent.setPackage(JgyUtils.PACKAGE_OS); + mContext.sendBroadcast(intent); +// NetInterfaceManager.getInstance().sendRunningApp(); + NetInterfaceManager.getInstance().updateAdminInfo(); + NetInterfaceManager.getInstance().SendAppInstallInfo(); + if (JgyUtils.getInstance().isScreenOn()) { + NetInterfaceManager.getInstance().screenshot(); + } + } + + private void setUsbStatus(String jsonString) { + if (!TextUtils.isEmpty(jsonString)) { + JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); + String setting_usb = jsonObject.get("setting_usb").getAsString(); +// ControlPanelManager.getInstance().setUsbStatus(setting_usb); + AdminManager.getInstance().setUSBDataDisabled(!"usb_mtp".equals(setting_usb)); + } else { + Toaster.debugShow("setUsbState jsonString is NULL"); + } + } + private void startHome() { Intent intent = new Intent(mContext, HomeActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -95,13 +549,118 @@ public class PushManager { } private void sendHomework(String extras) { - Intent intent = new Intent(UserFragment.ACTION_REFRESH_HOMEWORK_REMINDERS); + Intent intent = new Intent(HomeActivity.ACTION_REFRESH_HOMEWORK_REMINDERS); mContext.sendBroadcast(intent); + + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + int id = jsonObject.get("id").getAsInt(); + Intent homeworkIntent = new Intent(mContext, HomeworkDetailsActivity.class); + homeworkIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + homeworkIntent.putExtra("HomeworkBeanID", id); + mContext.startActivity(homeworkIntent); } private void sendEncouragement(String extras) { - Intent intent = new Intent(UserFragment.ACTION_REFRESH_LOVE_ENCOURAGEMENT); + Intent intent = new Intent(HomeActivity.ACTION_REFRESH_LOVE_ENCOURAGEMENT); mContext.sendBroadcast(intent); } + public void screenshot(String s) { + long createTime = System.currentTimeMillis() / 1000; + PowerManager.WakeLock mWakeLock = JgyUtils.acquireWakeLock(mContext, 60 * 1000); + JgyUtils.release(mWakeLock); + Log.e("createTime", String.valueOf(createTime)); + doscreenshot(createTime); + } + + public void doscreenshot(long time) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + String filepath = mContext.getExternalFilesDir("db").getAbsolutePath() + File.separator + time + ".db"; + Bitmap bitmap = AdminManager.getInstance().captureScreen(); + File file = BitmapUtils.saveBitmap(bitmap, filepath); + e.onNext(file); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + Log.e("doscreenshot", "onSubscribe: "); + } + + @Override + public void onNext(File file) { + if (file != null && file.exists() && !file.isDirectory()) { + uplaodImage(time); + } else { + Log.e("doscreenshot", "onNext: " + "失败"); + } + } + + @Override + public void onError(Throwable e) { + Log.e("doscreenshot", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("doscreenshot", "onComplete: "); + } + }); + } + + private void uplaodImage(long time) { + String filepath = mContext.getExternalFilesDir("db").getAbsolutePath(); +// String filepath = mContext.getFileStreamPath("screenshot").getAbsolutePath(); + //放在app内部data下面 + File file = new File(filepath + File.separator + time + ".db"); + //不要直接使用常用图片格式 + if (!file.exists()) { + Log.e("uplaodImage", "File does not exists"); + return; + } + //设置图片格式 +// RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpg"), file); + //File转RequestBody + MediaType mediaType = MediaType.Companion.parse("image/png"); + RequestBody fileBody = RequestBody.Companion.create(file, mediaType); + //设置一个file文件 + MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), fileBody); + Map params = new HashMap<>(); + params.put("sn", Utils.getSerial(mContext)); + params.put("createtime", String.valueOf(time)); + Call call = NetInterfaceManager.getInstance().getUploadScreenshotControl().uploadScreenshotCall(Utils.getSerial(mContext), body); + call.enqueue(new RetryCallback(call, 10, 30 * 1000) { + @Override + public void onRequestResponse(Call call, Response response) { + Log.e(TAG, "onRequestResponse: " + response.body().toString()); + } + + @Override + public void onRequestFail(Call call, Throwable t) { + Log.e(TAG, "onRequestFail: "); + } + + @Override + public void onStartRetry() { + Log.e(TAG, "onStartRetry: "); + } + }); + } + + private void sendZyosRefreshIntent() { + Intent intent = new Intent(UserFragment.ACTION_REFRESH_BINDING_STATUS); + intent.setPackage("com.uiui.zyos"); + mContext.sendBroadcast(intent); + } + + private void setReturnAndrdoid(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + int isReturnAndroid = jsonObject.get("is_return_android").getAsInt(); + mMMKV.encode(CommonConfig.UIUI_RETURN_ANDROID_KEY, isReturnAndroid); + sendZyosRefreshIntent(); + } + } diff --git a/app/src/main/java/com/xwad/os/service/DownloadService.java b/app/src/main/java/com/xwad/os/service/DownloadService.java index 5e152ba..4101416 100644 --- a/app/src/main/java/com/xwad/os/service/DownloadService.java +++ b/app/src/main/java/com/xwad/os/service/DownloadService.java @@ -24,6 +24,7 @@ import com.google.gson.reflect.TypeToken; import com.hjq.toast.Toaster; import com.xwad.os.R; import com.xwad.os.bean.AriaDownloadInfo; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.utils.ApkUtils; import java.io.File; @@ -204,7 +205,7 @@ public class DownloadService extends Service { @Download.onTaskComplete void taskComplete(DownloadTask task) { Log.e(TAG, "taskComplete: " + task.getFilePath()); - ApkUtils.installApkFile(DownloadService.this, task.getFilePath()); + ApkUtils.installApp(DownloadService.this, task.getFilePath()); String jsonString = task.getExtendField(); Log.e(TAG, "taskComplete: " + "下载完成:" + jsonString); AriaDownloadInfo ariaDownloadInfo = getAriaDownloadInfo(jsonString); diff --git a/app/src/main/java/com/xwad/os/service/ManagerService.java b/app/src/main/java/com/xwad/os/service/ManagerService.java new file mode 100644 index 0000000..b9dfa14 --- /dev/null +++ b/app/src/main/java/com/xwad/os/service/ManagerService.java @@ -0,0 +1,808 @@ +package com.xwad.os.service; + +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.media.AudioAttributes; +import android.media.SoundPool; +import android.os.Build; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.alibaba.sdk.android.push.PushControlService; +import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory; +import com.blankj.utilcode.util.NetworkUtils; +import com.google.gson.JsonObject; +import com.tencent.mmkv.MMKV; +import com.tuo.customview.VerificationCodeView; +import com.uiui.zy.KeepAliveConnection; +import com.xwad.os.BuildConfig; +import com.xwad.os.R; +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.config.CommonConfig; +import com.xwad.os.gson.GsonUtils; +import com.xwad.os.mdm.AdminManager; +import com.xwad.os.network.NetInterfaceManager; +import com.xwad.os.receiver.ApkInstallReceiver; +import com.xwad.os.receiver.BootReceiver; +import com.xwad.os.service.main.MainService; +import com.xwad.os.utils.ActivationUtil; +import com.xwad.os.utils.ApkUtils; +import com.xwad.os.utils.JgyUtils; +import com.xwad.os.utils.ServiceAliveUtils; +import com.xwad.os.utils.TimeUtils; +import com.xwad.os.utils.Utils; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableEmitter; +import io.reactivex.rxjava3.core.ObservableOnSubscribe; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; + +public class ManagerService extends Service implements NetworkUtils.OnNetworkStatusChangedListener { + private static final String TAG = "ManagerService"; + + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + public static final String ACTION_LOCK = BuildConfig.APPLICATION_ID + "_LockScreenReceiver_lockscreen"; + public static final String ACTION_UNLOCK = BuildConfig.APPLICATION_ID + "_LockScreenReceiver_unlockscreen"; + public static final String ACTION_UPDATE = BuildConfig.APPLICATION_ID + "_TimeChangedReceiver_update"; + public static final String LOCK_SCREEN_PASSWORD = "Iflytek_lockScreenPasswordKey"; + public static final String DEFAULT_PASSWORD = "072814"; + + private WindowManager windowManager; + private View topView; + /*是否锁屏*/ + private boolean screenlocked = false; + /*是否时间控制*/ + private boolean timelocked = false; + + private SoundPool soundPool; + private int soundId; + + + @Override + public void onDisconnected() { + + } + + @Override + public void onConnected(NetworkUtils.NetworkType networkType) { +// getScreenLockState(); + } + + + private interface Start { + void onstar(long time); + } + + private Start start; + + private final ObservableOnSubscribe subscribe = new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) throws Exception { + start = new Start() { + @Override + public void onstar(long time) { + emitter.onNext(time); + } + }; + } + }; + + private Observer timeObserver = new Observer() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onNext(Long aLong) { + Log.e("TimeObserver", "onNext: " + aLong); + int isLogined = mMMKV.decodeInt(CommonConfig.isLogined, 0); + if (isLogined != 1) { + + } + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + + } + }; + + + private static KillAppListener killAppListener; + + public interface KillAppListener { + void killApp(String action); + } + + private final ObservableOnSubscribe killSubscribe = new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) throws Exception { + killAppListener = new KillAppListener() { + @Override + public void killApp(String action) { + emitter.onNext(action); + } + }; + } + }; + + private Observer killObserver = new Observer() { + @Override + public void onSubscribe(Disposable d) { + Log.e("killObserver", "onSubscribe: "); + } + + @Override + public void onNext(String action) { + Log.e("killObserver", "onNext: " + action); + if (!JgyUtils.getInstance().isScreenOn()) { + AdminManager.getInstance().killApplicationProcess("com.jxw.mskt.video"); + AdminManager.getInstance().killApplicationProcess("com.jxw.teacher.video"); + AdminManager.getInstance().killApplicationProcess("com.jxw.newyouer.video"); + AdminManager.getInstance().killApplicationProcess("com.jxw.question"); + AdminManager.getInstance().killApplicationProcess(JgyUtils.PACKAGE_APPSTORE); + AdminManager.getInstance().killApplicationProcess(JgyUtils.PACKAGE_BROWSER); + int is_activation = ActivationUtil.getInstance().getActivationStateCode(); + Log.e(TAG, "onReceive: is_activation = " + is_activation); +// if (is_activation == 0) { + AdminManager.getInstance().killApplicationProcess("com.jxw.launcher"); + AdminManager.getInstance().killApplicationProcess("com.jxw.online_study"); +// } + if (!ActivationUtil.getInstance().isActivation()) { + AdminManager.getInstance().killApplicationProcess(JgyUtils.PACKAGE_OS); + } + } else { + Log.e("killObserver", "onNext: ScreenOn"); + } + } + + @Override + public void onError(Throwable e) { + Log.e("killObserver", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("killObserver", "onComplete: "); + } + }; + + private ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + Log.e(TAG, "onServiceConnected: componentName = " + componentName); + boolean isServiceRunning = ServiceAliveUtils.isServiceAlive(ManagerService.this, MainService.class.getName()); + Log.e(TAG, "onServiceConnected: isServiceRunning = " + isServiceRunning); + if (!isServiceRunning) { + startService(new Intent(ManagerService.this, MainService.class)); + } + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + Log.e(TAG, "onServiceDisconnected: "); + // 断开链接 + startService(new Intent(ManagerService.this, MainService.class)); + // 重新绑定 + bindService(new Intent(ManagerService.this, MainService.class), mServiceConnection, Context.BIND_IMPORTANT); + } + }; + + @Override + public IBinder onBind(Intent intent) { + return new KeepAliveConnection.Stub() { + }; + } + + @Override + public void onCreate() { + super.onCreate(); + AudioAttributes attr = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME) // 设置音效使用场景 + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build(); // 设置音效的类型 + soundPool = new SoundPool.Builder().setAudioAttributes(attr) // 设置音效池的属性 + .setMaxStreams(1) // 设置最多可容纳10个音频流 + .build(); // ① + // load方法加载指定音频文件,并返回所加载的音效ID + // 此处使用HashMap来管理这些音频流 + soundId = soundPool.load(this, R.raw.click, 1); + NetworkUtils.registerNetworkStatusChangedListener(this); + registerReceivers(); + setFloatingWindow(); + Observable.create(subscribe) + .throttleFirst(3, TimeUnit.HOURS) + .subscribe(timeObserver); + + Observable.create(killSubscribe) + .throttleLast(1, TimeUnit.MINUTES) +// .throttleLast(3, TimeUnit.SECONDS) + .subscribe(killObserver); + + boolean isServiceRunning = ServiceAliveUtils.isServiceAlive(this, MainService.class.getName()); + Log.e(TAG, "onCreate: isServiceRunning = " + isServiceRunning); + if (!isServiceRunning) { + startService(new Intent(this, MainService.class)); + } + bindService(new Intent(this, MainService.class), mServiceConnection, Context.BIND_IMPORTANT); + + PushServiceFactory.getPushControlService().setConnectionChangeListener(new PushControlService.ConnectionChangeListener() { + @Override + public void onConnect() { + Log.e("ConnectionChange", "onConnect: "); + } + + @Override + public void onDisconnect(String code, String msg) { + Log.e("ConnectionChange", "onConnect: code = " + code + " msg = " + msg); + PushServiceFactory.getPushControlService().reconnect(); + } + }); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + start.onstar(System.currentTimeMillis()); + return START_STICKY; + } + + private void getScreenLockState() { + NetInterfaceManager.getInstance() + .getSnInfoApi() + .getScreenshot(Utils.getSerial()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + Log.e("getScreenLockState", "onSubscribe: "); + } + + @Override + public void onNext(BaseResponse baseResponse) { + Log.e("getScreenLockState", "onNext: "); + int code = baseResponse.code; + if (code == 200) { + JsonObject jsonObject = GsonUtils.getJsonObject(GsonUtils.toJSONString(baseResponse.data)); + int is_screen_lock = jsonObject.get("is_screen_lock").getAsInt(); + setLockedState(is_screen_lock); + } else { + if (!timelocked) { + hideFloatingWindow(); + } + screenlocked = false; + mMMKV.encode(LOCK_STATE, 0); + } + } + + @Override + public void onError(Throwable e) { + Log.e("getScreenLockState", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getScreenLockState", "onComplete: "); + } + }); + } + + private void setLockedState(int lockedState) { + if (lockedState == 1) { + if (!timelocked) { + showFloatingWindow("屏幕已锁定"); + } + screenlocked = true; + mMMKV.encode(LOCK_STATE, 1); + } else { + if (!timelocked) { + hideFloatingWindow(); + } + screenlocked = false; + mMMKV.encode(LOCK_STATE, 0); + } + } + + public static final String LOCK_STATE = "SCRENN_LOOCKED_STATE"; + + private void showFloatingWindow(String name) { + AdminManager.getInstance().setStatusBarExpandPanelDisabled(true); + AdminManager.getInstance().setNavigationBarDisabled(true); + if (Settings.canDrawOverlays(this)) { + // 获取WindowManager服务 + if (null == windowManager) { + windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); + } + DisplayMetrics dm = new DisplayMetrics(); + windowManager.getDefaultDisplay().getRealMetrics(dm); + int width = dm.widthPixels; // 屏幕宽度(像素) + int height = dm.heightPixels; // 屏幕高度(像素) + // 新建悬浮窗控件 + final Button button = new Button(getApplicationContext()); + button.setText("霸屏测试"); + button.setAlpha(0.9f); + button.setBackgroundColor(Color.BLACK); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { +// windowManager.removeView(button); + } + }); + if (null == topView) { + topView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.activity_screen_lock, null); + initTopView(topView, name); + } else { + if ("added".equals(topView.getTag())) { + initTopView(topView, name); + } else { + return; + } + return; + } + // topView.setAlpha(0.8f); + // 设置LayoutParam + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// layoutParams.type = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; + layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + //TYPE_SYSTEM_OVERLAY可以下滑通知栏 +// layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; + } else { + layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE; + } + layoutParams.flags |= WindowManager.LayoutParams.FLAG_BLUR_BEHIND + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + layoutParams.format = PixelFormat.RGBA_8888; + layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; + layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; + //systemUiVisibility 关闭通知栏和导航栏 + layoutParams.systemUiVisibility = + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + layoutParams.x = 0; + layoutParams.y = 0; + // 将悬浮窗控件添加到WindowManager + windowManager.addView(topView, layoutParams); + topView.setTag("added"); + } else { + Log.e(TAG, "showFloatingWindow: floating window permission not granted"); + } + } + + private void initTopView(View view, String name) { + TextView textView = view.findViewById(R.id.textView); + TextView tv_hint = view.findViewById(R.id.tv_hint); + textView.setText(name); + LinearLayout ll_keyboard = view.findViewById(R.id.ll_keyboard); + VerificationCodeView codeView = view.findViewById(R.id.icv); + codeView.getEditText().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + ll_keyboard.setVisibility(View.VISIBLE); + } + }); + codeView.setInputCompleteListener(new VerificationCodeView.InputCompleteListener() { + @Override + public void inputComplete() { + checkPassword(codeView, tv_hint); + } + + @Override + public void deleteContent() { + + } + }); + TextView bt0 = view.findViewById(R.id.bt_0); + TextView bt1 = view.findViewById(R.id.bt_1); + TextView bt2 = view.findViewById(R.id.bt_2); + TextView bt3 = view.findViewById(R.id.bt_3); + TextView bt4 = view.findViewById(R.id.bt_4); + TextView bt5 = view.findViewById(R.id.bt_5); + TextView bt6 = view.findViewById(R.id.bt_6); + TextView bt7 = view.findViewById(R.id.bt_7); + TextView bt8 = view.findViewById(R.id.bt_8); + TextView bt9 = view.findViewById(R.id.bt_9); + TextView tv_del = view.findViewById(R.id.tv_del); +// ImageView bt_del = view.findViewById(R.id.bt_del); +// ImageView bt_confirm = view.findViewById(R.id.bt_confirm); + bt0.setOnClickListener(view1 -> add(codeView, "0")); + bt1.setOnClickListener(view1 -> add(codeView, "1")); + bt2.setOnClickListener(view1 -> add(codeView, "2")); + bt3.setOnClickListener(view1 -> add(codeView, "3")); + bt4.setOnClickListener(view1 -> add(codeView, "4")); + bt5.setOnClickListener(view1 -> add(codeView, "5")); + bt6.setOnClickListener(view1 -> add(codeView, "6")); + bt7.setOnClickListener(view1 -> add(codeView, "7")); + bt8.setOnClickListener(view1 -> add(codeView, "8")); + bt9.setOnClickListener(view1 -> add(codeView, "9")); + tv_del.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + tv_hint.setText(""); + codeView.clearInputContent(); + } + }); +// bt_confirm.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// checkPassword(codeView, tv_hint); +// } +// }); + } + + private void checkPassword(VerificationCodeView codeView, TextView tv_hint) { + String content = codeView.getInputContent(); + if (TextUtils.isEmpty(content) || content.length() != 6) { + return; + } + Log.e(TAG, "inputComplete: " + content); + String password = mMMKV.decodeString(LOCK_SCREEN_PASSWORD, DEFAULT_PASSWORD); + if (password.equals(content)) { + hide(); + } else if (DEFAULT_PASSWORD.equals(content)) { + hide(); + } else { + postDelayed(codeView, tv_hint); + tv_hint.setText("密码错误"); + } + } + + private void postDelayed(VerificationCodeView view, TextView tv_hint) { + tv_hint.setText("密码错误"); + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + @Override + public void run() { + view.clearInputContent(); + tv_hint.setText(""); + } + }, 1000); + } + + private void hide() { + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + @Override + public void run() { + hideFloatingWindow(); + } + }, 1000); + screenlocked = false; + mMMKV.encode(ManagerService.LOCK_STATE, 0); + mMMKV.encode(TimeUtils.AOLELEARN_TIME_CONTROL_KEY, 0); + NetInterfaceManager.getInstance().getUpdateLockScreenObservable() + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("getUpdateLockScreen", "onNext: " + baseResponse); + } + + @Override + public void onError(@NonNull Throwable e) { + + } + + @Override + public void onComplete() { + + } + }); + JgyUtils.getInstance().setDefaultDesktop("com.uiui.zyos", "com.uiui.zyos.activity.main.MainActivity"); + ApkUtils.openApp(ManagerService.this, "com.uiui.zyos"); + } + + private void add(VerificationCodeView codeView, String text) { + Log.e(TAG, "add: text = " + text); + String oldText = codeView.getEditText().getText().toString(); + Log.e(TAG, "add: " + oldText); + codeView.getEditText().setText(text); +// soundPool.play(soundId, 1, 1, 0, 0, 1); + } + + private void hideFloatingWindow() { + + AdminManager.getInstance().setStatusBarExpandPanelDisabled(false); + AdminManager.getInstance().setNavigationBarDisabled(false); + + if (null == windowManager) { + return; + } + if (null != topView) { + windowManager.removeView(topView); + topView = null; + NetInterfaceManager.getInstance().getSystemSettings(); + } + } + + private void registerReceivers() { + registLockReceiver(); + registerTimeReceiver(); + registerScreenLockReceiver(); + registAppReceive(); + registBootReceive(); + registerBatteryReceiver(); + } + + private void unregisterReceivers() { + if (null != mTimeChangedReceiver) { + unregisterReceiver(mTimeChangedReceiver); + } + if (null != mLockScreenReceiver) { + unregisterReceiver(mLockScreenReceiver); + } + if (null != mScreenLockReceiver) { + unregisterReceiver(mScreenLockReceiver); + } + if (null != mApkInstallReceiver) { + unregisterReceiver(mApkInstallReceiver); + } + if (null != mBootReceiver) { + unregisterReceiver(mBootReceiver); + } + if (null != mBatteryReceiver) { + unregisterReceiver(mBatteryReceiver); + } + } + + private LockScreenReceiver mLockScreenReceiver; + + private void registLockReceiver() { + if (null == mLockScreenReceiver) { + mLockScreenReceiver = new LockScreenReceiver(); + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(ACTION_LOCK); + filter.addAction(ACTION_UNLOCK); + registerReceiver(mLockScreenReceiver, filter); + } + } + + private class LockScreenReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.e("LockScreenReceiver", "onReceive: " + action); + if (TextUtils.isEmpty(action)) { + getScreenLockState(); + return; + } + if (ACTION_LOCK.equals(action)) { +// String name = intent.getStringExtra("name"); + String name = "屏幕已锁定"; + if (!timelocked) { + showFloatingWindow(name); + } + screenlocked = true; + } else if (ACTION_UNLOCK.equals(action)) { + if (!timelocked) { + hideFloatingWindow(); + } + screenlocked = false; + } + } + } + + private TimeChangedReceiver mTimeChangedReceiver; + + /** + * 监听时间和日期变化 + */ + private void registerTimeReceiver() { + mTimeChangedReceiver = new TimeChangedReceiver(); + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(Intent.ACTION_DATE_CHANGED); + filter.addAction(Intent.ACTION_TIME_CHANGED); + filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + filter.addAction(Intent.ACTION_TIME_TICK); + filter.addAction(ACTION_UPDATE); + registerReceiver(mTimeChangedReceiver, filter); + } + + private class TimeChangedReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_DATE_CHANGED.equals(action)) { + Log.e(TAG, "TimeChangedReceiver:" + "data changed"); + } else if (Intent.ACTION_TIME_CHANGED.equals(action)) { + Log.e(TAG, "TimeChangedReceiver:" + "time changed"); + } else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) { + Log.e(TAG, "TimeChangedReceiver:" + "timezone changed"); + } else if (Intent.ACTION_TIME_TICK.equals(action)) { + Log.e(TAG, "TimeChangedReceiver:" + "time tick"); + setFloatingWindow(); + } else if (ACTION_UPDATE.equals(action)) { + Log.e(TAG, "TimeChangedReceiver:" + "date update"); + setFloatingWindow(); + } + + // String packages = ForegroundAppUtil.getForegroundPackageName(context); +// if (!packages.equals("com.estrongs.android.pop")) { +// ApkUtils.openApp(context, "com.estrongs.android.pop"); +// } +// Log.e("TimeChangedReceiver", "packages:" + packages); + } + } + + private void setFloatingWindow() { +// TimeUtils.ContralTime workingContralTime = TimeUtils.getWorkingDayContralTime(ManagerService.this); +// TimeUtils.ContralTime weekContralTime = TimeUtils.getWeekDayContralTime(ManagerService.this); +// TimeUtils.ContralTime contralTime = TimeUtils.getDayContralTime(ManagerService.this); + List contralTimes = TimeUtils.getDayContralTimeList(ManagerService.this); +// if (null != workingContralTime) { +// if (TimeUtils.inContralTime(workingContralTime, weekContralTime)) { + if (TimeUtils.inDayContralTime(contralTimes)) { + if (!screenlocked) { + showFloatingWindow(getString(R.string.available_time) + TimeUtils.getDayTimeString(ManagerService.this)); + } else { + TextView textView = topView.findViewById(R.id.textView); + textView.setText(getString(R.string.available_time) + TimeUtils.getDayTimeString(ManagerService.this)); + } + timelocked = true; + } else { +// getScreenLockState(); + int isScreenLock = mMMKV.decodeInt(LOCK_STATE, 0); + setLockedState(isScreenLock); + if (!screenlocked) { + hideFloatingWindow(); + } + timelocked = false; + } +// } else { +// if (!screenlocked) { +// hideFloatingWindow() +// } +// getScreenLockState() +// timelocked = false +// } + } + + private ScreenLockReceiver mScreenLockReceiver; + + private void registerScreenLockReceiver() { + if (null == mScreenLockReceiver) { + mScreenLockReceiver = new ScreenLockReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_BOOT_COMPLETED); + filter.addAction(Intent.ACTION_USER_PRESENT); + filter.addAction(Intent.ACTION_SHUTDOWN); + filter.addAction("android.intent.action.FACTORY_RESET"); + filter.addAction("android.intent.action.MASTER_CLEAR"); + registerReceiver(mScreenLockReceiver, filter); + } + + private class ScreenLockReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.e(TAG, "onReceive:" + action); + if (TextUtils.isEmpty(action)) { + Log.e(TAG, "onReceive: is NULL"); + return; + } + switch (action) { + case Intent.ACTION_USER_PRESENT: + case Intent.ACTION_SCREEN_ON: +// JgyUtils.getInstance().startJxwLauncher(); + PushServiceFactory.getPushControlService().reconnect(); + + break; + case Intent.ACTION_SCREEN_OFF: + case Intent.ACTION_SHUTDOWN: + case "android.intent.action.FACTORY_RESET": + case "android.intent.action.MASTER_CLEAR": + killAppListener.killApp(action); + break; + default: + break; + } + } + } + + private ApkInstallReceiver mApkInstallReceiver; + + private void registAppReceive() { + if (null == mApkInstallReceiver) { + mApkInstallReceiver = new ApkInstallReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + registerReceiver(mApkInstallReceiver, filter); + } + + private BootReceiver mBootReceiver; + + private void registBootReceive() { + if (null == mBootReceiver) { + mBootReceiver = new BootReceiver(); + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(Intent.ACTION_USER_PRESENT); + registerReceiver(mBootReceiver, filter); + } + } + + private BatteryReceiver mBatteryReceiver; + + private void registerBatteryReceiver() { + if (null == mBatteryReceiver) { + mBatteryReceiver = new BatteryReceiver(); + } + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(Intent.ACTION_POWER_DISCONNECTED); + registerReceiver(mBatteryReceiver, filter); + } + + private class BatteryReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { + + } else if (Intent.ACTION_POWER_CONNECTED.equals(action) || Intent.ACTION_POWER_DISCONNECTED.equals(action)) { +// ControlManager.getInstance().setDefaultUSBstate(); + } else if (Intent.ACTION_BATTERY_LOW.equals(action) || Intent.ACTION_BATTERY_OKAY.equals(action)) { + + } + } + } + + + @Override + public void onDestroy() { + super.onDestroy(); + NetworkUtils.unregisterNetworkStatusChangedListener(this); + unregisterReceivers(); + if (soundPool != null) { + soundPool.release(); + soundPool = null; + } + unbindService(mServiceConnection); + } + +} diff --git a/app/src/main/java/com/xwad/os/service/SocketService.java b/app/src/main/java/com/xwad/os/service/SocketService.java index da0d70c..3ad93e5 100644 --- a/app/src/main/java/com/xwad/os/service/SocketService.java +++ b/app/src/main/java/com/xwad/os/service/SocketService.java @@ -26,6 +26,7 @@ import com.xwad.os.activity.login.LoginActivity; import com.xwad.os.config.CommonConfig; import com.xwad.os.gson.GsonUtils; import com.xwad.os.manager.DeviceSNManager; +import com.xwad.os.mdm.AdminManager; import com.xwad.os.network.NetInterfaceManager; import com.xwad.os.network.UrlAddress; import com.xwad.os.utils.ActivationUtil; @@ -207,7 +208,7 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat } private void bindSn() { - String sn = DeviceSNManager.getDeviceSN(); + String sn = AdminManager.getInstance().getSerial(); if (TextUtils.isEmpty(sn)) { return; } @@ -250,8 +251,8 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat filter.addAction(Intent.ACTION_BOOT_COMPLETED); filter.addAction(Intent.ACTION_USER_PRESENT); filter.addAction(Intent.ACTION_SHUTDOWN); - filter.addAction(Intent.ACTION_FACTORY_RESET); - filter.addAction(Intent.ACTION_MASTER_CLEAR); + filter.addAction("android.intent.action.FACTORY_RESET"); + filter.addAction("android.intent.action.MASTER_CLEAR"); registerReceiver(mScreenLockReceiver, filter); } @@ -273,8 +274,8 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat break; case Intent.ACTION_SCREEN_OFF: case Intent.ACTION_SHUTDOWN: - case Intent.ACTION_FACTORY_RESET: - case Intent.ACTION_MASTER_CLEAR: + case "android.intent.action.FACTORY_RESET": + case "android.intent.action.MASTER_CLEAR": sendOnlineMsgScreen(); break; default: @@ -324,7 +325,7 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat * 初始化websocket连接 */ private void initOnlineSocketClient() { - URI uri = URI.create(UrlAddress.WEBSOCKET_URL_ONLINE + "?sn=" + DeviceSNManager.getDeviceSN()); + URI uri = URI.create(UrlAddress.WEBSOCKET_URL_ONLINE + "?sn=" + AdminManager.getInstance().getSerial()); mOnlineJWebSocketClient = new JWebSocketClient(uri) { @Override public void onMessage(String message) { @@ -403,7 +404,7 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat */ public void sendOnlinePingMsg() { JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("sn", DeviceSNManager.getDeviceSN()); + jsonObject.addProperty("sn", AdminManager.getInstance().getSerial()); jsonObject.addProperty("type", "ping"); if (null != mOnlineJWebSocketClient) { Log.i(TAG, "sendOnlinePingMsg: 发送的消息:" + jsonObject.toString()); @@ -413,7 +414,7 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat public void sendOnlineMsgScreen() { JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("sn", DeviceSNManager.getDeviceSN()); + jsonObject.addProperty("sn", AdminManager.getInstance().getSerial()); if (Utils.isScreenOn(SocketService.this)) { jsonObject.addProperty("type", "device_open_screen"); } else { @@ -475,7 +476,7 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat * 初始化websocket连接 */ private void initSsoSocketClient() { - URI uri = URI.create(UrlAddress.WEBSOCKET_URL_SSO + "?sn=" + DeviceSNManager.getDeviceSN() + "&token=" + NetInterfaceManager.getInstance().getToken()); + URI uri = URI.create(UrlAddress.WEBSOCKET_URL_SSO + "?sn=" + AdminManager.getInstance().getSerial() + "&token=" + NetInterfaceManager.getInstance().getToken()); mSsoJWebSocketClient = new JWebSocketClient(uri) { @Override public void onMessage(String message) { @@ -558,7 +559,7 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat public void sendSsoPingMsg() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("type", "ping"); - jsonObject.addProperty("sn", DeviceSNManager.getDeviceSN()); + jsonObject.addProperty("sn", AdminManager.getInstance().getSerial()); jsonObject.addProperty("token", NetInterfaceManager.getInstance().getToken()); if (null != mSsoJWebSocketClient) { Log.i(TAG, "sendPingMsg: 发送的消息:" + jsonObject.toString()); diff --git a/app/src/main/java/com/xwad/os/service/main/MainSContact.java b/app/src/main/java/com/xwad/os/service/main/MainSContact.java index 1ecee21..60d1699 100644 --- a/app/src/main/java/com/xwad/os/service/main/MainSContact.java +++ b/app/src/main/java/com/xwad/os/service/main/MainSContact.java @@ -2,14 +2,100 @@ package com.xwad.os.service.main; import com.xwad.os.base.mvp.BasePresenter; import com.xwad.os.base.mvp.BaseView; +import com.xwad.os.bean.AppInfo; +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.bean.IsActivationBean; +import com.xwad.os.bean.SnInfo; + +import java.util.List; public class MainSContact { public interface Presenter extends BasePresenter { + /*是否已经激活*/ + void getSnIsActivation(); + + /*上传未激活设备的信息*/ + void uploadNotActivate(); + /*获取公网ip*/ + void getPublicIp(); + /*激活九学王*/ + void setJxwActivation(); + /*激活后获取九学王app*/ + void getJxwApp(); + + /*获取设备信息*/ + void getSnInfo(); + + + /*需要绑定设备才能使用的功能*/ /*获取网课模式*/ void getCloudLessonSettings(); + /*上传设备信息*/ + void updateDeviceInfo(); + + /*获取时间管控*/ + void getTimeControl(); + /*获取所有app包名*/ + void getAllApp(); + /*获取强制下载*/ + void getForceInstall(); + /*图标隐藏*/ + void getAppIcon(); + /*获取wifi密码*/ + void getWiFiPasswd(); + /*获取锁屏管控*/ + void getScreenLock(); + + /*获取锁定状态*/ + void getLocked(); + /*检查更新*/ + void checkUpdate(); + /*获取灰度更新*/ + void getTestApp(); + /*获取管理员应用*/ + void getAdminApp(); + /*获取id管控*/ + void getAppInside(); + + /*获取app联网管控*/ + void getAppNetwork(); + /*获取系统设置*/ + void getSystemSettings(); + /*获取锁屏密码*/ + void getLockScreenPwd(); } public interface MainSView extends BaseView { + void isActivation(IsActivationBean isActivationBean); + + void uploadNotActivateFinish(); + void setPublicIp(String ip); +// void activationJxw(JxwResponse jxwResponse); + void activationJxwComplete(); + void setJxwApp(List appInfos); + + void setSnInfo(BaseResponse response); + + /*需要绑定设备才能使用的功能*/ void setCloudLessonSettings(); + + void updateInfoFinish(); + + void getTimeControlFinish(); + void getAllAppFinish(); + void setForceInstall(); + void setAppIcon(); + void setWiFiPasswd(); + void setScreenLock(); + + void setLocked(int lockedStatus); + void checkUpdateFinish(); + void getTestAppFinish(); + void getAdminAppFinish(); + void setAppInside(); + + void setAppNetwork(); + void setSystemSettings(); + void setLockScreenPwd(); } } diff --git a/app/src/main/java/com/xwad/os/service/main/MainSPresenter.java b/app/src/main/java/com/xwad/os/service/main/MainSPresenter.java index ce64b6c..54a3250 100644 --- a/app/src/main/java/com/xwad/os/service/main/MainSPresenter.java +++ b/app/src/main/java/com/xwad/os/service/main/MainSPresenter.java @@ -1,16 +1,32 @@ package com.xwad.os.service.main; import android.content.Context; +import android.content.Intent; import android.util.Log; +import com.google.gson.JsonObject; import com.tencent.mmkv.MMKV; +import com.trello.rxlifecycle4.RxLifecycle; import com.trello.rxlifecycle4.android.ActivityEvent; import com.xwad.os.bean.AlarmClockData; +import com.xwad.os.bean.AppInfo; +import com.xwad.os.bean.BaseResponse; import com.xwad.os.config.CommonConfig; +import com.xwad.os.gson.GsonUtils; import com.xwad.os.network.NetInterfaceManager; +import com.xwad.os.service.ManagerService; +import com.xwad.os.utils.ServiceAliveUtils; +import com.xwad.os.utils.Utils; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.BehaviorSubject; @@ -51,9 +67,39 @@ public class MainSPresenter implements MainSContact.Presenter { this.mView = null; } + @Override + public void getSnIsActivation() { + + } + + @Override + public void uploadNotActivate() { + + } + + @Override + public void getPublicIp() { + + } + + @Override + public void setJxwActivation() { + + } + + @Override + public void getJxwApp() { + + } + + @Override + public void getSnInfo() { + + } + @Override public void getCloudLessonSettings() { - NetInterfaceManager.getInstance().getCloudLessonSettings(lifecycle, new NetInterfaceManager.onCompleteCallback() { + NetInterfaceManager.getInstance().getCloudLessonSettings(lifecycle, new NetInterfaceManager.OnCompleteCallback() { @Override public void onComplete() { mView.setCloudLessonSettings(); @@ -61,22 +107,154 @@ public class MainSPresenter implements MainSContact.Presenter { }); } - public void getAlarmClock() { - NetInterfaceManager.getInstance().getAlarmClock(true, getLifecycle(), new NetInterfaceManager.AlarmClockCallback() { - @Override - public void setAlarmClock(List alarmClockList) { - Log.e(TAG, "setAlarmClock: " + alarmClockList); - } + @Override + public void updateDeviceInfo() { - @Override - public void setAlarmClockEmpty() { - Log.e(TAG, "setAlarmClock: setAlarmClockEmpty"); - } - - @Override - public void onError() { - Log.e(TAG, "setAlarmClock: onError"); - } - }); } + + @Override + public void getTimeControl() { + + } + + @Override + public void getAllApp() { + + } + + @Override + public void getForceInstall() { + + } + + @Override + public void getAppIcon() { + + } + + @Override + public void getWiFiPasswd() { + + } + + @Override + public void getScreenLock() { + NetInterfaceManager.getInstance() + .getSnInfoApi() + .getScreenshot(Utils.getSerial()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + Log.e("getScreenLock", "onSubscribe: "); + } + + @Override + public void onNext(BaseResponse baseResponse) { + Log.e("getScreenLock", "onNext: " + baseResponse); + int code = baseResponse.code; + if (code == 200) { + JsonObject jsonObject = GsonUtils.getJsonObject(GsonUtils.toJSONString(baseResponse.data)); + int is_screen_lock = jsonObject.get("is_screen_lock").getAsInt(); + if (!ServiceAliveUtils.isServiceAlive(mContext, ManagerService.class.getName())) { + mContext.startService(new Intent(mContext, ManagerService.class)); + } + mMMKV.encode(ManagerService.LOCK_STATE, is_screen_lock); + Intent intent = new Intent(); +// intent.putExtra("name", name); + if (1 == is_screen_lock) { + intent.setAction(ManagerService.ACTION_LOCK); + } else if (0 == is_screen_lock) { + intent.setAction(ManagerService.ACTION_UNLOCK); + } + mContext.sendBroadcast(intent); + } + } + + @Override + public void onError(Throwable e) { + Log.e("getScreenLock", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getScreenLock", "onComplete: "); + mView.setScreenLock(); + } + }); + } + + @Override + public void getLocked() { + + } + + @Override + public void checkUpdate() { + + } + + @Override + public void getTestApp() { + + } + + @Override + public void getAdminApp() { + NetInterfaceManager.getInstance().getAdminAppObservable() + .subscribe(new Observer>>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getAdminApp", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse> listBaseResponse) { + Log.e("getAdminApp", "onNext: " + listBaseResponse); + if (listBaseResponse.code == 200) { + List appInfoList = listBaseResponse.data; + Set pkgList = appInfoList.stream().map(AppInfo::getApp_package).collect(Collectors.toSet()); + Log.e("getAdminApp", "onNext: " + pkgList); + mMMKV.encode(CommonConfig.ADMIN_APP_LIST, pkgList); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getAdminApp", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("getAdminApp", "onComplete: "); + mView.getAdminAppFinish(); + } + }); + } + + @Override + public void getAppInside() { + + } + + @Override + public void getAppNetwork() { + + } + + @Override + public void getSystemSettings() { + NetInterfaceManager.getInstance().getSystemSettings(); + } + + @Override + public void getLockScreenPwd() { + + } + + } diff --git a/app/src/main/java/com/xwad/os/service/main/MainService.java b/app/src/main/java/com/xwad/os/service/main/MainService.java index f723398..c2d80df 100644 --- a/app/src/main/java/com/xwad/os/service/main/MainService.java +++ b/app/src/main/java/com/xwad/os/service/main/MainService.java @@ -23,11 +23,16 @@ import com.xwad.os.activity.main.MainActivity; import com.xwad.os.alarm.AlarmUtils; import com.xwad.os.base.rx.BaseRxService; import com.xwad.os.bean.AlarmClockData; +import com.xwad.os.bean.AppInfo; +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.bean.IsActivationBean; +import com.xwad.os.bean.SnInfo; import com.xwad.os.config.CommonConfig; import com.xwad.os.service.SocketService; import java.util.Calendar; import java.util.HashMap; +import java.util.List; public class MainService extends BaseRxService implements MainSContact.MainSView, NetworkUtils.OnNetworkStatusChangedListener { private static final String TAG = "MainService"; @@ -63,10 +68,16 @@ public class MainService extends BaseRxService implements MainSContact.MainSView public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: "); + long time = System.currentTimeMillis(); + mPresenter = new MainSPresenter(this); mPresenter.attachView(this); mPresenter.setLifecycle(getLifecycleSubject()); + mPresenter.getCloudLessonSettings(); + mPresenter.getScreenLock(); + mPresenter.getAdminApp(); + registerReceivers(); NetworkUtils.registerNetworkStatusChangedListener(this); startJxwLauncher(); @@ -77,6 +88,9 @@ public class MainService extends BaseRxService implements MainSContact.MainSView sendSimpleNotification(); startService(new Intent(MainService.this, SocketService.class)); + + Log.e(TAG, "setDefault: startServices time = " + (System.currentTimeMillis() - time) + "ms"); + } @Override @@ -218,11 +232,6 @@ public class MainService extends BaseRxService implements MainSContact.MainSView } } - @Override - public void setCloudLessonSettings() { - - } - public static final String JXW_REGISTER_SUCCESS = "com.zzj.regist_success"; private JxwRegisterReceiver mJxwRegisterReceiver; @@ -247,4 +256,115 @@ public class MainService extends BaseRxService implements MainSContact.MainSView } } + + @Override + public void isActivation(IsActivationBean isActivationBean) { + + } + + @Override + public void uploadNotActivateFinish() { + + } + + @Override + public void setPublicIp(String ip) { + + } + + @Override + public void activationJxwComplete() { + + } + + @Override + public void setJxwApp(List appInfos) { + + } + + @Override + public void setSnInfo(BaseResponse response) { + + } + + @Override + public void setCloudLessonSettings() { + + } + + @Override + public void updateInfoFinish() { + + } + + @Override + public void getTimeControlFinish() { + + } + + @Override + public void getAllAppFinish() { + + } + + @Override + public void setForceInstall() { + + } + + @Override + public void setAppIcon() { + + } + + @Override + public void setWiFiPasswd() { + + } + + @Override + public void setScreenLock() { + + } + + @Override + public void setLocked(int lockedStatus) { + + } + + @Override + public void checkUpdateFinish() { + + } + + @Override + public void getTestAppFinish() { + + } + + @Override + public void getAdminAppFinish() { + + } + + @Override + public void setAppInside() { + + } + + @Override + public void setAppNetwork() { + + } + + @Override + public void setSystemSettings() { + + } + + @Override + public void setLockScreenPwd() { + + } + } diff --git a/app/src/main/java/com/xwad/os/utils/ApkUtils.java b/app/src/main/java/com/xwad/os/utils/ApkUtils.java index 2fc3a8e..f8f34d7 100644 --- a/app/src/main/java/com/xwad/os/utils/ApkUtils.java +++ b/app/src/main/java/com/xwad/os/utils/ApkUtils.java @@ -23,6 +23,7 @@ import androidx.core.content.FileProvider; import com.hjq.toast.Toaster; import com.xwad.os.BuildConfig; import com.xwad.os.R; +import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.AppUpdateInfo; import com.xwad.os.bean.DesktopIcon; import com.xwad.os.mdm.AdminManager; @@ -133,6 +134,61 @@ public class ApkUtils { this.add("com.android.uiuios"); }}; + public static final List mJxwApps = new ArrayList() {{ + this.add("air.com.zhihuiyoujiao.flashplayer"); + this.add("com.example.arithmeticformula"); + this.add("com.example.elementcycleapp"); + this.add("com.example.pianpangbushou"); + this.add("com.iflytek.cyber.iot.show.core"); + this.add("com.iflytek.speechcloud"); + this.add("com.jxw.bihuamingcheng"); + this.add("com.jxw.bishunguize"); + this.add("com.jxw.characterlearning"); + this.add("com.jxw.dmxcy"); + this.add("com.jxw.englishsoundmark"); + this.add("com.jxw.examsystem"); + this.add("com.jxw.game"); + this.add("com.jxw.gb.zwpg"); + this.add("com.jxw.handwrite"); + this.add("com.jxw.jinfangyici"); + this.add("com.jxw.jxwbook"); + this.add("com.jxw.jxwcalculator"); + this.add("com.jxw.laboratory"); + this.add("com.jxw.learnchinesepinyin"); + this.add("com.jxw.letterstudynew"); + this.add("com.jxw.liancichengju"); + this.add("com.jxw.mskt.video"); + this.add("com.jxw.newyouer.video"); + this.add("com.jxw.online_study"); + this.add("com.jxw.question"); + this.add("com.jxw.schultegrid"); + this.add("com.jxw.singsound"); + this.add("com.jxw.studydigital"); + this.add("com.jxw.teacher.video"); + this.add("com.jxw.wuweijidanci"); + this.add("com.jxw.youer.video"); + this.add("com.jxw.yuwenxiezuo"); + this.add("com.jxw.yyhb"); + this.add("com.jxw.zncd"); + this.add("com.jxw.souti"); + this.add("com.jxw.xdfzq"); + this.add("com.jxw.huiben"); + this.add("com.oirsdfg89.flg"); + this.add("com.study.flashplayer"); + this.add("com.tech.translate"); + this.add("com.uiui.zybrowser"); + this.add("com.uiui.zysn "); + this.add("com.jxw.launcher"); + this.add("com.uiui.zyappstore"); + this.add("com.uiui.zy"); + this.add("com.uiui.zyos"); + this.add("com.teclast.zyos"); + this.add("com.teclast.zybrowser"); + this.add("com.teclast.zyappstore"); + this.add("com.teclast.zy"); + }}; + + public static final String ANDROID_LAUNCHER3_PACKAGE_NAME = "com.android.launcher3"; public static final String ANDROID_LAUNCHER3_CLASS_NAME = "com.android.launcher3.Launcher"; public static final String ANDROID_LAUNCHER3_Quickstep_CLASS_NAME = "com.android.launcher3.uioverrides.QuickstepLauncher"; @@ -248,7 +304,7 @@ public class ApkUtils { // if (adminApp.contains(pkg)) { // resolveInfos.add(resolveInfo); // } else if (showPackageName.contains(pkg)) { - resolveInfos.add(resolveInfo); + resolveInfos.add(resolveInfo); // } } // } @@ -470,6 +526,24 @@ public class ApkUtils { return versionName; } + public static long getAppLastUpdateTime(Context context, String pkg) { + if (TextUtils.isEmpty(pkg)) { + return 0; + } + PackageManager pm = context.getPackageManager(); + PackageInfo packageInfo = null; + try { + packageInfo = pm.getPackageInfo(pkg, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + return 0; + } else { + return packageInfo.lastUpdateTime / 1000; + } + } + public static String getAppNameByPackage(Context context, String pkg) { PackageManager packageManager = context.getPackageManager(); try { @@ -780,6 +854,11 @@ public class ApkUtils { } } + public static boolean isUpdate(Context context, AppInfo appUpdateInfo) { + String packageName = appUpdateInfo.getApp_package(); + long versionCode = appUpdateInfo.getApp_version_code(); + return isUpdate(context, packageName, versionCode); + } public static boolean isUpdate(Context context, AppUpdateInfo appUpdateInfo) { String packageName = appUpdateInfo.getApp().getApp_package(); @@ -817,6 +896,33 @@ public class ApkUtils { installApkFile(context, apk); } + public static void checkAppUpdate(Context context, AppInfo appUpdateInfo) { + String packageName = appUpdateInfo.getApp_package(); + long versionCode = appUpdateInfo.getApp_version_code(); + String url = appUpdateInfo.getApp_url(); + PackageInfo packageInfo = null; + try { + packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + FileUtil.ariaDownload(context, url, appUpdateInfo); + } else { + long appVersionCode; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + appVersionCode = packageInfo.getLongVersionCode(); + } else { + appVersionCode = packageInfo.versionCode; + } + if (appVersionCode < versionCode) { + FileUtil.ariaDownload(context, url, appUpdateInfo); + } else { + Log.e(TAG, "checkUpdate: " + packageName + "\t已经是最新版"); + } + } + } + public static void checkAppUpdate(Context context, AppUpdateInfo appUpdateInfo) { String packageName = appUpdateInfo.getApp().getApp_package(); long versionCode = appUpdateInfo.getApp_version_code(); diff --git a/app/src/main/java/com/xwad/os/utils/BitmapUtils.java b/app/src/main/java/com/xwad/os/utils/BitmapUtils.java index 17e866b..c636edd 100644 --- a/app/src/main/java/com/xwad/os/utils/BitmapUtils.java +++ b/app/src/main/java/com/xwad/os/utils/BitmapUtils.java @@ -14,6 +14,7 @@ import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; +import android.util.Log; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; @@ -24,10 +25,46 @@ import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.xwad.os.R; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.util.HashMap; import java.util.Map; public class BitmapUtils { + private static final String TAG = "BitmapUtils"; + + public static File saveBitmap(Bitmap bitmap, String filePath) { + long time = System.currentTimeMillis(); + Log.e(TAG, "saveBitmap: " + time); + File file = new File(filePath); + // 打开输出流,并将Bitmap压缩成PNG格式输出到文件中 + OutputStream fos = null; + try { + fos = new FileOutputStream(file); + // png 1550ms jpeg 358 + long time2 = System.currentTimeMillis(); + Log.e(TAG, "saveBitmap: compress " + time2); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); + Log.e(TAG, "saveBitmap: compress " + System.currentTimeMillis()); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + try { + if (fos != null) { + fos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + Log.e(TAG, "saveBitmap: " + (System.currentTimeMillis() - time)); + return file; + } + public static Bitmap Bytes2Bimap(byte[] b) { if (b.length != 0) { return BitmapFactory.decodeByteArray(b, 0, b.length); @@ -186,4 +223,37 @@ public class BitmapUtils { } return null; } + + /** + * drawable转为file + * + * @param mContext + * @param drawable drawable + * @param fileName 转换后的文件名 + * @return + */ + public static File drawableToFile(Context mContext, Drawable drawable, String fileName) { +// InputStream is = view.getContext().getResources().openRawResource(R.drawable.logo); + Bitmap bitmap = drawableToBitmap(drawable); +// Bitmap bitmap = BitmapFactory.decodeStream(is); + String defaultPath = Utils.getCacheDir(mContext) + "/iconCache"; + File file = new File(defaultPath); + if (!file.exists()) { + file.mkdirs(); + } + String defaultImgPath = defaultPath + "/" + fileName; + File iconFile = new File(defaultImgPath); + try { + iconFile.createNewFile(); + FileOutputStream fOut = new FileOutputStream(iconFile); + bitmap.compress(Bitmap.CompressFormat.PNG, 20, fOut); +// is.close(); + fOut.flush(); + fOut.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return iconFile; + } + } diff --git a/app/src/main/java/com/xwad/os/utils/BrightnessUtils.java b/app/src/main/java/com/xwad/os/utils/BrightnessUtils.java new file mode 100644 index 0000000..0620517 --- /dev/null +++ b/app/src/main/java/com/xwad/os/utils/BrightnessUtils.java @@ -0,0 +1,140 @@ + +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.xwad.os.utils; + +public class BrightnessUtils { + + public static final int GAMMA_SPACE_MIN = 0; + public static final int GAMMA_SPACE_MAX = 65535; + + // Hybrid Log Gamma constant values + private static final float R = 0.5f; + private static final float A = 0.17883277f; + private static final float B = 0.28466892f; + private static final float C = 0.55991073f; + + /** + * A function for converting from the gamma space that the slider works in to the + * linear space that the setting works in. + *

+ * The gamma space effectively provides us a way to make linear changes to the slider that + * result in linear changes in perception. If we made changes to the slider in the linear space + * then we'd see an approximately logarithmic change in perception (c.f. Fechner's Law). + *

+ * Internally, this implements the Hybrid Log Gamma electro-optical transfer function, which is + * a slight improvement to the typical gamma transfer function for displays whose max + * brightness exceeds the 120 nit reference point, but doesn't set a specific reference + * brightness like the PQ function does. + *

+ * Note that this transfer function is only valid if the display's backlight value is a linear + * control. If it's calibrated to be something non-linear, then a different transfer function + * should be used. + * + * @param val The slider value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding setting value. + */ + public static final int convertGammaToLinear(int val, int min, int max) { + final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val); + final float ret; + if (normalizedVal <= R) { + ret = MathUtils.sq(normalizedVal / R); + } else { + ret = MathUtils.exp((normalizedVal - C) / A) + B; + } + + // HLG is normalized to the range [0, 12], so we need to re-normalize to the range [0, 1] + // in order to derive the correct setting value. + return Math.round(MathUtils.lerp(min, max, ret / 12)); + } + + /** + * Version of {@link #convertGammaToLinear} that takes and returns float values. + * TODO(flc): refactor Android Auto to use float version + * + * @param val The slider value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding setting value. + */ + public static final float convertGammaToLinearFloat(int val, float min, float max) { + final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val); + final float ret; + if (normalizedVal <= R) { + ret = MathUtils.sq(normalizedVal / R); + } else { + ret = MathUtils.exp((normalizedVal - C) / A) + B; + } + + // HLG is normalized to the range [0, 12], ensure that value is within that range, + // it shouldn't be out of bounds. + final float normalizedRet = MathUtils.constrain(ret, 0, 12); + + // Re-normalize to the range [0, 1] + // in order to derive the correct setting value. + return MathUtils.lerp(min, max, normalizedRet / 12); + } + + /** + * A function for converting from the linear space that the setting works in to the + * gamma space that the slider works in. + *

+ * The gamma space effectively provides us a way to make linear changes to the slider that + * result in linear changes in perception. If we made changes to the slider in the linear space + * then we'd see an approximately logarithmic change in perception (c.f. Fechner's Law). + *

+ * Internally, this implements the Hybrid Log Gamma opto-electronic transfer function, which is + * a slight improvement to the typical gamma transfer function for displays whose max + * brightness exceeds the 120 nit reference point, but doesn't set a specific reference + * brightness like the PQ function does. + *

+ * Note that this transfer function is only valid if the display's backlight value is a linear + * control. If it's calibrated to be something non-linear, then a different transfer function + * should be used. + * + * @param val The brightness setting value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding slider value + */ + public static final int convertLinearToGamma(int val, int min, int max) { + return convertLinearToGammaFloat((float) val, (float) min, (float) max); + } + + /** + * Version of {@link #convertLinearToGamma} that takes float values. + * TODO: brightnessfloat merge with above method(?) + * + * @param val The brightness setting value. + * @param min The minimum acceptable value for the setting. + * @param max The maximum acceptable value for the setting. + * @return The corresponding slider value + */ + public static final int convertLinearToGammaFloat(float val, float min, float max) { + // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1] + final float normalizedVal = MathUtils.norm(min, max, val) * 12; + final float ret; + if (normalizedVal <= 1f) { + ret = MathUtils.sqrt(normalizedVal) * R; + } else { + ret = A * MathUtils.log(normalizedVal - B) + C; + } + + return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret)); + } +} diff --git a/app/src/main/java/com/xwad/os/utils/FileUtil.java b/app/src/main/java/com/xwad/os/utils/FileUtil.java index 82131be..3eafcf6 100644 --- a/app/src/main/java/com/xwad/os/utils/FileUtil.java +++ b/app/src/main/java/com/xwad/os/utils/FileUtil.java @@ -19,6 +19,7 @@ import com.xwad.os.bean.AppUpdateInfo; import com.xwad.os.bean.AriaDownloadInfo; import com.xwad.os.bean.HomeworkBean; import com.xwad.os.gson.GsonUtils; +import com.xwad.os.mdm.AdminManager; import java.io.File; import java.io.FileInputStream; @@ -254,7 +255,7 @@ public class FileUtil { String fileMd5 = com.blankj.utilcode.util.FileUtils.getFileMD5ToString(file); Log.e("ariaDownload", "fileMD5 = " + fileMd5); if (fileMd5.equalsIgnoreCase(app_md5)) { - ApkUtils.installApkFile(context, file); + ApkUtils.installApp(context, file.getAbsolutePath()); } else { file.delete(); Aria.download(context) diff --git a/app/src/main/java/com/xwad/os/utils/GlideLoadUtils.java b/app/src/main/java/com/xwad/os/utils/GlideLoadUtils.java index 63d782e..b2ab4bb 100644 --- a/app/src/main/java/com/xwad/os/utils/GlideLoadUtils.java +++ b/app/src/main/java/com/xwad/os/utils/GlideLoadUtils.java @@ -61,6 +61,14 @@ public class GlideLoadUtils { } } + public void glideLoad(Context context, Drawable drawable, ImageView imageView) { + if (context != null) { + Glide.with(context).load(drawable).centerCrop().into(imageView); + } else { + Log.i(TAG, "Picture loading failed,context is null"); + } + } + public void glideLoad(Context context, File file, ImageView imageView, int default_image) { if (context != null) { Glide.with(context).load(file).centerCrop().error(default_image).into(imageView); diff --git a/app/src/main/java/com/xwad/os/utils/JgyUtils.java b/app/src/main/java/com/xwad/os/utils/JgyUtils.java index 6f1c9ad..9237e96 100644 --- a/app/src/main/java/com/xwad/os/utils/JgyUtils.java +++ b/app/src/main/java/com/xwad/os/utils/JgyUtils.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.ActivityTaskManager; -import android.app.NotificationManager; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.ContentResolver; @@ -84,13 +83,13 @@ public class JgyUtils { private ContentResolver resolver; private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); - public static final int MINI2_PLATFORM = 28; - public static final int HONER_PLATFORM = 29; + public static final int HONOR_PLATFORM = 1; + public static final int LENOVO_PLATFORM = 2; public static final int UNKNOW_PLATFORM = 0; - public static final String MINI2_TAG = "6gen1s"; - public static final String HONER2_TAG = "honer"; + public static final String HONOR_TAG = "HONOR"; + public static final String LENOVO_TAG = "lenovo"; private HashSet ownApp = new HashSet() {{ @@ -405,13 +404,6 @@ public class JgyUtils { } } - public void killPackage(String pkg) { - Log.e(TAG, "killPackage: " + pkg); - ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - manager.killBackgroundProcesses(pkg); - CmdUtil.execute("am force-stop " + pkg); - } - public void KillOTA() { ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); manager.killBackgroundProcesses("com.adups.fota"); @@ -435,7 +427,7 @@ public class JgyUtils { } public void openCubeOta() { - if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONER_PLATFORM + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONOR_PLATFORM ) { openCubeUnisocOta(); // } else if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.MTKPlatform) { @@ -473,7 +465,7 @@ public class JgyUtils { public void openLauncher() { Log.e(TAG, "openLauncher: "); - killPackage("com.android.launcher3"); + AdminManager.getInstance().killApplicationProcess("com.android.launcher3"); Intent intent = new Intent(); // 为Intent设置Action、Category属性 intent.setAction(Intent.ACTION_MAIN);// "android.intent.action.MAIN" @@ -494,12 +486,12 @@ public class JgyUtils { public int checkAppPlatform() { String platform = BuildConfig.platform; - if (HONER2_TAG.equalsIgnoreCase(platform)) { + if (HONOR_TAG.equalsIgnoreCase(platform)) { Log.i(TAG, "checkAppPlatform: " + "honer"); - return HONER_PLATFORM; - } else if (MINI2_TAG.equalsIgnoreCase(platform)) { + return HONOR_PLATFORM; + } else if (LENOVO_TAG.equalsIgnoreCase(platform)) { Log.i(TAG, "checkAppPlatform: " + "6gen1s"); - return MINI2_PLATFORM; + return LENOVO_PLATFORM; } else { Log.i(TAG, "checkAppPlatform: " + "没有数据"); return UNKNOW_PLATFORM; @@ -512,17 +504,17 @@ public class JgyUtils { public void getAppPlatform(GetAppPlatformCallback getAppPlatformCallback) { String platform = BuildConfig.platform; - if (HONER2_TAG.equalsIgnoreCase(platform)) { - getAppPlatformCallback.AppPlatform(HONER_PLATFORM); - } else if (MINI2_TAG.equalsIgnoreCase(platform)) { - getAppPlatformCallback.AppPlatform(MINI2_PLATFORM); + if (HONOR_TAG.equalsIgnoreCase(platform)) { + getAppPlatformCallback.AppPlatform(HONOR_PLATFORM); + } else if (LENOVO_TAG.equalsIgnoreCase(platform)) { + getAppPlatformCallback.AppPlatform(LENOVO_PLATFORM); } else { getAppPlatformCallback.AppPlatform(UNKNOW_PLATFORM); } } public static String getCustomVersion() { - if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONER_PLATFORM + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONOR_PLATFORM ) { return getProperty("ro.build.display.id", "获取失败"); } else { @@ -531,7 +523,7 @@ public class JgyUtils { } public static String getRomVersion() { - if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONER_PLATFORM + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONOR_PLATFORM ) { return getProperty("ro.build.id", "获取失败"); } else { @@ -1306,7 +1298,9 @@ public class JgyUtils { Log.e(TAG, "startServices: noti = " + noti); if (noti) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + long time = System.currentTimeMillis(); mContext.startForegroundService(new Intent(mContext, MainService.class)); + Log.e(TAG, "setDefault: startServices time = " + (System.currentTimeMillis() - time) + "ms"); } else { mContext.startService(new Intent(mContext, MainService.class)); } diff --git a/app/src/main/java/com/xwad/os/utils/MathUtils.java b/app/src/main/java/com/xwad/os/utils/MathUtils.java new file mode 100644 index 0000000..4790c06 --- /dev/null +++ b/app/src/main/java/com/xwad/os/utils/MathUtils.java @@ -0,0 +1,196 @@ +package com.xwad.os.utils; + +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by Fernflower decompiler) +// + +public final class MathUtils { + private static final float DEG_TO_RAD = 0.017453292F; + private static final float RAD_TO_DEG = 57.295784F; + + private MathUtils() { + } + + public static float abs(float v) { + return v > 0.0F ? v : -v; + } + + public static int constrain(int amount, int low, int high) { + return amount < low ? low : (amount > high ? high : amount); + } + + public static long constrain(long amount, long low, long high) { + return amount < low ? low : (amount > high ? high : amount); + } + + public static float constrain(float amount, float low, float high) { + return amount < low ? low : (amount > high ? high : amount); + } + + public static float log(float a) { + return (float) Math.log((double) a); + } + + public static float exp(float a) { + return (float) Math.exp((double) a); + } + + public static float pow(float a, float b) { + return (float) Math.pow((double) a, (double) b); + } + + public static float sqrt(float a) { + return (float) Math.sqrt((double) a); + } + + public static float max(float a, float b) { + return a > b ? a : b; + } + + public static float max(int a, int b) { + return a > b ? (float) a : (float) b; + } + + public static float max(float a, float b, float c) { + return a > b ? (a > c ? a : c) : (b > c ? b : c); + } + + public static float max(int a, int b, int c) { + return a > b ? (float) (a > c ? a : c) : (float) (b > c ? b : c); + } + + public static float min(float a, float b) { + return a < b ? a : b; + } + + public static float min(int a, int b) { + return a < b ? (float) a : (float) b; + } + + public static float min(float a, float b, float c) { + return a < b ? (a < c ? a : c) : (b < c ? b : c); + } + + public static float min(int a, int b, int c) { + return a < b ? (float) (a < c ? a : c) : (float) (b < c ? b : c); + } + + public static float dist(float x1, float y1, float x2, float y2) { + float x = x2 - x1; + float y = y2 - y1; + return (float) Math.hypot((double) x, (double) y); + } + + public static float dist(float x1, float y1, float z1, float x2, float y2, float z2) { + float x = x2 - x1; + float y = y2 - y1; + float z = z2 - z1; + return (float) Math.sqrt((double) (x * x + y * y + z * z)); + } + + public static float mag(float a, float b) { + return (float) Math.hypot((double) a, (double) b); + } + + public static float mag(float a, float b, float c) { + return (float) Math.sqrt((double) (a * a + b * b + c * c)); + } + + public static float sq(float v) { + return v * v; + } + + public static float dot(float v1x, float v1y, float v2x, float v2y) { + return v1x * v2x + v1y * v2y; + } + + public static float cross(float v1x, float v1y, float v2x, float v2y) { + return v1x * v2y - v1y * v2x; + } + + public static float radians(float degrees) { + return degrees * 0.017453292F; + } + + public static float degrees(float radians) { + return radians * 57.295784F; + } + + public static float acos(float value) { + return (float) Math.acos((double) value); + } + + public static float asin(float value) { + return (float) Math.asin((double) value); + } + + public static float atan(float value) { + return (float) Math.atan((double) value); + } + + public static float atan2(float a, float b) { + return (float) Math.atan2((double) a, (double) b); + } + + public static float tan(float angle) { + return (float) Math.tan((double) angle); + } + + public static float lerp(float start, float stop, float amount) { + return start + (stop - start) * amount; + } + + public static float lerpInv(float a, float b, float value) { + return a != b ? (value - a) / (b - a) : 0.0F; + } + + public static float saturate(float value) { + return constrain(value, 0.0F, 1.0F); + } + + public static float lerpInvSat(float a, float b, float value) { + return saturate(lerpInv(a, b, value)); + } + + public static float lerpDeg(float start, float end, float amount) { + float minAngle = (end - start + 180.0F) % 360.0F - 180.0F; + return minAngle * amount + start; + } + + public static float norm(float start, float stop, float value) { + return (value - start) / (stop - start); + } + + public static float map(float minStart, float minStop, float maxStart, float maxStop, float value) { + return maxStart + (maxStop - maxStart) * ((value - minStart) / (minStop - minStart)); + } + + public static float constrainedMap(float rangeMin, float rangeMax, float valueMin, float valueMax, float value) { + return lerp(rangeMin, rangeMax, lerpInvSat(valueMin, valueMax, value)); + } + + public static float smoothStep(float start, float end, float x) { + return constrain((x - start) / (end - start), 0.0F, 1.0F); + } + + public static int addOrThrow(int a, int b) throws IllegalArgumentException { + if (b == 0) { + return a; + } else if (b > 0 && a <= 2147483647 - b) { + return a + b; + } else if (b < 0 && a >= -2147483648 - b) { + return a + b; + } else { + throw new IllegalArgumentException("Addition overflow: " + a + " + " + b); + } + } + +// public static void fitRect(Rect outToResize, int largestSide) { +// if (!outToResize.isEmpty()) { +// float maxSize = (float)Math.max(outToResize.width(), outToResize.height()); +// outToResize.scale((float)largestSide / maxSize); +// } +// } +} + diff --git a/app/src/main/java/com/xwad/os/utils/ScreenUtils.java b/app/src/main/java/com/xwad/os/utils/ScreenUtils.java index de03bdb..795173f 100644 --- a/app/src/main/java/com/xwad/os/utils/ScreenUtils.java +++ b/app/src/main/java/com/xwad/os/utils/ScreenUtils.java @@ -1,9 +1,15 @@ package com.xwad.os.utils; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; +import android.util.Log; + +import java.lang.reflect.Method; public class ScreenUtils { + private static final String TAG = "ScreenUtils"; + /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ @@ -29,4 +35,51 @@ public class ScreenUtils { final float scale = resources.getDisplayMetrics().scaledDensity; return (int) (sp * scale); } + + public static String getSystemProperties(String key, String defaultValue) { + String value = defaultValue; + try { + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class, String.class); + value = (String) (get.invoke(c, key, defaultValue)); + } catch (Exception e) { + e.printStackTrace(); + } finally { + return value; + } + } + + /** + * 应用需反射调用 + */ + public static boolean isTablet() { +// String characteristics = android.os.SystemProperties.get("ro.build.characteristics"); + String characteristics = getSystemProperties("ro.build.characteristics", "unknow"); + Log.e(TAG, "isTablet: " + characteristics); + return characteristics.contains("tablet"); + } + + public static boolean isTablet(Context context) { + boolean isTablet = (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; + Log.e(TAG, "isTablet: " + isTablet); + return isTablet; + } + + + public static int isTabletInt(Context context) { + boolean isTablet = (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; + Log.e(TAG, "isTablet: " + isTablet); + return isTablet ? 1 : 0; + } + + /** + * 是否是平板 + * + * @param context 上下文 + * @return 是平板则返回true,反之返回false + */ + public static boolean isPad(Context context) { + return (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; + } } diff --git a/app/src/main/java/com/xwad/os/utils/TimeUtils.java b/app/src/main/java/com/xwad/os/utils/TimeUtils.java index 0523d15..d610e49 100644 --- a/app/src/main/java/com/xwad/os/utils/TimeUtils.java +++ b/app/src/main/java/com/xwad/os/utils/TimeUtils.java @@ -1,44 +1,86 @@ package com.xwad.os.utils; import android.content.Context; +import android.content.Intent; import android.os.Build; +import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tencent.mmkv.MMKV; +import com.xwad.os.bean.TimeControl; +import com.xwad.os.config.CommonConfig; +import com.xwad.os.service.ManagerService; + +import java.lang.reflect.Type; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; +import java.util.List; import java.util.Locale; +import java.util.Objects; +import java.util.TimeZone; +import java.util.function.Function; +import java.util.stream.Collectors; public class TimeUtils { private static final String TAG = "TimeUtils"; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); - private static DateFormat df = new SimpleDateFormat("HH:mm", Locale.getDefault()); + private static DateFormat df = new SimpleDateFormat("HH:mm", Locale.CHINA); public static final long DAY_TIME = 60 * 60 * 24 * 1000; public static final long MINUTE_TIME = 60 * 1000; - @RequiresApi(api = Build.VERSION_CODES.O) - public static boolean isTodayTime(long timeStamp) { - String time = transferLongToDate(timeStamp); - DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - LocalDateTime localTime = LocalDateTime.parse(time, dtf); - LocalDateTime startTime = LocalDate.now().atTime(0, 0, 0); - LocalDateTime endTime = LocalDate.now().atTime(23, 59, 59); - return localTime.isAfter(startTime) && localTime.isBefore(endTime); + public static final String START_TIME_KEY = "START_TIME"; + public static final String END_TIME_KEY = "END_TIME"; + public static final String WEEK_START_TIME_KEY = "WEEK_START_TIME"; + public static final String WEEK_END_TIME_KEY = "WEEK_END_TIME"; + + /*新增 时间控制开关*/ + public static final String AOLELEARN_TIME_CONTROL_KEY = "aolelearn_time_control"; + /*多个时间段*/ + public static final String AOLELEARN_TTIMECONTROL_LIST_KEY = "aolelearn_timecontrol_list"; + + /*可以使用时间开始*/ + @Deprecated + public static final String AOLELEARN_TTIMECONTROL_START_KEY = "aolelearn_timecontrol_start"; + /*可以使用时间结束*/ + @Deprecated + public static final String AOLELEARN_TTIMECONTROL_END_KEY = "aolelearn_timecontrol_end"; + + + public static String getNowTime() { + long nowTime = System.currentTimeMillis(); + DateFormat df = ContralTime.getDf(); + return df.format(nowTime); } - public static String transferLongToDate(Long millisecond) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Date date = new Date(millisecond); +// public static boolean CurrentInTimeScope(ContralTime contralTime) { +// boolean result = true; +// final long aDayInMillis = 1000 * 60 * 60 * 24; +// long currentTimeMillis = System.currentTimeMillis(); +// +// } + + public static String transferLongToDate(Long millSec) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); + Date date = new Date(millSec); return sdf.format(date); } @@ -55,6 +97,28 @@ public class TimeUtils { return dateString + "\t" + getWeek(); } + + public static String transferSecondToDate(long second) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); + + Date date = new Date(second * 1000); + return sdf.format(date); + } + + public static String transferSecond(long second) { + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); + sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + Date date = new Date(second * 1000); + return sdf.format(date); + } + + public static String getPhotoDate() { + long millisecond = System.currentTimeMillis(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + Date date = new Date(millisecond); + return sdf.format(date); + } + public static String getHomeworkTime(String timeString) { SimpleDateFormat old = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); @@ -168,6 +232,244 @@ public class TimeUtils { return String.format("%d小时%d分", hour, min); } + private static final long ONE_DAY_TIME_OF_SECOND = 24 * 60 * 60; + + public static long timestampInterval(long nowTime, long expireTime) { + long num = expireTime - nowTime;//时间戳相差的毫秒数 + long day = num / ONE_DAY_TIME_OF_SECOND; + return day; + } + + @RequiresApi(api = Build.VERSION_CODES.O) + public static boolean isTodayTime(long timeStamp) { + String time = transferLongToDate(timeStamp); + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime localTime = LocalDateTime.parse(time, dtf); + LocalDateTime startTime = LocalDate.now().atTime(0, 0, 0); + LocalDateTime endTime = LocalDate.now().atTime(23, 59, 59); + return localTime.isAfter(startTime) && localTime.isBefore(endTime); + } + + public static ContralTime String2WorkingTime(Context context, @NonNull String timeText) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + DateFormat df = ContralTime.getDf(); + String[] time = timeText.trim().split("-"); + if (time.length != 2) { +// return null; + throw new RuntimeException("Time format error!" + Arrays.toString(time)); + } + try { + mmkv.encode(START_TIME_KEY, time[0].trim()); + mmkv.encode(END_TIME_KEY, time[1].trim()); + Date startDate = df.parse(time[0].trim()); + Date endDate = df.parse(time[1].trim()); + ContralTime contralTime = new ContralTime(); +// if (date1.getTime() < date2.getTime()) { + contralTime.setStartTime(df.format(startDate)); + contralTime.setEndTime(df.format(endDate)); +// } else { +// contralTime.setStartTime(df.format(date2)); +// contralTime.setEndTime(df.format(date1)); +// } + return contralTime; + } catch (ParseException e) { + e.printStackTrace(); + return null; + } + } + + /** + * @param context + * @param timeText HH:mm-HH:mm 格式转化为ContralTime + * @return + */ + public static ContralTime string2WeekTime(Context context, @NonNull String timeText) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + DateFormat df = ContralTime.getDf(); + String[] time = timeText.trim().split("-"); + if (time.length != 2) { +// return null; + throw new RuntimeException("Time format error!" + Arrays.toString(time)); + } + try { + mmkv.encode(WEEK_START_TIME_KEY, time[0].trim()); + mmkv.encode(WEEK_END_TIME_KEY, time[1].trim()); + Date startDate = df.parse(time[0].trim()); + Date endDate = df.parse(time[1].trim()); + ContralTime contralTime = new ContralTime(); +// if (date1.getTime() < date2.getTime()) { + contralTime.setStartTime(df.format(startDate)); + contralTime.setEndTime(df.format(endDate)); +// } else { +// contralTime.setStartTime(df.format(date2)); +// contralTime.setEndTime(df.format(date1)); +// } + return contralTime; + } catch (ParseException e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取工作日时间控制 + * + * @param context + * @return + */ + @Deprecated + public static ContralTime getWorkingDayContralTime(Context context) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + String startTime = mmkv.decodeString(START_TIME_KEY, "00:00"); + String endTime = mmkv.decodeString(END_TIME_KEY, "00:00"); + return getContralTime(context, startTime, endTime); + } + + /** + * 获取休息日时间控制 + * + * @param context + * @return + */ + @Deprecated + public static ContralTime getWeekDayContralTime(Context context) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + String startTime = mmkv.decodeString(WEEK_START_TIME_KEY, "00:00"); + String endTime = mmkv.decodeString(WEEK_END_TIME_KEY, "00:00"); + return getContralTime(context, startTime, endTime); + } + + /** + * 是否在管控时间内 + * + * @param workingTime + * @param weekTime + * @return + */ + @Deprecated + public static boolean inContralTime(ContralTime workingTime, ContralTime weekTime) { + if (inWeekDay()) { + if (weekTime == null) { + return false; + } else { + return weekTime.inControlTime(); + } + } else { + if (workingTime == null) { + return false; + } else { + return workingTime.inControlTime(); + } + } + } + + /** + * 获取新的时间管控 + * + * @param context + * @return + */ + @Deprecated + public static ContralTime getDayContralTime(Context context) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + String timecontrol_start = mmkv.decodeString(AOLELEARN_TTIMECONTROL_START_KEY, "00:00"); + String timecontrol_end = mmkv.decodeString(AOLELEARN_TTIMECONTROL_END_KEY, "00:00"); + return getContralTime(context, timecontrol_start, timecontrol_end); + } + + @Deprecated + public static boolean inDayContralTime(ContralTime contralTime) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + int is_timecontrol = mmkv.decodeInt(TimeUtils.AOLELEARN_TIME_CONTROL_KEY, 0); + if (is_timecontrol == 0) { + return false; + } + if (contralTime == null) { + return false; + } + if ("00:00".equals(contralTime.getStartTime()) && "00:00".equals(contralTime.getEndTime()) + || "00:00".equals(contralTime.getStartTime()) && "24:00".equals(contralTime.getEndTime()) + || "24:00".equals(contralTime.getStartTime()) && "00:00".equals(contralTime.getEndTime()) + || Objects.equals(contralTime.getStartTime(), contralTime.getEndTime()) + ) { + return false; + } + return contralTime.inControlTime(); + } + + public static List getDayContralTimeList(Context context) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + String listJsonString = mmkv.decodeString(AOLELEARN_TTIMECONTROL_LIST_KEY, ""); + if (!TextUtils.isEmpty(listJsonString)) { + Gson gson = new Gson(); + Type listType = new TypeToken>() { + }.getType(); + try { + List timeControls = gson.fromJson(listJsonString, listType); + List contralTimes = timeControls.stream().map(new Function() { + @Override + public ContralTime apply(TimeControl timeControl) { + return getContralTime(context, timeControl.getStart_time(), timeControl.getEnd_time()); + } + }).collect(Collectors.toList()); + return contralTimes; + } catch (Exception e) { + Log.e(TAG, "getDayContralTimeList: " + e.getMessage()); + mmkv.remove(AOLELEARN_TTIMECONTROL_LIST_KEY); + } + } + return null; + } + + public static boolean inDayContralTime(List contralTimes) { + Log.e(TAG, "inDayContralTime: " + contralTimes); + if (contralTimes == null || contralTimes.isEmpty()) { + Log.e(TAG, "inDayContralTime: isEmpty"); + return false; + } + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + int is_timecontrol = mmkv.decodeInt(TimeUtils.AOLELEARN_TIME_CONTROL_KEY, 0); + if (is_timecontrol == 0) { + Log.e(TAG, "inDayContralTime: false"); + return false; + } + List booleans = new ArrayList<>(); + for (ContralTime contralTime : contralTimes) { + if (contralTime == null) { + continue; + } + if ("00:00".equals(contralTime.getStartTime()) && "00:00".equals(contralTime.getEndTime()) + || "00:00".equals(contralTime.getStartTime()) && "24:00".equals(contralTime.getEndTime()) + || "24:00".equals(contralTime.getStartTime()) && "00:00".equals(contralTime.getEndTime()) + || Objects.equals(contralTime.getStartTime(), contralTime.getEndTime()) + ) { + continue; + } + booleans.add(contralTime.inControlTime()); +// if (!contralTime.inControlTime()) { +// Log.e(TAG, "inDayContralTime: " + contralTime + " true"); +// return true; +// } + } + Log.e(TAG, "inDayContralTime: " + booleans); + return !booleans.contains(false); +// Log.e(TAG, "inDayContralTime: false"); +// return false; + } + + public static String getDayTimeString(Context context) { +// ContralTime contralTime = getDayContralTime(context); + List contralTimes = TimeUtils.getDayContralTimeList(context); + StringBuilder stringBuilder = new StringBuilder(); + if (contralTimes != null) { + for (ContralTime contralTime : contralTimes) { + stringBuilder.append(contralTime).append("\t"); + } + } + return stringBuilder.toString(); + } + + /** * 是否在管控时间内 * @@ -194,7 +496,6 @@ public class TimeUtils { } } - /** * @return 根据日期取得星期几 */ @@ -210,6 +511,140 @@ public class TimeUtils { return weeks[weekIndex]; } + /** + * 获取控制时间文本 + * + * @param context + * @return + */ + @Deprecated + public static String getNowTimeString(Context context) { + ContralTime work = getWorkingDayContralTime(context); + ContralTime week = getWeekDayContralTime(context); + StringBuilder stringBuilder = new StringBuilder(); + if (work != null) { + stringBuilder.append("周一至周五:").append(work).append("\n"); + } + if (week != null) { + stringBuilder.append("周末:").append(week); + } + return stringBuilder.toString(); + } + + /** + * 设置为空 + * + * @param context + */ + public static void setEmpty(Context context) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + mmkv.encode(START_TIME_KEY, "00:00"); + mmkv.encode(END_TIME_KEY, "00:00"); + mmkv.encode(WEEK_START_TIME_KEY, "00:00"); + mmkv.encode(WEEK_END_TIME_KEY, "00:00"); + Intent intent = new Intent(); + intent.setAction(ManagerService.ACTION_UPDATE); + context.sendBroadcast(intent); + } + + /** + * 获取格式化后的时间 + * + * @param time 时间戳 + * @return 时间戳格式化文本 + */ + public static String getDate(long time) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String finaWayDate = sdf.format(time); + Log.e(TAG, "getDate: " + finaWayDate); + return finaWayDate; + } + + /** + * 获取周几 + * + * @return 周几的数字 + */ + public static int getWeekDay() { + long time = System.currentTimeMillis(); + Log.e(TAG, "getWeekDay: " + time); + return getWeekDay(time); + } + + /** + * 获取周几 + * + * @param time 时间戳 + * @return 周几的数字 1-7 + */ + public static int getWeekDay(long time) { + getDate(time); + Calendar now = Calendar.getInstance(); + now.setTimeInMillis(time); + //一周第一天是否为星期天 + boolean isFirstSunday = (now.getFirstDayOfWeek() == Calendar.SUNDAY); + //获取周几 + int weekDay = now.get(Calendar.DAY_OF_WEEK); + //若一周第一天为星期天,则-1 + if (isFirstSunday) { + weekDay = weekDay - 1; + if (weekDay == 0) { + weekDay = 7; + } + } + return weekDay; + } + + private String[] weekDays = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"}; + + /** + * 获取星期几 + * + * @return 星期的文本 + */ + public String getWeekDayString() { + return weekDays[getWeekDay() - 1]; + } + + /** + * 获取星期几 + * + * @param time 时间戳 + * @return 星期的文本 + */ + public String getWeekDayString(long time) { + return weekDays[getWeekDay(time) - 1]; + } + + /** + * 是否未周末 + * + * @return 周末返回ture 工作日返回false + */ + public static boolean inWeekDay() { + long time = System.currentTimeMillis(); + return inWeekDay(time); + } + + /** + * 是否未周末 + * + * @param time 时间戳 + * @return 周末返回ture 工作日返回false + */ + public static boolean inWeekDay(long time) { + int weekDay = getWeekDay(time); + if (weekDay > 5) { + return true; + } else { + return false; + } + } + + public static void setSystemTime(long time) { + SystemClock.setCurrentTimeMillis(time); + } + public static class ContralTime { //format HH:mm String startTime; @@ -253,13 +688,16 @@ public class TimeUtils { return df.format(new Date(time)); } + public boolean inControlTime() { long time = System.currentTimeMillis(); return inControlTime(time); } public boolean inControlTime(long time) { - return inControlTime(df.format(new Date(time))); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); + sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + return inControlTime(sdf.format(new Date(time))); } public boolean inControlTime(String time) { @@ -280,8 +718,7 @@ public class TimeUtils { } Log.e(TAG, "inControlTime: " + (startDate.getTime() - MINUTE_TIME)); assert nowDate != null; -// if (nowDate.getTime() <= startDate.getTime() - MINUTE_TIME || nowDate.getTime() >= endDate.getTime()) { - if (nowDate.getTime() >= startDate.getTime() && nowDate.getTime() <= endDate.getTime()) { + if (nowDate.getTime() <= startDate.getTime() - MINUTE_TIME || nowDate.getTime() >= endDate.getTime()) { return true; } else { return false; @@ -295,8 +732,221 @@ public class TimeUtils { @NonNull @Override public String toString() { - return startTime + "\t-\t" + endTime; + return startTime + " - " + endTime; } } + private static SntpClient mNtpClient; + + public static long getTimeFromNtpServer(String hostAddress) { + Log.d(TAG, "getTimeFromNtpServer()"); + if (TextUtils.isEmpty(hostAddress)) { + Log.e(TAG, "Ntp host is null."); + return -1; + } + if (mNtpClient == null) { + mNtpClient = new SntpClient(); + } + boolean isSuccessful = mNtpClient.requestTime(hostAddress, 20000); + Log.e(TAG, "requestTime:" + isSuccessful); + if (isSuccessful) { + long now = mNtpClient.getNtpTime();//now就是获取的时间 + return now; + } else { + + } + return -1; + } + + public static class SntpClient { + private static final String TAG = "SntpClient"; + + private static final int REFERENCE_TIME_OFFSET = 16; + private static final int ORIGINATE_TIME_OFFSET = 24; + private static final int RECEIVE_TIME_OFFSET = 32; + private static final int TRANSMIT_TIME_OFFSET = 40; + private static final int NTP_PACKET_SIZE = 48; + + private static final int NTP_PORT = 123; + private static final int NTP_MODE_CLIENT = 3; + private static final int NTP_VERSION = 3; + + // Number of seconds between Jan 1, 1900 and Jan 1, 1970 + // 70 years plus 17 leap days + private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L; + + // system time computed from NTP server response + private long mNtpTime; + + // value of SystemClock.elapsedRealtime() corresponding to mNtpTime + private long mNtpTimeReference; + + // round trip time in milliseconds + private long mRoundTripTime; + + /** + * Sends an SNTP request to the given host and processes the response. + * + * @param host host name of the server. + * @param timeout network timeout in milliseconds. + * @return true if the transaction was successful. + */ + public boolean requestTime(String host, int timeout) { + DatagramSocket socket = null; + try { + socket = new DatagramSocket(); + socket.setSoTimeout(timeout); + InetAddress address = InetAddress.getByName(host); + byte[] buffer = new byte[NTP_PACKET_SIZE]; + DatagramPacket request = new DatagramPacket(buffer, + buffer.length, address, NTP_PORT); + + // set mode = 3 (client) and version = 3 + // mode is in low 3 bits of first byte + // version is in bits 3-5 of first byte + buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3); + + // get current time and write it to the request packet + long requestTime = System.currentTimeMillis(); + Log.d(TAG, "RequestTime:" + new Date(requestTime)); + long requestTicks = SystemClock.elapsedRealtime(); + writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime); + + socket.send(request); + + // read the response + DatagramPacket response = new DatagramPacket(buffer, + buffer.length); + socket.receive(response); + long responseTicks = SystemClock.elapsedRealtime(); + long responseTime = requestTime + + (responseTicks - requestTicks); + + // extract the results + long originateTime = readTimeStamp(buffer, + ORIGINATE_TIME_OFFSET); + long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET); + long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET); + long roundTripTime = responseTicks - requestTicks + - (transmitTime - receiveTime); + // receiveTime = originateTime + transit + skew + // responseTime = transmitTime + transit - skew + // clockOffset = ((receiveTime - originateTime) + (transmitTime + // - responseTime))/2 + // = ((originateTime + transit + skew - originateTime) + + // (transmitTime - (transmitTime + transit - skew)))/2 + // = ((transit + skew) + (transmitTime - transmitTime - transit + // + skew))/2 + // = (transit + skew - transit + skew)/2 + // = (2 * skew)/2 = skew + long clockOffset = ((receiveTime - requestTime) + (transmitTime - System.currentTimeMillis())) / 2; + // if (false) Log.d(TAG, "round trip: " + roundTripTime + + // " ms"); + // if (false) Log.d(TAG, "clock offset: " + clockOffset + + // " ms"); + + // save our results - use the times on this side of the network + // latency + // (response rather than request time) + mNtpTime = System.currentTimeMillis() + clockOffset; +// mNtpTime = transmitTime; + mNtpTimeReference = responseTicks; + mRoundTripTime = roundTripTime; + } catch (Exception e) { + if (false) + Log.e(TAG, "request time failed:" + e); + e.printStackTrace(); + return false; + } finally { + if (socket != null) { + socket.close(); + } + } + + return true; + } + + /** + * Returns the time computed from the NTP transaction. + * + * @return time value computed from NTP server response. + */ + public long getNtpTime() { + return mNtpTime; + } + + /** + * Returns the reference clock value (value of + * SystemClock.elapsedRealtime()) corresponding to the NTP time. + * + * @return reference clock corresponding to the NTP time. + */ + public long getNtpTimeReference() { + return mNtpTimeReference; + } + + /** + * Returns the round trip time of the NTP transaction + * + * @return round trip time in milliseconds. + */ + public long getRoundTripTime() { + return mRoundTripTime; + } + + /** + * Reads an unsigned 32 bit big endian number from the given offset in + * the buffer. + */ + private long read32(byte[] buffer, int offset) { + byte b0 = buffer[offset]; + byte b1 = buffer[offset + 1]; + byte b2 = buffer[offset + 2]; + byte b3 = buffer[offset + 3]; + + // convert signed bytes to unsigned values + int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0); + int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1); + int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2); + int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3); + + return ((long) i0 << 24) + ((long) i1 << 16) + ((long) i2 << 8) + + (long) i3; + } + + /** + * Reads the NTP time stamp at the given offset in the buffer and + * returns it as a system time (milliseconds since January 1, 1970). + */ + private long readTimeStamp(byte[] buffer, int offset) { + long seconds = read32(buffer, offset); + long fraction = read32(buffer, offset + 4); + return ((seconds - OFFSET_1900_TO_1970) * 1000) + + ((fraction * 1000L) / 0x100000000L); + } + + /** + * Writes system time (milliseconds since January 1, 1970) as an NTP + * time stamp at the given offset in the buffer. + */ + private void writeTimeStamp(byte[] buffer, int offset, long time) { + long seconds = time / 1000L; + long milliseconds = time - seconds * 1000L; + seconds += OFFSET_1900_TO_1970; + + // write seconds in big endian format + buffer[offset++] = (byte) (seconds >> 24); + buffer[offset++] = (byte) (seconds >> 16); + buffer[offset++] = (byte) (seconds >> 8); + buffer[offset++] = (byte) (seconds >> 0); + + long fraction = milliseconds * 0x100000000L / 1000L; + // write fraction in big endian format + buffer[offset++] = (byte) (fraction >> 24); + buffer[offset++] = (byte) (fraction >> 16); + buffer[offset++] = (byte) (fraction >> 8); + // low order bits should be random data + buffer[offset++] = (byte) (Math.random() * 255.0); + } + } } diff --git a/app/src/main/java/com/xwad/os/utils/Utils.java b/app/src/main/java/com/xwad/os/utils/Utils.java index 48d6e18..825463e 100644 --- a/app/src/main/java/com/xwad/os/utils/Utils.java +++ b/app/src/main/java/com/xwad/os/utils/Utils.java @@ -2,6 +2,9 @@ package com.xwad.os.utils; import android.Manifest; import android.app.Activity; +import android.app.ActivityManager; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; @@ -14,13 +17,19 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; +import android.media.AudioManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.Build; import android.os.Environment; import android.os.PowerManager; +import android.os.StatFs; +import android.os.SystemClock; +import android.provider.Settings; +import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.text.format.Formatter; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; @@ -28,18 +37,23 @@ import android.view.WindowManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import com.google.gson.JsonObject; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import com.tencent.mmkv.MMKV; import com.xwad.os.BuildConfig; import com.xwad.os.R; +import com.xwad.os.config.CommonConfig; import com.xwad.os.mdm.AdminManager; +import com.xwad.os.network.NetInterfaceManager; import java.io.BufferedReader; import java.io.File; +import java.io.FileFilter; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; @@ -47,11 +61,17 @@ import java.io.LineNumberReader; import java.io.Reader; import java.lang.reflect.Method; import java.net.NetworkInterface; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import static android.content.Context.WIFI_SERVICE; public class Utils { private static final String TAG = "Utils"; @@ -333,6 +353,60 @@ public class Utils { return "未获取到设备Mac地址"; } + public static String getIMEI(Context context) { + String IMEI = "unknown"; + String IMEI1, IMEI2, IMEI3; + //获取手机设备号 + TelephonyManager TelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + //8.0及以后版本获取 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + IMEI = TelephonyMgr.getDeviceId(); + } catch (Exception e) { + Log.e(TAG, "getIMEI: " + e.getMessage()); + } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { +// try { +// Method method = TelephonyMgr.getClass().getMethod("getImei"); +// IMEI = (String) method.invoke(TelephonyMgr); +// } catch (Exception e) { +// e.printStackTrace(); +// Log.e("getIMEI", e.getMessage()); +// } +// IMEI = TelephonyMgr.getDeviceId(); + +// } else {//9.0到10.0获取 + IMEI = Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); + } +// Log.e("IMEI:", "IMEI: " + IMEI); + if (null == IMEI) { + return "-"; + } else { + return IMEI.toUpperCase(); + } + } + + /** + * 获取电池容量 + * + * @param context + * @return + */ + public static double getBatterymAh(Context context) { + Object mPowerProfile; + double batteryCapacity = 0; //电池的容量mAh + final String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile"; + try { + mPowerProfile = Class.forName(POWER_PROFILE_CLASS).getConstructor(Context.class).newInstance(context); + batteryCapacity = (double) Class.forName(POWER_PROFILE_CLASS).getMethod("getBatteryCapacity").invoke(mPowerProfile); + Log.e("getBattery", "battery mAh: " + batteryCapacity); + } catch (Exception e) { + Log.e("getBattery", "get batteryCapacity mAh error:" + batteryCapacity); + e.printStackTrace(); + } + return batteryCapacity; + } + /** * 获取电量 * @@ -571,6 +645,28 @@ public class Utils { return macSerial; } + // MD5 设备地址标识 + public static String getMAC(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 如果当前设备系统大于等于6.0 使用下面的方法 + return getMac(); + } else { + try { + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + // 获取MAC地址 + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + String mac = wifiInfo.getMacAddress(); + if (null == mac) { + // 未获取到 + mac = ""; + } + return mac; + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + } + public static String loadFileAsString(String fileName) throws Exception { FileReader reader = new FileReader(fileName); String text = loadReaderAsString(reader); @@ -605,4 +701,287 @@ public class Utils { } return cachePath; } + + public static String getMachine(Context context) { + MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + String device = Build.MODEL;//机型 + String imei = getIMEI(context); + Log.e(TAG, "getMachine: " + imei); + String system_version = Build.VERSION.RELEASE; + String firmware_version = JgyUtils.getRomVersion(); + String rom = JgyUtils.getCustomVersion(); + String pushid = mMMKV.decodeString(CommonConfig.ALIYUN_PUSH_ID, ""); + String screen_rate = getAndroiodScreenProperty(context); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("device", device); + jsonObject.addProperty("imei", imei); + jsonObject.addProperty("system_version", system_version); + jsonObject.addProperty("firmware_version", firmware_version); + jsonObject.addProperty("rom", rom); + jsonObject.addProperty("push_id", pushid); + jsonObject.addProperty("screen_rate", screen_rate); + return jsonObject.toString(); + } + + public static String getHardware(Context context) { + MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + int electric = getBattery(context); + int charging = getIsCharging(context); + String memory = Formatter.formatFileSize(context, getUsedMemory(context)) + "\t 已用" + "/" + "共" + Formatter.formatFileSize(context, getTotalMemory(context)); + Log.e(TAG, "getHardware: memory = " + memory); + int use_ram = (int) ((float) (1.0 * getUsedMemory(context)) / (1.0 * getTotalMemory(context)) * 100); + Log.e(TAG, "getHardware: use_ram = " + use_ram); + String storage = getUsedSize(context) + "/" + getDataTotalSize(context); + Log.e(TAG, "getHardware: storage = " + storage); + double use_space = getUse_space(context); + Log.e(TAG, "getHardware: use_space = " + use_space); + long wifi_time = mmkv.decodeLong("wifi_last_connect_time", 0L) / 1000; + Log.e(TAG, "getHardware: wifi_time" + wifi_time); + int CPU = getNumCores(); + WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE); + // WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + WifiInfo info = wifiManager.getConnectionInfo(); + + AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + //最大音量 + int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + Log.e(TAG, "getHardware: maxVolume = " + maxVolume); + //音量 + int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + Log.e(TAG, "getHardware: streamVolume = " + streamVolume); + int currentVolume = (int) (((double) streamVolume / (double) maxVolume) * 100f); + Log.e(TAG, "getHardware: currentVolume = " + currentVolume); + + //亮度 + int brightness = Settings.System.getInt(context.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 0); + Log.e(TAG, "getHardware: brightness = " + brightness); + int gamma = BrightnessUtils.convertLinearToGamma(brightness, 1, 255); + Log.e(TAG, "getHardware: gamma = " + gamma); + long percentage = Math.round((((double) gamma / 65535) * 100f)); + Log.e(TAG, "getHardware: percentage = " + percentage); + + //字体大小 + float fontScale = Settings.System.getFloat(context.getContentResolver(), Settings.System.FONT_SCALE, 0.0f); + Log.e(TAG, "getHardware: fontScale = " + fontScale); + List mEntries = Arrays.asList(context.getResources().getStringArray(R.array.entries_font_size)); + List strEntryValues = Arrays.asList(context.getResources().getStringArray(R.array.entryvalues_font_size)); + String font_size; + int index = strEntryValues.indexOf(String.valueOf(fontScale)); + if (index == -1) { + font_size = "默认"; + } else { + font_size = mEntries.get(index); + } + Log.e(TAG, "getHardware: font_size = " + font_size); + + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("electric", electric); + jsonObject.addProperty("charging", charging); + jsonObject.addProperty("memory", memory); + jsonObject.addProperty("mac", getMAC(context)); + jsonObject.addProperty("storage", storage); + jsonObject.addProperty("is_wifi", JgyUtils.getInstance().isWifiConnect()); + jsonObject.addProperty("CPU", CPU + "核"); + jsonObject.addProperty("use_space", use_space); + jsonObject.addProperty("use_ram", use_ram); + jsonObject.addProperty("wifi_ssid", getWifiSSID(context)); + jsonObject.addProperty("wifi_time", wifi_time); + jsonObject.addProperty("boot_time", SystemClock.elapsedRealtime()); + jsonObject.addProperty("battery_capacity", getBatterymAh(context)); + jsonObject.addProperty("wifi_signal", info.getRssi()); + jsonObject.addProperty("bluetooth", getBluetoothList()); + jsonObject.addProperty("current_volume", currentVolume); + jsonObject.addProperty("current_brightness", percentage); + jsonObject.addProperty("font_scale", font_size); + jsonObject.addProperty("ip", MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE).decodeString(NetInterfaceManager.WHOIS_IP, "未知")); + + Log.e(TAG, "getHardware: " + jsonObject.toString()); + return jsonObject.toString(); + } + + public static String getWifiSSID(Context context) { + WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + if (wifiInfo != null) { + return wifiInfo.getSSID(); + } else { + return ""; + } + } + + public static String getBluetoothList() { + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter == null) { + return "没有蓝牙设备"; + } else { + if (!bluetoothAdapter.isEnabled())//判断蓝牙设备是否已开起 + { + return "蓝牙未开启"; +// //开起蓝牙设备 +// Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); +// context.startActivity(intent); + } else { + Set devices = bluetoothAdapter.getBondedDevices(); + StringBuilder stringBuilder = new StringBuilder(); + for (Iterator iterator = devices.iterator(); iterator.hasNext(); ) { + BluetoothDevice device = iterator.next(); + stringBuilder.append(device.getAlias()).append(";"); + } + Log.e(TAG, "getBluetoothList: " + stringBuilder.toString()); + return stringBuilder.toString(); + } + } + } + + public static int getBattery(Context context) { + try { + BatteryManager batteryManager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE); + return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + } catch (Exception e) { + Log.e("getBattery", "getBattery" + e.getMessage()); + } + return 0; + } + + public static int getIsCharging(Context context) { + IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + Intent batteryStatus = context.registerReceiver(null, ifilter); + // Are we charging / charged? + int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1); + boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || + status == BatteryManager.BATTERY_STATUS_FULL; + + // How are we charging? +// int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); +// boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB; +// boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC; + if (isCharging) { + return 1; + } else { + return 0; + } + } + + /** + * @param context + * @return 已经使用 + */ + public static long getUsedMemory(Context context) { + ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); + activityManager.getMemoryInfo(memoryInfo); + long freeMem = memoryInfo.totalMem - memoryInfo.availMem; +// Log.e("getHardware", "getFreeMemory: " + freeMem); + return freeMem; + } + + /** + * 描述:获取可用内存. + * + * @param context + * @return + */ + public static long getAvailMemory(Context context) { + // 获取android当前可用内存大小 + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); + activityManager.getMemoryInfo(memoryInfo); + // 当前系统可用内存 ,将获得的内存大小规格化 + + return memoryInfo.availMem; + } + + /** + * 描述:总内存. + * + * @param context + * @return + */ + public static long getTotalMemory(Context context) { + // 系统内存信息文件 + String file = "/proc/meminfo"; + String memInfo; + String[] strs; + long memory = 0; + + try { + FileReader fileReader = new FileReader(file); + BufferedReader bufferedReader = new BufferedReader(fileReader, 8192); + // 读取meminfo第一行,系统内存大小 + memInfo = bufferedReader.readLine(); + strs = memInfo.split("\\s+"); +// for (String str : strs) { +// L.d(AppUtil.class, str + "\t"); +// } + // 获得系统总内存,单位KB + memory = Integer.valueOf(strs[1]).intValue(); + bufferedReader.close(); + } catch (Exception e) { + e.printStackTrace(); + } + // Byte转位KB或MB + return memory * 1024; + } + + public static float getUse_space(Context context) { + StatFs sf = new StatFs(context.getCacheDir().getAbsolutePath()); + long availableSize = sf.getAvailableBytes(); + Log.e(TAG, "getUse_space: availableSize = " + availableSize); + long blockSize = sf.getBlockSize(); + Log.e(TAG, "getUse_space: blockSize = " + blockSize); + long totalBlocks = sf.getBlockCount(); + Log.e(TAG, "getUse_space: totalBlocks = " + totalBlocks); + + return (float) 100.0 * ((blockSize * totalBlocks) - availableSize) / (blockSize * totalBlocks); + } + + public static String getRemnantSize(Context context) { + StatFs sf = new StatFs(context.getCacheDir().getAbsolutePath()); + long availableSize = sf.getAvailableBytes(); + return Formatter.formatFileSize(context, availableSize); + } + + public static String getUsedSize(Context context) { + StatFs sf = new StatFs(context.getCacheDir().getAbsolutePath()); + long availableSize = sf.getAvailableBytes(); + long blockSize = sf.getBlockSize(); + long totalBlocks = sf.getBlockCount(); + return Formatter.formatFileSize(context, blockSize * totalBlocks - availableSize); + } + + public static String getDataTotalSize(Context context) { + StatFs sf = new StatFs(context.getCacheDir().getAbsolutePath()); + long blockSize = sf.getBlockSize(); + long totalBlocks = sf.getBlockCount(); + return Formatter.formatFileSize(context, blockSize * totalBlocks); + } + + private static int getNumCores() { + // Private Class to display only CPU devices in the directory listing + class CpuFilter implements FileFilter { + @Override + public boolean accept(File pathname) { + // Check if filename is "cpu", followed by a single digit number + if (Pattern.matches("cpu[0-9]", pathname.getName())) { + return true; + } + return false; + } + } + + try { + // Get directory containing CPU info + File dir = new File("/sys/devices/system/cpu/"); + // Filter to only list the devices we care about + File[] files = dir.listFiles(new CpuFilter()); + // Return the number of cores (virtual CPU devices) + return files.length; + } catch (Exception e) { + // Default to return 1 core + return 1; + } + } } diff --git a/app/src/main/res/drawable-hdpi/icon_homework.png b/app/src/main/res/drawable-hdpi/icon_homework.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2ac25e3d7db696fcae72040001ac36c247ca66 GIT binary patch literal 33934 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

L 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 Q-~a#s07*qoM6N<$g7b#1ssI20 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/bt_disable.xml b/app/src/main/res/drawable/bt_disable.xml new file mode 100644 index 0000000..90c8cfd --- /dev/null +++ b/app/src/main/res/drawable/bt_disable.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bt_main_background.xml b/app/src/main/res/drawable/bt_main_background.xml new file mode 100644 index 0000000..7233ecf --- /dev/null +++ b/app/src/main/res/drawable/bt_main_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bt_pressed.xml b/app/src/main/res/drawable/bt_pressed.xml new file mode 100644 index 0000000..9b667f9 --- /dev/null +++ b/app/src/main/res/drawable/bt_pressed.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/debug_edit_background.xml b/app/src/main/res/drawable/debug_edit_background.xml new file mode 100644 index 0000000..6130919 --- /dev/null +++ b/app/src/main/res/drawable/debug_edit_background.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/home_card_bg.xml b/app/src/main/res/drawable/home_card_bg.xml new file mode 100644 index 0000000..86f1dd3 --- /dev/null +++ b/app/src/main/res/drawable/home_card_bg.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_debug.xml b/app/src/main/res/layout/activity_debug.xml new file mode 100644 index 0000000..75aa6e4 --- /dev/null +++ b/app/src/main/res/layout/activity_debug.xml @@ -0,0 +1,514 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index aee66b2..30dbf4e 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -39,6 +39,24 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + + android:layout_marginStart="3dp" + android:visibility="gone" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_update.xml b/app/src/main/res/layout/activity_update.xml index a5207e6..3b953e8 100644 --- a/app/src/main/res/layout/activity_update.xml +++ b/app/src/main/res/layout/activity_update.xml @@ -8,7 +8,7 @@ + type="com.xwad.os.bean.AppInfo" /> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/eula_layout.xml b/app/src/main/res/layout/eula_layout.xml new file mode 100644 index 0000000..b415519 --- /dev/null +++ b/app/src/main/res/layout/eula_layout.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/license_layout.xml b/app/src/main/res/layout/license_layout.xml new file mode 100644 index 0000000..f461a2a --- /dev/null +++ b/app/src/main/res/layout/license_layout.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + +