init: mdm版本初始化
This commit is contained in:
90
.gitignore
vendored
Normal file
90
.gitignore
vendored
Normal 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
85
app/.gitignore
vendored
Normal 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
125
app/build.gradle
Normal 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
BIN
app/libs/framework.jar
Normal file
Binary file not shown.
BIN
app/libs/magic-android-34.38.1.200.jar
Normal file
BIN
app/libs/magic-android-34.38.1.200.jar
Normal file
Binary file not shown.
116
app/src/main/AndroidManifest.xml
Normal file
116
app/src/main/AndroidManifest.xml
Normal 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>
|
||||||
72
app/src/main/java/com/ttstd/sn/App.java
Normal file
72
app/src/main/java/com/ttstd/sn/App.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
473
app/src/main/java/com/ttstd/sn/mdm/AdminManager.java
Normal file
473
app/src/main/java/com/ttstd/sn/mdm/AdminManager.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
app/src/main/java/com/ttstd/sn/ui/base/BaseActivity.java
Normal file
55
app/src/main/java/com/ttstd/sn/ui/base/BaseActivity.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
192
app/src/main/java/com/ttstd/sn/ui/base/GlobalCrashHandler.java
Normal file
192
app/src/main/java/com/ttstd/sn/ui/base/GlobalCrashHandler.java
Normal 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
52
app/src/main/java/com/ttstd/sn/ui/base/rx/BaseRxService.java
Normal file
52
app/src/main/java/com/ttstd/sn/ui/base/rx/BaseRxService.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
179
app/src/main/java/com/ttstd/sn/ui/main/MainActivity.java
Normal file
179
app/src/main/java/com/ttstd/sn/ui/main/MainActivity.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
109
app/src/main/java/com/ttstd/sn/ui/main/MainUiState.java
Normal file
109
app/src/main/java/com/ttstd/sn/ui/main/MainUiState.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/src/main/java/com/ttstd/sn/ui/main/MainViewModel.java
Normal file
17
app/src/main/java/com/ttstd/sn/ui/main/MainViewModel.java
Normal 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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
73
app/src/main/java/com/ttstd/sn/utils/DateUtils.java
Normal file
73
app/src/main/java/com/ttstd/sn/utils/DateUtils.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
84
app/src/main/java/com/ttstd/sn/utils/NetworkUtils.java
Normal file
84
app/src/main/java/com/ttstd/sn/utils/NetworkUtils.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
app/src/main/res/drawable/bt_blue_background.xml
Normal file
18
app/src/main/res/drawable/bt_blue_background.xml
Normal 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>
|
||||||
19
app/src/main/res/drawable/main_card_bg.xml
Normal file
19
app/src/main/res/drawable/main_card_bg.xml
Normal 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>
|
||||||
338
app/src/main/res/layout/activity_main.xml
Normal file
338
app/src/main/res/layout/activity_main.xml
Normal 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>
|
||||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
66
app/src/main/res/values/colors.xml
Normal file
66
app/src/main/res/values/colors.xml
Normal 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>
|
||||||
451
app/src/main/res/values/dimens.xml
Normal file
451
app/src/main/res/values/dimens.xml
Normal 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>
|
||||||
40
app/src/main/res/values/string_magic_os.xml
Normal file
40
app/src/main/res/values/string_magic_os.xml
Normal 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>
|
||||||
9
app/src/main/res/values/strings.xml
Normal file
9
app/src/main/res/values/strings.xml
Normal 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>
|
||||||
92
app/src/main/res/values/styles.xml
Normal file
92
app/src/main/res/values/styles.xml
Normal 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>
|
||||||
14
app/src/main/res/xml/device_admin_sample.xml
Normal file
14
app/src/main/res/xml/device_admin_sample.xml
Normal 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>
|
||||||
27
app/src/main/res/xml/file_paths.xml
Normal file
27
app/src/main/res/xml/file_paths.xml
Normal 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>
|
||||||
4
app/src/main/res/xml/network.xml
Normal file
4
app/src/main/res/xml/network.xml
Normal 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
64
build.gradle
Normal 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
16
gradle.properties
Normal 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
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
172
gradlew
vendored
Normal 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
84
gradlew.bat
vendored
Normal 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
2
settings.gradle
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
include ':app'
|
||||||
|
rootProject.name='ElderlyDialerMdm'
|
||||||
Reference in New Issue
Block a user