From d1f392b839fb325437203b21274d30661d98188d Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Sat, 10 Jan 2026 17:58:48 +0800 Subject: [PATCH] =?UTF-8?q?version:1.0.0=20fix:=20update:=E6=9B=B4?= =?UTF-8?q?=E6=8D=A2=E4=B8=BA=E8=8D=A3=E8=80=80mdm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 10 +- app/libs/CSDK_TBY11_AiYouDu_250312.jar | Bin 8926 -> 0 bytes app/libs/magic-android-31.35.6.300.jar | Bin 0 -> 36212 bytes app/src/main/AndroidManifest.xml | 13 + .../xwad/os/activity/edit/EditActivity.java | 2 - .../xwad/os/activity/main/MainActivity.java | 2 - .../selectegrade/SelecteGradeActivity.java | 4 - .../xwad/os/activity/user/UserActivity.java | 1 - .../com/xwad/os/base/BaseApplication.java | 6 +- .../java/com/xwad/os/config/CommonConfig.java | 20 + .../xwad/os/fragment/user/UserViewModel.java | 5 - .../usercenter/device/DeviceFragment.java | 3 - .../usercenter/info/InfoFragment.java | 2 - .../java/com/xwad/os/mdm/AdminManager.java | 2031 +++++++++++++++++ .../os/receiver/AoleDeviceAdminReceiver.java | 20 + .../main/java/com/xwad/os/utils/ApkUtils.java | 141 ++ .../main/java/com/xwad/os/utils/JgyUtils.java | 1322 +++++++++++ .../com/xwad/os/utils/LenovoCsdkUtil.java | 83 - .../main/java/com/xwad/os/utils/Utils.java | 261 ++- app/src/main/res/values/strings.xml | 42 + app/src/main/res/xml/device_admin_sample.xml | 14 + settings.gradle | 2 +- 22 files changed, 3839 insertions(+), 145 deletions(-) delete mode 100644 app/libs/CSDK_TBY11_AiYouDu_250312.jar create mode 100644 app/libs/magic-android-31.35.6.300.jar create mode 100644 app/src/main/java/com/xwad/os/mdm/AdminManager.java create mode 100644 app/src/main/java/com/xwad/os/receiver/AoleDeviceAdminReceiver.java create mode 100644 app/src/main/java/com/xwad/os/utils/JgyUtils.java delete mode 100644 app/src/main/java/com/xwad/os/utils/LenovoCsdkUtil.java create mode 100644 app/src/main/res/xml/device_admin_sample.xml diff --git a/app/build.gradle b/app/build.gradle index 8b41c97..bb609de 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,11 +13,12 @@ android { defaultConfig { applicationId "com.xwad.os" + //There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature. minSdkVersion 23 targetSdkVersion 29 - versionCode 24 - versionName "1.2.3" + versionCode 1 + versionName "1.0.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -131,8 +132,9 @@ android { dependencies { // implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation files('libs/CSDK_TBY11_AiYouDu_250312.jar') - compileOnly files('libs/framework.jar') +// compileOnly files('libs/framework.jar') + compileOnly files('libs/magic-android-31.35.6.300.jar') + implementation project(path: ':niceimageview') implementation project(path: ':FlycoTabLayoutZ_Lib') implementation project(path: ':verification-view') diff --git a/app/libs/CSDK_TBY11_AiYouDu_250312.jar b/app/libs/CSDK_TBY11_AiYouDu_250312.jar deleted file mode 100644 index abff99a61e6b0dda8bb8527eb264dbad6ce0b229..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8926 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 literal 0 HcmV?d00001 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 86bdb75..94b8c86 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -280,6 +280,19 @@ android:enabled="true" android:exported="true" /> + + + + + + + { diff --git a/app/src/main/java/com/xwad/os/fragment/usercenter/info/InfoFragment.java b/app/src/main/java/com/xwad/os/fragment/usercenter/info/InfoFragment.java index 3086038..af4fe54 100644 --- a/app/src/main/java/com/xwad/os/fragment/usercenter/info/InfoFragment.java +++ b/app/src/main/java/com/xwad/os/fragment/usercenter/info/InfoFragment.java @@ -19,9 +19,7 @@ import com.xwad.os.bean.SnInfo; import com.xwad.os.config.CommonConfig; import com.xwad.os.databinding.FragmentInfoBinding; import com.xwad.os.manager.DeviceSNManager; -import com.xwad.os.manager.RemoteManager; import com.xwad.os.utils.ActivationUtil; -import com.xwad.os.utils.LenovoCsdkUtil; import java.util.HashMap; import java.util.Map; diff --git a/app/src/main/java/com/xwad/os/mdm/AdminManager.java b/app/src/main/java/com/xwad/os/mdm/AdminManager.java new file mode 100644 index 0000000..34af8bb --- /dev/null +++ b/app/src/main/java/com/xwad/os/mdm/AdminManager.java @@ -0,0 +1,2031 @@ +package com.xwad.os.mdm; + +import android.annotation.SuppressLint; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; + +import androidx.core.content.FileProvider; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.hihonor.android.app.admin.DeviceApplicationManager; +import com.hihonor.android.app.admin.DeviceBluetoothManager; +import com.hihonor.android.app.admin.DeviceCameraManager; +import com.hihonor.android.app.admin.DeviceControlManager; +import com.hihonor.android.app.admin.DeviceEmailManager; +import com.hihonor.android.app.admin.DeviceFirewallManager; +import com.hihonor.android.app.admin.DeviceHwSystemManager; +import com.hihonor.android.app.admin.DeviceInfraredManager; +import com.hihonor.android.app.admin.DeviceLocationManager; +import com.hihonor.android.app.admin.DeviceNetworkManager; +import com.hihonor.android.app.admin.DeviceP2PManager; +import com.hihonor.android.app.admin.DevicePackageManager; +import com.hihonor.android.app.admin.DevicePasswordManager; +import com.hihonor.android.app.admin.DevicePhoneManager; +import com.hihonor.android.app.admin.DeviceRestrictionManager; +import com.hihonor.android.app.admin.DeviceSettingsManager; +import com.hihonor.android.app.admin.DeviceStorageManagerEx; +import com.hihonor.android.app.admin.DeviceTelephonyManager; +import com.hihonor.android.app.admin.DeviceVpnManager; +import com.hihonor.android.app.admin.DeviceWifiPolicyManager; +import com.hjq.toast.Toaster; +import com.tencent.mmkv.MMKV; +import com.xwad.os.BuildConfig; +import com.xwad.os.config.CommonConfig; +import com.xwad.os.gson.GsonUtils; +import com.xwad.os.receiver.AoleDeviceAdminReceiver; +import com.xwad.os.utils.JgyUtils; +import com.xwad.os.utils.Utils; + +import java.io.File; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +public class AdminManager { + private static final String TAG = "AdminManager"; + + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + private static final int STATUS_DISABLE = 0; + private static final int STATUS_ENABLE = 1; + + @SuppressLint("StaticFieldLeak") + private static AdminManager sInstance; + + private Context mContext; + private ComponentName mAdminName; + private DevicePolicyManager mDevicePolicyManager; + + /*设备应用程序管理类*/ + private DeviceApplicationManager mDeviceApplicationManager; + /*蓝牙相关的管理类*/ + private DeviceBluetoothManager mDeviceBluetoothManager; + /*相机相关的类*/ + private DeviceCameraManager mDeviceCameraManager; + /*设备控制相关的类*/ + private DeviceControlManager mDeviceControlManager; + /*邮箱相关的管理类*/ + private DeviceEmailManager mDeviceEmailManager; + /*防火墙相关管理类*/ + private DeviceFirewallManager mDeviceFirewallManager; + /*系统相关类*/ + private DeviceHwSystemManager mDeviceHwSystemManager; + /*设备红外管理类*/ + private DeviceInfraredManager mDeviceInfraredManager; + /*地理位置相关的类*/ + private DeviceLocationManager mDeviceLocationManager; + /*网络管理相关的类*/ + private DeviceNetworkManager mDeviceNetworkManager; + /*Wifi 直连权限管理授权*/ + private DeviceP2PManager mDeviceP2PManager; + /*设备包管理类*/ + private DevicePackageManager mDevicePackageManager; + /*密码相关类*/ + private DevicePasswordManager mDevicePasswordManager; + /*设备通话管理类*/ + private DevicePhoneManager mDevicePhoneManager; + /*禁用/启用管理类*/ + private DeviceRestrictionManager mDeviceRestrictionManager; + /*设置相关类*/ + private DeviceSettingsManager mDeviceSettingsManager; + /*设备存储管理类*/ + private DeviceStorageManagerEx mDeviceStorageManagerEx; + /*通讯服务管理类*/ + private DeviceTelephonyManager mDeviceTelephonyManager; + /*智慧屏相关管理类*/ +// private DeviceTelevisionManager mDeviceTelevisionManager; + /*VPN 相关管理类*/ + private DeviceVpnManager mDeviceVpnManager; + /*WIFI 管理相关类*/ + private DeviceWifiPolicyManager mDeviceWifiPolicyManager; + + + private AdminManager(Context context) { + if (context == null) { + throw new RuntimeException("Context is NULL"); + } + 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(); +// this.mDeviceTelevisionManager = new DeviceTelevisionManager(); + this.mDeviceVpnManager = new DeviceVpnManager(); + this.mDeviceWifiPolicyManager = new DeviceWifiPolicyManager(); + removeAllInstallPackageTrustList(); + Log.e(TAG, "AdminManager: setCallStatusNotificationApp = " + setCallStatusNotificationApp(BuildConfig.APPLICATION_ID)); + getCallStatusNotificationApp(); + } + + public static void init(Context context) { + if (sInstance == null) { + Log.e(TAG, "init: "); + sInstance = new AdminManager(context); + } + } + + public static AdminManager getInstance() { + if (sInstance == null) { + throw new IllegalStateException("You must be init AdminManager first"); + } + return sInstance; + } + + public ComponentName getAdminName() { + return mAdminName; + } + + public DeviceApplicationManager getDeviceApplicationManager() { + return mDeviceApplicationManager; + } + + public DeviceBluetoothManager getDeviceBluetoothManager() { + return mDeviceBluetoothManager; + } + + public DeviceCameraManager getDeviceCameraManager() { + return mDeviceCameraManager; + } + + public DeviceControlManager getDeviceControlManager() { + return mDeviceControlManager; + } + + public DeviceEmailManager getDeviceEmailManager() { + return mDeviceEmailManager; + } + + public DeviceFirewallManager getDeviceFirewallManager() { + return mDeviceFirewallManager; + } + + public DeviceHwSystemManager getDeviceHwSystemManager() { + return mDeviceHwSystemManager; + } + + public DeviceInfraredManager getDeviceInfraredManager() { + return mDeviceInfraredManager; + } + + public DeviceLocationManager getDeviceLocationManager() { + return mDeviceLocationManager; + } + + public DeviceNetworkManager getDeviceNetworkManager() { + return mDeviceNetworkManager; + } + + public DeviceP2PManager getDeviceP2PManager() { + return mDeviceP2PManager; + } + + public DevicePackageManager getDevicePackageManager() { + return mDevicePackageManager; + } + + public DevicePasswordManager getDevicePasswordManager() { + return mDevicePasswordManager; + } + + public DevicePhoneManager getDevicePhoneManager() { + return mDevicePhoneManager; + } + + public DeviceRestrictionManager getDeviceRestrictionManager() { + return mDeviceRestrictionManager; + } + + public DeviceSettingsManager getDeviceSettingsManager() { + return mDeviceSettingsManager; + } + + public DeviceStorageManagerEx getDeviceStorageManagerEx() { + return mDeviceStorageManagerEx; + } + + public DeviceTelephonyManager getDeviceTelephonyManager() { + return mDeviceTelephonyManager; + } + +// public DeviceTelevisionManager getDeviceTelevisionManager() { +// return mDeviceTelevisionManager; +// } + + public DeviceVpnManager getDeviceVpnManager() { + return mDeviceVpnManager; + } + + public DeviceWifiPolicyManager getDeviceWifiPolicyManager() { + return mDeviceWifiPolicyManager; + } + + public String getSerial() { + String sn = ""; + DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); + // dpm.setPermissionGrantState(componentName, packageName, Manifest.permission.READ_PHONE_STATE, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + try { + dpm.setPermissionPolicy(mAdminName, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); + } catch (Exception e) { + Log.e(TAG, "getSerial: " + e.getMessage()); + } + } +// requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, PackageManager.PERMISSION_GRANTED); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + sn = Build.getSerial(); + } catch (Exception e) { + Log.e(TAG, "getSerial: " + e.getMessage()); + } + } + return sn; + } + + public boolean isActiveMe() { + if (mDevicePolicyManager == null) { + return false; + } else { + return mDevicePolicyManager.isAdminActive(mAdminName); + } + } + + /** + * 添加保持某应用始终运行名单 + * + * @param pkg + */ + public void addPersistentApp(String pkg) { + Log.e(TAG, "addPersistentApp: " + pkg); + List forceAppList = new ArrayList<>(); + forceAppList.add(pkg); + try { + // 添加保持某应用始终运行名单 + mDeviceApplicationManager.addPersistentApp(mAdminName, forceAppList); + } catch (Exception e) { + Log.e(TAG, "addPersistentApp: " + e.getMessage()); + } + } + + /** + * 添加保持某应用始终运行名单 + * + * @param packageNames + */ + public void addPersistentApp(List packageNames) { + Log.e(TAG, "addPersistentApp: " + packageNames); + try { + mDeviceApplicationManager.addPersistentApp(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "addPersistentApp: " + e.getMessage()); + } + } + + /** + * 获取保持某应用始终运行名单 + * + * @return + */ + public List getPersistentApp() { + try { + return mDeviceApplicationManager.getPersistentApp(mAdminName); + } catch (Exception e) { + Log.e(TAG, "getPersistentApp: " + e.getMessage()); + } + return null; + } + + /** + * @param pkg 添加保持某应用始终运行名单 + */ + public void removePersistentApp(String pkg) { + Log.e(TAG, "removePersistentApp: " + pkg); + List packageNames = new ArrayList<>(); + packageNames.add(pkg); + try { + // 添加保持某应用始终运行名单 + mDeviceApplicationManager.removePersistentApp(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "removePersistentApp: " + e.getMessage()); + } + } + + public void removePersistentApp(List packageNames) { + Log.e(TAG, "removePersistentApp: " + packageNames); + try { + // 添加保持某应用始终运行名单 + mDeviceApplicationManager.removePersistentApp(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "removePersistentApp: " + e.getMessage()); + } + } + + /** + * 添加阻止某应用启动运行名单 + * + * @param packageNames + */ + public void addDisallowedRunningApp(List packageNames) { + if (packageNames == null || packageNames.size() == 0) return; + Log.e(TAG, "addDisallowedRunningApp: packageNames = " + packageNames); + List packageList = getDisallowedRunningApp(); + Log.e(TAG, "addDisallowedRunningApp: getDisallowedRunningApp = " + packageList); +// if (packageList != null && packageList.size() != 0) { +// mDeviceApplicationManager.removeDisallowedRunningApp(mAdminName, packageList); +// } + try { + mDeviceApplicationManager.addDisallowedRunningApp(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "addDisallowedRunningApp: " + e.getMessage()); + } + + Log.e(TAG, "addDisallowedRunningApp: getDisallowedRunningApp = " + getDisallowedRunningApp()); + } + + /** + * 添加阻止某应用启动运行名单 + * + * @param pkg 添加后,黑名单中的应用不能打开,正在使用的应用也会被停止运行。 + */ + public void addDisallowedRunningApp(String pkg) { + List packageList = getDisallowedRunningApp(); + Log.e(TAG, "addDisallowedRunningApp: packageList = " + packageList); + packageList.add(pkg); + try { + mDeviceApplicationManager.addDisallowedRunningApp(mAdminName, packageList); + } catch (Exception e) { + Log.e(TAG, "addDisallowedRunningApp: " + e.getMessage()); + } + Log.e(TAG, "addDisallowedRunningApp: getDisallowedRunningApp = " + getDisallowedRunningApp()); + } + + + /** + * 删除阻止某应用启动运行名单 + * + * @param packageNames + */ + public void removeDisallowedRunningApp(List packageNames) { + if (packageNames == null || packageNames.size() == 0) return; + mDeviceApplicationManager.removeDisallowedRunningApp(mAdminName, packageNames); + Log.e(TAG, "removeDisallowedRunningApp: getDisallowedRunningApp = " + getDisallowedRunningApp()); + } + + + /** + * 删除阻止某应用启动运行名单 + * + * @param pkg 待删除的应用包名列表 + */ + public void removeDisallowedRunningApp(String pkg) { + Log.e(TAG, "removeDisallowedRunningApp: pkg = " + pkg); + ArrayList packageList = new ArrayList<>(); + packageList.add(pkg); + mDeviceApplicationManager.removeDisallowedRunningApp(mAdminName, packageList); + Log.e(TAG, "removeDisallowedRunningApp: getDisallowedRunningApp = " + getDisallowedRunningApp()); + } + + /** + * @param pkg + * @return 是否阻止某应用启动 + */ + public boolean isDisallowedRunningApp(String pkg) { + List packageList = getDisallowedRunningApp(); + Log.e(TAG, "isDisallowedRunningApp: packageList = " + packageList); + return packageList.contains(pkg); + } + + public List getDisallowedRunningApp() { + try { + return mDeviceApplicationManager.getDisallowedRunningApp(mAdminName); + } catch (Exception e) { + Log.e(TAG, "getDisallowedRunningApp: " + e.getMessage()); + } + return new ArrayList<>(); + } + + + /** + * 设置允许应用启动运行名单 + * 慎用,开启后只能打开名单内的应用了 + * + * @param packageNames 设置允许应用启动运行名单,设置后只允许名单中的应用启动(荣耀桌面、荣耀响 + * 铃界面、手机管家、权限控制器等部分系统应用除外)。同时在开机之后拉起名单中 + * 的第一个应用。 + * 允许应用启动运行名单为空或者 null 时代表清除名单。 + * 注意:1.需要申请 com.hihonor.permission.sec.MDM_APP_MANAGEMENT 权限。 + * 2.与 addSingleApp(ComponentName admin, String packageName)接口不可同时使用, + * 会出现冲突场景。 + * 3.调试时请注意将调试应用添加到名单中并在调试应用中预留退出的入口(名单为 + * 空或者 null 即可),以便调试时取消策略。 + */ + public boolean setTaskLockAppList(ArrayList packageNames) { + Log.e(TAG, "setTaskLockAppList: packageNames = " + packageNames); + try { + return mDeviceApplicationManager.setTaskLockAppList(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "setTaskLockAppList: " + e.getMessage()); + } + return false; + } + + public boolean addSingleApps(ArrayList packageNames) { + if (packageNames != null && packageNames.size() != 0) { + return addSingleApp(packageNames.get(0)); + } else { + return clearSingleApp(getSingleApp()); + } + } + + /** + * 添加独占应用 + * + * @param packageName + */ + public boolean addSingleApp(String packageName) { + Log.e(TAG, "addSingleApp: " + packageName); + return mDeviceApplicationManager.addSingleApp(mAdminName, packageName); + } + + /** + * 清除独占应用 + * + * @param packageName + */ + public boolean clearSingleApp(String packageName) { + Log.e(TAG, "clearSingleApp: " + packageName); + if (!TextUtils.isEmpty(packageName)) { + return mDeviceApplicationManager.clearSingleApp(mAdminName, packageName); + } else { + Log.e(TAG, "clearSingleApp: packageName is empty"); + return true; + } + } + + /** + * 获取当前独占应用的名字 + */ + public String getSingleApp() { + if (isActiveMe()) { + String pkg = mDeviceApplicationManager.getSingleApp(mAdminName); + Log.e(TAG, "getSingleApp: " + pkg); + return pkg; + } else { + return ""; + } + } + + public String getTopAppPackageName() { + return mDeviceApplicationManager.getTopAppPackageName(mAdminName); + } + + public void killApplicationProcess(String pkg) { + Log.e(TAG, "killApplicationProcess: " + pkg + " start"); + try { + mDeviceApplicationManager.killApplicationProcess(mAdminName, pkg); + Log.e(TAG, "killApplicationProcess: " + pkg + " finish"); + } catch (Exception e) { + Log.e(TAG, "killApplicationProcess: Exception: " + e.getMessage()); + } + } + + + /** + * 禁止/允许蓝牙文件传输 + * + * @param isDisable 是否禁用蓝牙传输。 + * @return + */ + public boolean setBluetoothDataTransferDisable(boolean isDisable) { + try { + return mDeviceBluetoothManager.setBluetoothDataTransferDisable(mAdminName, isDisable); + } catch (Exception e) { + Log.e(TAG, "setBluetoothDataTransferDisable: " + e.getMessage()); + } + return false; + } + + /** + * 设置可信任应用列表 + * + * @param packageNames + */ + public void setSuperTrustListForHwSystemManger(String packageNames) { + + } + + /** + * 设置可信任应用列表 + * + * @param packageNames + */ + public void setSuperTrustListForHwSystemManger(ArrayList packageNames) { + try { + mDeviceHwSystemManager.setSuperTrustListForHwSystemManger(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "setSuperTrustListForHwSystemManger: " + e.getMessage()); + } + } + + public ArrayList getSuperTrustListForHwSystemManger() { + try { + return mDeviceHwSystemManager.getSuperTrustListForHwSystemManger(mAdminName); + } catch (Exception e) { + Log.e(TAG, "getSuperTrustListForHwSystemManger: " + e.getMessage()); + } + return null; + } + + public void removeSuperTrustListForHwSystemManger(ArrayList packageNames) { + try { + mDeviceHwSystemManager.removeSuperTrustListForHwSystemManger(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "removeSuperTrustListForHwSystemManger: " + e.getMessage()); + } + } + + + /** + * 关机 + */ + public void shutdownDevice() { + if (BuildConfig.DEBUG) { + Toaster.show("收到设备关机指令"); + } else { + mDeviceControlManager.shutdownDevice(mAdminName); + } + } + + /** + * 重启 + */ + public void rebootDevice() { + if (BuildConfig.DEBUG) { + Toaster.show("收到设备重启指令"); + } else { + mDeviceControlManager.rebootDevice(mAdminName); + } + } + + /** + * 获取 root 状态 + * + * @return + */ + public boolean isRooted() { + return mDeviceControlManager.isRooted(mAdminName); + } + + public void setDefaultLauncher(String packageName) { + Log.e(TAG, "setDefaultLauncher: packageName = " + packageName); + try { + mDeviceControlManager.clearDefaultLauncher(mAdminName); + } catch (Exception e) { + Log.e(TAG, "setDefaultLauncher: clearDefaultLauncher Exception: " + e.getMessage()); + } + try { + String clazz = JgyUtils.getInstance().getStartClassName(packageName); + Log.e(TAG, "setDefaultLauncher: class = " + clazz); + mDeviceControlManager.setDefaultLauncher(mAdminName, packageName, clazz); + Log.e(TAG, "setDefaultLauncher: setDefaultLauncher successful"); + } catch (Exception e) { + Log.e(TAG, "setDefaultLauncher: setDefaultLauncher Exception: " + e.getMessage()); + } + } + + /** + * 设置第三方桌面为默认桌面 + * + * @param packageName 要设置的第三方桌面包名,不能为 null。 + * @param className 要设置的第三方桌面类名,不能为 null + */ + public void setDefaultLauncher(String packageName, String className) { + Log.e(TAG, "setDefaultLauncher: packageName = " + packageName + " className = " + className); + if (JgyUtils.getInstance().isDefaultLauncher(packageName, className)) { + Log.e(TAG, "setDefaultLauncher: Already set as default desktop"); + return; + } +// throw Exception the device is already hava third default launcher, you must clear it first + clearDefaultLauncher(); + try { + mDeviceControlManager.setDefaultLauncher(mAdminName, packageName, className); + Log.e(TAG, "setDefaultLauncher: finish"); + } catch (Exception e) { + Log.e(TAG, "setDefaultLauncher: " + e.getMessage()); + } + } + + /** + * 清除默认桌面(第三方桌面) + */ + public void clearDefaultLauncher() { + Log.e(TAG, "clearDefaultLauncher: "); + try { + mDeviceControlManager.clearDefaultLauncher(mAdminName); + } catch (Exception e) { + Log.e(TAG, "clearDefaultLauncher: " + e.getMessage()); + } + } + + /** + * 截图 + * + * @return + */ + public Bitmap captureScreen() { + return mDeviceControlManager.captureScreen(mAdminName); + } + + 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 Uri.fromFile(new File(filePath)); + } + + private Set defaultAllowInstallPackages = new HashSet() {{ + this.add(BuildConfig.APPLICATION_ID); + this.add("com.uiui.aios"); + this.add("com.uiui.appstore"); + }}; + + public void addInstallPackageDefaultTrustList(List packages) { + Log.e(TAG, "addInstallPackageDefaultTrustList: " + packages); + removeAllInstallPackageTrustList(); + List trustList = new ArrayList<>(defaultAllowInstallPackages); + if (packages != null && !packages.isEmpty()) { + trustList.addAll(packages); + } + addInstallPackageTrustList(trustList); + } + + private List getInstallPackageTrustList() { + List packageTrustList = mDevicePackageManager.getInstallPackageTrustList(mAdminName); + return packageTrustList; + } + + /** + * 添加应用安装白名单 + * + * @param packages + */ + public void addInstallPackageTrustList(List packages) { + int app_whitelist = mMMKV.decodeInt(CommonConfig.APP_WHITELIST_CONTROL, 0); + Log.e(TAG, "addInstallPackageTrustList: app_whitelist = " + app_whitelist); + if (app_whitelist == 1) { + if (packages == null || packages.size() == 0) { + Log.e(TAG, "addInstallPackageTrustList: packages is empty"); + return; + } + Log.e(TAG, "addInstallPackageTrustList: packages = " + packages); +// packages.addAll(JgyUtils.getInstance().externalPkg); + try { + mDevicePackageManager.addInstallPackageTrustList(mAdminName, packages); + } catch (Exception e) { + Log.e(TAG, "addInstallPackageTrustList: " + e.getMessage()); + } + Log.e(TAG, "addInstallPackageTrustList: getInstallPackageTrustList = " + getInstallPackageTrustList()); + } else { + removeAllInstallPackageTrustList(); + } + } + + /** + * 删除应用安装白名单 + * + * @param packages + */ + public void removeInstallPackageTrustList(List packages) { + if (packages == null || packages.size() == 0) { + Log.e(TAG, "removeInstallPackageTrustList: packages is empty"); + return; + } + try { + mDevicePackageManager.removeInstallPackageTrustList(mAdminName, packages); + } catch (Exception e) { + Log.e(TAG, "removeInstallPackageTrustList: " + e.getMessage()); + } + } + + /** + * 删除所有安装白名单 + */ + public void removeAllInstallPackageTrustList() { + try { + List trustList = mDevicePackageManager.getInstallPackageTrustList(mAdminName); + Log.e(TAG, "removeAllInstallPackageTrustList: trustList = " + trustList); + removeInstallPackageTrustList(trustList); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 静默安装某应用 + * + * @param filePath + */ + public void installPackage(String 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(); + Log.e("installPackage", "uriPath: " + uriPath); + try { + mDevicePackageManager.installPackage(mAdminName, uriPath); + } catch (Exception e) { + Log.e(TAG, "installPackage: " + e.getMessage()); + } + +// Observable.create(new ObservableOnSubscribe() { +// @Override +// public void subscribe(@NonNull ObservableEmitter emitter) throws Throwable { +// emitter.onNext(filePath); +// } +// }).subscribeOn(Schedulers.io()) +// .observeOn(AndroidSchedulers.mainThread()) +// .subscribe(new Observer() { +// @Override +// public void onSubscribe(@NonNull Disposable d) { +// Log.e("installPackage", "onSubscribe: "); +// } +// +// @Override +// public void onNext(@NonNull String s) { +// Log.e("installPackage", "onNext: " + s); +// } +// +// @Override +// public void onError(@NonNull Throwable e) { +// Log.e("installPackage", "onError: " + e.getMessage()); +// } +// +// @Override +// public void onComplete() { +// Log.e("installPackage", "onComplete: "); +// } +// }); + } + + /** + * 静默卸载某应用 + * + * @param packageName + */ + public void uninstallPackage(String packageName) { + removeDisallowedUninstallPackage(packageName); + mDevicePackageManager.uninstallPackage(mAdminName, packageName, false); + } + + public void uninstallPackage(String packageName, boolean keepData) { + + } + + /** + * 删除某应用数据 + * + * @param packageName + */ + public void clearPackageData(String packageName) { + Log.e(TAG, "clearPackageData: " + packageName); + try { + mDevicePackageManager.clearPackageData(mAdminName, packageName); + Log.e(TAG, "clearPackageData: " + packageName + " finish"); + } catch (Exception e) { + Log.e(TAG, "clearPackageData: " + e.getMessage()); + } + } + + + /** + * 添加禁止反激活名单 + * + * @param packages 需要添加到不可反激活的APK包名 + */ + public void addDisabledDeactivateMdmPackages(List packages) { + try { + mDevicePackageManager.addDisabledDeactivateMdmPackages(mAdminName, packages); + } catch (Exception e) { + Log.e(TAG, "addDisabledDeactivateMdmPackages: " + e.getMessage()); + } + } + + /** + * 删除禁止反激活名单 + * + * @param packages 需要移除的APK包名 + */ + public void removeDisabledDeactivateMdmPackages(List packages) { + try { + mDevicePackageManager.removeDisabledDeactivateMdmPackages(mAdminName, packages); + } catch (Exception e) { + Log.e(TAG, "addDisabledDeactivateMdmPackages: " + e.getMessage()); + } + } + + + /** + * 获取阻止某应用被卸载名单 + * + * @return List:获取软件不能被卸载名单; + * null:当 list 为 empty 或无 list 时,返回为 null + */ + public List getDisallowedUninstallPackageList() { + List packageList = mDevicePackageManager.getDisallowedUninstallPackageList(mAdminName); + Log.e(TAG, "getDisallowedUninstallPackageList: " + packageList); + return packageList; + } + + /** + * 添加阻止某应用被卸载名单 + * + * @param packageNames 待添加的应用包名列表 + */ + public void addDisallowedUninstallPackages(List packageNames) { + if (packageNames == null || packageNames.size() == 0) { + Log.e(TAG, "addDisallowedUninstallPackages: packageNames is empty"); + return; + } +// packageNames.addAll(JgyUtils.getInstance().externalPkg); + Log.e(TAG, "addDisallowedUninstallPackages: packageNames = " + packageNames); + try { + removeAllDisallowedUninstallPackages(); + mDevicePackageManager.addDisallowedUninstallPackages(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "checkActiveAdmin: addDisallowedUninstallPackages Exception: " + e.getMessage()); + } + } + + public void removeDisallowedUninstallPackage(String packageNames) { + Log.e(TAG, "removeDisallowedUninstallPackage: " + packageNames); + List pkg = new ArrayList<>(); + pkg.add(packageNames); + removeDisallowedUninstallPackages(pkg); + } + + /** + * 删除阻止某应用被卸载名单 + * + * @param packageNames 待从名单中删除的应用包名列表 + */ + private void removeDisallowedUninstallPackages(List packageNames) { + if (packageNames == null || packageNames.size() == 0) { + Log.e(TAG, "removeDisallowedUninstallPackages: packageNames is empty"); + return; + } + Log.e(TAG, "removeDisallowedUninstallPackages: " + packageNames); + try { + mDevicePackageManager.removeDisallowedUninstallPackages(mAdminName, packageNames); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void disableInstallSource(List trustList) { + try { + mDevicePackageManager.disableInstallSource(mAdminName, trustList); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "disableInstallSource: " + e.getMessage()); + } + } + + public void enableInstallPackage() { + try { + mDevicePackageManager.enableInstallPackage(mAdminName); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "enableInstallPackage: " + e.getMessage()); + } + } + + public boolean isInstallSourceDisabled() { + try { + return mDevicePackageManager.isInstallSourceDisabled(mAdminName); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "isInstallSourceDisabled: " + e.getMessage()); + } + return false; + } + + public List getInstallPackageSourceTrustList() { + try { + return mDevicePackageManager.getInstallPackageSourceTrustList(mAdminName); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "getInstallPackageSourceTrustList: " + e.getMessage()); + } + return null; + } + + + /** + * 移除所有阻止某应用被卸载名单 + */ + public void removeAllDisallowedUninstallPackages() { + Log.e(TAG, "removeAllDisallowedUninstallPackages: "); + List packageList = getDisallowedUninstallPackageList(); + removeDisallowedUninstallPackages(packageList); + } + + public void turnOnUsbDebugMode(int on) { + if (on == STATUS_DISABLE) { + turnOnUsbDebugMode(false); + } else if (on == STATUS_ENABLE) { + turnOnUsbDebugMode(true); + } + } + + /** + * 开启/关闭 USB 调试模式 + * + * @param on true:开启 USB 调试模式。 + * false:关闭 USB 调试模式。 + */ + public boolean turnOnUsbDebugMode(boolean on) { + Log.e(TAG, "turnOnUsbDebugMode: " + on); + try { + if (!BuildConfig.DEBUG) { + return mDeviceControlManager.turnOnUsbDebugMode(mAdminName, on); + } + } catch (Exception e) { + Log.e(TAG, "turnOnUsbDebugMode: " + e.getMessage()); + } + return false; + } + + /** + * 禁止/允许开发人员选项 + * + * @param disable true 表示禁用 + * false 表示启用 + */ + public boolean setDevelopmentOptionDisabled(int disable) { + if (disable == STATUS_DISABLE) { + return setDevelopmentOptionDisabled(true); + } else if (disable == STATUS_ENABLE) { + return setDevelopmentOptionDisabled(false); + } + return false; + } + + /** + * 禁止/允许开发人员选项 + * + * @param disable true 表示禁用 + * false 表示启用 + */ + public boolean setDevelopmentOptionDisabled(boolean disable) { + Log.e(TAG, "setDevelopmentOptionDisabled: " + disable); + try { + return mDeviceSettingsManager.setDevelopmentOptionDisabled(mAdminName, disable); + } catch (Exception e) { + Log.e(TAG, "setDevelopmentOptionDisabled: " + e.getMessage()); + } + return false; + } + + /** + * 查询是否禁用开发人员选项 + * + * @return + */ + public boolean isDevelopmentOptionDisabled() { + boolean isDevelopment = mDeviceSettingsManager.isDevelopmentOptionDisabled(mAdminName); + Log.e(TAG, "isDevelopmentOptionDisabled: isDevelopment = " + isDevelopment); + return isDevelopment; + } + + /** + * 开启/取消导航栏隐藏 + * + * @param disable true:虚拟导航栏被禁用。 + * false:虚拟导航栏被启用。 + */ + public void setNavigationBarDisabled(boolean disable) { + Log.e(TAG, "setNavigationBarDisabled: " + disable); + try { + mDeviceSettingsManager.setNavigationBarDisabled(mAdminName, disable); + Log.e(TAG, "isNavigationBarDisabled: " + isNavigationBarDisabled()); + } catch (Exception e) { + Log.e(TAG, "setNavigationBarDisabled: " + e.getMessage()); + } + } + + public void setNavigationBarDisabled(int status) { + Log.e(TAG, "setNavigationBarDisabled: status = " + status); + setNavigationBarDisabled(status == STATUS_DISABLE); + } + + /** + * 查询导航栏是否被隐藏 + * + * @return + */ + public boolean isNavigationBarDisabled() { + try { + return mDeviceSettingsManager.isNavigationBarDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isNavigationBarDisabled: " + e.getMessage()); + } + return false; + } + + public void setRestoreFactoryDisabled(int status) { + Log.e(TAG, "setRestoreFactoryDisabled: status = " + status); + setRestoreFactoryDisabled(status == STATUS_DISABLE); + } + + /** + * 禁用/启用恢复出厂设置 + * + * @param disabled + * @return + */ + public boolean setRestoreFactoryDisabled(boolean disabled) { + Log.e(TAG, "setRestoreFactoryDisabled: " + disabled); + boolean successful = false; + try { + successful = mDeviceSettingsManager.setRestoreFactoryDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setRestoreFactoryDisabled: " + e.getMessage()); + } + Log.e(TAG, "setRestoreFactoryDisabled: successful = " + successful); + return successful; + } + + /** + * 查询恢复出厂设置禁用状态 + * + * @return + */ + public boolean isRestoreFactoryDisabled() { + boolean dis = false; + try { + dis = mDeviceSettingsManager.isRestoreFactoryDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isRestoreFactoryDisabled: " + e.getMessage()); + } + Log.e(TAG, "isRestoreFactoryDisabled: disable = " + dis); + return dis; + } + + /** + * 禁用/启用 Bluetooth + * + * @param status + */ + public void setBluetoothDisabled(int status) { + Log.e(TAG, "setBluetoothDisabled: " + status); + setBluetoothDisabled(status == STATUS_DISABLE); + } + + /** + * 禁用/启用 Bluetooth + * + * @param disabled true:禁用 Bluetooth; + * false:启用 Bluetooth + */ + public boolean setBluetoothDisabled(boolean disabled) { + Log.e(TAG, "setBluetoothDisabled: " + disabled); + try { + mDeviceRestrictionManager.setBluetoothDisabled(mAdminName, disabled); + return true; + } catch (Exception e) { + Log.e(TAG, "setBluetoothDisabled : " + e.getMessage()); + } + return false; + } + + public boolean setBluetoothTetheringDisabled(int status) { + Log.e(TAG, "setBluetoothTetheringDisabled: status = " + status); + return setBluetoothTetheringDisabled(status == STATUS_DISABLE); + } + + /** + * 禁用/启用蓝牙网络共享菜单 + * + * @param disabled true:禁用蓝牙网络共享; + * false:恢复正常状态 + * @return true:配置成功; + * false:配置失败。 + */ + public boolean setBluetoothTetheringDisabled(boolean disabled) { + Log.e(TAG, "setBluetoothTetheringDisabled: " + disabled); + try { + return mDeviceSettingsManager.setBluetoothTetheringDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setBluetoothTetheringDisabled : " + e.getMessage()); + } + return false; + } + + /** + * 查询蓝牙网络共享禁用状态 + * + * @return true:禁用蓝牙网络共享策略激活; + * false:禁用蓝牙网络共享策略未激活。 + */ + public boolean isBluetoothTetheringDisabled() { + try { + return mDeviceSettingsManager.isBluetoothTetheringDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isBluetoothTetheringDisabled: " + e.getMessage()); + } + return false; + } + + /** + * 禁用/启用状态栏下拉菜单 + * + * @param disable + */ + public void setStatusBarExpandPanelDisabled(boolean disable) { + Log.e(TAG, "setStatusBarExpandPanelDisabled: " + disable); + try { + mDeviceRestrictionManager.setStatusBarExpandPanelDisabled(mAdminName, disable); + } catch (Exception e) { + Log.e(TAG, "setStatusBarExpandPanelDisabled: " + e.getMessage()); + } + try { + //禁用全屏窗口下的状态栏 + mDeviceRestrictionManager.setStatusBarDisabled(mAdminName, disable); + } catch (Exception e) { + Log.e(TAG, "setStatusBarDisabled: " + e.getMessage()); + } + } + + public void setStatusBarExpandPanelDisabled(int status) { + Log.e(TAG, "setStatusBarExpandPanelDisabled: status = " + status); + setStatusBarExpandPanelDisabled(status == STATUS_DISABLE); + } + + /** + * 查询状态栏下拉菜单是否被禁用 + * + * @return + */ + public boolean isStatusBarExpandPanelDisabled() { + try { + return mDeviceRestrictionManager.isStatusBarExpandPanelDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isStatusBarExpandPanelDisabled: " + e.getMessage()); + } + return false; + } + + /** + * 禁用全屏窗口下的状态栏 + * + * @param disable + */ + public void setStatusBarDisabled(boolean disable) { + mDeviceRestrictionManager.setStatusBarDisabled(mAdminName, disable); + } + + /** + * 查询全屏窗口下的状态栏禁用状态 + * + * @return + */ + public boolean isStatusBarDisabled() { + return mDeviceRestrictionManager.isStatusBarDisabled(mAdminName); + } + + public void addSsidToTrustList(String listString) { + + } + + /** + * 3.1.17 禁用/启用USB调试模式、数据传输 + * 禁用/启用USB数据传输功能,仅保持充电功能; + * + * @param disabled + */ + public void setUSBDataDisabled(boolean disabled) { + Log.e(TAG, "setUSBDataDisabled: " + disabled); + try { + if (BuildConfig.DEBUG) { + mDeviceRestrictionManager.setUSBDataDisabled(mAdminName, false); + } else { + mDeviceRestrictionManager.setUSBDataDisabled(mAdminName, disabled); + } + } catch (Exception e) { + Log.e(TAG, "setUSBDataDisabled: " + e.getMessage()); + } + } + + /** + * 3.1.18 查询USB调试模式、数据传输是否被禁用(EMUI4.1) + * + * @return + */ + public boolean isUSBDataDisabled() { + try { + return mDeviceRestrictionManager.isUSBDataDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isUSBDataDisabled: " + e.getMessage()); + return false; + } + } + + + /** + * 3.1.15 禁用/启用存储访问(Micro SD) + * + * @param disabled true:禁止micro sd存储访问 + * false:启用micro sd存储访问 + */ + public void setExternalStorageDisabled(boolean disabled) { + Log.e(TAG, "setExternalStorageDisabled: " + disabled); + try { + mDeviceRestrictionManager.setExternalStorageDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setExternalStorageDisabled: " + e.getMessage()); + } + } + + /** + * 禁用/启用存储访问(Micro SD) + * + * @param status + */ + public void setExternalStorageDisabled(int status) { + Log.e(TAG, "setExternalStorageDisabled: status = " + status); + switch (status) { + default: + case 0: + setExternalStorageDisabled(true); + break; + case 1: + setExternalStorageDisabled(false); + break; + } + } + + + /** + * 3.1.16 查询存储访问(Micro SD)是否被禁用 + * + * @return + */ + public boolean isExternalStorageDisabled() { + try { + return mDeviceRestrictionManager.isExternalStorageDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isExternalStorageDisabled: " + e.getMessage()); + return false; + } + } + + /** + * 3.1.29 禁用/启用任务键(EMUI5.0) + * + * @param disabled + */ + public void setTaskButtonDisabled(boolean disabled) { + Log.e(TAG, "setTaskButtonDisabled: " + disabled); + try { + mDeviceRestrictionManager.setTaskButtonDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setTaskButtonDisabled: " + e.getMessage()); + } + } + + /** + * 3.1.30 查询任务键功能是否被禁用(EMUI5.0) + * + * @return + */ + public boolean isTaskButtonDisabled() { + try { + return mDeviceRestrictionManager.isTaskButtonDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isTaskButtonDisabled: " + e.getMessage()); + return false; + } + } + + /** + * 3.1.31 禁用/启用HOME键(EMUI5.0) + * + * @param disabled + */ + public void setHomeButtonDisabled(boolean disabled) { + Log.e(TAG, "setHomeButtonDisabled: " + disabled); + try { + mDeviceRestrictionManager.setHomeButtonDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setHomeButtonDisabled: " + e.getMessage()); + } + } + + /** + * 3.1.32 查询HOME键功能是否被禁用(EMUI5.0) + * + * @return + */ + public boolean isHomeButtonDisabled() { + try { + return mDeviceRestrictionManager.isHomeButtonDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isHomeButtonDisabled: " + e.getMessage()); + return false; + } + } + + /** + * 3.1.33 禁用/启用返回键(EMUI5.0) + * + * @param disabled + */ + public void setBackButtonDisabled(boolean disabled) { + Log.e(TAG, "setBackButtonDisabled: " + disabled); + try { + mDeviceRestrictionManager.setBackButtonDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setBackButtonDisabled: " + e.getMessage()); + } + } + + /** + * 3.1.34 查询返回键功能是否被禁用(EMUI5.0) + * + * @return + */ + public boolean isBackButtonDisabled() { + try { + return mDeviceRestrictionManager.isBackButtonDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isBackButtonDisabled: " + e.getMessage()); + return false; + } + } + + + /** + * 禁用/启用应用发送通知功能 + * + * @param disabled true:禁止应用发送通知功能。 + * false:启用应用发送通知功能。 + * @return true:配置成功; + * false:配置失败。 + */ + public boolean setSendNotificationDisabled(boolean disabled) { + Log.e(TAG, "setSendNotificationDisabled: " + disabled); + try { + return mDeviceRestrictionManager.setSendNotificationDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setSendNotificationDisabled: " + e.getMessage()); + } + return false; + } + + public void setSendNotificationDisabled(int status) { + Log.e(TAG, "setSendNotificationDisabled: status = " + status); + setSendNotificationDisabled(status == STATUS_DISABLE); + } + + /** + * 查询应用发送通知禁用状态 + * + * @return true:应用发送通知功能被禁止; + * false:应用发送通知功能未被禁止。 + */ + public boolean isSendNotificationDisabled() { + try { + return mDeviceRestrictionManager.isSendNotificationDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isSendNotificationDisabled: " + e.getMessage()); + } + return false; + } + + public void setWifiApDisabled(int status) { + Log.e(TAG, "setWifiApDisabled: " + status); + setWifiApDisabled(status == STATUS_DISABLE); + } + + /** + * 禁用/启用WLAN热点 + * + * @param disabled true:禁用WLAN热点; + * false:启用WLAN热点 + */ + public void setWifiApDisabled(boolean disabled) { + try { + mDeviceRestrictionManager.setWifiApDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setWifiApDisabled: " + e.getMessage()); + } + } + + /** + * 查询WLAN热点是否被禁用 + * + * @return true/false WLAN热点功能被禁止/未被禁止 + */ + public boolean isWifiApDisabled() { + try { + return mDeviceRestrictionManager.isWifiApDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isWifiApDisabled: " + e.getMessage()); + } + return false; + } + + /** + * 禁止/启用墙纸切换功能 + * + * @param disabled true:禁用切换壁纸。 + * false:启用切换壁纸。 + * @return true:配置成功; + * false:配置失败。 + */ + public boolean setChangeWallpaperDisabled(boolean disabled) { + try { + return mDeviceRestrictionManager.setChangeWallpaperDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setChangeWallpaperDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setChangeWallpaperDisabled(int status) { + Log.e(TAG, "setChangeWallpaperDisabled: status = " + status); + return setChangeWallpaperDisabled(status == STATUS_DISABLE); + } + + /** + * 查询壁纸切换禁用状态 + * + * @return true:切换壁纸功能已禁用; + * false:切换壁纸功能未禁用。 + */ + public boolean isChangeWallpaperDisabled() { + try { + return mDeviceRestrictionManager.isChangeWallpaperDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "setChangeWallpaperDisabled: " + e.getMessage()); + } + return false; + } + + /** + * 禁用/启用系统预装浏览器 + * + * @param disabled true:禁用系统预装浏览器。 + * false:启用系统预装浏览器。 + * @return true:配置成功; + * false:配置失败。 + */ + public void setSystemBrowserDisabled(boolean disabled) { + Log.e(TAG, "setSystemBrowserDisabled: " + disabled); + long time = System.currentTimeMillis(); + new Thread(new Runnable() { + @Override + public void run() { + try { + boolean successful = mDeviceRestrictionManager.setSystemBrowserDisabled(mAdminName, disabled); + Log.e(TAG, "setSystemBrowserDisabled: successful " + successful); + } catch (Exception e) { + Log.e(TAG, "setSystemBrowserDisabled: " + e.getMessage()); + } + } + }).start(); + Log.e(TAG, "setSystemBrowserDisabled: time = " + (System.currentTimeMillis() - time) + " ms"); + + } + + public void setSystemBrowserDisabled(int status) { + Log.e(TAG, "setSystemBrowserDisabled: " + status); + setSystemBrowserDisabled(status == STATUS_DISABLE); + } + + + /** + * 查询系统预装浏览器禁用状态 + * + * @return true:系统预装浏览器被禁止; + * false:系统预装浏览器未被禁止。 + */ + public boolean isSystemBrowserDisabled() { + try { + return mDeviceRestrictionManager.isSystemBrowserDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isSystemBrowserDisabled: " + e.getMessage()); + } + return false; + } + + + /** + * 添加 WIFI 热点白名单 + */ + public void addSsidToTrustList(ArrayList ssids) { + boolean status = mDeviceWifiPolicyManager.addSsidToTrustList(mAdminName, ssids); + Log.e(TAG, "addSsidToTrustList: " + status); + } + + public void removeSsidFromTrustList(ArrayList ssids) { + try { + boolean status = mDeviceWifiPolicyManager.removeSsidFromTrustList(mAdminName, ssids); + Log.e(TAG, "removeSsidFromTrustList: " + status); + } catch (Exception e) { + Log.e(TAG, "removeSsidFromTrustList: " + e.getMessage()); + } + } + + public ArrayList getSsidTrustList() { + if (isActiveMe()) { + return mDeviceWifiPolicyManager.getSsidTrustList(mAdminName); + } else { + return null; + } + } + +// public boolean isWIFIMacFixed() { +// if (isActiveMe()) { +// return mDeviceWifiPolicyManager.isWIFIMacFixed(mAdminName); +// } else { +// return false; +// } +// } +// +// public void setWIFIMacFixe(boolean isEnabled) { +// try { +// mDeviceWifiPolicyManager.setWIFIMacFixed(mAdminName, isEnabled); +// } catch (Exception e) { +// Log.e(TAG, "setWIFIMacFixe: " + e.getMessage()); +// } +// } +// +// public void setWIFIMacFixe() { +// if (!isWIFIMacFixed()) { +// try { +// mDeviceWifiPolicyManager.setWIFIMacFixed(mAdminName, true); +// } catch (Exception e) { +// Log.e(TAG, "setWIFIMacFixe: " + e.getMessage()); +// } +// } +// } + + public void setHuaweiLauncher() { + removeAllInstallPackageTrustList(); + try { + mDeviceControlManager.clearDefaultLauncher(mAdminName); + Log.e(TAG, "setHuaweiLauncher: setHuaweiLauncher "); + } catch (Exception e) { + Log.e(TAG, "setHuaweiLauncher: setHuaweiLauncher Exception: " + e.getMessage()); + } + try { +// mDeviceControlManager.setDefaultLauncher(mAdminName, SplashActivity.HUAWEI_DESKTOP_PACKAGE_NAME, SplashActivity.HUAWEI_DESKTOP_CLASS_NAME); + Log.e(TAG, "setHuaweiLauncher: setDefaultLauncher "); + } catch (Exception e) { + Log.e(TAG, "setHuaweiLauncher: setDefaultLauncher Exception: " + e.getMessage()); + } + try { +// mDeviceApplicationManager.killApplicationProcess(mAdminName, JgyUtils.PACKAGE_DESKTOP); + Log.e(TAG, "setHuaweiLauncher: killApplicationProcess "); + } catch (Exception e) { + Log.e(TAG, "setHuaweiLauncher: killApplicationProcess Exception: " + e.getMessage()); + } + } + + /** + * @param numbers 需要设置的电话号码,传入全数字号码。 + * @param blockMode 号码匹配的可选模式: + * 全匹配,黑白名单均适用: + * DevicePhoneManager.MATCH_ALL_MODE = 0; + * 匹配开头,黑白名单均适用: + * DevicePhoneManager.MATCH_PREFIX_MODE = 1; + * 拦截所有号码,黑名单适用: + * DevicePhoneManager.BLOCK_ALL_MODE = 2; + * 允许所有号码,白名单适用: + * DevicePhoneManager.ALLOW_ALL_MODE = 3; + * 其他 int 值非法。 + * @param isOutgoing 表示设置去电名单或来电名单。取值为“True”表 + * 示设置去电黑白名单;取值为“false”表示设置来 + * 电黑白名单。 + * @param isBlockList 表示设置通话黑名单或白名单。取值为“true”表 + * 示设置通话黑名单;取值为“false”表示设置通话 + * 白名单。 + * 如果设备已设置通话黑名单,则无法再设置通话白 + * 名单。必须先调用 removeMdmNumberList()接口移 + * 除已设置的通话黑名单。 + * 反之,如果设备已设置通话白名单,则无法再设置 + * 通话黑名单。必须先调用 removeMdmNumberList() + * 接口移除已设置的通话白名单。 + */ + private boolean addMdmNumberList(ArrayList numbers, int blockMode, boolean isOutgoing, boolean isBlockList) { + Log.e(TAG, "addMdmNumberList: numbers = " + numbers); + boolean successful = mDevicePhoneManager.addMdmNumberList(mAdminName, numbers, blockMode, isOutgoing, isBlockList); + Log.e(TAG, "addMdmNumberList: successful = " + successful); + return successful; + } + + private static final int mBlockMode = 0; + private static final boolean mOutgoing = false; + private static final boolean mBlockList = false; + + + public boolean addMdmNumberListWhite(ArrayList numbers) { + String json = GsonUtils.toJSONString(numbers); + mMMKV.encode(CommonConfig.NUMBER_BLACK_WHITE_LIST, json); + return addMdmNumberList(numbers, mBlockMode, mOutgoing, mBlockList); + } + + public boolean removeMdmNumberList(ArrayList numbers) { + return mDevicePhoneManager.removeMdmNumberList(mAdminName, numbers, mBlockMode, mOutgoing, true); + } + + public boolean removeMdmNumberList() { + String json = mMMKV.decodeString(CommonConfig.NUMBER_BLACK_WHITE_LIST, ""); + Log.e(TAG, "removeMdmNumberList: " + json); + if (!TextUtils.isEmpty(json)) { + Gson gson = new Gson(); + Type type = new TypeToken>() { + }.getType(); + try { + ArrayList numbers = gson.fromJson(json, type); + boolean successful = removeMdmNumberList(numbers); + if (successful) { + mMMKV.remove(CommonConfig.NUMBER_BLACK_WHITE_LIST); + } + return successful; + } catch (Exception e) { + Log.e(TAG, "removeMdmNumberList: " + e.getMessage()); + } + } + return false; + } + + public void setTimeAndDateSetDisabled(boolean disabled) { + try { + mDeviceSettingsManager.setTimeAndDateSetDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setTimeAndDateSetDisabled: " + e.getMessage()); + } + } + + public void setSearchIndexDisabled(boolean isDisabled) { + try { + mDeviceSettingsManager.setSearchIndexDisabled(mAdminName, isDisabled); + } catch (Exception e) { + Log.e(TAG, "mDeviceSettingsManager: " + e.getMessage()); + } + } + + public void setPowerSaveModeDisabled(boolean disabled) { + try { + mDeviceHwSystemManager.setPowerSaveModeDisabled(mAdminName, disabled); + } catch (Exception e) { + Log.e(TAG, "setPowerSaveModeDisabled: " + e.getMessage()); + } + } + + public void addAlertWindowApps(ArrayList appList) { + try { + int sdk_int = Utils.getMagicOsVersion(); + if (sdk_int >= 31) { + //Magic UI 7.0 及以上 + mDeviceHwSystemManager.addAlertWindowApps(mAdminName, appList); + } else { + Log.e(TAG, "addAlertWindowApps: not supported this magicos version"); + } + } catch (Exception e) { + Log.e(TAG, "addAlertWindowApps: " + e.getMessage()); + } + } + + public void setDefaultInputMethod(ComponentName component) { + Log.e(TAG, "setDefaultInputMethod: " + component); + int sdk_int = Utils.getMagicOsVersion(); + if (sdk_int < 31) { + Settings.Secure.putString(mContext.getContentResolver(), "default_input_method", component.getPackageName() + "/" + component.getClassName()); + } else { + try { + //MagicOS 7.0及以上 + mDeviceSettingsManager.setDefaultInputMethod(mAdminName, component, true); + } catch (Exception e) { + Log.e(TAG, "setDefaultInputMethod: " + e.getMessage()); + } + } + } + + @Deprecated + public void setControlMode(int controlMode) { + try { + mDeviceControlManager.setControlMode(mAdminName, controlMode); + } catch (Exception e) { + Log.e(TAG, "setControlMode: " + e.getMessage()); + } + } + + @Deprecated + public int getControlMode() { + try { + return mDeviceControlManager.getControlMode(mAdminName); + } catch (Exception e) { + Log.e(TAG, "getControlMode: " + e.getMessage()); + } + return 0; + } + + /** + * 解除激活设备管理器 + * + * @return + */ + public boolean removeActiveDeviceAdmin() { + boolean b = mDeviceControlManager.removeActiveDeviceAdmin(mAdminName); + Log.e(TAG, "checkActiveAdmin: removeActiveDeviceAdmin = " + b); + mDeviceControlManager.clearDeviceOwnerApp(); + return b; + } + + /** + * 强制激活设备管理器 + */ + @Deprecated + public void setForcedActiveDeviceAdmin() { + try { + mDeviceControlManager.setForcedActiveDeviceAdmin(mAdminName, mContext); + } catch (Exception e) { + Log.e(TAG, "setForcedActiveDeviceAdmin: " + e.getMessage()); + } + } + + public void setCustomSettingsMenu(List menusToDelete) { + try { + mDeviceControlManager.setCustomSettingsMenu(mAdminName, menusToDelete); + } catch (Exception e) { + Log.e(TAG, "setCustomSettingsMenu: " + e.getMessage()); + } + } + + public boolean addIgnoreFrequentRelaunchAppList(String pkg) { + ArrayList apps = new ArrayList<>(); + apps.add(pkg); + boolean successful = false; + try { + successful = mDeviceApplicationManager.addIgnoreFrequentRelaunchAppList(mAdminName, apps); + } catch (Exception e) { + Log.e(TAG, "addIgnoreFrequentRelaunchAppList: " + e.getMessage()); + } + Log.e(TAG, "addIgnoreFrequentRelaunchAppList: successful = " + successful); + if (successful) { + Log.e(TAG, "addIgnoreFrequentRelaunchAppList: " + mDeviceApplicationManager.getIgnoreFrequentRelaunchAppList(mAdminName)); + } + return successful; + } + + public boolean addIgnoreFrequentRelaunchAppList(ArrayList apps) { + boolean successful = false; + try { + successful = mDeviceApplicationManager.addIgnoreFrequentRelaunchAppList(mAdminName, apps); + } catch (Exception e) { + Log.e(TAG, "addIgnoreFrequentRelaunchAppList: " + e.getMessage()); + } + Log.e(TAG, "addIgnoreFrequentRelaunchAppList: successful = " + successful); + if (successful) { + Log.e(TAG, "addIgnoreFrequentRelaunchAppList: " + mDeviceApplicationManager.getIgnoreFrequentRelaunchAppList(mAdminName)); + } + return successful; + } + + public boolean isQuickToolsDisabled() { + try { + return mDevicePasswordManager.isQuickToolsDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isQuickToolsDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setQuickToolsDisabled(boolean disable) { + Log.e(TAG, "setQuickToolsDisabled: disable = " + disable); + try { + return mDevicePasswordManager.setQuickToolsDisabled(mAdminName, disable); + } catch (Exception e) { + Log.e(TAG, "setQuickToolsDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setQuickToolsDisabled(int status) { + Log.e(TAG, "setQuickToolsDisabled: status = " + status); + return setQuickToolsDisabled(status == STATUS_DISABLE); + } + + public boolean isPowerDisabled() { + try { + return mDeviceRestrictionManager.isPowerDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isPowerDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setPowerDisabled(boolean disable) { + Log.e(TAG, "setPowerDisabled: disable = " + disable); + try { + return mDeviceRestrictionManager.setPowerDisabled(mAdminName, disable); + } catch (Exception e) { + Log.e(TAG, "setPowerDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setPowerDisabled(int status) { + Log.e(TAG, "setPowerDisabled: status = " + status); + return setPowerDisabled(status == STATUS_DISABLE); + } + + public boolean setYoyoDisabled(boolean disable) { + Log.e(TAG, "setYoyoDisabled: disable = " + disable); + try { + if (disable) { + AdminManager.getInstance().addDisallowedRunningApp("com.hihonor.servicecenter"); + AdminManager.getInstance().addDisallowedRunningApp("com.hihonor.magicvoice"); + } else { + AdminManager.getInstance().removeDisallowedRunningApp("com.hihonor.servicecenter"); + AdminManager.getInstance().removeDisallowedRunningApp("com.hihonor.magicvoice"); + } + return mDeviceRestrictionManager.setVoiceAssistantButtonDisabled(mAdminName, disable); + } catch (Exception e) { + Log.e(TAG, "setYoyoDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setYoyoDisabled(int status) { + Log.e(TAG, "setYoyoDisabled: status = " + status); + return setYoyoDisabled(status == STATUS_DISABLE); + } + + public boolean isMultiWindowDisabled() { + try { + return mDeviceRestrictionManager.isMultiWindowDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isMultiWindowDisabled: " + e.getMessage()); + } + return false; + } + + public boolean setMultiWindowDisabled(boolean isDisabled) { + try { + return mDeviceRestrictionManager.setMultiWindowDisabled(mAdminName, isDisabled); + } catch (Exception e) { + Log.e(TAG, "setMultiWindowDisabled: " + e.getMessage()); + } + return false; + } + + public boolean isVoiceAssistantButtonDisabled() { + try { + return mDeviceRestrictionManager.isVoiceAssistantButtonDisabled(mAdminName); + } catch (Exception e) { + Log.e(TAG, "isVoiceAssistantButtonDisabled: " + e.getMessage()); + } + return false; + } + + + public boolean setVoiceAssistantButtonDisabled(boolean isDisabled) { + try { + return mDeviceRestrictionManager.setVoiceAssistantButtonDisabled(mAdminName, isDisabled); + } catch (Exception e) { + Log.e(TAG, "setVoiceAssistantButtonDisabled: " + e.getMessage()); + } + return false; + } + + /** + * 设置接收通话状态通知的应用 + * + * @param packageName + * @return + */ + public boolean setCallStatusNotificationApp(String packageName) { + try { + return mDevicePhoneManager.setCallStatusNotificationApp(mAdminName, packageName); + } catch (Exception e) { + Log.e(TAG, "setCallStatusNotificationApp: " + e.getMessage()); + } + return false; + } + + /** + * 获取接收通话状态通知的应用包名 + * + * @return + */ + public String getCallStatusNotificationApp() { + try { + String packageName = mDevicePhoneManager.getCallStatusNotificationApp(); + Log.e(TAG, "getCallStatusNotificationApp: " + packageName); + return packageName; + } catch (Exception e) { + Log.e(TAG, "getCallStatusNotificationApp: " + e.getMessage()); + } + return ""; + } + + /** + * 添加应用通知白名单 + * + * @param packageNames + * @return + */ + public boolean addAllowNotificationApps(ArrayList packageNames) { + Log.e(TAG, "addAllowNotificationApps: " + packageNames); + try { + return mDevicePackageManager.addAllowNotificationApps(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "addAllowNotificationApps: " + e.getMessage()); + } + return false; + } + + /** + * 移除应用通知白名单 + * + * @param packageNames + * @return + */ + public boolean removeAllowNotificationApps(ArrayList packageNames) { + try { + return mDevicePackageManager.removeAllowNotificationApps(mAdminName, packageNames); + } catch (Exception e) { + Log.e(TAG, "removeAllowNotificationApps: " + e.getMessage()); + } + return false; + } + + public boolean removeAllowNotificationApps() { + try { + ArrayList arrayList = getAllowNotificationApps(); + return mDevicePackageManager.removeAllowNotificationApps(mAdminName, arrayList); + } catch (Exception e) { + Log.e(TAG, "removeAllowNotificationApps: " + e.getMessage()); + } + return false; + } + + /** + * 获取应用通知白名单 + * + * @return + */ + public ArrayList getAllowNotificationApps() { + try { + return mDevicePackageManager.getAllowNotificationApps(mAdminName); + } catch (Exception e) { + Log.e(TAG, "getAllowNotificationApps: " + e.getMessage()); + } + return new ArrayList<>(); + } + + public boolean lockNow() { + if (mDevicePolicyManager.isAdminActive(mAdminName)) { + mDevicePolicyManager.lockNow(); // 核心锁屏方法 + return true; + } + return false; + } +} diff --git a/app/src/main/java/com/xwad/os/receiver/AoleDeviceAdminReceiver.java b/app/src/main/java/com/xwad/os/receiver/AoleDeviceAdminReceiver.java new file mode 100644 index 0000000..162721e --- /dev/null +++ b/app/src/main/java/com/xwad/os/receiver/AoleDeviceAdminReceiver.java @@ -0,0 +1,20 @@ +package com.xwad.os.receiver; + +import android.app.admin.DeviceAdminReceiver; +import android.content.Context; +import android.content.Intent; + +import com.xwad.os.R; + +public class AoleDeviceAdminReceiver extends DeviceAdminReceiver { + + @Override + public CharSequence onDisableRequested(Context context, Intent intent) { + return context.getString(R.string.disable_warning); + } + + @Override + public void onEnabled(Context context, Intent intent) { + super.onEnabled(context, intent); + } +} 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 1317003..096d553 100644 --- a/app/src/main/java/com/xwad/os/utils/ApkUtils.java +++ b/app/src/main/java/com/xwad/os/utils/ApkUtils.java @@ -20,6 +20,7 @@ import android.util.Log; import androidx.annotation.RequiresApi; 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.AppUpdateInfo; @@ -27,7 +28,12 @@ import com.xwad.os.bean.DesktopIcon; import com.xwad.os.manager.RemoteManager; import com.xwad.os.receiver.InstallResultReceiver; +import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.Collator; @@ -512,6 +518,141 @@ public class ApkUtils { } } + /** + * 通过路径安装APK,兼容Android 9以上 + * + * @param context 上下文 + * @param filePath apk文件路径 + */ + public static void installApp(Context context, String filePath) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + installAppatPie(context, filePath); + } else { + installApps(filePath); + } + } + + public static boolean installApps(String apkPath) { + Toaster.showShort("正在安装应用"); + Process process = null; + BufferedReader successResult = null; + BufferedReader errorResult = null; + StringBuilder successMsg = new StringBuilder(); + StringBuilder errorMsg = new StringBuilder(); + try { + process = new ProcessBuilder("pm", "install", "-i", BuildConfig.APPLICATION_ID, "--user", "0", apkPath).start(); + successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String s; + while ((s = successResult.readLine()) != null) { + successMsg.append(s); + } + while ((s = errorResult.readLine()) != null) { + errorMsg.append(s); + } + } catch (Exception e) { + Log.e("installApps1", e.getMessage()); + } finally { + try { + if (successResult != null) { + successResult.close(); + } + if (errorResult != null) { + errorResult.close(); + } + } catch (Exception e) { + Log.e("installApps2", e.getMessage()); + } + if (process != null) { + process.destroy(); + } + } + Log.e("result", "" + errorMsg.toString()); + //如果含有“success”认为安装成功 + Log.e("installApp", successMsg.toString()); +// if (!successMsg.toString().equalsIgnoreCase("success")) { +// install(context, new File(apkPath)); +// } + return successMsg.toString().equalsIgnoreCase("success"); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public static void installAppatPie(Context context, String apkFilePath) { + File file = new File(apkFilePath); + PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); + PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(PackageInstaller + .SessionParams.MODE_FULL_INSTALL); + sessionParams.setSize(file.length()); + int sessionId = createSession(packageInstaller, sessionParams); + if (sessionId != -1) { + boolean copySuccess = copyApkFile(packageInstaller, sessionId, apkFilePath); + if (copySuccess) { + install(packageInstaller, sessionId, context); + } + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static boolean copyApkFile(PackageInstaller pi, int sessionId, String apkFilePath) { + boolean success = false; + File apkFile = new File(apkFilePath); + PackageInstaller.Session session = null; + try { + session = pi.openSession(sessionId); + OutputStream out = session.openWrite("app.apk", 0, apkFile.length()); + FileInputStream input = new FileInputStream(apkFile); + int read = 0; + byte[] buffer = new byte[65536]; +// while (read != -1) { +// read = input.read(buffer); +// out.write(buffer, 0, read); +// } + while (true) { + read = input.read(buffer); + if (read == -1) { + session.fsync(out); + success = true; + out.close(); + input.close(); + break; + } + out.write(buffer, 0, read); + } + } catch (IOException e) { + e.printStackTrace(); + Log.e("fht", "copyApkFile" + e.getMessage()); + } + return success; + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static void install(PackageInstaller packageInstaller, int sessionId, Context context) { + try { + PackageInstaller.Session session = packageInstaller.openSession(sessionId); + Intent intent = new Intent(context, InstallResultReceiver.class); + PendingIntent pendingIntent = PendingIntent.getBroadcast( + context, + 1, intent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + session.commit(pendingIntent.getIntentSender()); + } catch (IOException e) { + e.printStackTrace(); + Log.e(TAG, "install: " + e.getMessage()); + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static int createSession(PackageInstaller packageInstaller, PackageInstaller.SessionParams sessionParams) { + int sessionId = -1; + try { + sessionId = packageInstaller.createSession(sessionParams); + } catch (IOException e) { + e.printStackTrace(); + } + return sessionId; + } + /** * 静默卸载应用 * diff --git a/app/src/main/java/com/xwad/os/utils/JgyUtils.java b/app/src/main/java/com/xwad/os/utils/JgyUtils.java new file mode 100644 index 0000000..6f1c9ad --- /dev/null +++ b/app/src/main/java/com/xwad/os/utils/JgyUtils.java @@ -0,0 +1,1322 @@ +package com.xwad.os.utils; + +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; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; +import android.content.res.Resources; +import android.media.AudioManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.Uri; +import android.os.BatteryManager; +import android.os.Build; +import android.os.Environment; +import android.os.PowerManager; +import android.os.Process; +import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import com.google.gson.JsonObject; +import com.hjq.toast.Toaster; +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.gson.GsonUtils; +import com.xwad.os.mdm.AdminManager; +import com.xwad.os.service.main.MainService; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +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 static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; + + +public class JgyUtils { + private static final String TAG = "JgyUtils"; + + @SuppressLint("StaticFieldLeak") + private static JgyUtils sInstance; + private Context mContext; + 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 UNKNOW_PLATFORM = 0; + + public static final String MINI2_TAG = "6gen1s"; + public static final String HONER2_TAG = "honer"; + + + private HashSet ownApp = new HashSet() {{ + this.add("com.tt.ttutils"); + this.add(BuildConfig.APPLICATION_ID); + this.add("com.uiui.sn"); + this.add("com.appstore.uiui"); + this.add("com.alarmclock.uiui"); + this.add("com.android.uiuios"); + this.add("com.aoleyun.os"); + this.add("com.jiaoguanyi.appstore"); + this.add("com.jiaoguanyi.store"); + this.add("com.uiui.appstore"); + this.add("com.uiui.info"); + this.add("com.uiui.browser"); + this.add("com.uiui.health"); + this.add("com.uiui.videoplayer"); + this.add("com.uiui.os"); + this.add("com.aoleyunos.dop1"); + this.add("com.aoleyunos.dop2"); + this.add("com.uiui.aios"); + this.add("com.uiuios.jgy1"); + this.add("com.uiuios.jgy2"); + this.add("com.info.chat"); + this.add("com.info.learning"); + this.add("com.uiui.multios"); + this.add("com.uiui.city"); + }}; + + private HashSet fuxiaoyingApp = new HashSet() {{ + this.add(gkwxhd); + this.add(fuxiaoying); + this.add(moshujia); + this.add(english); + this.add(zhiduoke); + this.add(aobama); + this.add(growthspace); + }}; + + public static final String gkwxhd = "com.gankao.gkwxhd"; + public static final String fuxiaoying = "com.fuying.fuxiaoying"; + public static final String moshujia = "com.moshujiamm.moshujia"; + public static final String english = "com.fuying.english"; + public static final String zhiduoke = "com.zhiduoke.fxy"; + public static final String aobama = "com.fuying.aobama.pad"; + public static final String growthspace = "com.pengren.growthspace"; + + public static final String FUXIAOYING_KEY = "fuxiaoying_update_key"; + + + public HashSet getOwnApp() { + return ownApp; + } + + public HashSet getFXYApp() { + return fuxiaoyingApp; + } + + private JgyUtils(Context context) { + if (context == null) { + throw new RuntimeException("Context is NULL"); + } + this.mContext = context; + this.resolver = mContext.getContentResolver(); + } + + public static void init(Context context) { + if (sInstance == null) { + sInstance = new JgyUtils(context); + } + } + + public static JgyUtils getInstance() { + if (sInstance == null) { + throw new IllegalStateException("You must be init JgyUtils first"); + } + return sInstance; + } + + public static String getAuthorization() { + return "Basic ZWRmOWNlYzIyNzMxYjhiMmZlZDU2ZWU2OmIzYWRlZDRmODk5N2E0ODM5ZTI5MjRjYg=="; + } + + + public static boolean isOfficialVersion() { + String channelValue = JgyUtils.getInstance().getStringMetaData(); + return "official".equals(channelValue); + } + + public static boolean isNewlyVersion() { + String channelValue = JgyUtils.getInstance().getStringMetaData(); + return "beta".equals(channelValue); + } + + public static boolean isBetaVersion() { + String channelValue = JgyUtils.getInstance().getStringMetaData(); + return "beta".equals(channelValue); + } + + /** + * 从Manifest中获取meta-data值 + * https://blog.csdn.net/yue_233/article/details/91453451 + * + * @return MetaData + */ + public String getStringMetaData() { + ApplicationInfo appInfo = null; + try { + appInfo = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), PackageManager.GET_META_DATA); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + String value = appInfo.metaData.getString("CHANNEL_VALUE"); + return value; + } + + private int getBatteryLevel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + BatteryManager batteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE); + return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + } else { + Intent intent = new ContextWrapper(mContext).registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + return (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) / + intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + } + } + + + private PowerManager.WakeLock wakeLock = null; + private static final String mWakeLockName = "BackupService"; + + /** + * 获取电源锁,保持该服务在屏幕熄灭时仍然获取CPU时,保持运行 + */ + @SuppressLint("InvalidWakeLockTag") + private synchronized void acquireWakeLock() { + if (null == wakeLock) { + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK + | PowerManager.ON_AFTER_RELEASE, mWakeLockName); + if (null != wakeLock) { + Log.e("fht", "acquireWakeLock!"); + wakeLock.acquire(); + } + } + } + + /** + * 释放设备电源锁 + */ + private synchronized void releaseWakeLock() { + if (null != wakeLock) { + Log.e("fht", "releaseWakeLock!"); + wakeLock.release(); + wakeLock = null; + } + } + + /** + * 点亮屏幕 + * + * @param timeout The timeout after which to release the wake lock, in milliseconds. + */ + @Nullable + public static PowerManager.WakeLock acquireWakeLock(@androidx.annotation.NonNull Context context, long timeout) { + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + if (pm == null) { + return null; + } + PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | + PowerManager.FULL_WAKE_LOCK | + PowerManager.ON_AFTER_RELEASE, + context.getClass().getName()); + wakeLock.acquire(timeout); + return wakeLock; + } + + public static void release(@Nullable PowerManager.WakeLock wakeLock) { + if (wakeLock != null && wakeLock.isHeld()) { + wakeLock.release(); + } + } + + public String getDownLoadPath() { + String path = ContextCompat.getExternalFilesDirs(mContext, Environment.DIRECTORY_DOWNLOADS)[0].getAbsolutePath(); + return path + File.separator; + } + + /** + * @param ids 需要管控的ID + * @param packages 应用程序包名 + */ + public void writeDeselectIDtoSystem(String ids, String packages) { + if (!TextUtils.isEmpty(ids) && !TextUtils.isEmpty(packages)) { + ArrayList idArrayList = new ArrayList<>(Arrays.asList(ids.split(","))); + ArrayList packageArrayList = new ArrayList<>(Arrays.asList(packages.split(","))); + LinkedHashSet idHashSet = new LinkedHashSet<>(idArrayList); + LinkedHashSet packageHashSet = new LinkedHashSet<>(packageArrayList); + ArrayList idList = new ArrayList<>(idHashSet); + ArrayList packageList = new ArrayList<>(packageHashSet); + StringBuilder idStringBuilder = new StringBuilder(); + for (String id : idList) { + if (idStringBuilder.length() > 0) { + idStringBuilder.append(","); + } + idStringBuilder.append(id); + } + StringBuilder packageStringBuilder = new StringBuilder(); + for (String pkg : packageList) { + if (packageStringBuilder.length() > 0) { + packageStringBuilder.append(","); + } + packageStringBuilder.append(pkg); + } + + } else { + + } + } + + + private void sendAllweb() { + Intent intent = new Intent("qch_app_website") + .setPackage("com.android.settings"); + intent.putExtra("package_name", ""); + mContext.sendBroadcast(intent); + } + + private void sendwebUrl() { + Intent intent = new Intent("qch_app_inside_website") + .setPackage("com.android.settings"); + intent.putExtra("websitelist", ""); + mContext.sendBroadcast(intent); + } + + /** + * 系统应用hook使用webview + */ + public static void hookWebView() { + int sdkInt = Build.VERSION.SDK_INT; + try { + Class factoryClass = Class.forName("android.webkit.WebViewFactory"); + Field field = factoryClass.getDeclaredField("sProviderInstance"); + field.setAccessible(true); + Object sProviderInstance = field.get(null); + if (sProviderInstance != null) { + Log.i(TAG, "sProviderInstance isn't null"); + return; + } + + Method getProviderClassMethod; + if (sdkInt > 22) { + getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass"); + } else if (sdkInt == 22) { + getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass"); + } else { + Log.i(TAG, "Don't need to Hook WebView"); + return; + } + getProviderClassMethod.setAccessible(true); + Class factoryProviderClass = (Class) getProviderClassMethod.invoke(factoryClass); + Class delegateClass = Class.forName("android.webkit.WebViewDelegate"); + Constructor delegateConstructor = delegateClass.getDeclaredConstructor(); + delegateConstructor.setAccessible(true); + if (sdkInt < 26) {//低于Android O版本 + Constructor providerConstructor = factoryProviderClass.getConstructor(delegateClass); + if (providerConstructor != null) { + providerConstructor.setAccessible(true); + sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance()); + } + } else { + Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD"); + chromiumMethodName.setAccessible(true); + String chromiumMethodNameStr = (String) chromiumMethodName.get(null); + if (chromiumMethodNameStr == null) { + chromiumMethodNameStr = "create"; + } + Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass); + if (staticFactory != null) { + sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance()); + } + } + + if (sProviderInstance != null) { + field.set("sProviderInstance", sProviderInstance); + Log.i(TAG, "Hook success!"); + } else { + Log.i(TAG, "Hook failed!"); + } + } catch (Throwable e) { + Log.w(TAG, e); + } + } + + + /** + * 忽略电池优化 + */ + private void ignoreBatteryOptimization() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + + PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + + boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(mContext.getPackageName()); + // 判断当前APP是否有加入电池优化的白名单,如果没有,弹出加入电池优化的白名单的设置对话框。 + if (!hasIgnored) { + Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + mContext.getPackageName())); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + } + } + + 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"); + CmdUtil.execute("am force-stop " + "com.adups.fota"); + } + + private static final String COlORFLY_OTA_PACKAGE_NAME = "com.adups.fota"; + private static final String COlORFLY_OTA_CLASS_NAME = "com.adups.fota.GoogleOtaClient"; + + private static final String CUBE_UNISOC_OTA_PACKAGE_NAME = "com.cube.update"; + private static final String CUBE_UNISOC_OTA_CLASS_NAME = "com.cube.update.GoogleOtaClient"; + + private static final String CUBE_MTK_OTA_PACKAGE_NAME = "com.droi.ota"; + private static final String CUBE_MTK_OTA_CLASS_NAME = "com.droi.ota.GoogleOtaClient"; + + private static final String CUBE_ABF_OTA_PACKAGE_NAME = "com.abfota.systemUpdate"; + private static final String CUBE_ABF_OTA_CLASS_NAME = "com.redstone.ota.ui.activity.RsMainActivity"; + + public void openJgyOta() { + openComponentNameApp(COlORFLY_OTA_PACKAGE_NAME, COlORFLY_OTA_CLASS_NAME); + } + + public void openCubeOta() { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONER_PLATFORM + ) { + openCubeUnisocOta(); +// } else if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.MTKPlatform) { +// openCubeMtkOta(); +// } else if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.iPlay50miniProPlatform) { +// openCubeAbfOta(); + } + } + + public void openCubeUnisocOta() { + openComponentNameApp(CUBE_UNISOC_OTA_PACKAGE_NAME, CUBE_UNISOC_OTA_CLASS_NAME); + } + + public void openCubeMtkOta() { + openComponentNameApp(CUBE_MTK_OTA_PACKAGE_NAME, CUBE_MTK_OTA_CLASS_NAME); + } + + public void openCubeAbfOta() { + openComponentNameApp(CUBE_ABF_OTA_PACKAGE_NAME, CUBE_ABF_OTA_CLASS_NAME); + } + + private void openComponentNameApp(String pkgName, String className) { + Intent intent = new Intent(Intent.ACTION_MAIN); + ComponentName componentName = new ComponentName(pkgName, className); + intent.setComponent(componentName); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + mContext.startActivity(intent); + } catch (Exception e) { + Log.e(TAG, "openComponentNameApp: " + e.getMessage()); + Toaster.show("打开失败"); + } + } + + public void openLauncher() { + Log.e(TAG, "openLauncher: "); + killPackage("com.android.launcher3"); + Intent intent = new Intent(); + // 为Intent设置Action、Category属性 + intent.setAction(Intent.ACTION_MAIN);// "android.intent.action.MAIN" + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addCategory(Intent.CATEGORY_HOME); //"android.intent.category.HOME" + mContext.startActivity(intent); + } + + public void cleanLauncherCache() { + Log.e(TAG, "cleanLauncherCache: Start"); + int cleaned = mMMKV.decodeInt("fristcleanLauncherCache", 0); + if (cleaned == 0) { + AdminManager.getInstance().clearPackageData("com.android.launcher3"); + mMMKV.encode("fristcleanLauncherCache", 1); + Log.e(TAG, "cleanLauncherCache: end"); + } + } + + public int checkAppPlatform() { + String platform = BuildConfig.platform; + if (HONER2_TAG.equalsIgnoreCase(platform)) { + Log.i(TAG, "checkAppPlatform: " + "honer"); + return HONER_PLATFORM; + } else if (MINI2_TAG.equalsIgnoreCase(platform)) { + Log.i(TAG, "checkAppPlatform: " + "6gen1s"); + return MINI2_PLATFORM; + } else { + Log.i(TAG, "checkAppPlatform: " + "没有数据"); + return UNKNOW_PLATFORM; + } + } + + public interface GetAppPlatformCallback { + void AppPlatform(int platform); + } + + 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); + } else { + getAppPlatformCallback.AppPlatform(UNKNOW_PLATFORM); + } + } + + public static String getCustomVersion() { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONER_PLATFORM + ) { + return getProperty("ro.build.display.id", "获取失败"); + } else { + return getProperty("ro.custom.build.version", "获取失败"); + } + } + + public static String getRomVersion() { + if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.HONER_PLATFORM + ) { + return getProperty("ro.build.id", "获取失败"); + } else { + return getProperty("ro.build.display.id", "获取失败"); + } + } + + /** + * 获取系统配置信息 + * + * @param key + * @param defaultValue + * @return + */ + public static String getProperty(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, "unknown")); + } catch (Exception e) { + e.printStackTrace(); + } finally { + return value; + } + } + + public void killBackgroundApp(Context context) { + List pkgList = ApkUtils.queryFilterAppList(context); + for (String pkg : pkgList) { + if (runningAppWhitelist.contains(pkg)) continue; + AdminManager.getInstance().killApplicationProcess(pkg); +// killBackgroundProcesses(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"); + }}; + + public void killBackgroundProcesses2(String packageName) { + ActivityManager activityManager; + try { + activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + activityManager.killBackgroundProcesses(packageName); + Method forceStopPackage = activityManager.getClass() + .getDeclaredMethod("forceStopPackage", String.class); +// Log.e(TAG, "killBackgroundProcesses: " + packageName); + forceStopPackage.setAccessible(true); + forceStopPackage.invoke(activityManager, packageName); + } catch (Exception e) { + Log.e(TAG, "killBackgroundProcesses: " + e.getMessage()); + e.printStackTrace(); + } + } + + @Deprecated + public void killBackgroundProcesses(String processName) { +// gotoLauncher(); + // mIsScanning = true; + removeTask(processName); + ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + String packageName = null; + try { + if (processName.indexOf(":") == -1) { + packageName = processName; + } else { + packageName = processName.split(":")[0]; + } + activityManager.killBackgroundProcesses(packageName); + // + Method forceStopPackage = activityManager.getClass() + .getDeclaredMethod("forceStopPackage", String.class); + forceStopPackage.setAccessible(true); + forceStopPackage.invoke(activityManager, packageName); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 清除所有最近记录 + */ + public void removeAllTask() { + List list = getRecentTasks(ActivityManager.getMaxRecentTasksStatic(), getCurrentUserId()); + + for (ActivityManager.RecentTaskInfo info : list) { + if (info.realActivity != null) { + Log.e(TAG, "removeAllTask: " + info.realActivity.getPackageName()); + //排除自身 + if (BuildConfig.APPLICATION_ID.equals(info.realActivity.getPackageName())) { + continue; + } + } + try { + ActivityManagerNative.getDefault().removeTask(info.id); + } catch (RemoteException e) { + e.printStackTrace(); + Log.e(TAG, "removeAllTask: " + e.getMessage()); + } + } + } + + public void removeTask(String packageName) { + List list = getRecentTasks(ActivityManager.getMaxRecentTasksStatic(), getCurrentUserId()); + HashMap taskMap = new HashMap<>(); + for (ActivityManager.RecentTaskInfo info : list) { + taskMap.put(info.realActivity.getPackageName(), info.id); + } + try { + ActivityManagerNative.getDefault().removeTask(taskMap.get(packageName)); + } catch (RemoteException e) { + e.printStackTrace(); + Log.e(TAG, "removeTask: " + e.getMessage()); + } catch (NullPointerException e) { + Log.e(TAG, "removeTask: " + e.getMessage()); + } + } + + /** + * 如果界面正在最近任务列表,有些app可能不会被清理 + */ + public void gotoLauncher() { + Intent i = new Intent(Intent.ACTION_MAIN); + i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //android123提示如果是服务里调用,必须加入new task标识 + i.addCategory(Intent.CATEGORY_HOME); + mContext.startActivity(i); + } + + + /** + * @return a list of the recents tasks. + * 获取近期任务列表 + */ + public List getRecentTasks(int numTasks, int userId) { + try { + return ActivityTaskManager.getService().getRecentTasks(numTasks, + RECENT_IGNORE_UNAVAILABLE, userId).getList(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get recent tasks", e); + return new ArrayList<>(); + } + } + + /** + * @return the current user's id. + * 获取userId + */ + public int getCurrentUserId() { + UserInfo ui; + try { + ui = ActivityManager.getService().getCurrentUser(); + return ui != null ? ui.id : 0; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public int isWifiConnect() { + // 网络管理对象 + ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + // 获取所有类型的链接管理对象 + NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + NetworkInfo.State state = info.getState(); + if (NetworkInfo.State.CONNECTED == state) { + return 1; + } + return 0; + } + +// synchronized public static int getInt(ContentResolver cr, String name, int def) { +// Log.i(TAG, "getInt: " + name); +// return Settings.System.getInt(cr, name, def); +// } +// +// synchronized public static int getInt(ContentResolver cr, String name) throws Settings.SettingNotFoundException { +// Log.i(TAG, "getInt: " + name); +// return Settings.System.getInt(cr, name); +// } +// +// synchronized public static String getString(ContentResolver cr, String name) { +// Log.i(TAG, "getString: " + name); +// return Settings.System.getString(cr, name); +// } +// +// synchronized public static boolean putInt(ContentResolver cr, String name, int value) { +// Log.i(TAG, "putInt: " + "name = " + name + ", value = " + value); +// return Settings.System.putInt(cr, name, value); +// } +// +// synchronized public static boolean putString(ContentResolver cr, String name, String value) { +// Log.i(TAG, "putString: " + "name = " + name + ", value = " + value); +// return Settings.System.putString(cr, name, value); +// } + + /** + * 获取当前进程名 + */ + public String getCurrentProcessName() { + int pid = Process.myPid(); + String processName = ""; + ActivityManager manager = (ActivityManager) mContext.getSystemService + (Context.ACTIVITY_SERVICE); + for (ActivityManager.RunningAppProcessInfo process : manager.getRunningAppProcesses()) { + if (process.pid == pid) { + processName = process.processName; + } + } + return processName; + } + + private String Launcher3 = "com.android.launcher3"; + private String Launcher3Class = "com.android.launcher3.Launcher"; + + public void setDefaultLauncher(Context context, String defPackageName, String defClassName) { + try { + if (!TextUtils.isEmpty(defPackageName) && !TextUtils.isEmpty(defClassName)) { + IntentFilter filter = new IntentFilter(); + filter.addAction("android.intent.action.MAIN"); + filter.addCategory("android.intent.category.HOME"); + filter.addCategory("android.intent.category.DEFAULT"); + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_HOME); + // 返回给定条件的所有ResolveInfo对象(本质上是Activity) + List list = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + int bestMatch = 0; + final int size = list.size(); + ComponentName[] set = new ComponentName[size]; + for (int i = 0; i < size; i++) { + ResolveInfo ri = list.get(i); + set[i] = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name); + if (ri.match > bestMatch) { + bestMatch = ri.match; + } + } + ComponentName preActivity = new ComponentName(defPackageName, defClassName); + context.getPackageManager().addPreferredActivity(filter, bestMatch, set, preActivity); + } + } catch (SecurityException e) { + e.printStackTrace(); + Log.e(TAG, "setDefaultLauncher: " + e.getMessage()); + } + } + + public void setRoleHolderAsUser(Context context, String packageName) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + String roleName = "android.app.role.HOME"; + boolean add = true; + int flags = 0; + UserHandle user = Process.myUserHandle(); + Log.i("settingssssssstemf", (add ? "Adding" : "Removing") + " package as role holder, role: " + + roleName + ", package: " + packageName); +// if (JgyUtils.getInstance().checkAppPlatform() != JgyUtils.MTKPlatform) { + RoleManager roleManager = context.getSystemService(RoleManager.class); + Executor executor = context.getMainExecutor(); + Consumer callback = successful -> { + if (successful) { + Log.d("settingssssssstemf", "Package " + (add ? "added" : "removed") + + " as role holder, role: " + roleName + ", package: " + packageName); + } else { + Log.d("settingssssssstemf", "Failed to " + (add ? "add" : "remove") + + " package as role holder, role: " + roleName + ", package: " + + packageName); + } + }; + roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback); + Log.i("settingssssssstemf", "addRoleHolderAsUser done"); +// } + } + } + + public void checkDefaultDesktop(String pkg) { + String desktopPkg = mMMKV.decodeString("default_launcher", ""); + Log.e(TAG, "checkDefaultDesktop: " + desktopPkg); + if (desktopPkg.equalsIgnoreCase(pkg)) { + setDefaultDesktop(pkg); + } + } + + //设置默认桌面 + public void setDefaultDesktop(String pkg) { + Log.e(TAG, "setDefaultDesktop: " + pkg); + if (TextUtils.isEmpty(pkg)) { + openLauncher3(); + } else { + String className = getStartClassName(pkg); + if (TextUtils.isEmpty(className)) { + openLauncher3(); + } else { + setDefaultDesktop(pkg, className); + } + } + } + + private void openLauncher3() { + setDefaultDesktop(Launcher3, Launcher3Class); +// ApkUtils.openPackage(mContext, Launcher3); + } + + public String getStartClassName(String pkg) { + PackageInfo packageInfo = null; + try { + packageInfo = mContext.getPackageManager().getPackageInfo(pkg, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + return ""; + } else { + // 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent + Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null); + resolveIntent.addCategory(Intent.CATEGORY_HOME); + resolveIntent.setPackage(packageInfo.packageName); + + // 通过getPackageManager()的queryIntentActivities方法遍历 + List resolveinfoList = mContext.getPackageManager() + .queryIntentActivities(resolveIntent, 0); + if (resolveinfoList == null || resolveinfoList.size() == 0) { + return ""; + } + + ResolveInfo resolveinfo = resolveinfoList.iterator().next(); + if (resolveinfo != null) { + // packagename = 参数packname + String packageName = resolveinfo.activityInfo.packageName; + // 这个就是我们要找的该APP的LAUNCHER的Activity[组织形式:packagename.mainActivityname] + String className = resolveinfo.activityInfo.name; + return className; + } else { + return ""; + } + } + } + + public boolean isDefaultLauncher(String pkg, String className) { + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_HOME); + ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivity(intent, 0); + if (resolveInfo != null && resolveInfo.activityInfo != null) { + Log.e(TAG, "isDefaultLauncher: pkg = " + resolveInfo.activityInfo.packageName); + Log.e(TAG, "isDefaultLauncher: class = " + resolveInfo.activityInfo.name); + return pkg.equals(resolveInfo.activityInfo.packageName) && className.equals(resolveInfo.activityInfo.name); + } + return false; + } + + public void setDefaultDesktop(String pkg, String className) { + if (!isDefaultLauncher(pkg, className)) { + AdminManager.getInstance().setDefaultLauncher(pkg, className); + } else { + Log.e(TAG, "setDefaultDesktop: pkg = already set default luancher"); + } +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { +// setRoleHolderAsUser(mContext, pkg); +// Log.e(TAG, "setDefaultDesktop: setRoleHolderAsUser"); +// } else { +// //爱华设置,暂时屏蔽 +//// setDefaultLauncher(mContext, pkg, className); +// Log.e(TAG, "setDefaultDesktop: setDefaultLauncher"); +// } +//// String oldDesktop = (String) mMMKV.get(mContext, "default_launcher", ""); +//// if (Objects.equals(oldDesktop, pkg)) { +//// Log.e(TAG, "setDefaultDesktop: " + "数据一致"); +//// return; +//// } +// Intent intent = new Intent("setDefaultLauncher"); +// intent.putExtra("package", pkg); +// intent.putExtra("className", className); +// +//// if (JgyUtils.getInstance().checkAppPlatform() == MTKPlatform) { +//// Log.e(TAG, "setDefaultDesktop: MTK"); +//// //爱华定制 +//// intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.AoleReceiver")); +//// // TODO: 2022/7/6 有问题 +//// setDefaultLauncher(mContext, "com.android.transfer", "com.android.transfer.MainActivity"); +//// SystemProperties.set("persist.sys.launcher.pkgname", pkg); +//// SystemProperties.set("persist.sys.launcher.classname", className); +//// } +// +// intent.setPackage("com.android.settings"); +// mContext.sendBroadcast(intent); +//// ApkUtils.openPackage(mContext, pkg); +// Log.e(TAG, "setDefaultDesktop: " + pkg + ":" + className); +// Log.e(TAG, "setDefaultDesktop: " + "persist.sys.launcher.pkgname = " + SystemProperties.get("persist.sys.launcher.pkgname")); +// Log.e(TAG, "setDefaultDesktop: " + "persist.sys.launcher.classname = " + SystemProperties.get("persist.sys.launcher.classname")); + } + +// public void setDefaultDesktop(String pkg, String className) { +// Intent intent = new Intent("setDefaultLauncher"); +// intent.putExtra("package", pkg); +// intent.putExtra("className", className); +// intent.setPackage("com.android.settings"); +// mContext.sendBroadcast(intent); +// } + + public ArrayList getForbidList() { + ArrayList disableApp = new ArrayList<>(); + int search_topic = mMMKV.decodeInt("search_topic", 0); + Log.e(TAG, "getForbidList: search_topic = " + search_topic); + Log.e(TAG, "getForbidList: " + GsonUtils.toJSONString(mMMKV.allKeys())); + + return disableApp; + } + + private static final String UPDATE_FORBID_APP = "UPDATE_FORBID_APP"; + + public void updateForbidList() { + Intent intent = new Intent(UPDATE_FORBID_APP); + intent.putStringArrayListExtra("forbid_app_list", getForbidList()); + Log.e(TAG, "updateForbidList: " + getForbidList()); +// intent.setComponent(new ComponentName("com.jiaoguanyi.os","com.jiaoguanyi.os.view.MainActivity")); + intent.setPackage("com.jiaoguanyi.os"); +// intent.setPackage("com.tt.ttutils"); + mContext.sendBroadcast(intent); + } + + public ArrayList getHideList() { + String appString = mMMKV.decodeString("Hide_APP_List", ""); + Log.e(TAG, "Hide_APP_List: " + appString); + if (TextUtils.isEmpty(appString)) { + return new ArrayList<>(); + } else { + return new ArrayList<>(Arrays.asList(appString.split(","))); + } + } + + private static final String UPDATE_HIDE_APP = "UPDATE_HIDE_APP"; + + public void updateHideList() { + Intent intent = new Intent(UPDATE_HIDE_APP); + intent.putStringArrayListExtra("hide_app_list", getHideList()); +// intent.setComponent(new ComponentName("com.jiaoguanyi.os","com.jiaoguanyi.os.view.MainActivity")); + intent.setPackage("com.jiaoguanyi.os"); +// intent.setPackage("com.tt.ttutils"); + mContext.sendBroadcast(intent); + } + + + @SuppressLint("NewApi") + synchronized public void setAppNetwork(HashSet blackList) { + + } + + @SuppressLint("NewApi") + synchronized public void onBootSendNetwork() { + String oldBlackListString = mMMKV.decodeString(CommonConfig.AOLE_ACTION_NETWORK_DISALLOW, ""); + HashSet oldBlackListSet = new HashSet<>(Arrays.asList(oldBlackListString.split(","))); + Log.e(TAG, "setAppNetwork: oldBlackListSet: " + oldBlackListSet); + oldBlackListSet.removeIf(s -> TextUtils.isEmpty(s.trim())); + for (String pkg : oldBlackListSet) { + if (TextUtils.isEmpty(pkg)) continue; + if (!ApkUtils.isAvailable(mContext, pkg)) { + Log.e(TAG, "setAppNetwork: skip: " + pkg); + continue; + } + Intent netControlNotIntent = new Intent(CommonConfig.AOLE_ACTION_NETWORK_DISALLOW); + netControlNotIntent.putExtra("package_name", pkg); + netControlNotIntent.setPackage("com.android.settings"); + mContext.sendBroadcast(netControlNotIntent); + } + } + + //删除用户除了在应用市场的其他应用 + @Deprecated + public void deleteOtherApp() { + + } + + public boolean isScreenOn() { + PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + //true为打开,false为关闭 + return powerManager.isInteractive(); + } + +// private int zenModOn = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; +// private int zenModOff = Settings.Global.ZEN_MODE_OFF; +// private String ZENNODETAG = "ZenModeSettingsBackend"; +// +// public void setZenMode(String extras) { +// JsonObject jsonObject = GsonUtils.getJsonObject(extras); +// int setting_disturbance = jsonObject.get("setting_disturbance").getAsInt(); +// NotificationManager.from(mContext).setZenMode(setting_disturbance, null, ZENNODETAG); +// } +// +// public void setRotationLock(String extras) { +// JsonObject jsonObject = GsonUtils.getJsonObject(extras); +// int setting_rotation = jsonObject.get("setting_rotation").getAsInt(); +// RotationPolicy.setRotationLock(mContext, setting_rotation == 0); +// } + + public void setScreenBrightness(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + int setting_luminance = jsonObject.get("setting_luminance").getAsInt(); + Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + int Scrern_brightness = (int) ((1.0 * 255 / 100) * setting_luminance); + Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, Scrern_brightness); + } + + private float[] mValues; + /** + * Index of the entry corresponding to current value of the settings. + */ + protected int mCurrentIndex; + /** + * List of entries corresponding the settings being set. + */ + protected List mEntries; + + public void setFontSize(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + String setting_typeface = jsonObject.get("setting_typeface").getAsString(); + final Resources res = mContext.getResources(); + mEntries = Arrays.asList(res.getStringArray(R.array.entries_font_size)); + final String[] strEntryValues = res.getStringArray(R.array.entryvalues_font_size); + mValues = new float[strEntryValues.length]; + for (int i = 0; i < strEntryValues.length; ++i) { + mValues[i] = Float.parseFloat(strEntryValues[i]); + } + mCurrentIndex = mEntries.indexOf(setting_typeface); + if (mCurrentIndex == -1) { + return; + } + Settings.System.putFloat(resolver, Settings.System.FONT_SCALE, mValues[mCurrentIndex]); + } + + public void setVolume(String extras) { + JsonObject jsonObject = GsonUtils.getJsonObject(extras); + int setting_volume = jsonObject.get("setting_volume").getAsInt(); + //获取系统的Audio管理者 + AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + //最大音量 + int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + //当前音量 +// int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + int currentVolume = (int) ((1.0f * maxVolume / 100) * setting_volume); + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0); + } + + public void setDefaultLauncher(String pkg) { + Intent intent = new Intent("setDefaultLauncher"); + intent.putExtra("package", "com.uiui.os"); + intent.putExtra("className", "com.uiui.os.Launcher"); + intent.setPackage("com.android.settings"); + mContext.sendBroadcast(intent); + } + + public void getLauncherClassName(String pkg) { + + } + + public String getInputMethodId(String pkg) { + InputMethodManager imeManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + List InputMethods = imeManager.getInputMethodList(); + Map inputMap = new HashMap<>(); + for (InputMethodInfo inputMethodInfo : InputMethods) { + inputMap.put(inputMethodInfo.getPackageName(), inputMethodInfo.getId()); + } + String id = inputMap.get(pkg); + Log.e(TAG, "getInputMethodId: " + id); + return id; + } + + public void setDefaultInputMethod(String pkg) { + String id = getInputMethodId(pkg); + if (TextUtils.isEmpty(id)) { + Log.e(TAG, "setDefaultInputMethod: id is empty"); + return; + } + Intent intent = new Intent("setDefaultInputMethod"); + intent.putExtra("package", id); + intent.setPackage("com.android.settings"); + mContext.sendBroadcast(intent); + } + + public void setDefaultBrowser(String pkg) { + Intent intent = new Intent("setDefaultBrowser"); + intent.putExtra("package", pkg); + intent.setPackage("com.android.settings"); + mContext.sendBroadcast(intent); + } + + + /*AI健康*/ + public static final String AIHealth = "com.uiui.health"; + /*同城服务*/ + public static final String CityService = "com.uiui.city"; + /*消息通知*/ + public static final String Notifications = "com.uiui.info"; + + public static final String PACKAGE_BROWSER = "com.uiui.browser"; + public static final String PACKAGE_VIDEOPLAYER = "com.uiui.videoplayer"; + public static final String PACKAGE_OS = "com.uiui.aios"; + public static final String PACKAGE_CALENDAR = "com.uiui.calendar"; + + public static final String CUBE_ZY_LAUNCHER = "com.uiui.zyos"; + public static final String CubeZYSN = "com.uiui.zy"; + + public static final String PACKAGE_DEVICEINFO = "com.uiui.sn"; + public static final String PACKAGE_APPSTORE = "com.uiui.appstore"; + public static final String PACKAGE_UPDATETOOLS = "com.uiui.updatetools"; + + public static final String CLASS_DEVICEINFO = "com.uiui.sn.receiver.BootReceiver"; + public static final String CLASS_APPSTORE = "com.uiui.appstore.receiver.BootReceiver"; + public static final String CLASS_UPDATETOOLS = "com.uiui.updatetools.receiver.BootReceiver"; + + public void wakeUpDeviceInfo() { + //启动设备信息 +// Intent bootIntent = new Intent(BootReceiver.BOOT_COMPLETED); +// bootIntent.setComponent(new ComponentName(PACKAGE_DEVICEINFO, CLASS_DEVICEINFO)); +// mContext.sendBroadcast(bootIntent); + } + + public void wakeUpAppstore() { + //启动应用市场 +// Intent bootIntent = new Intent(BootReceiver.BOOT_COMPLETED); +// bootIntent.setComponent(new ComponentName(PACKAGE_APPSTORE, CLASS_APPSTORE)); +// mContext.sendBroadcast(bootIntent); + } + + public void wakeUpUpdateTools() { + //启动升级组件 +// Intent bootIntent = new Intent(BootReceiver.BOOT_COMPLETED); +// bootIntent.setComponent(new ComponentName(PACKAGE_UPDATETOOLS, CLASS_UPDATETOOLS)); +// mContext.sendBroadcast(bootIntent); + } + + /** + * 判断网络连接状态 + * + * @return true:网络已链接, false:网络已断开连接 + */ + public boolean isNetworkConnected() { + if (mContext != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) mContext + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager + .getActiveNetworkInfo(); + if (mNetworkInfo != null) { + return mNetworkInfo.isAvailable(); + } + } + return false; + } + + + public String getIMEI() { + String IMEI = "unknown"; + String IMEI1, IMEI2, IMEI3; + //获取手机设备号 + TelephonyManager TelephonyMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + //8.0及以后版本获取 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + IMEI = TelephonyMgr.getDeviceId(); + } 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(mContext.getContentResolver(), Settings.Secure.ANDROID_ID); + } +// Log.e("IMEI:", "IMEI: " + IMEI); + if (null == IMEI) { + return "-"; + } else { + return IMEI.toUpperCase(); + } + } + + public String getPushMac() { + String macaddr = Utils.getAndroid10MAC(mContext); + return macaddr.replace(":", "").toUpperCase(); + } + + private static final String AOLE_DIR = "uiuiapp"; + + public void checkLocalExternalFiles() { + int install = mMMKV.decodeInt(CommonConfig.INSTALL_SD_APKS, 0); + Log.e(TAG, "checkLocalExternalFiles: installed = " + install); + if (install == 1) { + Log.e(TAG, "checkLocalExternalFiles: install"); +// return; + } + File[] externalFiles = mContext.getExternalFilesDirs(null); + Log.e(TAG, "checkLocalAppInstall: externalFiles = " + Arrays.toString(externalFiles)); + + String SdPath = Environment.getExternalStorageDirectory().getAbsolutePath(); + Log.e(TAG, "checkLocalAppInstall: SdPath = " + SdPath); + String aolePath = SdPath + File.separator + AOLE_DIR; + File file = new File(aolePath); + String[] apkName = file.list(); + if (apkName == null || apkName.length == 0) { + Log.e(TAG, "checkLocalAppInstall: apkName is empty"); + } else { + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(@NonNull ObservableEmitter> emitter) throws Throwable { + HashMap packageListMap = new HashMap<>(); + for (String fileName : apkName) { + String apkPath = aolePath + File.separator + fileName; + Log.e(TAG, "subscribe: " + apkPath); + String pkg = ApkUtils.getPackageName(mContext, apkPath); + if (mJxwApps.contains(pkg)) { + packageListMap.put(pkg, apkPath); + } else { + Log.e(TAG, "checkLocalAppInstall: skip: " + pkg + " fileName: " + fileName); + } + } + emitter.onNext(packageListMap); + emitter.onComplete(); + } + }).subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("checkLocalAppInstall", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull HashMap stringStringHashMap) { + Log.e("checkLocalAppInstall", "onNext: " + stringStringHashMap); + stringStringHashMap.forEach(new BiConsumer() { + @Override + public void accept(String key, String value) { + if (ApkUtils.isAvailable(mContext, key)) { + Log.e("checkLocalAppInstall", "accept: installed: " + key); + } else { + ApkUtils.installApp(mContext, value); + } + } + }); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("checkLocalAppInstall", "onError: " + e.getMessage()); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("checkLocalAppInstall", "onComplete: "); + mMMKV.encode(CommonConfig.INSTALL_SD_APKS, 1); + } + }); + } + } + + public void startServices() { + Log.e(TAG, "startServices: "); + boolean noti = mMMKV.decodeBool(CommonConfig.ALLOW_NOTIFICATION, true); + Log.e(TAG, "startServices: noti = " + noti); + if (noti) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mContext.startForegroundService(new Intent(mContext, MainService.class)); + } else { + mContext.startService(new Intent(mContext, MainService.class)); + } + } + } + + private Set mJxwApps = new HashSet() {{ + this.add("com.uiui.sn"); + this.add("com.uiui.appstore"); + this.add("com.uiui.browser"); + this.add("com.uiui.videoplayer"); + }}; +} diff --git a/app/src/main/java/com/xwad/os/utils/LenovoCsdkUtil.java b/app/src/main/java/com/xwad/os/utils/LenovoCsdkUtil.java deleted file mode 100644 index 2b9a141..0000000 --- a/app/src/main/java/com/xwad/os/utils/LenovoCsdkUtil.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.xwad.os.utils; - -import android.annotation.SuppressLint; -import android.app.csdk.CSDKManager; -import android.content.Context; -import android.util.Log; - -import com.tencent.mmkv.MMKV; -import com.xwad.os.BuildConfig; -import com.xwad.os.config.CommonConfig; - -public class LenovoCsdkUtil { - private static final String TAG = "LenovoCsdkUtil"; - - @SuppressLint("StaticFieldLeak") - private static LenovoCsdkUtil sInstance; - private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); - private Context mContext; - private CSDKManager mCSDKManager; - - - private LenovoCsdkUtil(Context context) { - if (context == null) { - throw new RuntimeException("Context is NULL"); - } - this.mContext = context; - try { - this.mCSDKManager = new CSDKManager(context); - if (mCSDKManager.isLicenseKeyEnabled(BuildConfig.APPLICATION_ID)) { - Log.e(TAG, "LenovoCsdkUtil: devices activated"); - } else { - Log.e(TAG, "LenovoCsdkUtil: devices not activated"); - } - } catch (Exception e) { - Log.e(TAG, "LenovoCsdkUtil: " + e.getMessage()); - } - - } - - public static void init(Context context) { - if (sInstance == null) { - Log.e(TAG, "init: "); - sInstance = new LenovoCsdkUtil(context); - } - } - - public static LenovoCsdkUtil getInstance() { - if (sInstance == null) { - throw new IllegalStateException("You must be init LenovoCsdkUtil first"); - } - return sInstance; - } - - /** - * int: 1 MAC - * int: 2 SN - * int: 3 Model - * int: 4 IMEI - */ - public String getDeviceMac() { - String mac = mCSDKManager.getDeviceInfo(1); - return mac; - } - -// public String getSerial() { -// if (BuildConfig.DEBUG) { -// return "T811MN128GB23529041363"; -// } -// String sn = mCSDKManager.getDeviceInfo(2); -// return sn; -// } - - public String getDeviceModel() { - String model = mCSDKManager.getDeviceInfo(3); - return model; - } - - public String getDeviceIMEI() { - String imei = mCSDKManager.getDeviceInfo(4); - return imei; - } - -} 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 2835af7..6c26aad 100644 --- a/app/src/main/java/com/xwad/os/utils/Utils.java +++ b/app/src/main/java/com/xwad/os/utils/Utils.java @@ -1,5 +1,6 @@ package com.xwad.os.utils; +import android.Manifest; import android.app.Activity; import android.content.ComponentName; import android.content.Context; @@ -13,14 +14,18 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; +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.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; +import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.google.zxing.BarcodeFormat; @@ -33,8 +38,10 @@ import com.xwad.os.BuildConfig; import com.xwad.os.R; import com.xwad.os.manager.RemoteManager; +import java.io.BufferedReader; import java.io.File; import java.io.FileReader; +import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.Reader; @@ -43,11 +50,58 @@ import java.net.NetworkInterface; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; public class Utils { private static final String TAG = "Utils"; + /** + * 判断MagicOS 版本 + * https://developer.honor.com/cn/docs/adaptation_guide/guides/general_adaptation_guide + * + * @return + */ + public static int getMagicOsVersion() { + if (!isHonorDevice()) { + // 非荣耀设备,暂不支持 + return -1; + } + // Android S及以上版本取用MAGIC_SDK_INT值 + if (Build.VERSION.SDK_INT >= 31) { + return com.hihonor.android.os.Build.VERSION.MAGIC_SDK_INT; + } + // Android R版本对应MagicUI 5.0 + if (Build.VERSION.SDK_INT == 30) { + return 31; + } + // Android Q版本对应MagicUI 4.0 + if (Build.VERSION.SDK_INT == 29) { + return 26; + } + // Android Q以下版本返回-1 + return -1; + } + + /** + * @return 判定荣耀折叠屏设备 + */ + public static boolean isHonorFoldableDevice(Context context) { + if (Build.MANUFACTURER.equalsIgnoreCase("HONOR") + && context.getPackageManager() != null + && context.getPackageManager().hasSystemFeature("com.hihonor.hardware.sensor.posture")) { + return true; + } + return false; + } + + /** + * @return 判定荣耀设备 + */ + public static boolean isHonorDevice() { + return "HONOR".equalsIgnoreCase(Build.MANUFACTURER); + } + /** * 获取设备序列号 *

@@ -76,6 +130,8 @@ public class Utils { // } // return serial; // } + + public static String getAndroiodScreenProperty(Context context) { Log.e("getAndroiodScreenProperty", "heightPixels:" + context.getResources().getDisplayMetrics().heightPixels); Log.e("getAndroiodScreenProperty", "widthPixels:" + context.getResources().getDisplayMetrics().widthPixels); @@ -102,16 +158,179 @@ public class Utils { return width + "×" + height; } - public static String getDeviceSN() { - String serial = null; + /** + * @return 序列号 + */ + public static String getSerial(Context context) { + String serialNumber = "unknow"; try { - Class c = Class.forName("android.os.SystemProperties"); - Method get = c.getMethod("get", String.class); - serial = (String) get.invoke(c, "persist.sys.hrSerial"); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+ + serialNumber = Build.getSerial(); + } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+ + serialNumber = Build.SERIAL; + } else {//8.0- + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class); + serialNumber = (String) get.invoke(c, "ro.serialno"); + } + } + } catch (Exception e) { + e.printStackTrace(); + Log.e("getSerial", "读取设备序列号异常:" + e.toString()); + } + return serialNumber; + } + + public static String getSerial() { + String serialNumber = "unknow"; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+ + serialNumber = Build.getSerial(); + } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+ + serialNumber = Build.SERIAL; + } else {//8.0- + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class); + serialNumber = (String) get.invoke(c, "ro.serialno"); + } + } catch (Exception e) { + e.printStackTrace(); + Log.e("getSerial", "读取设备序列号异常:" + e.toString()); + } + return serialNumber; + } + + /** + * @param context 获取真实的MAC地址 + * @return + */ + public static String getAndroid10MAC(Context context) { +// if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { +// return getMacAddress(context); +// } else { +// return getAndroid7MAC(); +// } + return getAllMacAddress(context); + } + + /** + * 获取MAC地址 + * + * @param context + * @return + */ + public static String getAllMacAddress(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return getMacDefault(context); + } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return getMacAddressM(); + } else { + return getMacFromHardware(); + } + } + + /** + * Android 6.0 之前(不包括6.0) + * + * @param context + * @return + */ + private static String getMacDefault(Context context) { + String mac = "未获取到设备Mac地址"; + if (context == null) { + return mac; + } + WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + WifiInfo info = null; + try { + info = wifi.getConnectionInfo(); } catch (Exception e) { e.printStackTrace(); } - return serial; + if (info == null) { + return mac; + } + mac = info.getMacAddress(); + if (!TextUtils.isEmpty(mac)) { + mac = mac.toUpperCase(Locale.ENGLISH); + } + + return mac; + } + + /** + * Android 6.0(包括) - Android 7.0(不包括) + * + * @return + */ + private static String getMacAddressM() { + String mac = "未获取到设备Mac地址"; + + try { + mac = new BufferedReader(new FileReader("/sys/class/net/wlan0/address")).readLine(); + } catch (IOException e) { + e.printStackTrace(); + } + return mac; + } + + /** + * 兼容7.0获取不到的问题 + * + * @return + */ + public static String getAndroid7MAC() { + try { + List all = Collections.list(NetworkInterface.getNetworkInterfaces()); + for (NetworkInterface nif : all) { + if (!nif.getName().equalsIgnoreCase("wlan0")) + continue; + byte[] macBytes = nif.getHardwareAddress(); + if (macBytes == null) { + return ""; + } + StringBuilder res1 = new StringBuilder(); + for (byte b : macBytes) { + res1.append(String.format("%02X:", b)); + } + if (res1.length() > 0) { + res1.deleteCharAt(res1.length() - 1); + } + return res1.toString(); + } + } catch (Exception ex) { + } + return ""; + } + + /** + * 遍历循环所有的网络接口,找到接口是 wlan0 + * + * @return + */ + private static String getMacFromHardware() { + try { + List all = Collections.list(NetworkInterface.getNetworkInterfaces()); + + for (NetworkInterface nif : all) { + if (!nif.getName().equalsIgnoreCase("wlan0")) { + continue; + } + byte[] macBytes = nif.getHardwareAddress(); + StringBuilder res1 = new StringBuilder(); + for (byte b : macBytes) { + res1.append(String.format("%02X:", b)); + } + if (res1 != null) { + res1.deleteCharAt(res1.length() - 1); + } + return res1.toString(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return "未获取到设备Mac地址"; } /** @@ -352,36 +571,6 @@ public class Utils { return macSerial; } - /** - * 兼容7.0获取不到的问题 - * - * @return - */ - public static String getAndroid7MAC() { - try { - List all = Collections.list(NetworkInterface.getNetworkInterfaces()); - for (NetworkInterface nif : all) { - if (!"wlan0".equalsIgnoreCase(nif.getName())) - continue; - byte[] macBytes = nif.getHardwareAddress(); - if (macBytes == null) { - return ""; - } - StringBuilder res1 = new StringBuilder(); - for (byte b : macBytes) { - res1.append(String.format("%02X:", b)); - } - if (res1.length() > 0) { - res1.deleteCharAt(res1.length() - 1); - } - return res1.toString(); - } - } catch (Exception ex) { - Log.e(TAG, "getAndroid7MAC: " + ex.getMessage()); - } - return ""; - } - public static String loadFileAsString(String fileName) throws Exception { FileReader reader = new FileReader(fileName); String text = loadReaderAsString(reader); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4479411..4e0a2f4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,4 +25,46 @@ 许可证验证成功,本账户已可长期使用,\n点击开启学习之旅! 有效期:%d年 二维码过期时间%s + + + "当前状态:" + "当前状态:" + "当前状态:" + 已禁用 + 未禁用 + 已保活 + 未保活 + 禁用WiFi + 启用WiFi + 将该应用保活 + 取消该应用保活 + 启用截屏 + 禁用截屏 + 启用数据连接 + 该应用未激活 + 无操作权限 + 本应用只支持MAGIC4及以上的版本 + 取消激活后将导致本软件的部分功能无法正常工作,您确定要取消激活么? + 同意 + 退出 + 已阅读 + 不再提示 + 免责声明与软件许可协议 + 权限使用声明 + 若您点击同意并开始使用本软件,代表您已阅读并接受《免责声明与软件许可协议》 + 请选择以下模式中的一种进行设备管理器的激活。 + 用户确认激活模式即普通的激活方式,激活后用户可随时解除激活。 + 强制激活模式只在企业定制版本(通过荣耀商城企业定制服务进行定制的终端版本)上生效,用户只能点击激活,激活成功后无法手动解除激活。 + 延时解除激活模式请先输入延迟时间(范围在1~72的数字),激活成功后用户在设定的延迟时间(单位:小时)过后才能解除激活设备管理器。 + 用户确认激活模式 + 强制激活模式 + 延时解除激活模式 + 请输入延迟时间,范围:1~72 + 解除激活设备管理器 + setForcedActiveDeviceAdmin error + setDelayDeactiveDeviceAdmin error + + 为关怀系统提供管控功能,请激活后使用 + 开启我吧 + diff --git a/app/src/main/res/xml/device_admin_sample.xml b/app/src/main/res/xml/device_admin_sample.xml new file mode 100644 index 0000000..5e82553 --- /dev/null +++ b/app/src/main/res/xml/device_admin_sample.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index cf2eaba..2835143 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ include ':app', ':niceimageview', ':FlycoTabLayoutZ_Lib', ':verification-view', ':PhotoPreview' -rootProject.name='九学王6_5桌面Lenovo' \ No newline at end of file +rootProject.name='学王365荣耀' \ No newline at end of file