init: mdm版本初始化

This commit is contained in:
2026-08-04 16:19:58 +08:00
commit e7d342644a
45 changed files with 3505 additions and 0 deletions

90
.gitignore vendored Normal file
View File

@@ -0,0 +1,90 @@
# Built application files
*.apk
*.aar
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Uncomment the following line in case you need and you don't have the release build type files in your app
# release/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml
# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/
/.idea/
/app/src/test/
/app/src/androidTest/java/com/jiaoguanyi/appstore/
/adb
/app/proguard-rules.pro

85
app/.gitignore vendored Normal file
View File

@@ -0,0 +1,85 @@
# Built application files
*.apk
*.aar
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Uncomment the following line in case you need and you don't have the release build type files in your app
# release/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml
# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/

125
app/build.gradle Normal file
View File

@@ -0,0 +1,125 @@
apply plugin: 'com.android.application'
static def appName() {
return "ElderlyDialerMdm"
}
static def releaseTime() {
return new Date().format("yyyyMMdd_HHmmss", TimeZone.getDefault())
}
android {
namespace "com.ttstd.sn"
compileSdkVersion 33
defaultConfig {
applicationId "com.ttstd.sn"
//There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature.
minSdkVersion 23
targetSdkVersion 33
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
ndk {
//选择要添加的对应 cpu 类型的 .so 库。
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
}
buildConfigField "String", "platform", '"honor"'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
dataBinding true
buildConfig true
aidl true
}
buildTypes {
debug {
debuggable true
versionNameSuffix "_debug"
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
release {
//混淆
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
// Add application variant configuration here instead
applicationVariants.all { variant ->
variant.outputs.each { output ->
def buildType = variant.buildType.name
if (buildType.contains("debug")) {
output.outputFileName = "app_debug.apk"
} else {
output.outputFileName = "${appName()}_${variant.versionCode}_V${variant.versionName}_${releaseTime()}_${buildType}.apk"
}
}
}
}
dependencies {
compileOnly files('libs/magic-android-34.38.1.200.jar')
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
//Annotations(BaseRxService 使用 @NotNull)
implementation 'org.jetbrains:annotations:24.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//RxJava
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
//生命周期管理
implementation 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2'
//图片加载框架
implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
//状态栏透明
implementation 'com.gitee.zackratos:UltimateBarX:0.8.0'
}
// 在 dependencies 之后添加
project.afterEvaluate {
android.applicationVariants.all { variant ->
variant.javaCompileProvider.get().options.bootstrapClasspath = files(
file('libs/framework.jar'),
android.getBootClasspath()
)
}
}

BIN
app/libs/framework.jar Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ttstd.sn">
<!--荣耀mdm权限-->
<!--已申请的-->
<uses-permission android:name="com.hihonor.permission.sec.MDM_APP_MANAGEMENT" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_BLUETOOTH" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_CAPTURE_SCREEN" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_DEVICE_MANAGER" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_DEVICE_OWNER" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_NETWORK_MANAGER" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_NFC" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_PHONE_MANAGER" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_SETTINGS_RESTRICTION" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_UPDATESTATE_MANAGER" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_USB" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_WIFI" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_CAMERA" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_CONNECTIVITY" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_MMS" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_PHONE" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_SDCARD" />
<uses-permission android:name="com.hihonor.permission.sec.MDM_TELEPHONY" />
<uses-permission android:name="com.hihonor.permission.sec.SDK_LAUNCHER" />
<uses-permission android:name="com.hihonor.systemmanager.permission.ACCESS_INTERFACE" />
<!--系统权限-->
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.MASTER_CLEAR" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.SHUTDOWN" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.GET_TASKS" />
<application
android:name=".App"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<activity
android:name=".ui.main.MainActivity"
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".receiver.AoleDeviceAdminReceiver"
android:description="@string/sample_device_admin_description"
android:exported="true"
android:label="@string/sample_device_admin"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<!-- 元数据 -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@@ -0,0 +1,72 @@
package com.ttstd.sn;
import android.app.Application;
import android.content.Context;
import android.text.TextUtils;
import androidx.multidex.MultiDex;
import com.ttstd.sn.mdm.AdminManager;
import com.ttstd.sn.ui.base.GlobalCrashHandler;
public class App extends Application {
private static final String TAG = "App";
private static App sInstance;
public static App getInstance() {
return sInstance;
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
sInstance = this;
}
@Override
public void onCreate() {
super.onCreate();
//非主进程不初始化
if (isMainProcessName(this, android.os.Process.myPid())) {
init();
}
}
private void init() {
// 全局异常捕获
GlobalCrashHandler.getInstance().init(this, null);
// 初始化 MDM(设备激活后才生效)
try {
AdminManager.init(this);
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 判断当前进程是否为主进程
*/
private boolean isMainProcessName(Context context, int pid) {
String processName = null;
try {
android.app.ActivityManager am =
(android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (am == null) return true;
java.util.List<android.app.ActivityManager.RunningAppProcessInfo> list = am.getRunningAppProcesses();
if (list == null || list.size() == 0) return true;
for (android.app.ActivityManager.RunningAppProcessInfo info : list) {
if (info.pid == pid) {
processName = info.processName;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (TextUtils.isEmpty(processName)) return true;
return processName.equalsIgnoreCase(getPackageName());
}
}

View File

@@ -0,0 +1,473 @@
package com.ttstd.sn.mdm;
import android.annotation.SuppressLint;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import com.ttstd.sn.receiver.AoleDeviceAdminReceiver;
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 java.util.ArrayList;
import java.util.List;
public class AdminManager {
private static final String TAG = "AdminManager";
public static final List<String> mDeleteMenus = new ArrayList<String>() {{
this.add("honor_id");
this.add("super_device");
this.add("vpn_settings");
this.add("apps_clone");
this.add("apps_startup_management");
this.add("apps_management");
this.add("apps_honor_tips");
this.add("pengine_settings");
this.add("screen_wallpaper");
}};
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;
/*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.mDeviceVpnManager = new DeviceVpnManager();
this.mDeviceWifiPolicyManager = new DeviceWifiPolicyManager();
Log.e(TAG, "AdminManager: isActiveMe = " + isActiveMe());
if (isActiveMe()) {
setYoyoDisabled(true);
}
}
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 DeviceVpnManager getDeviceVpnManager() {
return mDeviceVpnManager;
}
public DeviceWifiPolicyManager getDeviceWifiPolicyManager() {
return mDeviceWifiPolicyManager;
}
public String getSerial() {
String sn = "";
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
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());
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
sn = Build.getSerial();
} catch (Exception e) {
Log.e(TAG, "getSerial: " + e.getMessage());
}
}
// 未获取到 MDM 权限时,Build.getSerial() 可能返回 "unknown",
// 此时传 "" 给接口,避免获取到不属于本设备的配置
if ("unknown".equalsIgnoreCase(sn)) {
sn = "";
}
return sn;
}
public boolean isActiveMe() {
if (mDevicePolicyManager == null) {
return false;
} else {
return mDevicePolicyManager.isAdminActive(mAdminName);
}
}
/**
* 移除白名单
*/
public void removeTrustList() {
try {
List<String> trustList = mDevicePackageManager.getInstallPackageTrustList(mAdminName);
Log.e(TAG, "removeTrustList: " + trustList);
if (trustList != null && trustList.size() != 0) {
mDevicePackageManager.removeInstallPackageTrustList(mAdminName, trustList);
}
} catch (Exception e) {
Log.e(TAG, "removeTrustList: " + e.getMessage());
}
}
/**
* 添加保持某应用始终运行名单
*
* @param pkg
*/
public void addPersistentApp(String pkg) {
Log.e(TAG, "addPersistentApp: " + pkg);
List<String> 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<String> packageNames) {
Log.e(TAG, "addPersistentApp: " + packageNames);
try {
// 添加保持某应用始终运行名单
mDeviceApplicationManager.addPersistentApp(mAdminName, packageNames);
} catch (Exception e) {
Log.e(TAG, "addPersistentApp: Exception " + e.getMessage());
}
Log.e(TAG, "setDisallowUninstall: getPersistentApp: " + mDeviceApplicationManager.getPersistentApp(mAdminName));
}
/**
* @param pkg 添加保持某应用始终运行名单
*/
public void removePersistentApp(String pkg) {
Log.e(TAG, "removePersistentApp: " + pkg);
List<String> packageNames = new ArrayList<>();
packageNames.add(pkg);
try {
// 添加保持某应用始终运行名单
mDeviceApplicationManager.removePersistentApp(mAdminName, packageNames);
} catch (Exception e) {
Log.e(TAG, "removePersistentApp: " + e.getMessage());
}
}
public void removePersistentApp(List<String> 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<String> packageNames) {
if (packageNames == null || packageNames.size() == 0) return;
Log.e(TAG, "addDisallowedRunningApp: packageNames = " + packageNames);
List<String> packageList = mDeviceApplicationManager.getDisallowedRunningApp(mAdminName);
Log.e(TAG, "addDisallowedRunningApp: getDisallowedRunningApp = " + packageList);
try {
mDeviceApplicationManager.addDisallowedRunningApp(mAdminName, packageNames);
} catch (Exception e) {
Log.e(TAG, "addDisallowedRunningApp: " + e.getMessage());
}
Log.e(TAG, "addDisallowedRunningApp: getDisallowedRunningApp = " + mDeviceApplicationManager.getDisallowedRunningApp(mAdminName));
}
/**
* 添加阻止某应用启动运行名单
*
* @param pkg 添加后,黑名单中的应用不能打开,正在使用的应用也会被停止运行。
*/
public void addDisallowedRunningApp(String pkg) {
Log.e(TAG, "addDisallowedRunningApp: pkg = " + pkg);
if (TextUtils.isEmpty(pkg)) return;
if (!isAvailable(mContext, pkg)) return;
List<String> packageList = new ArrayList<>();
packageList.add(pkg);
try {
mDeviceApplicationManager.addDisallowedRunningApp(mAdminName, packageList);
} catch (Exception e) {
Log.e(TAG, "addDisallowedRunningApp: " + e.getMessage());
}
Log.e(TAG, "addDisallowedRunningApp: getDisallowedRunningApp = " + mDeviceApplicationManager.getDisallowedRunningApp(mAdminName));
}
/**
* 删除阻止某应用启动运行名单
*
* @param packageNames
*/
public void removeDisallowedRunningApp(List<String> packageNames) {
if (packageNames == null || packageNames.size() == 0) return;
mDeviceApplicationManager.removeDisallowedRunningApp(mAdminName, packageNames);
Log.e(TAG, "removeDisallowedRunningApp: getDisallowedRunningApp = " + mDeviceApplicationManager.getDisallowedRunningApp(mAdminName));
}
/**
* 删除阻止某应用启动运行名单
*
* @param pkg 待删除的应用包名列表
*/
public void removeDisallowedRunningApp(String pkg) {
Log.e(TAG, "removeDisallowedRunningApp: pkg = " + pkg);
if (TextUtils.isEmpty(pkg)) return;
List<String> stringList = new ArrayList<>();
stringList.add(pkg);
mDeviceApplicationManager.removeDisallowedRunningApp(mAdminName, stringList);
Log.e(TAG, "removeDisallowedRunningApp: getDisallowedRunningApp = " + mDeviceApplicationManager.getDisallowedRunningApp(mAdminName));
}
/**
* @param pkg
* @return 是否阻止某应用启动
*/
public boolean isDisallowedRunningApp(String pkg) {
List<String> packageList = mDeviceApplicationManager.getDisallowedRunningApp(mAdminName);
Log.e(TAG, "isDisallowedRunningApp: packageList = " + packageList);
return packageList.contains(pkg);
}
/**
* 设置 yoyo 助手
*
* @param disable true: 禁用 yoyo 助手
*/
public void setYoyoDisable(boolean disable) {
if (disable) {
setYoyoDisabled(true);
} else {
setYoyoDisabled(false);
}
}
public void setYoyoDisabled(boolean disable) {
Log.e(TAG, "setYoyoDisabled: " + disable);
try {
if (disable) {
addDisallowedRunningApp("com.hihonor.servicecenter");
} else {
removeDisallowedRunningApp("com.hihonor.servicecenter");
}
} catch (Exception e) {
Log.e(TAG, "setYoyoDisabled: " + e.getMessage());
}
}
/**
* 添加忽略频繁重新启动的应用
*
* @param packageNames
*/
public void addIgnoreFrequentRelaunchAppList(ArrayList<String> packageNames) {
Log.e(TAG, "addIgnoreFrequentRelaunchAppList: " + packageNames);
try {
if (packageNames != null && packageNames.size() > 0) {
mDeviceApplicationManager.addIgnoreFrequentRelaunchAppList(mAdminName, packageNames);
}
} catch (Exception e) {
Log.e(TAG, "addIgnoreFrequentRelaunchAppList: " + e.getMessage());
}
}
/**
* 判断应用是否已安装
*/
private boolean isAvailable(Context context, String pkg) {
if (TextUtils.isEmpty(pkg)) return false;
try {
PackageManager pm = context.getPackageManager();
pm.getPackageInfo(pkg, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
} catch (Exception e) {
return false;
}
}
}

View File

@@ -0,0 +1,20 @@
package com.ttstd.sn.receiver;
import android.app.admin.DeviceAdminReceiver;
import android.content.Context;
import android.content.Intent;
import com.ttstd.sn.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);
}
}

View File

@@ -0,0 +1,55 @@
package com.ttstd.sn.ui.base;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.ttstd.sn.R;
import com.ttstd.sn.ui.base.rx.BaseRxActivity;
import com.bumptech.glide.Glide;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
public abstract class BaseActivity extends BaseRxActivity {
public BaseActivity() {
super();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// StatusBarUtil.init(this);
UltimateBarX.statusBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(true)
.apply();
UltimateBarX.navigationBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(true)
.apply();
}
/**
* 设置布局
*/
protected abstract int getLayoutId();
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
if (level == TRIM_MEMORY_UI_HIDDEN) {
Glide.get(this).clearMemory();
}
Glide.get(this).trimMemory(level);
}
@Override
public void onLowMemory() {
super.onLowMemory();
Glide.get(this).clearMemory();
}
}

View File

@@ -0,0 +1,74 @@
package com.ttstd.sn.ui.base;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.ttstd.sn.R;
import com.ttstd.sn.ui.base.rx.BaseRxActivity;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
public abstract class BaseDataBindingActivity extends BaseRxActivity {
public BaseDataBindingActivity() {
super();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// StatusBarUtil.init(this);
if (initBar()) {
UltimateBarX.statusBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
UltimateBarX.navigationBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
}
initDataBinding();
initView();
initData();
}
public boolean initBar() {
return true;
}
/**
* @return 是否是黑色状态栏
*/
// protected abstract boolean setNightMode();
public boolean setNightMode() {
return false;
}
/**
* @return 是否是入侵
*/
// protected abstract boolean setNightMode();
public boolean setfitWindow() {
return false;
}
protected abstract void initDataBinding();
/**
* 初始化视图
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
}

View File

@@ -0,0 +1,51 @@
package com.ttstd.sn.ui.base;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.ttstd.sn.R;
import com.ttstd.sn.ui.base.rx.BaseRxActivity;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
public abstract class BaseTransparentActivity extends BaseRxActivity {
public BaseTransparentActivity() {
super();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// StatusBarUtil.init(this);
UltimateBarX.statusBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
UltimateBarX.navigationBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
}
/**
* 设置布局
*/
protected abstract int getLayoutId();
/**
* @return 是否是黑色状态栏
*/
protected abstract boolean setNightMode();
/**
* @return 是否是入侵
*/
protected abstract boolean setfitWindow();
}

View File

@@ -0,0 +1,192 @@
package com.ttstd.sn.ui.base;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Process;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
public class GlobalCrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
private static GlobalCrashHandler instance;
private Context context;
private UncaughtExceptionHandler defaultHandler;
private Class<?> restartActivityClass;
private GlobalCrashHandler() {
}
public static GlobalCrashHandler getInstance() {
if (instance == null) {
synchronized (GlobalCrashHandler.class) {
if (instance == null) {
instance = new GlobalCrashHandler();
}
}
}
return instance;
}
/**
* 初始化全局异常捕获
*
* @param context App Context
* @param restartActivityClass 崩溃后重新打开的 Activity,可传 MainActivity.class
*/
public void init(Context context, Class<?> restartActivityClass) {
this.context = context.getApplicationContext();
this.restartActivityClass = restartActivityClass;
// 保存系统默认异常处理器
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置当前类为全局异常处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
try {
handleException(thread, throwable);
} catch (Exception e) {
Log.e(TAG, "handle crash failed", e);
}
// 稍微等待一下,确保日志写入完成
try {
Thread.sleep(800);
} catch (InterruptedException ignored) {
}
// 重启 App
restartAppByAlarm();
// 杀死当前进程
Process.killProcess(Process.myPid());
System.exit(10);
}
private void handleException(Thread thread, Throwable throwable) {
if (throwable == null) {
return;
}
String crashInfo = getCrashInfo(thread, throwable);
Log.e(TAG, crashInfo);
// 这里可以做本地保存
saveCrashToLocal(crashInfo);
// 这里可以做服务器上报
uploadCrashToServer(crashInfo);
}
private String getCrashInfo(Thread thread, Throwable throwable) {
StringBuilder sb = new StringBuilder();
sb.append("========== Crash Start ==========\n");
sb.append("Thread: ").append(thread.getName()).append("\n\n");
sb.append("Device Info:\n");
sb.append("Brand: ").append(Build.BRAND).append("\n");
sb.append("Model: ").append(Build.MODEL).append("\n");
sb.append("Manufacturer: ").append(Build.MANUFACTURER).append("\n");
sb.append("Android Version: ").append(Build.VERSION.RELEASE).append("\n");
sb.append("SDK: ").append(Build.VERSION.SDK_INT).append("\n\n");
sb.append("Exception:\n");
sb.append(getStackTrace(throwable));
sb.append("\n========== Crash End ==========\n");
return sb.toString();
}
private String getStackTrace(Throwable throwable) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
pw.close();
return sw.toString();
}
private void saveCrashToLocal(String crashInfo) {
// 你可以写入文件,例如:
// /Android/data/你的包名/files/crash/crash_xxx.log
try {
File dir = new File(context.getExternalFilesDir(null), "crash");
if (!dir.exists()) {
dir.mkdirs();
}
String fileName = "crash_" + System.currentTimeMillis() + ".log";
File file = new File(dir, fileName);
FileOutputStream fos = new FileOutputStream(file);
fos.write(crashInfo.getBytes("UTF-8"));
fos.flush();
fos.close();
Log.e(TAG, "crash log saved: " + file.getAbsolutePath());
} catch (Exception e) {
Log.e(TAG, "save crash log failed", e);
}
}
private void uploadCrashToServer(String crashInfo) {
// 这里可以异步上传到服务器
// 注意:崩溃时进程即将退出,不建议做太耗时操作
Log.e(TAG, "uploadCrashToServer");
}
private void restartApp() {
if (context == null || restartActivityClass == null) {
return;
}
Intent intent = new Intent(context, restartActivityClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
}
private void restartAppByAlarm() {
if (context == null || restartActivityClass == null) {
return;
}
Intent intent = new Intent(context, restartActivityClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
android.app.PendingIntent pendingIntent = android.app.PendingIntent.getActivity(
context,
10086,
intent,
android.app.PendingIntent.FLAG_ONE_SHOT | android.app.PendingIntent.FLAG_IMMUTABLE
);
android.app.AlarmManager alarmManager =
(android.app.AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.set(
android.app.AlarmManager.RTC,
System.currentTimeMillis() + 1000,
pendingIntent
);
}
}
}

View File

@@ -0,0 +1,75 @@
package com.ttstd.sn.ui.base.mvvm;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModelProvider;
import com.ttstd.sn.ui.base.BaseTransparentActivity;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
/**
* MVVM 基类 Activity。
* <p>
* 采用 Android 标准 MVVM 架构:
* - ViewModel 通过 {@link ViewModelProvider} 创建,生命周期由系统统一管理;
* - 通过 DataBinding 将数据与 UI 绑定,UI 变化自动反映到绑定数据上;
* - ViewModel 不持有 Activity / Context 引用,避免内存泄漏。
*
* @param <VM> ViewModel 类型,需继承 {@link BaseViewModel}
* @param <VDB> 页面数据绑定类型,需继承 {@link ViewDataBinding}
*/
public abstract class BaseMvvmActivity<VM extends BaseViewModel<VDB>, VDB extends ViewDataBinding> extends BaseTransparentActivity {
protected VM mViewModel;
protected VDB mViewDataBinding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ViewDataBinding
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
mViewDataBinding.setLifecycleOwner(this);
// ViewModel(Android 标准:通过 ViewModelProvider 创建)
mViewModel = createViewModel();
if (mViewModel != null) {
mViewModel.setVDBinding(mViewDataBinding);
}
initDataBinding();
initView();
initData();
}
/**
* 创建 ViewModel 实例,默认根据泛型参数通过 {@link ViewModelProvider} 反射创建。
* 子类如需自定义 ViewModel 创建方式,可重写此方法。
*
* @return ViewModel 实例;若泛型类型为抽象类则返回 null
*/
protected VM createViewModel() {
Class<VM> vmClass = (Class<VM>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
if (Modifier.isAbstract(vmClass.getModifiers())) {
return null;
}
return new ViewModelProvider(this).get(vmClass);
}
/**
* 初始化数据绑定(在 ViewModel 创建并注入 binding 后调用)
*/
protected abstract void initDataBinding();
/**
* 初始化视图
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
}

View File

@@ -0,0 +1,48 @@
package com.ttstd.sn.ui.base.mvvm;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModel;
/**
* 所有 ViewModel 的基类。
* <p>
* 采用 Android 标准 MVVM 架构:
* 1. ViewModel 继承自 {@link ViewModel},生命周期由系统(ViewModelStore)统一管理;
* 2. ViewModel 不持有 Context / Activity 引用,避免内存泄漏;
* 3. 通过数据绑定(DataBinding)将 UI 与 ViewModel 中的数据建立绑定关系。
*
* @param <VDB> 当前 ViewModel 对应的页面数据绑定类型
*/
public abstract class BaseViewModel<VDB extends ViewDataBinding> extends ViewModel {
/**
* 当前 ViewModel 对应的页面 binding
*/
protected VDB binding;
/**
* 注入数据绑定实例(由 View 层在初始化时调用)
*
* @param binding 页面数据绑定实例
*/
public void setVDBinding(VDB binding) {
this.binding = binding;
}
/**
* 获取数据绑定实例
*
* @return 页面数据绑定实例
*/
public VDB getVDBinding() {
if (binding == null) {
throw new NullPointerException("BaseViewModel >> getVDBinding >> null!!!");
}
return binding;
}
/**
* 页面销毁时清理资源(由 View 层在 onDestroy 时调用)
*/
public abstract void onDestroy();
}

View File

@@ -0,0 +1,93 @@
package com.ttstd.sn.ui.base.rx;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
/**
* {@link com.trello.rxlifecycle4.components.RxActivity}
* copied form RxActivity}
*/
public abstract class BaseRxActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public BehaviorSubject<ActivityEvent> getLifecycleSubject() {
return lifecycleSubject;
}
@Override
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
@CallSuper
protected void onStart() {
super.onStart();
lifecycleSubject.onNext(ActivityEvent.START);
}
@Override
@CallSuper
protected void onResume() {
super.onResume();
lifecycleSubject.onNext(ActivityEvent.RESUME);
}
@Override
@CallSuper
protected void onPause() {
lifecycleSubject.onNext(ActivityEvent.PAUSE);
super.onPause();
}
@Override
@CallSuper
protected void onStop() {
lifecycleSubject.onNext(ActivityEvent.STOP);
super.onStop();
}
@Override
@CallSuper
protected void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}

View File

@@ -0,0 +1,52 @@
package com.ttstd.sn.ui.base.rx;
import android.app.Service;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import org.jetbrains.annotations.NotNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public abstract class BaseRxService extends Service implements LifecycleProvider<ActivityEvent> {
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public BehaviorSubject<ActivityEvent> getLifecycleSubject() {
return lifecycleSubject;
}
@NotNull
@Override
public Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@NotNull
@Override
public <T> LifecycleTransformer<T> bindUntilEvent(@NotNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@NotNull
@Override
public <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
public void onCreate() {
super.onCreate();
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycleSubject.onNext(ActivityEvent.DESTROY);
}
}

View File

@@ -0,0 +1,179 @@
package com.ttstd.sn.ui.main;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.CompoundButton;
import com.ttstd.sn.R;
import com.ttstd.sn.mdm.AdminManager;
import com.ttstd.sn.databinding.ActivityMainBinding;
import com.ttstd.sn.receiver.AoleDeviceAdminReceiver;
import com.ttstd.sn.ui.base.mvvm.BaseMvvmActivity;
import com.hihonor.android.app.admin.DeviceApplicationManager;
import com.hihonor.android.app.admin.DeviceControlManager;
import com.hihonor.android.app.admin.DeviceHwSystemManager;
import com.hihonor.android.app.admin.DevicePackageManager;
import com.hihonor.android.app.admin.DevicePasswordManager;
import com.hihonor.android.app.admin.DeviceRestrictionManager;
import com.hihonor.android.app.admin.DeviceSettingsManager;
public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBinding> {
private static final String TAG = "DebugActivity";
private DevicePolicyManager mDevicePolicyManager;
private DeviceRestrictionManager mDeviceRestrictionManager;
private DeviceControlManager mDeviceControlManager;
private DeviceApplicationManager mDeviceApplicationManager;
private DeviceHwSystemManager mDeviceHwSystemManager;
private DeviceSettingsManager mDeviceSettingsManager;
private DevicePasswordManager mDevicePasswordManager;
/*设备包管理类*/
private DevicePackageManager mDevicePackageManager;
private ComponentName mAdminName;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected boolean setNightMode() {
return true;
}
@Override
protected boolean setfitWindow() {
return false;
}
@Override
protected void initDataBinding() {
mViewDataBinding.setClick(new BtnClick());
}
@Override
protected void initView() {
mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mAdminName = new ComponentName(this, AoleDeviceAdminReceiver.class);
mDeviceRestrictionManager = new DeviceRestrictionManager();
mDeviceControlManager = new DeviceControlManager();
mDeviceApplicationManager = new DeviceApplicationManager();
mDeviceHwSystemManager = new DeviceHwSystemManager();
mDeviceSettingsManager = new DeviceSettingsManager();
mDevicePackageManager = new DevicePackageManager();
mDevicePasswordManager = new DevicePasswordManager();
mViewDataBinding.swWindow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
try {
mDeviceRestrictionManager.setMultiWindowDisabled(mAdminName, isChecked);
} catch (Exception e) {
Log.e(TAG, "onCheckedChanged: " + e.getMessage());
}
}
});
mViewDataBinding.swYoyo.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDeviceRestrictionManager.setVoiceAssistantButtonDisabled(mAdminName, isChecked);
if (isChecked) {
AdminManager.getInstance().removeDisallowedRunningApp("com.hihonor.servicecenter");
} else {
AdminManager.getInstance().addDisallowedRunningApp("com.hihonor.servicecenter");
}
}
});
mViewDataBinding.swRestore.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDeviceSettingsManager.setRestoreFactoryDisabled(mAdminName, isChecked);
}
});
mViewDataBinding.swUsbDebug.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDeviceRestrictionManager.setUSBDataDisabled(mAdminName, isChecked);
mDeviceControlManager.turnOnUsbDebugMode(mAdminName, !isChecked);
}
});
mViewDataBinding.swRemoveAdmin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mDeviceControlManager.setForcedActiveDeviceAdmin(mAdminName, MainActivity.this);
} else {
mDeviceControlManager.removeActiveDeviceAdmin(mAdminName);
mDeviceControlManager.clearDeviceOwnerApp();
}
}
});
mViewDataBinding.swQuickTools.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
try {
mDevicePasswordManager.setQuickToolsDisabled(mAdminName, isChecked);
} catch (Exception e) {
Log.e(TAG, "onCheckedChanged: " + e.getMessage());
}
}
});
}
@Override
protected void initData() {
}
@Override
protected void onResume() {
super.onResume();
getAdminStatus();
}
private void getAdminStatus() {
if (isActiveMe()) {
mViewDataBinding.tvAdmin.setText("已激活");
mViewDataBinding.swWindow.setChecked(mDeviceRestrictionManager.isMultiWindowDisabled(mAdminName));
mViewDataBinding.swYoyo.setChecked(mDeviceRestrictionManager.isVoiceAssistantButtonDisabled(mAdminName));
mViewDataBinding.swRestore.setChecked(mDeviceSettingsManager.isRestoreFactoryDisabled(mAdminName));
mViewDataBinding.swUsbDebug.setChecked(mDeviceRestrictionManager.isUSBDataDisabled(mAdminName));
mViewDataBinding.swRemoveAdmin.setChecked(mDeviceControlManager.isForcedActiveDeviceAdmin(mAdminName));
mViewDataBinding.swQuickTools.setChecked(mDevicePasswordManager.isQuickToolsDisabled(mAdminName));
} else {
mViewDataBinding.tvAdmin.setText("未激活");
}
}
/**
* 判断是否激活
*
* @return
*/
private boolean isActiveMe() {
boolean active;
if (mDevicePolicyManager == null) {
active = false;
} else {
active = mDevicePolicyManager.isAdminActive(mAdminName);
}
Log.e(TAG, "isActiveMe: active = " + active);
return active;
}
public class BtnClick {
public void refresh(View view) {
getAdminStatus();
}
}
}

View File

@@ -0,0 +1,109 @@
package com.ttstd.sn.ui.main;
/**
* 主界面 UI 状态。
* <p>
* 采用不可变数据类保存页面渲染所需的状态,
* 由 {@link MainViewModel} 持有并通过观察者(如 LiveData)下发给 View 层。
*/
public class MainUiState {
private final boolean deviceAdminActive;
private final boolean multiWindowDisabled;
private final boolean voiceAssistantDisabled;
private final boolean restoreFactoryDisabled;
private final boolean usbDebugDisabled;
private final boolean forcedDeviceAdmin;
private final boolean quickToolsDisabled;
private MainUiState(Builder builder) {
this.deviceAdminActive = builder.deviceAdminActive;
this.multiWindowDisabled = builder.multiWindowDisabled;
this.voiceAssistantDisabled = builder.voiceAssistantDisabled;
this.restoreFactoryDisabled = builder.restoreFactoryDisabled;
this.usbDebugDisabled = builder.usbDebugDisabled;
this.forcedDeviceAdmin = builder.forcedDeviceAdmin;
this.quickToolsDisabled = builder.quickToolsDisabled;
}
public boolean isDeviceAdminActive() {
return deviceAdminActive;
}
public boolean isMultiWindowDisabled() {
return multiWindowDisabled;
}
public boolean isVoiceAssistantDisabled() {
return voiceAssistantDisabled;
}
public boolean isRestoreFactoryDisabled() {
return restoreFactoryDisabled;
}
public boolean isUsbDebugDisabled() {
return usbDebugDisabled;
}
public boolean isForcedDeviceAdmin() {
return forcedDeviceAdmin;
}
public boolean isQuickToolsDisabled() {
return quickToolsDisabled;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private boolean deviceAdminActive;
private boolean multiWindowDisabled;
private boolean voiceAssistantDisabled;
private boolean restoreFactoryDisabled;
private boolean usbDebugDisabled;
private boolean forcedDeviceAdmin;
private boolean quickToolsDisabled;
public Builder deviceAdminActive(boolean deviceAdminActive) {
this.deviceAdminActive = deviceAdminActive;
return this;
}
public Builder multiWindowDisabled(boolean multiWindowDisabled) {
this.multiWindowDisabled = multiWindowDisabled;
return this;
}
public Builder voiceAssistantDisabled(boolean voiceAssistantDisabled) {
this.voiceAssistantDisabled = voiceAssistantDisabled;
return this;
}
public Builder restoreFactoryDisabled(boolean restoreFactoryDisabled) {
this.restoreFactoryDisabled = restoreFactoryDisabled;
return this;
}
public Builder usbDebugDisabled(boolean usbDebugDisabled) {
this.usbDebugDisabled = usbDebugDisabled;
return this;
}
public Builder forcedDeviceAdmin(boolean forcedDeviceAdmin) {
this.forcedDeviceAdmin = forcedDeviceAdmin;
return this;
}
public Builder quickToolsDisabled(boolean quickToolsDisabled) {
this.quickToolsDisabled = quickToolsDisabled;
return this;
}
public MainUiState build() {
return new MainUiState(this);
}
}
}

View File

@@ -0,0 +1,17 @@
package com.ttstd.sn.ui.main;
import com.ttstd.sn.databinding.ActivityMainBinding;
import com.ttstd.sn.ui.base.mvvm.BaseViewModel;
public class MainViewModel extends BaseViewModel<ActivityMainBinding> {
@Override
public ActivityMainBinding getVDBinding() {
return binding;
}
@Override
public void onDestroy() {
}
}

View File

@@ -0,0 +1,73 @@
package com.ttstd.sn.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
* 日期时间工具类
*/
public class DateUtils {
public static final String PATTERN_DATE = "yyyy-MM-dd";
public static final String PATTERN_TIME = "HH:mm:ss";
public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
public static final String PATTERN_DATETIME_COMPACT = "yyyyMMdd_HHmmss";
private DateUtils() {
}
/**
* 将时间戳格式化为指定格式的字符串
*
* @param timestamp 毫秒时间戳
* @param pattern 日期格式
*/
public static String format(long timestamp, String pattern) {
return new SimpleDateFormat(pattern, Locale.getDefault()).format(new Date(timestamp));
}
/**
* 将 Date 格式化为指定格式的字符串
*/
public static String format(Date date, String pattern) {
if (date == null) return "";
return new SimpleDateFormat(pattern, Locale.getDefault()).format(date);
}
/**
* 解析字符串为时间戳
*
* @param time 日期字符串
* @param pattern 日期格式
* @return 毫秒时间戳;解析失败返回 -1
*/
public static long parse(String time, String pattern) {
if (time == null || time.trim().isEmpty()) return -1;
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.getDefault());
try {
Date date = sdf.parse(time);
return date == null ? -1 : date.getTime();
} catch (ParseException e) {
return -1;
}
}
/**
* 当前毫秒时间戳
*/
public static long now() {
return System.currentTimeMillis();
}
/**
* 获取指定时区的当前时间
*/
public static String now(String pattern, String timeZoneId) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.getDefault());
sdf.setTimeZone(TimeZone.getTimeZone(timeZoneId));
return sdf.format(new Date());
}
}

View File

@@ -0,0 +1,84 @@
package com.ttstd.sn.utils;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
/**
* 网络工具类
*/
public class NetworkUtils {
private NetworkUtils() {
}
/**
* 判断当前是否有可用网络连接
*/
public static boolean isNetworkAvailable(Context context) {
if (context == null) return false;
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) return false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network network = cm.getActiveNetwork();
if (network == null) return false;
NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
return capabilities != null
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
}
@SuppressWarnings("deprecation")
NetworkInfo activeInfo = cm.getActiveNetworkInfo();
return activeInfo != null && activeInfo.isConnected();
}
/**
* 判断当前是否为 WIFI 网络
*/
public static boolean isWifi(Context context) {
if (context == null) return false;
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) return false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network network = cm.getActiveNetwork();
if (network == null) return false;
NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
return capabilities != null
&& capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
}
@SuppressWarnings("deprecation")
NetworkInfo activeInfo = cm.getActiveNetworkInfo();
return activeInfo != null
&& activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
}
/**
* 判断当前是否为移动网络
*/
public static boolean isMobileData(Context context) {
if (context == null) return false;
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) return false;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network network = cm.getActiveNetwork();
if (network == null) return false;
NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
return capabilities != null
&& capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
}
@SuppressWarnings("deprecation")
NetworkInfo activeInfo = cm.getActiveNetworkInfo();
return activeInfo != null
&& activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 内部颜色 -->
<solid android:color="@color/check_update_color" />
<!-- 圆角的幅度 -->
<corners
android:bottomLeftRadius="@dimen/dp_16"
android:bottomRightRadius="@dimen/dp_16"
android:topLeftRadius="@dimen/dp_16"
android:topRightRadius="@dimen/dp_16" />
<padding
android:bottom="@dimen/dp_4"
android:left="@dimen/dp_10"
android:right="@dimen/dp_10"
android:top="@dimen/dp_4" />
</shape>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 内部颜色 -->
<!-- 圆角的幅度 -->
<corners android:radius="12dp" />
<solid android:color="@color/white" />
<!-- <gradient-->
<!-- android:angle="270"-->
<!-- android:endColor="#404d6c"-->
<!-- android:startColor="#606c88" />-->
<!-- <padding-->
<!-- android:bottom="0dp"-->
<!-- android:left="8dp"-->
<!-- android:right="8dp"-->
<!-- android:top="0dp" />-->
</shape>

View File

@@ -0,0 +1,338 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.main.MainActivity">
<data>
<variable
name="click"
type="com.ttstd.sn.ui.main.MainActivity.BtnClick" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/main_card_bg"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="设备管理器激活状态"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_admin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:maxLength="30"
android:singleLine="true"
android:text="@string/unknown"
android:textColor="@color/textColor"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="禁止解除激活"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/sw_remove_admin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="禁用智慧窗口"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/sw_window"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="禁用yoyo助手"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/sw_yoyo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="禁止恢复出厂设置"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/sw_restore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="禁止USB调试"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/sw_usb_debug"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_weight="1"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="禁用锁屏工具栏"
android:textColor="@color/textColor"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/sw_quick_tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1px"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="@color/background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/main_card_bg"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_weight="1"
android:background="@drawable/bt_blue_background"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="刷新"
android:onClick="@{click::refresh}"
android:textColor="@color/white"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#efefef</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#4880ff</color>
<!-- <color name="colorPrimary">#3F51B5</color>-->
<!-- <color name="colorPrimaryDark">#303F9F</color>-->
<!-- <color name="colorAccent">#FF4081</color>-->
<color name="textColor">#ff797979</color>
<color name="topcolor">#878686</color>
<color name="white">#ffffff</color>
<color name="background_top">#d3d1d1</color>
<color name="top_bannar_background">#383749</color>
<color name="black">#E6000000</color>
<color name="black_50_opacity">#80000000</color>
<color name="white_transparency">#00ffffff</color>
<color name="yellow">#FFF45C</color>
<color name="gray">#80808080</color>
<color name="green_color">#00EE76</color>
<color name="babyline_color">#B44600</color>
<color name="backbg_color">#80000000</color>
<color name="baby_color">#C55C00</color>
<color name="young_textcolor">#BF5D13</color>
<color name="course_color">#F19149</color>
<color name="dialog_color">#626C4C</color>
<color name="charging_background_color">#023E6C</color>
<color name="appstore_bg_color">#A3D568</color>
<color name="appstore_btn_color">#F69200</color>
<color name="rangeseekbar_color">#18B6B1</color>
<color name="addwindow_color">#07BA63</color>
<color name="french_gray">#BEBDBF</color>
<color name="notify_progress_bg">#999999</color>
<color name="blue">#68cc21</color>
<color name="appstore_top_tab_line_color">#797979</color>
<color name="item_recommened_btn_color">#B3B1B1</color>
<color name="main_color">#00a0e9</color>
<!--<color name="main_bg_color">#eeeeee</color>-->
<color name="main_bg_color">@color/white</color>
<color name="main_text_color">#ff797979</color>
<color name="main_green_color">#55b68a</color>
<color name="appstore_selecte_color">#8f82bc</color>
<color name="check_update_color">#4880ff</color>
<color name="check_update_color_pressed">#3e76f6</color>
<color name="check_activation_color">#D3D3D3</color>
<color name="title_textcolor">#494949</color>
<color name="toast_color">#CD000000</color>
<color name="activation_color">#4880ff</color>
<color name="bt_join_background_color">#4880ff</color>
<color name="bt_joined_background_color">#D1D1D1</color>
<color name="bt_trial_color">#F19149</color>
<color name="text_gray">#9a9a9a</color>
<color name="text_black">#1f1f1f</color>
<color name="text_hint_gray">#989898</color>
</resources>

View File

@@ -0,0 +1,451 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<!-- Your custom size defind by references, can be writted in anywhere, any module, any values/*.xml, for example: -->
<dimen name="common_margin">@dimen/dp_15</dimen>
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<!-- dp and sp values, must be defind in this file! -->
<!-- view size,you can add if there is no one -->
<dimen name="dp_m_60">-60dp</dimen>
<dimen name="dp_m_30">-30dp</dimen>
<dimen name="dp_m_20">-20dp</dimen>
<dimen name="dp_m_12">-12dp</dimen>
<dimen name="dp_m_10">-10dp</dimen>
<dimen name="dp_m_8">-8dp</dimen>
<dimen name="dp_m_5">-5dp</dimen>
<dimen name="dp_m_2">-2dp</dimen>
<dimen name="dp_m_1">-1dp</dimen>
<dimen name="dp_0">0dp</dimen>
<dimen name="dp_0_1">0.1dp</dimen>
<dimen name="dp_0_5">0.5dp</dimen>
<dimen name="dp_1">1dp</dimen>
<dimen name="dp_1_5">1.5dp</dimen>
<dimen name="dp_2">2dp</dimen>
<dimen name="dp_2_5">2.5dp</dimen>
<dimen name="dp_3">3dp</dimen>
<dimen name="dp_3_5">3.5dp</dimen>
<dimen name="dp_4">4dp</dimen>
<dimen name="dp_4_5">4.5dp</dimen>
<dimen name="dp_5">5dp</dimen>
<dimen name="dp_6">6dp</dimen>
<dimen name="dp_7">7dp</dimen>
<dimen name="dp_8">8dp</dimen>
<dimen name="dp_9">9dp</dimen>
<dimen name="dp_10">10dp</dimen>
<dimen name="dp_11">11dp</dimen>
<dimen name="dp_12">12dp</dimen>
<dimen name="dp_13">13dp</dimen>
<dimen name="dp_14">14dp</dimen>
<dimen name="dp_15">15dp</dimen>
<dimen name="dp_16">16dp</dimen>
<dimen name="dp_17">17dp</dimen>
<dimen name="dp_18">18dp</dimen>
<dimen name="dp_19">19dp</dimen>
<dimen name="dp_20">20dp</dimen>
<dimen name="dp_21">21dp</dimen>
<dimen name="dp_22">22dp</dimen>
<dimen name="dp_23">23dp</dimen>
<dimen name="dp_24">24dp</dimen>
<dimen name="dp_25">25dp</dimen>
<dimen name="dp_26">26dp</dimen>
<dimen name="dp_27">27dp</dimen>
<dimen name="dp_28">28dp</dimen>
<dimen name="dp_29">29dp</dimen>
<dimen name="dp_30">30dp</dimen>
<dimen name="dp_31">31dp</dimen>
<dimen name="dp_32">32dp</dimen>
<dimen name="dp_33">33dp</dimen>
<dimen name="dp_34">34dp</dimen>
<dimen name="dp_35">35dp</dimen>
<dimen name="dp_36">36dp</dimen>
<dimen name="dp_37">37dp</dimen>
<dimen name="dp_38">38dp</dimen>
<dimen name="dp_39">39dp</dimen>
<dimen name="dp_40">40dp</dimen>
<dimen name="dp_41">41dp</dimen>
<dimen name="dp_42">42dp</dimen>
<dimen name="dp_43">43dp</dimen>
<dimen name="dp_44">44dp</dimen>
<dimen name="dp_45">45dp</dimen>
<dimen name="dp_46">46dp</dimen>
<dimen name="dp_47">47dp</dimen>
<dimen name="dp_48">48dp</dimen>
<dimen name="dp_49">49dp</dimen>
<dimen name="dp_50">50dp</dimen>
<dimen name="dp_51">51dp</dimen>
<dimen name="dp_52">52dp</dimen>
<dimen name="dp_53">53dp</dimen>
<dimen name="dp_54">54dp</dimen>
<dimen name="dp_55">55dp</dimen>
<dimen name="dp_56">56dp</dimen>
<dimen name="dp_57">57dp</dimen>
<dimen name="dp_58">58dp</dimen>
<dimen name="dp_59">59dp</dimen>
<dimen name="dp_60">60dp</dimen>
<dimen name="dp_61">61dp</dimen>
<dimen name="dp_62">62dp</dimen>
<dimen name="dp_63">63dp</dimen>
<dimen name="dp_64">64dp</dimen>
<dimen name="dp_65">65dp</dimen>
<dimen name="dp_66">66dp</dimen>
<dimen name="dp_67">67dp</dimen>
<dimen name="dp_68">68dp</dimen>
<dimen name="dp_69">69dp</dimen>
<dimen name="dp_70">70dp</dimen>
<dimen name="dp_71">71dp</dimen>
<dimen name="dp_72">72dp</dimen>
<dimen name="dp_73">73dp</dimen>
<dimen name="dp_74">74dp</dimen>
<dimen name="dp_75">75dp</dimen>
<dimen name="dp_76">76dp</dimen>
<dimen name="dp_77">77dp</dimen>
<dimen name="dp_78">78dp</dimen>
<dimen name="dp_79">79dp</dimen>
<dimen name="dp_80">80dp</dimen>
<dimen name="dp_81">81dp</dimen>
<dimen name="dp_82">82dp</dimen>
<dimen name="dp_83">83dp</dimen>
<dimen name="dp_84">84dp</dimen>
<dimen name="dp_85">85dp</dimen>
<dimen name="dp_86">86dp</dimen>
<dimen name="dp_87">87dp</dimen>
<dimen name="dp_88">88dp</dimen>
<dimen name="dp_89">89dp</dimen>
<dimen name="dp_90">90dp</dimen>
<dimen name="dp_91">91dp</dimen>
<dimen name="dp_92">92dp</dimen>
<dimen name="dp_93">93dp</dimen>
<dimen name="dp_94">94dp</dimen>
<dimen name="dp_95">95dp</dimen>
<dimen name="dp_96">96dp</dimen>
<dimen name="dp_97">97dp</dimen>
<dimen name="dp_98">98dp</dimen>
<dimen name="dp_99">99dp</dimen>
<dimen name="dp_100">100dp</dimen>
<dimen name="dp_101">101dp</dimen>
<dimen name="dp_102">102dp</dimen>
<dimen name="dp_103">103dp</dimen>
<dimen name="dp_104">104dp</dimen>
<dimen name="dp_105">105dp</dimen>
<dimen name="dp_106">106dp</dimen>
<dimen name="dp_107">107dp</dimen>
<dimen name="dp_108">108dp</dimen>
<dimen name="dp_109">109dp</dimen>
<dimen name="dp_110">110dp</dimen>
<dimen name="dp_111">111dp</dimen>
<dimen name="dp_112">112dp</dimen>
<dimen name="dp_113">113dp</dimen>
<dimen name="dp_114">114dp</dimen>
<dimen name="dp_115">115dp</dimen>
<dimen name="dp_116">116dp</dimen>
<dimen name="dp_117">117dp</dimen>
<dimen name="dp_118">118dp</dimen>
<dimen name="dp_119">119dp</dimen>
<dimen name="dp_120">120dp</dimen>
<dimen name="dp_121">121dp</dimen>
<dimen name="dp_122">122dp</dimen>
<dimen name="dp_123">123dp</dimen>
<dimen name="dp_124">124dp</dimen>
<dimen name="dp_125">125dp</dimen>
<dimen name="dp_126">126dp</dimen>
<dimen name="dp_127">127dp</dimen>
<dimen name="dp_128">128dp</dimen>
<dimen name="dp_129">129dp</dimen>
<dimen name="dp_130">130dp</dimen>
<dimen name="dp_131">131dp</dimen>
<dimen name="dp_132">132dp</dimen>
<dimen name="dp_133">133dp</dimen>
<dimen name="dp_134">134dp</dimen>
<dimen name="dp_135">135dp</dimen>
<dimen name="dp_136">136dp</dimen>
<dimen name="dp_137">137dp</dimen>
<dimen name="dp_138">138dp</dimen>
<dimen name="dp_139">139dp</dimen>
<dimen name="dp_140">140dp</dimen>
<dimen name="dp_141">141dp</dimen>
<dimen name="dp_142">142dp</dimen>
<dimen name="dp_143">143dp</dimen>
<dimen name="dp_144">144dp</dimen>
<dimen name="dp_145">145dp</dimen>
<dimen name="dp_146">146dp</dimen>
<dimen name="dp_147">147dp</dimen>
<dimen name="dp_148">148dp</dimen>
<dimen name="dp_149">149dp</dimen>
<dimen name="dp_150">150dp</dimen>
<dimen name="dp_151">151dp</dimen>
<dimen name="dp_152">152dp</dimen>
<dimen name="dp_153">153dp</dimen>
<dimen name="dp_154">154dp</dimen>
<dimen name="dp_155">155dp</dimen>
<dimen name="dp_156">156dp</dimen>
<dimen name="dp_157">157dp</dimen>
<dimen name="dp_158">158dp</dimen>
<dimen name="dp_159">159dp</dimen>
<dimen name="dp_160">160dp</dimen>
<dimen name="dp_161">161dp</dimen>
<dimen name="dp_162">162dp</dimen>
<dimen name="dp_163">163dp</dimen>
<dimen name="dp_164">164dp</dimen>
<dimen name="dp_165">165dp</dimen>
<dimen name="dp_166">166dp</dimen>
<dimen name="dp_167">167dp</dimen>
<dimen name="dp_168">168dp</dimen>
<dimen name="dp_169">169dp</dimen>
<dimen name="dp_170">170dp</dimen>
<dimen name="dp_171">171dp</dimen>
<dimen name="dp_172">172dp</dimen>
<dimen name="dp_173">173dp</dimen>
<dimen name="dp_174">174dp</dimen>
<dimen name="dp_175">175dp</dimen>
<dimen name="dp_176">176dp</dimen>
<dimen name="dp_177">177dp</dimen>
<dimen name="dp_178">178dp</dimen>
<dimen name="dp_179">179dp</dimen>
<dimen name="dp_180">180dp</dimen>
<dimen name="dp_181">181dp</dimen>
<dimen name="dp_182">182dp</dimen>
<dimen name="dp_183">183dp</dimen>
<dimen name="dp_184">184dp</dimen>
<dimen name="dp_185">185dp</dimen>
<dimen name="dp_186">186dp</dimen>
<dimen name="dp_187">187dp</dimen>
<dimen name="dp_188">188dp</dimen>
<dimen name="dp_189">189dp</dimen>
<dimen name="dp_190">190dp</dimen>
<dimen name="dp_191">191dp</dimen>
<dimen name="dp_192">192dp</dimen>
<dimen name="dp_193">193dp</dimen>
<dimen name="dp_194">194dp</dimen>
<dimen name="dp_195">195dp</dimen>
<dimen name="dp_196">196dp</dimen>
<dimen name="dp_197">197dp</dimen>
<dimen name="dp_198">198dp</dimen>
<dimen name="dp_199">199dp</dimen>
<dimen name="dp_200">200dp</dimen>
<dimen name="dp_201">201dp</dimen>
<dimen name="dp_202">202dp</dimen>
<dimen name="dp_203">203dp</dimen>
<dimen name="dp_204">204dp</dimen>
<dimen name="dp_205">205dp</dimen>
<dimen name="dp_206">206dp</dimen>
<dimen name="dp_207">207dp</dimen>
<dimen name="dp_208">208dp</dimen>
<dimen name="dp_209">209dp</dimen>
<dimen name="dp_210">210dp</dimen>
<dimen name="dp_211">211dp</dimen>
<dimen name="dp_212">212dp</dimen>
<dimen name="dp_213">213dp</dimen>
<dimen name="dp_214">214dp</dimen>
<dimen name="dp_215">215dp</dimen>
<dimen name="dp_216">216dp</dimen>
<dimen name="dp_217">217dp</dimen>
<dimen name="dp_218">218dp</dimen>
<dimen name="dp_219">219dp</dimen>
<dimen name="dp_220">220dp</dimen>
<dimen name="dp_221">221dp</dimen>
<dimen name="dp_222">222dp</dimen>
<dimen name="dp_223">223dp</dimen>
<dimen name="dp_224">224dp</dimen>
<dimen name="dp_225">225dp</dimen>
<dimen name="dp_226">226dp</dimen>
<dimen name="dp_227">227dp</dimen>
<dimen name="dp_228">228dp</dimen>
<dimen name="dp_229">229dp</dimen>
<dimen name="dp_230">230dp</dimen>
<dimen name="dp_231">231dp</dimen>
<dimen name="dp_232">232dp</dimen>
<dimen name="dp_233">233dp</dimen>
<dimen name="dp_234">234dp</dimen>
<dimen name="dp_235">235dp</dimen>
<dimen name="dp_236">236dp</dimen>
<dimen name="dp_237">237dp</dimen>
<dimen name="dp_238">238dp</dimen>
<dimen name="dp_239">239dp</dimen>
<dimen name="dp_240">240dp</dimen>
<dimen name="dp_241">241dp</dimen>
<dimen name="dp_242">242dp</dimen>
<dimen name="dp_243">243dp</dimen>
<dimen name="dp_244">244dp</dimen>
<dimen name="dp_245">245dp</dimen>
<dimen name="dp_246">246dp</dimen>
<dimen name="dp_247">247dp</dimen>
<dimen name="dp_248">248dp</dimen>
<dimen name="dp_249">249dp</dimen>
<dimen name="dp_250">250dp</dimen>
<dimen name="dp_251">251dp</dimen>
<dimen name="dp_252">252dp</dimen>
<dimen name="dp_253">253dp</dimen>
<dimen name="dp_254">254dp</dimen>
<dimen name="dp_255">255dp</dimen>
<dimen name="dp_256">256dp</dimen>
<dimen name="dp_257">257dp</dimen>
<dimen name="dp_258">258dp</dimen>
<dimen name="dp_259">259dp</dimen>
<dimen name="dp_260">260dp</dimen>
<dimen name="dp_261">261dp</dimen>
<dimen name="dp_262">262dp</dimen>
<dimen name="dp_263">263dp</dimen>
<dimen name="dp_264">264dp</dimen>
<dimen name="dp_265">265dp</dimen>
<dimen name="dp_266">266dp</dimen>
<dimen name="dp_267">267dp</dimen>
<dimen name="dp_268">268dp</dimen>
<dimen name="dp_269">269dp</dimen>
<dimen name="dp_270">270dp</dimen>
<dimen name="dp_271">271dp</dimen>
<dimen name="dp_272">272dp</dimen>
<dimen name="dp_273">273dp</dimen>
<dimen name="dp_274">274dp</dimen>
<dimen name="dp_275">275dp</dimen>
<dimen name="dp_276">276dp</dimen>
<dimen name="dp_277">277dp</dimen>
<dimen name="dp_278">278dp</dimen>
<dimen name="dp_279">279dp</dimen>
<dimen name="dp_280">280dp</dimen>
<dimen name="dp_281">281dp</dimen>
<dimen name="dp_282">282dp</dimen>
<dimen name="dp_283">283dp</dimen>
<dimen name="dp_284">284dp</dimen>
<dimen name="dp_285">285dp</dimen>
<dimen name="dp_286">286dp</dimen>
<dimen name="dp_287">287dp</dimen>
<dimen name="dp_288">288dp</dimen>
<dimen name="dp_289">289dp</dimen>
<dimen name="dp_290">290dp</dimen>
<dimen name="dp_291">291dp</dimen>
<dimen name="dp_292">292dp</dimen>
<dimen name="dp_293">293dp</dimen>
<dimen name="dp_294">294dp</dimen>
<dimen name="dp_295">295dp</dimen>
<dimen name="dp_296">296dp</dimen>
<dimen name="dp_297">297dp</dimen>
<dimen name="dp_298">298dp</dimen>
<dimen name="dp_299">299dp</dimen>
<dimen name="dp_300">300dp</dimen>
<dimen name="dp_301">301dp</dimen>
<dimen name="dp_302">302dp</dimen>
<dimen name="dp_303">303dp</dimen>
<dimen name="dp_304">304dp</dimen>
<dimen name="dp_305">305dp</dimen>
<dimen name="dp_306">306dp</dimen>
<dimen name="dp_307">307dp</dimen>
<dimen name="dp_308">308dp</dimen>
<dimen name="dp_309">309dp</dimen>
<dimen name="dp_310">310dp</dimen>
<dimen name="dp_311">311dp</dimen>
<dimen name="dp_312">312dp</dimen>
<dimen name="dp_313">313dp</dimen>
<dimen name="dp_314">314dp</dimen>
<dimen name="dp_315">315dp</dimen>
<dimen name="dp_316">316dp</dimen>
<dimen name="dp_317">317dp</dimen>
<dimen name="dp_318">318dp</dimen>
<dimen name="dp_319">319dp</dimen>
<dimen name="dp_320">320dp</dimen>
<dimen name="dp_321">321dp</dimen>
<dimen name="dp_322">322dp</dimen>
<dimen name="dp_323">323dp</dimen>
<dimen name="dp_324">324dp</dimen>
<dimen name="dp_325">325dp</dimen>
<dimen name="dp_326">326dp</dimen>
<dimen name="dp_327">327dp</dimen>
<dimen name="dp_328">328dp</dimen>
<dimen name="dp_329">329dp</dimen>
<dimen name="dp_330">330dp</dimen>
<dimen name="dp_331">331dp</dimen>
<dimen name="dp_332">332dp</dimen>
<dimen name="dp_333">333dp</dimen>
<dimen name="dp_334">334dp</dimen>
<dimen name="dp_335">335dp</dimen>
<dimen name="dp_336">336dp</dimen>
<dimen name="dp_337">337dp</dimen>
<dimen name="dp_338">338dp</dimen>
<dimen name="dp_339">339dp</dimen>
<dimen name="dp_340">340dp</dimen>
<dimen name="dp_341">341dp</dimen>
<dimen name="dp_342">342dp</dimen>
<dimen name="dp_343">343dp</dimen>
<dimen name="dp_344">344dp</dimen>
<dimen name="dp_345">345dp</dimen>
<dimen name="dp_346">346dp</dimen>
<dimen name="dp_347">347dp</dimen>
<dimen name="dp_348">348dp</dimen>
<dimen name="dp_349">349dp</dimen>
<dimen name="dp_350">350dp</dimen>
<dimen name="dp_351">351dp</dimen>
<dimen name="dp_352">352dp</dimen>
<dimen name="dp_353">353dp</dimen>
<dimen name="dp_354">354dp</dimen>
<dimen name="dp_355">355dp</dimen>
<dimen name="dp_356">356dp</dimen>
<dimen name="dp_357">357dp</dimen>
<dimen name="dp_358">358dp</dimen>
<dimen name="dp_359">359dp</dimen>
<dimen name="dp_360">360dp</dimen>
<dimen name="dp_365">365dp</dimen>
<dimen name="dp_370">370dp</dimen>
<dimen name="dp_400">400dp</dimen>
<dimen name="dp_410">410dp</dimen>
<dimen name="dp_422">422dp</dimen>
<dimen name="dp_472">472dp</dimen>
<dimen name="dp_500">500dp</dimen>
<dimen name="dp_600">600dp</dimen>
<dimen name="dp_640">640dp</dimen>
<dimen name="dp_720">720dp</dimen>
<!-- font size,you can add if there is no one -->
<dimen name="sp_1">1sp</dimen>
<dimen name="sp_2">2sp</dimen>
<dimen name="sp_3">3sp</dimen>
<dimen name="sp_4">4sp</dimen>
<dimen name="sp_5">5sp</dimen>
<dimen name="sp_6">6sp</dimen>
<dimen name="sp_7">7sp</dimen>
<dimen name="sp_8">8sp</dimen>
<dimen name="sp_9">9sp</dimen>
<dimen name="sp_10">10sp</dimen>
<dimen name="sp_11">11sp</dimen>
<dimen name="sp_12">12sp</dimen>
<dimen name="sp_13">13sp</dimen>
<dimen name="sp_14">14sp</dimen>
<dimen name="sp_15">15sp</dimen>
<dimen name="sp_16">16sp</dimen>
<dimen name="sp_17">17sp</dimen>
<dimen name="sp_18">18sp</dimen>
<dimen name="sp_19">19sp</dimen>
<dimen name="sp_20">20sp</dimen>
<dimen name="sp_21">21sp</dimen>
<dimen name="sp_22">22sp</dimen>
<dimen name="sp_23">23sp</dimen>
<dimen name="sp_24">24sp</dimen>
<dimen name="sp_25">25sp</dimen>
<dimen name="sp_26">26sp</dimen>
<dimen name="sp_27">27sp</dimen>
<dimen name="sp_28">28sp</dimen>
<dimen name="sp_29">29sp</dimen>
<dimen name="sp_30">30sp</dimen>
<dimen name="sp_301">31sp</dimen>
<dimen name="sp_32">32sp</dimen>
<dimen name="sp_33">33sp</dimen>
<dimen name="sp_34">34sp</dimen>
<dimen name="sp_35">35sp</dimen>
<dimen name="sp_36">36sp</dimen>
<dimen name="sp_37">37sp</dimen>
<dimen name="sp_38">38sp</dimen>
<dimen name="sp_39">39sp</dimen>
<dimen name="sp_40">40sp</dimen>
<dimen name="sp_41">41sp</dimen>
<dimen name="sp_42">42sp</dimen>
<dimen name="sp_43">43sp</dimen>
<dimen name="sp_44">44sp</dimen>
<dimen name="sp_45">45sp</dimen>
<dimen name="sp_46">46sp</dimen>
<dimen name="sp_47">47sp</dimen>
<dimen name="sp_48">48sp</dimen>
<dimen name="sp_49">49sp</dimen>
<dimen name="sp_50">50sp</dimen>
</resources>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--MagicOS-->
<string name="current_state_wifi">"当前状态:"</string>
<string name="current_state_keep_alive">"当前状态:"</string>
<string name="current_state_screen_capture">"当前状态:"</string>
<string name="state_restricted">已禁用</string>
<string name="state_nomal">未禁用</string>
<string name="state_keep_alive">已保活</string>
<string name="state_cancel_alive">未保活</string>
<string name="disable_wifi">禁用WiFi</string>
<string name="enable_wifi">启用WiFi</string>
<string name="keep_alive">将该应用保活</string>
<string name="cancel_alive">取消该应用保活</string>
<string name="enable_screen_capture">启用截屏</string>
<string name="disable_screen_capture">禁用截屏</string>
<string name="enable_data_conn">启用数据连接</string>
<string name="state_not_actived">该应用未激活</string>
<string name="no_permission">无操作权限</string>
<string name="not_support">本应用只支持MAGIC4及以上的版本</string>
<string name="disable_warning">取消激活后将导致本软件的部分功能无法正常工作,您确定要取消激活么?</string>
<string name="accept_btn">同意</string>
<string name="exit_btn">退出</string>
<string name="know">已阅读</string>
<string name="not_show_anymore">不再提示</string>
<string name="title_license">免责声明与软件许可协议</string>
<string name="title_permissions">权限使用声明</string>
<string name="read_statement">若您点击同意并开始使用本软件,代表您已阅读并接受<a href="http://www.hihonor.mdm.com">《免责声明与软件许可协议》</a>。</string>
<string name="title_activemode">请选择以下模式中的一种进行设备管理器的激活。</string>
<string name="user_active_description">用户确认激活模式即普通的激活方式,激活后用户可随时解除激活。</string>
<string name="force_active_description">强制激活模式只在企业定制版本(通过荣耀商城企业定制服务进行定制的终端版本)上生效,用户只能点击激活,激活成功后无法手动解除激活。</string>
<string name="delay_active_description">延时解除激活模式请先输入延迟时间(范围在1~72的数字),激活成功后用户在设定的延迟时间(单位:小时)过后才能解除激活设备管理器。</string>
<string name="user_activemode">用户确认激活模式</string>
<string name="force_activemode">强制激活模式</string>
<string name="delay_activemode">延时解除激活模式</string>
<string name="delay_hint">请输入延迟时间,范围:1~72</string>
<string name="remove_active_admin">解除激活设备管理器</string>
<string name="force_active_error">setForcedActiveDeviceAdmin error</string>
<string name="delay_deactive_error">setDelayDeactiveDeviceAdmin error</string>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">设备管理</string>
<string name="unknown">-</string>
<string name="sample_device_admin">为关怀系统提供管控功能,请激活后使用</string>
<string name="sample_device_admin_description">开启我吧</string>
</resources>

View File

@@ -0,0 +1,92 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@color/colorPrimary</item>
<item name="android:fitsSystemWindows">true</item>
<item name="android:navigationBarColor">?attr/colorPrimary</item>
</style>
<style name="password_dialog_style">
<!-- 动画 -->
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<!-- 边框 -->
<item name="android:windowFrame">@null</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<item name="android:windowFullscreen">true</item>
<!-- 半透明 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 无标题 -->
<item name="android:windowNoTitle">true</item>
<!-- 背景透明 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 屏幕背景是否变暗 -->
<item name="android:backgroundDimEnabled">true</item>
</style>
<style name="activity_styles" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- <item name="android:windowFullscreen">true</item>-->
<!--设置dialog的背景-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--设置Dialog的windowFrame框为无-->
<item name="android:windowFrame">@null</item>
<!--设置无标题-->
<item name="windowNoTitle">true</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">false</item>
<!--是否半透明-->
<item name="android:windowIsTranslucent">true</item>
<!--设置窗口内容不覆盖-->
<item name="android:windowContentOverlay">@null</item>
<!--设置动画,在这里使用让它继承系统的Animation.Dialog-->
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<!--背景是否模糊显示-->
<item name="android:backgroundDimEnabled">true</item>
</style>
<style name="CustomDialog" parent="Theme.AppCompat.Dialog.Alert">
<!--背景颜色及和透明程度-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--是否去除标题 -->
<item name="android:windowNoTitle">true</item>
<!--是否去除边框-->
<item name="android:windowFrame">@null</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--是否模糊-->
<item name="android:backgroundDimEnabled">true</item>
</style>
<style name="dialog" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:textColor">@color/black</item>
<item name="android:windowFullscreen">false</item>
<!-- <item name="android:windowFrame">@null</item> //Dialog的windowFrame框为无-->
<!-- <item name="android:windowIsFloating">true</item> //是否浮现在activity之上-->
<!-- <item name="android:windowIsTranslucent">true</item> //是否半透明-->
<!-- <item name="android:windowNoTitle">true</item> //是否显示title-->
<!-- <item name="android:background_main">@android:color/transparent</item> //设置dialog的背景-->
<!-- <item name="android:windowBackground">@android:color/transparent</item>-->
<!-- <item name="android:backgroundDimAmount">0.7</item> //就是用来控制灰度的值,当为1时,界面除了我们的dialog内容是高亮显示的,dialog以外的区域是黑色的,完全看不到其他内容-->
<!-- <item name="android:backgroundDimEnabled">true</item>-->
</style>
<style name="UserDebugDialog" parent="Theme.AppCompat.Dialog.Alert">
<!--背景颜色及和透明程度-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--是否去除标题 -->
<item name="android:windowNoTitle">true</item>
<!--是否去除边框-->
<item name="android:windowFrame">@null</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--是否模糊-->
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowSoftInputMode">stateVisible|adjustPan</item>
</style>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
<disable-keyguard-features />
</uses-policies>
</device-admin>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- 共享内部存储文件 -->
<files-path
name="my_internal_files"
path="." />
<!-- 共享内部缓存 -->
<cache-path
name="my_internal_cache"
path="." />
<!-- 共享外部存储根目录下的文件 (谨慎使用) -->
<external-path
name="my_external_storage"
path="." />
<!-- 共享应用外部存储专属目录下的文件 -->
<external-files-path
name="my_app_external_files"
path="downloads/" />
<!-- 共享应用外部缓存 -->
<external-cache-path
name="my_app_external_cache"
path="." />
<!-- 备选方案:共享设备根目录下的文件 (不推荐常规使用) -->
<!-- <root-path name="root" path="" /> -->
</paths>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

64
build.gradle Normal file
View File

@@ -0,0 +1,64 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://maven.google.com' }
maven { url 'https://developer.huawei.com/repo/' }
maven { url 'https://developer.hihonor.com/repo' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:8.13.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
configurations.all {
resolutionStrategy {
force 'androidx.constraintlayout:constraintlayout:2.0.4'
force 'androidx.core:core:1.5.0'
//for targetSdkVersion 29
force 'androidx.activity:activity:1.2.2'
force 'androidx.lifecycle:lifecycle-livedata:2.3.1'
force 'androidx.lifecycle:lifecycle-livedata-core:2.3.1'
force 'androidx.lifecycle:lifecycle-runtime:2.3.1'
force 'androidx.lifecycle:lifecycle-viewmodel:2.3.1'
force 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1'
force 'androidx.lifecycle:lifecycle-service:2.3.1'
force 'androidx.lifecycle:lifecycle-process:2.3.1'
force 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
force 'androidx.savedstate:savedstate:1.1.0'
force 'androidx.profileinstaller:profileinstaller:1.1.0'
force 'androidx.startup:startup-runtime:1.0.0'
force 'androidx.arch.core:core-runtime:2.1.0'
force 'androidx.sqlite:sqlite:2.1.0'
force 'androidx.sqlite:sqlite-framework:2.1.0'
force 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
}
}
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://maven.google.com' }
maven { url 'https://developer.huawei.com/repo/' }
maven { url 'https://developer.hihonor.com/repo' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
}

16
gradle.properties Normal file
View File

@@ -0,0 +1,16 @@
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Thu Apr 15 10:50:40 CST 2021
android.enableJetifier=true
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
android.useAndroidX=true

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Tue Mar 16 15:27:10 CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip

172
gradlew vendored Normal file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

2
settings.gradle Normal file
View File

@@ -0,0 +1,2 @@
include ':app'
rootProject.name='ElderlyDialerMdm'