diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DKit.iml b/DKit.iml
new file mode 100644
index 0000000..1cbfb92
--- /dev/null
+++ b/DKit.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DebugKit.iml b/DebugKit.iml
new file mode 100644
index 0000000..d51aceb
--- /dev/null
+++ b/DebugKit.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/app.iml b/app/app.iml
new file mode 100644
index 0000000..0038a61
--- /dev/null
+++ b/app/app.iml
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..ab6a8f8
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,36 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.0"
+ defaultConfig {
+ applicationId "vip.devkit.DebugKit.Demo"
+ minSdkVersion 19
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+
+ implementation project(':dklib')
+
+ api 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'
+
+
+
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/androidTest/java/vip/devkit/DebugKit/Demo/ExampleInstrumentedTest.java b/app/src/androidTest/java/vip/devkit/DebugKit/Demo/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..3aaf7fd
--- /dev/null
+++ b/app/src/androidTest/java/vip/devkit/DebugKit/Demo/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package vip.devkit.DebugKit.Demo;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("vip.devkit.DebugKit.Demo", appContext.getPackageName());
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e1e74e6
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/vip/devkit/DebugKit/Demo/MainActivity.java b/app/src/main/java/vip/devkit/DebugKit/Demo/MainActivity.java
new file mode 100644
index 0000000..6c0a83b
--- /dev/null
+++ b/app/src/main/java/vip/devkit/DebugKit/Demo/MainActivity.java
@@ -0,0 +1,39 @@
+package vip.devkit.DebugKit.Demo;
+
+import android.Manifest;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import vip.devkit.debugkit.ui.KitManagerActivity;
+
+public class MainActivity extends AppCompatActivity {
+
+ /**
+ * Debug
+ */
+ private TextView mTvDebug;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ initView();
+
+ }
+
+ private void initView() {
+ mTvDebug = (TextView) findViewById(R.id.tv_debug);
+ mTvDebug.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(MainActivity.this, KitManagerActivity.class);
+ startActivity(intent);
+ String[] permissions=new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/vip/devkit/DebugKit/Demo/PDF.java b/app/src/main/java/vip/devkit/DebugKit/Demo/PDF.java
new file mode 100644
index 0000000..e763d27
--- /dev/null
+++ b/app/src/main/java/vip/devkit/DebugKit/Demo/PDF.java
@@ -0,0 +1,43 @@
+package vip.devkit.DebugKit.Demo;
+
+import android.os.Bundle;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.joanzapata.pdfview.PDFView;
+
+/**
+ * Package Name: vip.devkit.DebugKit.Demo
+ * File Name: PDF.java
+ * Create Date: 2019/7/5 16:51
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class PDF extends AppCompatActivity {
+
+
+ private PDFView mPdfView;
+ /**
+ * Debug
+ */
+ private TextView mTvDebug;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_pdf);
+ initView();
+ }
+
+ private void initView() {
+ mPdfView = (PDFView) findViewById(R.id.pdf_view);
+ mTvDebug = (TextView) findViewById(R.id.tv_debug);
+
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/shape_debug.xml b/app/src/main/res/drawable/shape_debug.xml
new file mode 100644
index 0000000..024d9bc
--- /dev/null
+++ b/app/src/main/res/drawable/shape_debug.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..dc38795
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_pdf.xml b/app/src/main/res/layout/activity_pdf.xml
new file mode 100644
index 0000000..07aa4e3
--- /dev/null
+++ b/app/src/main/res/layout/activity_pdf.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..69b2233
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0240004
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ DebugKit
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5885930
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/app/src/test/java/vip/devkit/DebugKit/Demo/ExampleUnitTest.java b/app/src/test/java/vip/devkit/DebugKit/Demo/ExampleUnitTest.java
new file mode 100644
index 0000000..14605e6
--- /dev/null
+++ b/app/src/test/java/vip/devkit/DebugKit/Demo/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package vip.devkit.DebugKit.Demo;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..485ea3d
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,28 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ google()
+ jcenter()
+
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ maven { url 'https://jitpack.io' }
+
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/dklib/.gitignore b/dklib/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/dklib/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/dklib/build.gradle b/dklib/build.gradle
new file mode 100644
index 0000000..7bb2a1f
--- /dev/null
+++ b/dklib/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 29
+
+ defaultConfig {
+ minSdkVersion 19
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation('com.android.support:recyclerview-v7:29.0.0') {
+ exclude group: 'com.android.support'
+ }
+ implementation 'com.android.support:design:29.0.0'
+
+}
+
+//https://github.com/nisrulz/easydeviceinfo/wiki/Usage#easyappmod
diff --git a/dklib/dklib.iml b/dklib/dklib.iml
new file mode 100644
index 0000000..6662db8
--- /dev/null
+++ b/dklib/dklib.iml
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/proguard-rules.pro b/dklib/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/dklib/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/dklib/src/androidTest/java/vip/devkit/debugkit/ExampleInstrumentedTest.java b/dklib/src/androidTest/java/vip/devkit/debugkit/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..e97630c
--- /dev/null
+++ b/dklib/src/androidTest/java/vip/devkit/debugkit/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package vip.devkit.debugkit;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("vip.devkit.debugkit.test", appContext.getPackageName());
+ }
+}
diff --git a/dklib/src/main/AndroidManifest.xml b/dklib/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..484381b
--- /dev/null
+++ b/dklib/src/main/AndroidManifest.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dklib/src/main/aidl/android/content/pm/IPackageStatsObserver.aidl b/dklib/src/main/aidl/android/content/pm/IPackageStatsObserver.aidl
new file mode 100644
index 0000000..4ce6f7a
--- /dev/null
+++ b/dklib/src/main/aidl/android/content/pm/IPackageStatsObserver.aidl
@@ -0,0 +1,14 @@
+// PackageStats.aidl
+package android.content.pm;
+
+import android.content.pm.PackageStats;
+/**
+ * API for package data change related callbacks from the Package Manager.
+ * Some usage scenarios include deletion of cache directory, generate
+ * statistics related to code, data, cache usage(TODO)
+ * {@hide}
+ */
+oneway interface IPackageStatsObserver {
+
+ void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
+}
\ No newline at end of file
diff --git a/dklib/src/main/aidl/android/content/pm/PackageStats.aidl b/dklib/src/main/aidl/android/content/pm/PackageStats.aidl
new file mode 100644
index 0000000..97e19ff
--- /dev/null
+++ b/dklib/src/main/aidl/android/content/pm/PackageStats.aidl
@@ -0,0 +1,3 @@
+package android.content.pm;
+
+parcelable PackageStats;
\ No newline at end of file
diff --git a/dklib/src/main/java/android/content/pm/IPackageStatsObserver.aidl b/dklib/src/main/java/android/content/pm/IPackageStatsObserver.aidl
new file mode 100644
index 0000000..4ce6f7a
--- /dev/null
+++ b/dklib/src/main/java/android/content/pm/IPackageStatsObserver.aidl
@@ -0,0 +1,14 @@
+// PackageStats.aidl
+package android.content.pm;
+
+import android.content.pm.PackageStats;
+/**
+ * API for package data change related callbacks from the Package Manager.
+ * Some usage scenarios include deletion of cache directory, generate
+ * statistics related to code, data, cache usage(TODO)
+ * {@hide}
+ */
+oneway interface IPackageStatsObserver {
+
+ void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/android/content/pm/PackageStats.aidl b/dklib/src/main/java/android/content/pm/PackageStats.aidl
new file mode 100644
index 0000000..97e19ff
--- /dev/null
+++ b/dklib/src/main/java/android/content/pm/PackageStats.aidl
@@ -0,0 +1,3 @@
+package android.content.pm;
+
+parcelable PackageStats;
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/DataSource.java b/dklib/src/main/java/vip/devkit/debugkit/DataSource.java
new file mode 100644
index 0000000..d2f655a
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/DataSource.java
@@ -0,0 +1,199 @@
+package vip.devkit.debugkit;
+
+import android.content.Context;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import vip.devkit.debugkit.kit.GroupKitItem;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.kit.KitItem;
+import vip.devkit.debugkit.kit.debug.AppInfo;
+import vip.devkit.debugkit.kit.debug.BaseUrlManger;
+import vip.devkit.debugkit.kit.debug.CachesManager;
+import vip.devkit.debugkit.kit.debug.CrashManger;
+import vip.devkit.debugkit.kit.debug.DataExport;
+import vip.devkit.debugkit.kit.debug.FileExplorer;
+import vip.devkit.debugkit.kit.debug.WebBrowse;
+import vip.devkit.debugkit.kit.debug.LogManager;
+import vip.devkit.debugkit.kit.debug.PermissionManager;
+import vip.devkit.debugkit.kit.debug.Simulation;
+import vip.devkit.debugkit.kit.performance.Battery;
+import vip.devkit.debugkit.kit.performance.CPU;
+import vip.devkit.debugkit.kit.performance.FTPS;
+import vip.devkit.debugkit.kit.performance.RAM;
+import vip.devkit.debugkit.kit.performance.Time;
+import vip.devkit.debugkit.kit.performance.Traffic;
+import vip.devkit.debugkit.kit.system.CpuKit;
+import vip.devkit.debugkit.kit.system.HardwareKit;
+import vip.devkit.debugkit.kit.system.NetworkKit;
+import vip.devkit.debugkit.kit.system.ScreenKit;
+import vip.devkit.debugkit.kit.system.SysInfo;
+import vip.devkit.debugkit.kit.ue.ColorPicker;
+import vip.devkit.debugkit.kit.ue.UE;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit
+ * File Name: DataSource.java
+ * Create Date: 2019/7/1 17:24
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class DataSource {
+
+ private List mItemList = new ArrayList<>();
+ private List mDiyKitItems = new ArrayList<>();
+ private Context mContext;
+
+ public List getKitList() {
+ return mItemList;
+ }
+
+ public DataSource(Context context) {
+ mContext = context;
+ initKit();
+ }
+
+ private void initKit() {
+ sysKit();
+ debugKit();
+ developerKit();
+ performanceKit();
+ ueKit();
+ diyKit();
+ }
+
+
+ public void sysKit() {
+ GroupKitItem sys = new GroupKitItem();
+ sys.mGroupName = ResUtil.getString(mContext, R.string.dk_sys_system);
+
+ List d = new ArrayList<>();
+ d.add(new SysInfo());
+ d.add(new ScreenKit());
+ d.add(new NetworkKit());
+ d.add(new HardwareKit());
+ d.add(new CpuKit());
+
+ List kitItems = new ArrayList<>();
+ for (IKit kit : d) {
+ kitItems.add(new KitItem(kit));
+ }
+ sys.mKitList = kitItems;
+ mItemList.add(sys);
+
+ }
+
+
+ public void debugKit() {
+ GroupKitItem mGroupBean = new GroupKitItem();
+ mGroupBean.mGroupName = ResUtil.getString(mContext, R.string.dk_debug);
+
+
+ List d = new ArrayList<>();
+ d.add(new AppInfo());
+ d.add(new FileExplorer());
+ d.add(new LogManager());
+ d.add(new PermissionManager());
+ d.add(new BaseUrlManger());
+ d.add(new CachesManager());
+ d.add(new CrashManger());
+ d.add(new Simulation());
+ d.add(new DataExport());
+ d.add(new WebBrowse());
+
+
+ List kitItems = new ArrayList<>();
+ for (IKit kit : d) {
+ kitItems.add(new KitItem(kit));
+ }
+ mGroupBean.mKitList = kitItems;
+ mItemList.add(mGroupBean);
+
+
+
+ }
+
+ public void developerKit() {
+ GroupKitItem mGroupBean = new GroupKitItem();
+ mGroupBean.mGroupName = ResUtil.getString(mContext, R.string.dk_developer);
+
+ List d = new ArrayList<>();
+ d.add(new SysInfo());
+ d.add(new ScreenKit());
+ d.add(new NetworkKit());
+ d.add(new HardwareKit());
+ d.add(new CpuKit());
+
+ List kitItems = new ArrayList<>();
+ for (IKit kit : d) {
+ kitItems.add(new KitItem(kit));
+ }
+ mGroupBean.mKitList = kitItems;
+ mItemList.add(mGroupBean);
+
+ }
+
+ public void performanceKit() {
+ GroupKitItem mGroupBean = new GroupKitItem();
+ mGroupBean.mGroupName = ResUtil.getString(mContext, R.string.dk_performance);
+
+ List d = new ArrayList<>();
+ d.add(new FTPS());
+ d.add(new CPU());
+ d.add(new RAM());
+ d.add(new Traffic());
+ d.add(new Battery());
+ d.add(new Time());
+
+ List kitItems = new ArrayList<>();
+ for (IKit kit : d) {
+ kitItems.add(new KitItem(kit));
+ }
+ mGroupBean.mKitList = kitItems;
+ mItemList.add(mGroupBean);
+
+ }
+
+ public void ueKit() {
+ GroupKitItem mGroupBean = new GroupKitItem();
+ mGroupBean.mGroupName = ResUtil.getString(mContext, R.string.dk_ue);
+
+ List d = new ArrayList<>();
+ d.add(new ColorPicker());
+ d.add(new UE());
+
+ List kitItems = new ArrayList<>();
+ for (IKit kit : d) {
+ kitItems.add(new KitItem(kit));
+ }
+ mGroupBean.mKitList = kitItems;
+ mItemList.add(mGroupBean);
+
+ }
+
+
+ public void diyKit() {
+ if (mDiyKitItems.size() > 0) {
+ GroupKitItem mGroupBean = new GroupKitItem();
+ mGroupBean.mGroupName = ResUtil.getString(mContext, R.string.dk_diy);
+ mGroupBean.mKitList = mDiyKitItems;
+ }
+ }
+
+
+ public void add(IKit mIKit) {
+ mDiyKitItems.add(new KitItem(mIKit));
+ }
+
+ public void add(List list) {
+ for (IKit kit : list) {
+ mDiyKitItems.add(new KitItem(kit));
+ }
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/DebugKitFileProvider.java b/dklib/src/main/java/vip/devkit/debugkit/DebugKitFileProvider.java
new file mode 100644
index 0000000..505cfc7
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/DebugKitFileProvider.java
@@ -0,0 +1,17 @@
+package vip.devkit.debugkit;
+
+import androidx.core.content.FileProvider;
+
+/**
+ * Package Name: vip.devkit.debugkit
+ * File Name: DebugKitFileProvider.java
+ * Create Date: 2019/6/28 11:06
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class DebugKitFileProvider extends FileProvider {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/KitAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/KitAdapter.java
new file mode 100644
index 0000000..5366b58
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/KitAdapter.java
@@ -0,0 +1,49 @@
+package vip.devkit.debugkit;
+
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import java.util.List;
+
+import vip.devkit.debugkit.kit.KitItem;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+import vip.devkit.debugkit.widget.recyclerview.BaseViewHolder;
+
+/**
+ * Package Name: vip.devkit.debugkit
+ * File Name: KitAdapter.java
+ * Create Date: 2019/7/1 14:59
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class KitAdapter extends BaseRecyclerAdapter {
+
+
+ public KitAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper,final KitItem mItem) {
+ helper.setText(R.id.tv_name, mItem.kit.getName())
+ .setImageResource(R.id.iv_icon, mItem.kit.getIcon());
+ helper.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mItem.kit.onClick(mContext);
+ }
+ });
+ }
+
+
+ @Override
+ public void setOnItemClick(View v, int position) {
+ super.setOnItemClick(v, position);
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/KitManagerAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/KitManagerAdapter.java
new file mode 100644
index 0000000..d35d71f
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/KitManagerAdapter.java
@@ -0,0 +1,41 @@
+package vip.devkit.debugkit;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+import vip.devkit.debugkit.kit.GroupKitItem;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+import vip.devkit.debugkit.widget.recyclerview.BaseViewHolder;
+
+/**
+ * Package Name: vip.devkit.debugkit
+ * File Name: KitManagerAdapter.java
+ * Create Date: 2019/7/1 11:16
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class KitManagerAdapter extends BaseRecyclerAdapter {
+
+ public KitManagerAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, GroupKitItem mItem) {
+
+ helper.setText(R.id.tv_group_name, mItem.mGroupName);
+ RecyclerView mKitList = (RecyclerView) helper.getView(R.id.rv_group_kit);
+ mKitList.setLayoutManager(new GridLayoutManager(mContext, 4));
+ KitAdapter mKitAdapter = new KitAdapter(R.layout.dk_item_kit, mItem.mKitList);
+ mKitList.setAdapter(mKitAdapter);
+
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/adapter/BaseUrlManagerAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/adapter/BaseUrlManagerAdapter.java
new file mode 100644
index 0000000..1532e41
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/adapter/BaseUrlManagerAdapter.java
@@ -0,0 +1,67 @@
+package vip.devkit.debugkit.adapter;
+
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+import androidx.annotation.Nullable;
+
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.ui.base_url.UrlInfo;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+import vip.devkit.debugkit.widget.recyclerview.BaseViewHolder;
+
+/**
+ * Package Name: vip.devkit.debugkit.adapter
+ * File Name: BaseUrlManagerAdapter.java
+ * Create Date: 2019/7/3 10:34
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class BaseUrlManagerAdapter extends BaseRecyclerAdapter {
+
+ public interface OnUrlCheckedListener {
+ void onChecked(UrlInfo urlInfo);
+ }
+
+ private OnUrlCheckedListener mOnUrlCheckedListener;
+ private int checkPosition=-1;
+
+ public void setOnUrlCheckedListener(OnUrlCheckedListener onUrlCheckedListener) {
+ mOnUrlCheckedListener = onUrlCheckedListener;
+ }
+
+ public BaseUrlManagerAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(final BaseViewHolder helper, final UrlInfo mItem) {
+ helper.setText(R.id.tv_url, mItem.getBaseUrl());
+ CheckBox checkBox = (CheckBox) helper.getView(R.id.cb_check);
+ LogCat.i("----------"+helper.getAdapterPosition());
+ if (helper.getAdapterPosition()==checkPosition){
+ checkBox.setChecked(true);
+ }else {
+ checkBox.setChecked(false);
+ }
+ checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ LogCat.i("----------"+helper.getAdapterPosition()+"/"+isChecked);
+ if (isChecked && mOnUrlCheckedListener != null) {
+ checkPosition=helper.getAdapterPosition();
+ mOnUrlCheckedListener.onChecked(mItem);
+ } else {
+ checkPosition=-1;
+ }
+ }
+ });
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/adapter/CrashListAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/adapter/CrashListAdapter.java
new file mode 100644
index 0000000..32690ba
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/adapter/CrashListAdapter.java
@@ -0,0 +1,62 @@
+package vip.devkit.debugkit.adapter;
+
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.bean.CrashInfoBean;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+import vip.devkit.debugkit.widget.recyclerview.BaseViewHolder;
+
+/**
+ * Package Name: vip.devkit.debugkit.adapter
+ * File Name: CrashListAdapter.java
+ * Create Date: 2019/7/9 10:00
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CrashListAdapter extends BaseRecyclerAdapter {
+ public CrashListAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, CrashInfoBean mItem) {
+ LogCat.i(" 1" + mItem.tr.toString());
+
+ Throwable throwable = mItem.tr;
+ String type = throwable.toString();
+// LogCat.i("throwable 99999 "+type.substring(0,type.indexOf(":")));
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ helper.setText(R.id.tv_time,""+dateFormat.format(new Date(mItem.time)))
+ .setText(R.id.tv_crash_name,type.substring(0,type.indexOf(":")));
+ if (helper.getAdapterPosition()==0){
+ LogCat.i(Log.getStackTraceString(throwable));
+ }
+
+// StackTraceElement[] elements= throwable .getStackTrace();
+// for (int i = 0; i {
+ public FileFolderAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, FileInfoBean mItem) {
+ helper.setText(R.id.tv_folder,mItem.file.getName()+" >");
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/adapter/FileInfoAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/adapter/FileInfoAdapter.java
new file mode 100644
index 0000000..e7c8090
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/adapter/FileInfoAdapter.java
@@ -0,0 +1,56 @@
+package vip.devkit.debugkit.adapter;
+
+import android.widget.ImageView;
+
+import androidx.annotation.Nullable;
+
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.bean.FileInfoBean;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.util.FileUtil;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+import vip.devkit.debugkit.widget.recyclerview.BaseViewHolder;
+
+/**
+ * Package Name: vip.devkit.debugkit.adapter
+ * File Name: FileInfoAdapter.java
+ * Create Date: 2019/7/9 14:27
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class FileInfoAdapter extends BaseRecyclerAdapter {
+ public FileInfoAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, FileInfoBean fileInfo) {
+ helper.setText(R.id.tv_name, fileInfo.file.getName())
+ .setVisible(R.id.iv_more, !fileInfo.file.isFile());
+
+ ImageView mIcon = (ImageView) helper.getView(R.id.iv_icon);
+ if (fileInfo.file.isFile()) {
+ String suffix = FileUtil.getSuffix(fileInfo.file);
+ LogCat.i("---------------"+suffix);
+ if (suffix.equals("gif") || suffix.equals("jpg") || suffix.equals("jpeg") || suffix.equals("png") || suffix.equals("bmp")) {
+ mIcon.setImageResource(R.mipmap.dk_file_img);
+ } else if (suffix.equals(FileUtil.TXT)||suffix.equals("json")||suffix.equals("xml")) {
+ mIcon.setImageResource(R.mipmap.dk_file_txt);
+ } else if (suffix.equals(FileUtil.SHARED_PREFS)) {
+ } else if (suffix.equals(FileUtil.DB)) {
+ mIcon.setImageResource(R.mipmap.dk_file_db);
+ } else {
+ mIcon.setImageResource(R.mipmap.dk_file_ohter);
+ }
+ } else {
+ mIcon.setImageResource(R.mipmap.dk_file_folder);
+ }
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/adapter/PermissionManagerAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/adapter/PermissionManagerAdapter.java
new file mode 100644
index 0000000..a311aa7
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/adapter/PermissionManagerAdapter.java
@@ -0,0 +1,39 @@
+package vip.devkit.debugkit.adapter;
+
+import android.content.pm.PermissionInfo;
+
+import androidx.annotation.Nullable;
+
+
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.ui.permission.PermissionData;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+import vip.devkit.debugkit.widget.recyclerview.BaseViewHolder;
+
+/**
+ * Package Name: vip.devkit.debugkit.adapter
+ * File Name: PermissionManagerAdapter.java
+ * Create Date: 2019/7/3 11:58
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class PermissionManagerAdapter extends BaseRecyclerAdapter {
+
+
+ public PermissionManagerAdapter(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, String name) {
+ helper.setText(R.id.tv_permission, name)
+ .setText(R.id.tv_desc,""+PermissionData.getPermissionName(name))
+ .setChecked(R.id.cb_check, PermissionData.hasSelfPermission(mContext, name));
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/bean/AppInfoBean.java b/dklib/src/main/java/vip/devkit/debugkit/bean/AppInfoBean.java
new file mode 100644
index 0000000..c12743c
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/bean/AppInfoBean.java
@@ -0,0 +1,281 @@
+package vip.devkit.debugkit.bean;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+
+import androidx.annotation.Keep;
+
+import vip.devkit.debugkit.util.AppUtil;
+import vip.devkit.debugkit.util.DeviceUtils;
+import vip.devkit.debugkit.util.FileUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.bean
+ * File Name: AppInfoBean.java
+ * Create Date: 2019/7/8 13:56
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class AppInfoBean {
+
+ @Keep // App 包名
+ private String appPackName;
+ @Keep // App 应用名
+ private String appName;
+ @Keep // App 图标
+ private transient Drawable appIcon;
+ @Keep // App 类型
+ private AppType appType;
+ @Keep // App 版本号
+ private int versionCode;
+ @Keep // App 版本名
+ private String versionName;
+ @Keep // App 首次安装时间
+ private long firstInstallTime;
+ @Keep // App 最后一次更新时间
+ private long lastUpdateTime;
+ @Keep // App 地址
+ private String sourceDir;
+ @Keep // APK 大小
+ private long apkSize;
+ @Keep //Sign MD5
+ private String apkSign;
+ @Keep //最小支持
+ private int minSdkVersion = -1;
+ @Keep //兼容
+ private int targetSdkVersion = -1;
+
+ @Keep //activity 数量
+ private int activityCount;
+ @Keep //service 数量
+ private int serviceCount;
+ @Keep //receiver 数量
+ private int receiverCount;
+ @Keep //provider 数量
+ private int providerCount;
+ @Keep //permission 数量
+ private int permissionCount;
+
+
+ private Context context;
+
+
+ /**
+ * 初始化 AppInfoBean
+ */
+ protected AppInfoBean() {
+
+ init();
+ }
+
+ public AppInfoBean(Context context) {
+ this.context = context;
+ init();
+ }
+
+ private void init() {
+ //GET_CONFIGURATIONS
+ PackageInfo packageInfo = DeviceUtils.getPackageInfo(context);
+
+ PackageManager packageManager = context.getPackageManager();
+ // App 包名
+ appPackName = packageInfo.applicationInfo.packageName;
+ // App 应用名
+ appName = packageManager.getApplicationLabel(packageInfo.applicationInfo).toString();
+ // App 图标
+ appIcon = packageManager.getApplicationIcon(packageInfo.applicationInfo);
+ // App 类型
+ appType = AppInfoBean.getAppType(packageInfo);
+ // App 版本号
+ versionCode = packageInfo.versionCode;
+ // App 版本名
+ versionName = packageInfo.versionName;
+ // App 首次安装时间
+ firstInstallTime = packageInfo.firstInstallTime;
+ // App 最后一次更新时间
+ lastUpdateTime = packageInfo.lastUpdateTime;
+ // App 地址
+ sourceDir = packageInfo.applicationInfo.sourceDir;
+ // APK 大小
+// apkSize = FileUtil.getFileSize(context,sourceDir);
+ // APK sign
+ apkSign = AppUtil.getSign(context, packageInfo.packageName);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ minSdkVersion = context.getApplicationInfo().minSdkVersion;
+ }
+ targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+ PackageInfo pia = DeviceUtils.getPackageInfo(context, PackageManager.GET_ACTIVITIES);
+ if (pia.activities != null) {
+ activityCount = pia.activities.length;
+ }
+
+ PackageInfo pis = DeviceUtils.getPackageInfo(context, PackageManager.GET_SERVICES);
+ if (pis.services != null) {
+ serviceCount = pis.services.length;
+ }
+
+ PackageInfo pir = DeviceUtils.getPackageInfo(context, PackageManager.GET_RECEIVERS);
+ if (pir.receivers != null) {
+ receiverCount = pir.receivers.length;
+ }
+ PackageInfo pip = DeviceUtils.getPackageInfo(context, PackageManager.GET_PROVIDERS);
+ if (pip.providers != null) {
+ providerCount = pip.providers.length;
+ }
+
+ PackageInfo permissions = DeviceUtils.getPackageInfo(context, PackageManager.GET_PERMISSIONS);
+ if (permissions.requestedPermissions != null) {
+ permissionCount = permissions.requestedPermissions.length;
+ }
+ }
+
+
+ /**
+ * detail: 应用类型
+ */
+ public enum AppType {
+
+ USER, // 用户 App
+
+ SYSTEM, // 系统 App
+
+ ALL // 全部 App
+ }
+
+ public String getAppPackName() {
+ return appPackName;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public Drawable getAppIcon() {
+ return appIcon;
+ }
+
+ public AppType getAppType() {
+ return appType;
+ }
+
+ public int getVersionCode() {
+ return versionCode;
+ }
+
+ public String getVersionName() {
+ return versionName;
+ }
+
+ public long getFirstInstallTime() {
+ return firstInstallTime;
+ }
+
+ public long getLastUpdateTime() {
+ return lastUpdateTime;
+ }
+
+ public String getSourceDir() {
+ return sourceDir;
+ }
+
+ public long getApkSize() {
+ return apkSize;
+ }
+
+ public String getApkSign() {
+ return apkSign;
+ }
+
+ public int getMinSdkVersion() {
+ return minSdkVersion;
+ }
+
+ public int getTargetSdkVersion() {
+ return targetSdkVersion;
+ }
+
+ public int getActivityCount() {
+ return activityCount;
+ }
+
+ public int getServiceCount() {
+ return serviceCount;
+ }
+
+ public int getReceiverCount() {
+ return receiverCount;
+ }
+
+ public int getProviderCount() {
+ return providerCount;
+ }
+
+ public int getPermissionCount() {
+ return permissionCount;
+ }
+
+ /**
+ * 获取 App 类型
+ *
+ * @param packageInfo {@link PackageInfo}
+ * @return {@link AppType} 应用类型
+ */
+ public static AppType getAppType(final PackageInfo packageInfo) {
+ if (!isSystemApp(packageInfo) && !isSystemUpdateApp(packageInfo)) {
+ return AppType.USER;
+ }
+ return AppType.SYSTEM;
+ }
+
+ /**
+ * 是否系统程序
+ *
+ * @param packageInfo {@link PackageInfo}
+ * @return {@code true} yes, {@code false} no
+ */
+ public static boolean isSystemApp(final PackageInfo packageInfo) {
+ return ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+ }
+
+ /**
+ * 是否系统程序被手动更新后, 也成为第三方应用程序
+ *
+ * @param packageInfo {@link PackageInfo}
+ * @return {@code true} yes, {@code false} no
+ */
+ public static boolean isSystemUpdateApp(final PackageInfo packageInfo) {
+ return ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+ }
+
+ @Override
+ public String toString() {
+ return "AppInfoBean{" +
+ "appPackName='" + appPackName + '\'' +
+ ", appName='" + appName + '\'' +
+ ", appIcon=" + appIcon +
+ ", appType=" + appType +
+ ", versionCode=" + versionCode +
+ ", versionName='" + versionName + '\'' +
+ ", firstInstallTime=" + firstInstallTime +
+ ", lastUpdateTime=" + lastUpdateTime +
+ ", sourceDir='" + sourceDir + '\'' +
+ ", apkSize=" + apkSize +
+ ", apkSign='" + apkSign + '\'' +
+ ", minSdkVersion='" + targetSdkVersion + '\'' +
+ ", activityCount=" + activityCount +
+ ", serviceCount=" + serviceCount +
+ ", receiverCount=" + receiverCount +
+ ", providerCount=" + providerCount +
+ ", permissionCount=" + permissionCount +
+ '}';
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/bean/CrashInfoBean.java b/dklib/src/main/java/vip/devkit/debugkit/bean/CrashInfoBean.java
new file mode 100644
index 0000000..fca5878
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/bean/CrashInfoBean.java
@@ -0,0 +1,26 @@
+package vip.devkit.debugkit.bean;
+
+import java.io.Serializable;
+
+/**
+ * Package Name: vip.devkit.debugkit.bean
+ * File Name: CrashInfoBean.java
+ * Create Date: 2019/7/9 9:24
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CrashInfoBean implements Serializable {
+ public final Throwable tr;
+
+ public final long time;
+
+ public CrashInfoBean(Throwable tr, long l) {
+ this.tr = tr;
+ this.time = l;
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/bean/FileInfoBean.java b/dklib/src/main/java/vip/devkit/debugkit/bean/FileInfoBean.java
new file mode 100644
index 0000000..f96befe
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/bean/FileInfoBean.java
@@ -0,0 +1,22 @@
+package vip.devkit.debugkit.bean;
+
+import java.io.File;
+
+/**
+ * Package Name: vip.devkit.debugkit.bean
+ * File Name: FileInfoBean.java
+ * Create Date: 2019/7/9 14:23
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class FileInfoBean {
+ public final File file;
+
+ public FileInfoBean(File file) {
+ this.file = file;
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/bean/PermissionInfo.java b/dklib/src/main/java/vip/devkit/debugkit/bean/PermissionInfo.java
new file mode 100644
index 0000000..acdb2db
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/bean/PermissionInfo.java
@@ -0,0 +1,15 @@
+package vip.devkit.debugkit.bean;
+
+/**
+ * Package Name: vip.devkit.debugkit.bean
+ * File Name: PermissionData.java
+ * Create Date: 2019/7/3 11:59
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class PermissionInfo {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/Category.java b/dklib/src/main/java/vip/devkit/debugkit/kit/Category.java
new file mode 100644
index 0000000..df4baac
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/Category.java
@@ -0,0 +1,25 @@
+package vip.devkit.debugkit.kit;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit
+ * File Name: Category.java
+ * Create Date: 2019/6/28 10:57
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public interface Category {
+ int BIZ = 0;
+
+ int TOOLS = 1;
+
+ int PERFORMANCE = 2;
+
+ int UI = 3;
+
+ int CLOSE = 5;
+}
+
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/GroupKitItem.java b/dklib/src/main/java/vip/devkit/debugkit/kit/GroupKitItem.java
new file mode 100644
index 0000000..9124fad
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/GroupKitItem.java
@@ -0,0 +1,30 @@
+package vip.devkit.debugkit.kit;
+
+import java.security.acl.Group;
+import java.util.List;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit
+ * File Name: GroupKitItem.java
+ * Create Date: 2019/7/1 14:53
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class GroupKitItem {
+
+
+ public String mGroupName;
+ public List mKitList;
+
+ public GroupKitItem() {
+ }
+
+ public GroupKitItem(String groupName, List kitList) {
+ mGroupName = groupName;
+ mKitList = kitList;
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/IKit.java b/dklib/src/main/java/vip/devkit/debugkit/kit/IKit.java
new file mode 100644
index 0000000..bf28e61
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/IKit.java
@@ -0,0 +1,31 @@
+package vip.devkit.debugkit.kit;
+
+import android.content.Context;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.StringRes;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit
+ * File Name: IKit.java
+ * Create Date: 2019/6/28 10:57
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public interface IKit {
+ int getCategory();
+
+ @StringRes
+ int getName();
+
+ @DrawableRes
+ int getIcon();
+
+ void onClick(Context context);
+
+ void onAppInit(Context context);
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/KitItem.java b/dklib/src/main/java/vip/devkit/debugkit/kit/KitItem.java
new file mode 100644
index 0000000..1c0b253
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/KitItem.java
@@ -0,0 +1,23 @@
+package vip.devkit.debugkit.kit;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit
+ * File Name: KitItem.java
+ * Create Date: 2019/7/1 15:00
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class KitItem {
+ public IKit kit;
+
+ public KitItem(){
+
+ }
+ public KitItem(IKit kit) {
+ this.kit = kit;
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CacheConfig.java b/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CacheConfig.java
new file mode 100644
index 0000000..92fff47
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CacheConfig.java
@@ -0,0 +1,27 @@
+package vip.devkit.debugkit.kit.crash;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.crash
+ * File Name: CacheConfig.java
+ * Create Date: 2019/7/9 9:33
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CacheConfig {
+
+ static String CRASH_HISTORY_DIR = "crash";
+
+ static int CRASH_FILE_SZIE = 5;
+
+ static boolean isCrashCapture = false;
+
+
+
+
+
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CacheUtils.java b/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CacheUtils.java
new file mode 100644
index 0000000..3df701f
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CacheUtils.java
@@ -0,0 +1,115 @@
+package vip.devkit.debugkit.kit.crash;
+
+import android.content.Context;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import vip.devkit.debugkit.kit.log.LogCat;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.crash
+ * File Name: CacheUtils.java
+ * Create Date: 2019/7/9 9:30
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CacheUtils {
+
+ private CacheUtils() {
+ }
+
+ public static boolean saveObject(Context context, String key, Serializable ser) {
+ File file = new File(context.getCacheDir() + "/" + key);
+ if (!file.exists()) {
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ LogCat.e(e.toString());
+ }
+ }
+ return saveObject(ser, file);
+ }
+
+ public static Serializable readObject(Context context, String key) {
+ File file = new File(context.getCacheDir() + "/" + key);
+ return readObject(file);
+ }
+
+ public static boolean saveObject(Serializable ser, File file) {
+ FileOutputStream fos = null;
+ ObjectOutputStream oos = null;
+ try {
+ fos = new FileOutputStream(file);
+ oos = new ObjectOutputStream(fos);
+ oos.writeObject(ser);
+ oos.flush();
+ return true;
+ } catch (IOException e) {
+ LogCat.e(e.toString());
+ return false;
+ } finally {
+ if (oos != null) {
+ try {
+ oos.close();
+ } catch (IOException e) {
+ LogCat.e(e.toString());
+ }
+ }
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException e) {
+ LogCat.e(e.toString());
+ }
+ }
+ }
+ }
+
+ public static Serializable readObject(File file) {
+ if (file == null || !file.exists() || file.isDirectory()) {
+ return null;
+ }
+ FileInputStream fis = null;
+ ObjectInputStream ois = null;
+ try {
+ fis = new FileInputStream(file);
+ ois = new ObjectInputStream(fis);
+ return (Serializable) ois.readObject();
+ } catch (IOException e) {
+ if (e instanceof InvalidClassException) {
+ file.delete();
+ }
+ LogCat.e(e.toString());
+ return null;
+ } catch (ClassNotFoundException e) {
+ LogCat.e(e.toString());
+ return null;
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ LogCat.e(e.toString());
+ }
+ }
+ if (ois != null) {
+ try {
+ ois.close();
+ } catch (IOException e) {
+ LogCat.e(e.toString());
+ }
+ }
+ }
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CrashCaptureManager.java b/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CrashCaptureManager.java
new file mode 100644
index 0000000..f06de2e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/crash/CrashCaptureManager.java
@@ -0,0 +1,126 @@
+package vip.devkit.debugkit.kit.crash;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.Log;
+import android.widget.Toast;
+
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.bean.CrashInfoBean;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.util.FileUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.crash
+ * File Name: CrashCaptureManager.java
+ * Create Date: 2019/7/9 9:26
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CrashCaptureManager implements Thread.UncaughtExceptionHandler {
+ private static final String TAG = "CrashCaptureManager";
+ private final Thread.UncaughtExceptionHandler mDefaultHandler;
+ private final Handler mHandler;
+ private Context mContext;
+ private CrashCaptureManager() {
+ mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ HandlerThread handlerThread = new HandlerThread(TAG);
+ handlerThread.start();
+ mHandler = new Handler(handlerThread.getLooper());
+ }
+
+ private static class Holder {
+ private static final CrashCaptureManager INSTANCE = new CrashCaptureManager();
+ }
+
+ public static CrashCaptureManager getInstance() {
+ return Holder.INSTANCE;
+ }
+
+ public void init(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ public void start() {
+ Thread.setDefaultUncaughtExceptionHandler(this);
+ }
+
+ public void stop() {
+ Thread.setDefaultUncaughtExceptionHandler(mDefaultHandler);
+ }
+
+ @Override
+ public void uncaughtException(final Thread t, final Throwable e) {
+ LogCat.d(t.toString());
+ LogCat.d(Log.getStackTraceString(e));
+ CacheUtils.saveObject(e, getCrashCacheFile());
+ post(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(mContext, mContext.getString(R.string.dk_crash_capture_tips), Toast.LENGTH_SHORT).show();
+ }
+ });
+ postDelay(new Runnable() {
+ @Override
+ public void run() {
+ if (mDefaultHandler != null) {
+ mDefaultHandler.uncaughtException(t, e);
+ }
+ }
+ }, 2000);
+ }
+
+ private void post(Runnable r) {
+ mHandler.post(r);
+ }
+
+ private void postDelay(Runnable r, long delayMillis) {
+ mHandler.postDelayed(r, delayMillis);
+ }
+
+ public File getCrashCacheDir() {
+ File dir = new File(mContext.getCacheDir() + File.separator + "crash");
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+ return dir;
+ }
+
+ private File getCrashCacheFile() {
+ String fileName = new Date().toString();
+ return new File(getCrashCacheDir() + File.separator + fileName);
+ }
+
+ public void clearCacheHistory() {
+ FileUtil.deleteDirectory(getCrashCacheDir());
+ }
+
+ public List getCrashCaches() {
+ File[] caches = getCrashCacheDir().listFiles();
+ List result = new ArrayList<>();
+ if (caches == null) {
+ return result;
+ }
+ for (File cache : caches) {
+ Serializable serializable = CacheUtils.readObject(cache);
+ if (serializable instanceof Throwable) {
+ CrashInfoBean info = new CrashInfoBean((Throwable) serializable, cache.lastModified());
+ result.add(info);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/AppInfo.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/AppInfo.java
new file mode 100644
index 0000000..6ee3a95
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/AppInfo.java
@@ -0,0 +1,49 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.bean.AppInfoBean;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.kit.log.LogCat;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class AppInfo implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_info;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_app_info;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ AppInfoBean appInfoBean = new AppInfoBean(context);
+// LogCat.i("build netInfo:"+appInfoBean.toString());
+ LogCat.i("dk_log:"+123);
+ LogCat.i("dk_log----------------","build netInfo:"+appInfoBean.toString());
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/BaseUrlManger.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/BaseUrlManger.java
new file mode 100644
index 0000000..60db114
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/BaseUrlManger.java
@@ -0,0 +1,50 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.content.Intent;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.base_url.BaseUrlManagerActivity;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class BaseUrlManger implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_base_url;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_base_url;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Intent intent = new Intent(context, BaseUrlManagerActivity.class);
+ context.startActivity(intent);
+
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/CachesManager.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/CachesManager.java
new file mode 100644
index 0000000..5f1e2e1
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/CachesManager.java
@@ -0,0 +1,50 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.content.Intent;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.AppDataCleanActivity;
+import vip.devkit.debugkit.ui.crash.CrashManagerActivity;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CachesManager implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_clean;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_data_clean;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Intent intent = new Intent(context, AppDataCleanActivity.class);
+ context.startActivity(intent);
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/CrashManger.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/CrashManger.java
new file mode 100644
index 0000000..c8298b0
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/CrashManger.java
@@ -0,0 +1,53 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.content.Intent;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.kit.crash.CrashCaptureManager;
+import vip.devkit.debugkit.ui.crash.CrashManagerActivity;
+import vip.devkit.debugkit.ui.permission.PermissionManagerActivity;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CrashManger implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_crash;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_crash_catch;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ CrashCaptureManager.getInstance().init(context);
+ CrashCaptureManager.getInstance().start();
+ Intent intent = new Intent(context, CrashManagerActivity.class);
+ context.startActivity(intent);
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/DataExport.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/DataExport.java
new file mode 100644
index 0000000..056ea6e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/DataExport.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class DataExport implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_data_export;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_data_export;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/FileExplorer.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/FileExplorer.java
new file mode 100644
index 0000000..48e1760
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/FileExplorer.java
@@ -0,0 +1,50 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.content.Intent;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.FileExplorer.FileExplorerActivity;
+import vip.devkit.debugkit.ui.crash.CrashManagerActivity;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class FileExplorer implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_file;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_file_explorer;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Intent intent = new Intent(context, FileExplorerActivity.class);
+ context.startActivity(intent);
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/LogManager.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/LogManager.java
new file mode 100644
index 0000000..efecf8d
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/LogManager.java
@@ -0,0 +1,47 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: PermissionManager.java
+ * Create Date: 2019/7/1 17:48
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class LogManager implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_log;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_log_info;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/PermissionManager.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/PermissionManager.java
new file mode 100644
index 0000000..ef78e9f
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/PermissionManager.java
@@ -0,0 +1,47 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.content.Intent;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.permission.PermissionManagerActivity;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: PermissionManager.java
+ * Create Date: 2019/7/1 17:48
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class PermissionManager implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_permission;
+ }
+
+ @Override
+ public int getIcon() {
+ return R.mipmap.dk_crash_permission;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Intent intent = new Intent(context, PermissionManagerActivity.class);
+ context.startActivity(intent);
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/Simulation.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/Simulation.java
new file mode 100644
index 0000000..054fb88
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/Simulation.java
@@ -0,0 +1,47 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: Simulation.java
+ * Create Date: 2019/7/1 17:52
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Simulation implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_simulation;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/debug/WebBrowse.java b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/WebBrowse.java
new file mode 100644
index 0000000..21d878e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/debug/WebBrowse.java
@@ -0,0 +1,47 @@
+package vip.devkit.debugkit.kit.debug;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class WebBrowse implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_web;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/developer/Language.java b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/Language.java
new file mode 100644
index 0000000..e0d8f79
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/Language.java
@@ -0,0 +1,15 @@
+package vip.devkit.debugkit.kit.developer;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.developer
+ * File Name: Language.java
+ * Create Date: 2019/7/1 18:04
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Language {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/developer/RuningService.java b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/RuningService.java
new file mode 100644
index 0000000..3f7c756
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/RuningService.java
@@ -0,0 +1,15 @@
+package vip.devkit.debugkit.kit.developer;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.developer
+ * File Name: SystemSetting.java
+ * Create Date: 2019/7/1 18:00
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class RuningService {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/developer/SystemSetting.java b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/SystemSetting.java
new file mode 100644
index 0000000..0f5694f
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/SystemSetting.java
@@ -0,0 +1,15 @@
+package vip.devkit.debugkit.kit.developer;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.developer
+ * File Name: SystemSetting.java
+ * Create Date: 2019/7/1 18:00
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class SystemSetting {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/developer/USBKit.java b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/USBKit.java
new file mode 100644
index 0000000..87ec20e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/developer/USBKit.java
@@ -0,0 +1,47 @@
+package vip.devkit.debugkit.kit.developer;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/1 17:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class USBKit implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_debug_info;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/log/IPrinter.java b/dklib/src/main/java/vip/devkit/debugkit/kit/log/IPrinter.java
new file mode 100644
index 0000000..6a6ec90
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/log/IPrinter.java
@@ -0,0 +1,73 @@
+package vip.devkit.debugkit.kit.log;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.log
+ * File Name: IPrinter.java
+ * Create Date: 2019/7/8 15:16
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public interface IPrinter {
+
+ /**
+ * 获取日志配置信息
+ *
+ * @return {@link LogConfig} 日志配置
+ */
+ LogConfig getLogConfig();
+
+ /**
+ * 初始化日志配置信息 ( 使用默认配置 )
+ *
+ * @return {@link LogConfig} 日志配置
+ */
+ LogConfig init();
+
+
+ /**
+ * 自定义日志配置信息
+ *
+ * @param logConfig 日志配置
+ */
+ void init(LogConfig logConfig);
+
+
+ void d(String log);
+
+ void i(Object... log);
+
+ void w(String log);
+
+ void e(String log);
+
+ void e(Throwable throwable);
+
+ void a(String log);
+
+ void json(String log);
+
+ void xml(String log);
+
+
+
+ void d(String tag, String log);
+
+ void i(String tag, Object... log);
+
+ void w(String tag, String log);
+
+ void e(String tag, String log);
+
+ void e(String tag, Throwable throwable);
+
+ void a(String tag, String log);
+
+ void json(String tag, String log);
+
+ void xml(String tag, String log);
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogCat.java b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogCat.java
new file mode 100644
index 0000000..98052ab
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogCat.java
@@ -0,0 +1,113 @@
+package vip.devkit.debugkit.kit.log;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: LogCat.java
+ * Create Date: 2019/7/1 11:51
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class LogCat {
+
+ private static final IPrinter sPrinter = new LogPrinter();
+
+
+ private LogCat() {
+ }
+
+ /**
+ * @return {@link LogConfig} config
+ */
+ public static LogConfig getLogConfig() {
+ return sPrinter.getLogConfig();
+ }
+
+ /**
+ * default
+ * @return {@link LogConfig} log config
+ */
+ public static LogConfig init() {
+ return sPrinter.init();
+ }
+
+ /**
+ * @param logConfig config
+ */
+ public static void init(final LogConfig logConfig) {
+ sPrinter.init(logConfig);
+ }
+
+
+
+ public static void d(String msg) {
+ sPrinter.d(msg);
+ }
+
+ public static void i(Object... msg) {
+ sPrinter.i(msg);
+ }
+
+ public static void w(String msg) {
+ sPrinter.w(msg);
+ }
+
+
+ public static void e(String msg) {
+ sPrinter.e(msg);
+ }
+
+ public static void e(Throwable msg) {
+ sPrinter.e(msg);
+ }
+
+ public static void a(String msg) {
+ sPrinter.a(msg);
+ }
+
+
+ public static void d(String tag, String msg) {
+ sPrinter.d(tag,msg);
+ }
+ public static void i(String tag, String msg) {
+ sPrinter.i(tag,msg);
+ }
+ public static void w(String tag, String msg) {
+ sPrinter.w(tag,msg);
+ }
+ public static void e(String tag, String msg) {
+ sPrinter.e(tag,msg);
+ }
+ public static void e(String tag,Throwable msg) {
+ sPrinter.e(tag,msg);
+ }
+ public static void a(String tag, String msg) {
+ sPrinter.a(tag,msg);
+ }
+
+
+
+
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogConfig.java b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogConfig.java
new file mode 100644
index 0000000..bca7619
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogConfig.java
@@ -0,0 +1,45 @@
+package vip.devkit.debugkit.kit.log;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.log
+ * File Name: LogConfig.java
+ * Create Date: 2019/7/8 15:00
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class LogConfig {
+
+ public static final int VERBOSE = 2;
+ public static final int DEBUG = 3;
+ public static final int INFO = 4;
+ public static final int WARN = 5;
+ public static final int ERROR = 6;
+ public static final int ASSERT = 7;
+ public static final int JSON = 8;
+ public static final int XML = 9;
+
+ public static final int JSON_INDENT = 4;
+
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+
+ public static String LOG_TAG = "dk_log";
+
+ public static LogLevel DEFAULT_LOG_LEVEL = LogLevel.DEBUG;
+
+
+ public static LogLevel logLevel=DEFAULT_LOG_LEVEL;
+
+ public static void setLogTag(String logTag) {
+ LOG_TAG = logTag;
+ }
+
+ public void setLogLevel(LogLevel logLevel) {
+ this.logLevel = logLevel;
+ }
+}
+
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogLevel.java b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogLevel.java
new file mode 100644
index 0000000..0f0cc9c
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogLevel.java
@@ -0,0 +1,39 @@
+package vip.devkit.debugkit.kit.log;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.log
+ * File Name: LogLevel.java
+ * Create Date: 2019/7/8 14:59
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public enum LogLevel {
+ /**
+ * 全部不打印
+ */
+ NONE,
+
+ /**
+ * 调试级别 v, d - 全部打印
+ */
+ DEBUG,
+
+ /**
+ * 正常级别 i
+ */
+ INFO,
+
+ /**
+ * 警告级别 w
+ */
+ WARN,
+
+ /**
+ * 异常级别 e, wtf
+ */
+ ERROR
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogPrinter.java b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogPrinter.java
new file mode 100644
index 0000000..b5e325e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/log/LogPrinter.java
@@ -0,0 +1,327 @@
+package vip.devkit.debugkit.kit.log;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import static vip.devkit.debugkit.kit.log.LogConfig.ASSERT;
+import static vip.devkit.debugkit.kit.log.LogConfig.DEBUG;
+import static vip.devkit.debugkit.kit.log.LogConfig.ERROR;
+import static vip.devkit.debugkit.kit.log.LogConfig.INFO;
+import static vip.devkit.debugkit.kit.log.LogConfig.JSON_INDENT;
+import static vip.devkit.debugkit.kit.log.LogConfig.LINE_SEPARATOR;
+import static vip.devkit.debugkit.kit.log.LogConfig.VERBOSE;
+import static vip.devkit.debugkit.kit.log.LogConfig.WARN;
+import static vip.devkit.debugkit.kit.log.LogConfig.JSON;
+import static vip.devkit.debugkit.kit.log.LogConfig.XML;
+import static vip.devkit.debugkit.kit.log.Util.getObjectsString;
+import static vip.devkit.debugkit.kit.log.Util.printLine;
+
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.log
+ * File Name: LogLevel.java
+ * Create Date: 2019/7/8 14:59
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class LogPrinter implements IPrinter {
+
+ LogConfig mLogConfig;
+
+ @Override
+ public LogConfig getLogConfig() {
+ return mLogConfig;
+ }
+
+ @Override
+ public LogConfig init() {
+ if (mLogConfig == null) {
+ mLogConfig = new LogConfig();
+ }
+ return mLogConfig;
+ }
+
+ @Override
+ public void init(LogConfig logConfig) {
+ mLogConfig = logConfig;
+ }
+
+
+ @Override
+ public void d(String log) {
+ d(mLogConfig.LOG_TAG, log);
+ }
+
+ @Override
+ public void i(Object... log) {
+ StringBuilder sb = new StringBuilder();
+ for (Object obj : log) {
+ sb.append(obj + ",");
+ }
+ log(INFO,mLogConfig.LOG_TAG,String.valueOf(sb));
+ }
+
+
+ @Override
+ public void w(String log) {
+ log(WARN,mLogConfig.LOG_TAG,log);
+ }
+
+ @Override
+ public void e(String log) {
+ log(INFO,mLogConfig.LOG_TAG,log);
+ }
+
+ @Override
+ public void e(Throwable throwable) {
+ log(ERROR,mLogConfig.LOG_TAG,throwable.toString());
+ }
+
+ @Override
+ public void a(String log) {
+ log(ASSERT,mLogConfig.LOG_TAG,log);
+ }
+
+ @Override
+ public void json(String log) {
+ log(JSON,mLogConfig.LOG_TAG,log);
+ }
+
+ @Override
+ public void xml(String log) {
+ log(XML,mLogConfig.LOG_TAG,log);
+ }
+
+
+ @Override
+ public void d(String tag, String log) {
+ log(DEBUG,tag,log);
+ }
+
+
+ @Override
+ public void i(String tag, Object... log) {
+ StringBuilder sb = new StringBuilder();
+ for (Object obj : log) {
+ sb.append(obj + ",");
+ }
+ log(INFO,tag,String.valueOf(sb));
+ }
+
+ @Override
+ public void w(String tag, String log) {
+ log(WARN,tag,log);
+ }
+
+ @Override
+ public void e(String tag, String log) {
+ log(ERROR,tag,log);
+ }
+
+ @Override
+ public void e(String tag, Throwable throwable) {
+ log(ERROR,tag,throwable.toString());
+ }
+
+ @Override
+ public void a(String tag, String log) {
+ log(ASSERT,tag,log);
+ }
+
+ @Override
+ public void json(String tag, String log) {
+ log(JSON,tag,log);
+ }
+
+ @Override
+ public void xml(String tag, String log) {
+ log(XML,tag,log);
+ }
+
+
+ private void log(int logType, String tagStr, Object objects) {
+ String[] contents = wrapperContent(tagStr, objects);
+ String tag = contents[0];
+ String msg = contents[1];
+ String headString = contents[2];
+ if (mLogConfig.logLevel != LogLevel.NONE) {
+ switch (logType) {
+ case VERBOSE:
+ case DEBUG:
+ case INFO:
+ case WARN:
+ case ERROR:
+ case ASSERT:
+ printDefault(logType, tag, headString + msg);
+ break;
+ case JSON:
+ printJson(tag, msg, headString);
+ break;
+ case XML:
+ printXml(tag, msg, headString);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ public String[] wrapperContent(String tag, Object... objects) {
+ if (TextUtils.isEmpty(tag)) {
+ tag = LogConfig.LOG_TAG;
+ }
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ StackTraceElement targetElement = stackTrace[6];
+ if (TextUtils.isEmpty(tag)) {
+ targetElement = stackTrace[6];
+ }
+ String className = targetElement.getClassName();
+ String[] classNameInfo = className.split("\\.");
+ if (classNameInfo.length > 0) {
+ className = classNameInfo[classNameInfo.length-1] + ".java";
+ }
+ String methodName = targetElement.getMethodName();
+ int lineNumber = targetElement.getLineNumber();
+ if (lineNumber < 0) {
+ lineNumber = 0;
+ }
+ String methodNameShort = methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
+ String msg = (objects == null) ? "Log with null object" : getObjectsString(objects);
+ String headString = "[(" + className + ":" + lineNumber + ")#" + methodNameShort + " ] ";
+ return new String[]{tag, msg, headString};
+ }
+
+ private void printDefault(int type, String tag, String msg) {
+ if (!Util.isPrintLog(mLogConfig, type)) {
+ return;
+ }
+ if (TextUtils.isEmpty(tag)) {
+ tag = mLogConfig.LOG_TAG;
+ }
+ int index = 0;
+ int maxLength = 4000;
+ int countOfSub = msg.length() / maxLength;
+
+ if (countOfSub > 0) { // The log is so long
+ for (int i = 0; i < countOfSub; i++) {
+ String sub = msg.substring(index, index + maxLength);
+ printSub(type, tag, sub);
+ index += maxLength;
+ }
+ //printSub(type, msg.substring(index, msg.length()));
+ } else {
+ printSub(type, tag, msg);
+ }
+
+ }
+
+ private void printSub(int type, String tag, String sub) {
+ if (tag == null) {
+ tag = mLogConfig.LOG_TAG;
+ }
+ switch (type) {
+ case VERBOSE:
+ Log.v(tag, sub);
+ break;
+ case DEBUG:
+ Log.d(tag, sub);
+ break;
+ case INFO:
+ Log.i(tag, sub);
+ break;
+ case WARN:
+ Log.w(tag, sub);
+ break;
+ case ERROR:
+ Log.e(tag, sub);
+ break;
+ case ASSERT:
+ Log.wtf(tag, sub);
+ break;
+ }
+ }
+
+
+ private void printJson(String tag, String json, String headString) {
+ if (TextUtils.isEmpty(json)) {
+ d("Empty/Null json content");
+ return;
+ }
+ if (TextUtils.isEmpty(tag)) {
+ tag = mLogConfig.LOG_TAG;
+ }
+ String message;
+
+ try {
+ if (json.startsWith("{")) {
+ JSONObject jsonObject = new JSONObject(json);
+ message = jsonObject.toString(JSON_INDENT);
+ } else if (json.startsWith("[")) {
+ JSONArray jsonArray = new JSONArray(json);
+ message = jsonArray.toString(JSON_INDENT);
+ } else {
+ message = json;
+ }
+ } catch (JSONException e) {
+ message = json;
+ }
+
+ printLine(tag, true);
+ message = headString + LINE_SEPARATOR + message;
+ String[] lines = message.split(LINE_SEPARATOR);
+ for (String line : lines) {
+ Log.d(tag, "|" + line);
+ }
+ printLine(tag, false);
+ }
+
+ private void printXml(String tag, String xml, String headString) {
+ if (TextUtils.isEmpty(tag)) {
+ tag = mLogConfig.LOG_TAG;
+ }
+ if (xml != null) {
+ try {
+ Source xmlInput = new StreamSource(new StringReader(xml));
+ StreamResult xmlOutput = new StreamResult(new StringWriter());
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+ transformer.transform(xmlInput, xmlOutput);
+ xml = xmlOutput.getWriter().toString().replaceFirst(">", ">\n");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ xml = headString + "\n" + xml;
+ } else {
+ xml = headString + "Log with null object";
+ }
+
+ printLine(tag, true);
+ String[] lines = xml.split(LINE_SEPARATOR);
+ for (String line : lines) {
+ if (!TextUtils.isEmpty(line)) {
+ Log.d(tag, "|" + line);
+ }
+ }
+ printLine(tag, false);
+ }
+
+
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/log/Util.java b/dklib/src/main/java/vip/devkit/debugkit/kit/log/Util.java
new file mode 100644
index 0000000..c0d79e7
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/log/Util.java
@@ -0,0 +1,104 @@
+package vip.devkit.debugkit.kit.log;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.log
+ * File Name: Util.java
+ * Create Date: 2019/7/8 15:38
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Util {
+
+
+
+ public static String getObjectsString(Object... objects) {
+
+ if (objects.length > 1) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("\n");
+ for (int i = 0; i < objects.length; i++) {
+ Object object = objects[i];
+ if (object == null) {
+ stringBuilder.append("param").append("[").append(i).append("]").append(" = ").append("null").append("\n");
+ } else {
+ stringBuilder.append("param").append("[").append(i).append("]").append(" = ").append(object.toString()).append("\n");
+ }
+ }
+ return stringBuilder.toString();
+ } else {
+ Object object = objects[0];
+ return object == null ? "null" : object.toString();
+ }
+ }
+
+ public static void printLine(String tag, boolean isTop) {
+ if (isTop) {
+ Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");
+ } else {
+ Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");
+ }
+ }
+
+ /**
+ * 是否打印日志
+ * @param logConfig 日志配置
+ * @param logType 日志类型
+ * @return {@code true} yes, {@code false} no
+ */
+ public static boolean isPrintLog(final LogConfig logConfig, final int logType) {
+ boolean isPrint = false;
+ LogLevel logLevel = logConfig.logLevel;
+ switch (logLevel) {
+ case NONE: //
+ break;
+ case DEBUG: // v, d - all
+ isPrint = true;
+ break;
+ case INFO: // i
+ case WARN: // w
+ case ERROR: // e, wtf
+ isPrint = checkLogLevel(logLevel, logType);
+ break;
+ default:
+ break;
+ }
+ return isPrint;
+ }
+ /**
+ * 判断日志级别是否允许输出
+ * @param logLevel 日志级别
+ * @param logType 日志类型
+ * @return {@code true} yes, {@code false} no
+ */
+ private static boolean checkLogLevel(final LogLevel logLevel, final int logType) {
+ switch (logLevel) {
+ case INFO: // i
+ if (logType != Log.VERBOSE && logType != Log.DEBUG) {
+ return true;
+ }
+ break;
+ case WARN: // w
+ if (logType != Log.VERBOSE && logType != Log.DEBUG && logType != Log.INFO) {
+ return true;
+ }
+ break;
+ case ERROR: // e, wtf
+ if (logType == Log.ERROR || logType == Log.ASSERT) {
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Battery.java b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Battery.java
new file mode 100644
index 0000000..218e2a7
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Battery.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.performance;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.performance
+ * File Name: Battery.java
+ * Create Date: 2019/7/1 18:05
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Battery implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_performance_battery;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/performance/CPU.java b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/CPU.java
new file mode 100644
index 0000000..f26c492
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/CPU.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.performance;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.performance
+ * File Name: FTPS.java
+ * Create Date: 2019/7/1 18:04
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CPU implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_performance_cpu;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/performance/FTPS.java b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/FTPS.java
new file mode 100644
index 0000000..cb809de
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/FTPS.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.performance;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.performance
+ * File Name: FTPS.java
+ * Create Date: 2019/7/1 18:04
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class FTPS implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_performance_fps;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/performance/RAM.java b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/RAM.java
new file mode 100644
index 0000000..467fa34
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/RAM.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.performance;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.performance
+ * File Name: RAM.java
+ * Create Date: 2019/7/2 9:14
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class RAM implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_performance_ram;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Time.java b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Time.java
new file mode 100644
index 0000000..603354b
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Time.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.performance;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.performance
+ * File Name: Time.java
+ * Create Date: 2019/7/2 9:15
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Time implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_performance_open_time;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Traffic.java b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Traffic.java
new file mode 100644
index 0000000..c245194
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/performance/Traffic.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.performance;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.performance
+ * File Name: Traffic.java
+ * Create Date: 2019/7/2 9:14
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Traffic implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_performance_traffic;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/system/CpuKit.java b/dklib/src/main/java/vip/devkit/debugkit/kit/system/CpuKit.java
new file mode 100644
index 0000000..43c7fef
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/system/CpuKit.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.system;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.system
+ * File Name: HardwareKit.java
+ * Create Date: 2019/7/1 15:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CpuKit implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_sys_cpu;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/system/HardwareKit.java b/dklib/src/main/java/vip/devkit/debugkit/kit/system/HardwareKit.java
new file mode 100644
index 0000000..c990cdc
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/system/HardwareKit.java
@@ -0,0 +1,47 @@
+package vip.devkit.debugkit.kit.system;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.system
+ * File Name: HardwareKit.java
+ * Create Date: 2019/7/1 15:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class HardwareKit implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_sys_hardware;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/system/NetworkKit.java b/dklib/src/main/java/vip/devkit/debugkit/kit/system/NetworkKit.java
new file mode 100644
index 0000000..3d454af
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/system/NetworkKit.java
@@ -0,0 +1,50 @@
+package vip.devkit.debugkit.kit.system;
+
+import android.content.Context;
+import android.util.Log;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.sysinfo.SysInfoKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.system
+ * File Name: HardwareKit.java
+ * Create Date: 2019/7/1 15:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class NetworkKit implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_sys_network;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ SysInfoKit sysInfoKit =new SysInfoKit();
+ Log.i("build netInfo:",0+sysInfoKit.getNetInfo(context).toString());
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/system/ScreenKit.java b/dklib/src/main/java/vip/devkit/debugkit/kit/system/ScreenKit.java
new file mode 100644
index 0000000..708799b
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/system/ScreenKit.java
@@ -0,0 +1,50 @@
+package vip.devkit.debugkit.kit.system;
+
+import android.content.Context;
+import android.util.Log;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.sysinfo.SysInfoKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.system
+ * File Name: HardwareKit.java
+ * Create Date: 2019/7/1 15:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class ScreenKit implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_sys_screen;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ SysInfoKit sysInfoKit =new SysInfoKit();
+ Log.i("build getScreen:",0+sysInfoKit.getScreen(context).toString());
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/system/SysInfo.java b/dklib/src/main/java/vip/devkit/debugkit/kit/system/SysInfo.java
new file mode 100644
index 0000000..e4282cd
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/system/SysInfo.java
@@ -0,0 +1,53 @@
+package vip.devkit.debugkit.kit.system;
+
+import android.content.Context;
+import android.util.Log;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.ui.sysinfo.SysInfoKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit
+ * File Name: SysInfo.java
+ * Create Date: 2019/7/1 15:30
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class SysInfo implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_sys_system;
+ }
+
+
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+
+ SysInfoKit sysInfoKit =new SysInfoKit();
+ Log.i("build SysInfo:",0+sysInfoKit.getInfo().toString());
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/ue/ColorPicker.java b/dklib/src/main/java/vip/devkit/debugkit/kit/ue/ColorPicker.java
new file mode 100644
index 0000000..b73a2f5
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/ue/ColorPicker.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.ue;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.ue
+ * File Name: ColorPicker.java
+ * Create Date: 2019/7/2 9:09
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class ColorPicker implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_ue_color_picker;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/kit/ue/UE.java b/dklib/src/main/java/vip/devkit/debugkit/kit/ue/UE.java
new file mode 100644
index 0000000..551a7fd
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/kit/ue/UE.java
@@ -0,0 +1,46 @@
+package vip.devkit.debugkit.kit.ue;
+
+import android.content.Context;
+import android.widget.Toast;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.IKit;
+import vip.devkit.debugkit.util.ResUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.kit.ue
+ * File Name: ColorPicker.java
+ * Create Date: 2019/7/2 9:09
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class UE implements IKit {
+ @Override
+ public int getCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getName() {
+ return R.string.dk_ue_ue;
+ }
+
+ @Override
+ public int getIcon() {
+ return android.R.mipmap.sym_def_app_icon;
+ }
+
+ @Override
+ public void onClick(Context context) {
+ Toast.makeText(context, ResUtil.getString(context,getName()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onAppInit(Context context) {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/AppDataCleanActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/AppDataCleanActivity.java
new file mode 100644
index 0000000..165b26c
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/AppDataCleanActivity.java
@@ -0,0 +1,36 @@
+package vip.devkit.debugkit.ui;
+
+import vip.devkit.debugkit.ui.base.BaseActivity;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui
+ * File Name: AppDataCleanActivity.java
+ * Create Date: 2019/7/9 11:41
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class AppDataCleanActivity extends BaseActivity {
+ @Override
+ protected void initData() {
+
+ }
+
+ @Override
+ protected int setLayoutId() {
+ return 0;
+ }
+
+ @Override
+ protected void initView() {
+
+ }
+
+ @Override
+ protected void setListener() {
+
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/FileExplorer/FileExplorerActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/FileExplorer/FileExplorerActivity.java
new file mode 100644
index 0000000..16e5136
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/FileExplorer/FileExplorerActivity.java
@@ -0,0 +1,250 @@
+package vip.devkit.debugkit.ui.FileExplorer;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.adapter.FileFolderAdapter;
+import vip.devkit.debugkit.adapter.FileInfoAdapter;
+import vip.devkit.debugkit.bean.FileInfoBean;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.ui.base.BaseActivity;
+import vip.devkit.debugkit.widget.recyclerview.BaseRecyclerAdapter;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.FileExplorer
+ * File Name: FileExplorerActivity.java
+ * Create Date: 2019/7/9 14:17
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class FileExplorerActivity extends BaseActivity implements View.OnClickListener, FileInfoAdapter.OnItemClickListener {
+ private LinearLayout mLlTitleBack;
+ private TextView mTvTitle;
+ private TextView mTvTitleRight;
+ private LinearLayout mLlTitleRight;
+ private LinearLayout mLlCommonLayout;
+ private RecyclerView mRlList;
+ private RecyclerView mRlFileFolder;
+ private LinearLayout mLlFolder;
+
+ private File mCurDir;
+ private FileInfoAdapter mAdapter;
+ private List mBeanList = new ArrayList<>();
+ private FileFolderAdapter mFolderAdapter;
+ private List mFolderList = new ArrayList<>();
+
+ @Override
+ protected void initData() {
+
+ }
+
+ @Override
+ protected int setLayoutId() {
+ return R.layout.dk_activity_file_explorer;
+ }
+
+ @Override
+ protected void initView() {
+
+ mLlTitleBack = (LinearLayout) findViewById(R.id.ll_title_back);
+ mLlTitleBack.setOnClickListener(this);
+ mTvTitle = (TextView) findViewById(R.id.tv_title);
+ mTvTitleRight = (TextView) findViewById(R.id.tv_title_right);
+ mLlTitleRight = (LinearLayout) findViewById(R.id.ll_title_right);
+ mLlCommonLayout = (LinearLayout) findViewById(R.id.ll_common_layout);
+ mRlList = (RecyclerView) findViewById(R.id.rl_list);
+ mRlFileFolder = (RecyclerView) findViewById(R.id.rl_file_folder);
+ mLlFolder = (LinearLayout) findViewById(R.id.ll_folder);
+ mTvTitle.setOnClickListener(this);
+ mTvTitleRight.setOnClickListener(this);
+ mLlFolder.setOnClickListener(this);
+
+ mFolderAdapter = new FileFolderAdapter(R.layout.dk_item_file_folder, mFolderList);
+ LinearLayoutManager layoutManager = new LinearLayoutManager(this);
+ layoutManager.setOrientation(RecyclerView.HORIZONTAL);
+ mRlFileFolder.setLayoutManager(layoutManager);
+ mRlFileFolder.setAdapter(mFolderAdapter);
+
+
+ mBeanList.addAll(initRootFileInfos(this));
+ mAdapter = new FileInfoAdapter(R.layout.dk_item_file, mBeanList);
+ mAdapter.setOnItemClickListener(this);
+ mRlList.setLayoutManager(new LinearLayoutManager(this));
+ mRlList.setAdapter(mAdapter);
+
+
+ }
+
+ @Override
+ protected void setListener() {
+
+ mFolderAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseRecyclerAdapter adapter, View view, int position) {
+ FileInfoBean fileInfoBean = mFolderAdapter.getItem(position);
+ if (fileInfoBean.file == mCurDir) {
+ LogCat.i("当前文件夹");
+ return;
+ }
+ setAdapterData(getFileInfos(fileInfoBean.file));
+ for (int i = 0; i < mFolderList.size(); i++) {
+ LogCat.i("当前文件夹" + i);
+ if (i > position) {
+ mFolderList.remove(i);
+ }
+ }
+ mFolderAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+
+
+ @Override
+ public void onItemClick(BaseRecyclerAdapter adapter, View view, int position) {
+ FileInfoBean fileInfoBean = mAdapter.getItem(position);
+ if (fileInfoBean.file.isFile()) {
+ openFile(this,fileInfoBean.file);
+ } else {
+ mCurDir = fileInfoBean.file;
+ setAdapterData(getFileInfos(fileInfoBean.file));
+ mFolderList.add(fileInfoBean);
+ mFolderAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void setAdapterData(List fileInfos) {
+ mBeanList.clear();
+ if (!fileInfos.isEmpty()) {
+ mBeanList.addAll(fileInfos);
+ }
+ mAdapter.notifyDataSetChanged();
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.ll_title_back) {
+ finish();
+ } else if (v.getId() == R.id.ll_folder) {
+ mFolderList.clear();
+ mFolderAdapter.notifyDataSetChanged();
+ mBeanList.clear();
+ mBeanList.addAll(initRootFileInfos(this));
+ mAdapter.notifyDataSetChanged();
+ }
+ }
+
+
+ /**
+ * 调用系统应用打开图片
+ *
+ * @param context context
+ * @param file file
+ */
+ public static void openFile(Context context, File file) {
+ Intent intent = new Intent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setAction(Intent.ACTION_VIEW);
+ Uri uri = null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ // 方式一
+ uri = getImageContentUri(context, file);
+ // 方式二
+ // uri = FileProvider.getUriForFile(context, ".fileProvider", file);
+ // intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ } else {
+ uri = Uri.fromFile(file);
+ }
+
+ String type = null;
+ intent.setDataAndType(uri, type);
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ LogCat.e("FileUtil"+ e.getMessage());
+ Toast.makeText(context, "找不到打开此文件的应用!", Toast.LENGTH_SHORT).show();
+ }
+ }
+ /**
+ * 转换 content:// uri
+ *
+ * @param imageFile imageFile
+ * @return
+ */
+ public static Uri getImageContentUri(Context context, File imageFile) {
+ String filePath = imageFile.getAbsolutePath();
+ Cursor cursor = context.getContentResolver().query(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ new String[] { MediaStore.Images.Media._ID },
+ MediaStore.Images.Media.DATA + "=? ",
+ new String[] { filePath }, null);
+
+ if (cursor != null && cursor.moveToFirst()) {
+ int id = cursor.getInt(cursor
+ .getColumnIndex(MediaStore.MediaColumns._ID));
+ Uri baseUri = Uri.parse("content://media/external/images/media");
+ return Uri.withAppendedPath(baseUri, "" + id);
+ } else {
+ if (imageFile.exists()) {
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Images.Media.DATA, filePath);
+ return context.getContentResolver().insert(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ private List getFileInfos(File dir) {
+ List fileInfos = new ArrayList<>();
+ if (dir.listFiles() == null) {
+ return fileInfos;
+ }
+ for (File file : dir.listFiles()) {
+ FileInfoBean fileInfo = new FileInfoBean(file);
+ fileInfos.add(fileInfo);
+ }
+ return fileInfos;
+ }
+
+ private List initRootFileInfos(Context context) {
+ List fileInfos = new ArrayList<>();
+ fileInfos.add(new FileInfoBean(context.getFilesDir().getParentFile()));
+ fileInfos.add(new FileInfoBean(context.getExternalCacheDir()));
+ fileInfos.add(new FileInfoBean(context.getExternalFilesDir(null)));
+ return fileInfos;
+ }
+
+ private boolean isRootFile(Context context, File file) {
+ if (file == null) {
+ return false;
+ }
+ return file.equals(context.getExternalCacheDir())
+ || file.equals(context.getExternalFilesDir(null))
+ || file.equals(context.getFilesDir().getParentFile());
+ }
+}
+
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/KitManagerActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/KitManagerActivity.java
new file mode 100644
index 0000000..c356d4e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/KitManagerActivity.java
@@ -0,0 +1,95 @@
+package vip.devkit.debugkit.ui;
+
+import android.content.pm.IPackageStatsObserver;
+import android.content.pm.PackageStats;
+import android.os.RemoteException;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import vip.devkit.debugkit.DataSource;
+import vip.devkit.debugkit.KitManagerAdapter;
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.kit.GroupKitItem;
+import vip.devkit.debugkit.kit.KitItem;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.ui.base.BaseActivity;
+import vip.devkit.debugkit.ui.base_url.BaseUrlManager;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui
+ * File Name: KitManagerActivity.java
+ * Create Date: 2019/7/1 10:43
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class KitManagerActivity extends BaseActivity {
+
+
+ private RecyclerView mRvList;
+ private KitManagerAdapter mManagerAdapter;
+
+ List mItemList = new ArrayList<>();
+ List mKitItems = new ArrayList<>();
+
+ private BaseUrlManager mBaseUrlManager;
+ @Override
+ protected void initData() {
+
+ }
+
+ @Override
+ protected int setLayoutId() {
+ return R.layout.act_kit_manager;
+ }
+
+ @Override
+ protected void initView() {
+ mRvList = (RecyclerView) findViewById(R.id.rv_list);
+ mRvList.setLayoutManager(new LinearLayoutManager(this));
+ mManagerAdapter = new KitManagerAdapter(R.layout.dk_item_group_kit, mItemList);
+ mRvList.setAdapter(mManagerAdapter);
+
+ DataSource dataSource = new DataSource(this);
+
+ mItemList.addAll(dataSource.getKitList());
+ mManagerAdapter.notifyDataSetChanged();
+
+ mBaseUrlManager = new BaseUrlManager(this);
+
+ LogCat.i("mBaseUrlManager:"+mBaseUrlManager.getBaseUrl());
+
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mBaseUrlManager.refreshData();
+ LogCat.i("mBaseUrlManager:"+mBaseUrlManager.getBaseUrl());
+
+ }
+
+ @Override
+ protected void setListener() {
+
+ }
+ //aidl文件形成的Bindler机制服务类
+ public class PkgSizeObserver extends IPackageStatsObserver.Stub{
+ /*** 回调函数,
+ * @param pStats ,返回数据封装在PackageStats对象中
+ * @param succeeded 代表回调成功
+ */
+ @Override
+ public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ }
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base/BaseActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base/BaseActivity.java
new file mode 100644
index 0000000..2e944a3
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base/BaseActivity.java
@@ -0,0 +1,222 @@
+package vip.devkit.debugkit.ui.base;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.base
+ * File Name: BaseActivity.java
+ * Create Date: 2019/7/1 10:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public abstract class BaseActivity extends AppCompatActivity {
+
+ private long lastBackKeyDownTick = 0;
+ public static final long MAX_DOUBLE_BACK_DURATION = 1500;
+ protected Context mContext;
+
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+ supportRequestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏应用的标题栏
+ setContentView(setLayoutId());
+ mContext = this;
+ initBase();
+ initData();
+ initView();
+ setListener();
+ }
+
+ protected boolean isOrientation() {
+ return true;
+ }
+
+ private void initBase() {
+ }
+
+
+ protected abstract void initData();
+
+ protected abstract int setLayoutId();
+
+ protected abstract void initView();
+
+ protected abstract void setListener();
+
+
+
+
+ /**
+ * @return RootView FrameLayout
+ */
+ protected FrameLayout getRootView() {
+ View re = this.findViewById(android.R.id.content);
+ if (re != null && re instanceof FrameLayout) {
+ return (FrameLayout) re;
+ }
+ ViewGroup viewGroup = (ViewGroup) this.getWindow().getDecorView();
+ re = viewGroup.getChildAt(viewGroup.getChildCount() - 1);
+ if (re != null && re instanceof FrameLayout) {
+ return (FrameLayout) re;
+ } else {
+ re = new FrameLayout(this);
+ this.getActionBar().getHeight();
+ ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
+ , ViewGroup.LayoutParams.MATCH_PARENT);
+ viewGroup.addView(re, lp);
+ return (FrameLayout) re;
+ }
+ }
+
+ protected T getView(int id) {
+ return (T) super.findViewById(id);
+ }
+
+ /**
+ * startActivity
+ *
+ * @param clazz
+ */
+ protected void startActivity(Class> clazz) {
+ Intent intent = new Intent(this, clazz);
+ startActivity(intent);
+ }
+
+
+ /**
+ * startActivity putExtras(Bundle)
+ *
+ * @param clazz
+ * @param extras
+ */
+ protected void startActivity(Class> clazz, Bundle extras) {
+ Intent intent = new Intent(this, clazz);
+ intent.putExtras(extras);
+ startActivity(intent);
+ }
+
+ /**
+ * startActivity putExtras(Bundle)
+ *
+ * @param clazz
+ * @param requestCode
+ * @param extras
+ */
+ protected void startActivity(Class> clazz, int requestCode, Bundle extras) {
+ Intent intent = new Intent(this, clazz);
+ intent.putExtras(extras);
+ startActivityForResult(intent, requestCode);
+ }
+
+ /**
+ * startActivity putExtras(Bundle)
+ *
+ * @param clazz
+ * @param code
+ */
+ protected void startActivity(Class> clazz, int code) {
+ Intent intent = new Intent(this, clazz);
+ startActivityForResult(intent, code);
+ }
+
+
+ /**
+ * 重启当前Activity
+ */
+ private void reStartActivity() {
+ Intent intent = getIntent();
+ finish();
+ startActivity(intent);
+ }
+
+ /**
+ * 初始化是否全屏
+ */
+ protected void initFlagFullscreen() {
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏
+ }
+
+
+
+ /**
+ * @return 设置android app 的字体大小不受系统字体大小改变的影响
+ */
+ @Override
+ public Resources getResources() {
+ Resources res = super.getResources();
+ Configuration config = new Configuration();
+ config.setToDefaults();
+ res.updateConfiguration(config, res.getDisplayMetrics());
+ return res;
+ }
+
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ long currentTick = System.currentTimeMillis();
+ if (currentTick - lastBackKeyDownTick > MAX_DOUBLE_BACK_DURATION) {
+ lastBackKeyDownTick = currentTick;
+ } else {
+ finish();
+ System.exit(0);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public void finish() {
+ hideSoftInput();
+ super.finish();
+ }
+
+ private void hideSoftInput() {
+ View view = getCurrentFocus();
+ if (view == null) view = new View(this);
+ InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base/BaseFragment.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base/BaseFragment.java
new file mode 100644
index 0000000..b766be1
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base/BaseFragment.java
@@ -0,0 +1,143 @@
+package vip.devkit.debugkit.ui.base;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.base
+ * File Name: BaseFragment.java
+ * Create Date: 2019/7/1 10:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public abstract class BaseFragment extends Fragment {
+
+ protected AppCompatActivity mActivity;
+ protected View mRootView;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (context instanceof BaseActivity) {
+ mActivity = (BaseActivity) context;
+ } else {
+ mActivity = (AppCompatActivity) context;
+ }
+ }
+
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ mRootView = inflater.inflate(setLayoutId(), container, false);
+ return mRootView;
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ initView(view);
+ initData();
+ setListener();
+ }
+
+
+
+ protected abstract void initData();
+
+ protected abstract int setLayoutId();
+
+ protected abstract void initView(View view);
+
+ protected abstract void setListener();
+
+
+
+
+
+ protected T getView(int id) {
+ return (T) mRootView.findViewById(id);
+ }
+
+ /**
+ * startActivity
+ *
+ * @param clazz
+ */
+ protected void startActivity(Class> clazz) {
+ Intent intent = new Intent(mActivity, clazz);
+ startActivity(intent);
+ }
+
+
+ /**
+ * startActivity putExtras(Bundle)
+ *
+ * @param clazz
+ * @param extras
+ */
+ protected void startActivity(Class> clazz, Bundle extras) {
+ Intent intent = new Intent(mActivity, clazz);
+ intent.putExtras(extras);
+ startActivity(intent);
+ }
+
+ /**
+ * startActivity putExtras(Bundle)
+ *
+ * @param clazz
+ * @param requestCode
+ * @param extras
+ */
+ protected void startActivity(Class> clazz, int requestCode, Bundle extras) {
+ Intent intent = new Intent(mActivity, clazz);
+ intent.putExtras(extras);
+ startActivityForResult(intent, requestCode);
+ }
+
+ /**
+ * startActivity putExtras(Bundle)
+ *
+ * @param clazz
+ * @param code
+ */
+ protected void startActivity(Class> clazz, int code) {
+ Intent intent = new Intent(mActivity, clazz);
+ startActivityForResult(intent, code);
+ }
+
+
+ /**
+ * 重启当前Activity
+ */
+ private void reStartActivity() {
+ Intent intent = mActivity.getIntent();
+ mActivity.finish();
+ startActivity(intent);
+ }
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base/GCBaseExpandableListAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base/GCBaseExpandableListAdapter.java
new file mode 100644
index 0000000..88af7b4
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base/GCBaseExpandableListAdapter.java
@@ -0,0 +1,121 @@
+package vip.devkit.debugkit.ui.base;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.base
+ * File Name: GCBaseExpandableListAdapter
+ * Create Date: 2019/7/1 10:48
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public abstract class GCBaseExpandableListAdapter extends BaseExpandableListAdapter {
+
+ protected Map> mDatas = new HashMap<>();
+ protected List mGroup = new ArrayList<>();
+ protected LayoutInflater mInflater;
+ protected Context mContext;
+ protected int groupLayoutId;
+ protected int childLayoutId;
+
+ public GCBaseExpandableListAdapter(Context context, int groupLayoutId, int childLayoutId, List mGroup, Map> datas) {
+ this.mContext = context;
+ this.mGroup = mGroup;
+ this.mDatas = datas;
+ this.groupLayoutId = groupLayoutId;
+ this.childLayoutId = childLayoutId;
+ mInflater = LayoutInflater.from(context);
+ }
+
+
+ @Override
+ public int getGroupCount() {
+ return mGroup.size();
+ }
+
+ @Override
+ public Group getGroup(int i) {
+ return mGroup.get(i);
+ }
+
+ @Override
+ public int getChildrenCount(int i) {
+ return isEmpty(mDatas.get(getGroup(i))) ? 0 : mDatas.get(getGroup(i)).size();
+ }
+
+ @Override
+ public Child getChild(int i, int i1) {
+ List mGroup = mDatas.get(getGroup(i));
+ return mGroup.get(i1);
+ }
+
+ @Override
+ public long getGroupId(int i) {
+ return i;
+ }
+
+ @Override
+ public long getChildId(int i, int i1) {
+ return i1;
+ }
+
+
+ @Override
+ public View getGroupView(int position, boolean b, View view, ViewGroup viewGroup) {
+ ViewHolder mGroupHolder = ViewHolder.get(mContext, view, viewGroup, groupLayoutId, position);
+ convertGroup(mGroupHolder, getGroup(position), position);
+ return mGroupHolder.getConvertView();
+ }
+
+
+ @Override
+ public View getChildView(int groupPosition, int childPosition, boolean b, View view, ViewGroup viewGroup) {
+ ViewHolder childHolder = ViewHolder.get(mContext, view, viewGroup, childLayoutId, childPosition);
+ convertChild(childHolder, getGroup(groupPosition), getChild(groupPosition, childPosition), groupPosition, childPosition);
+ return childHolder.getConvertView();
+ }
+
+ public abstract void convertGroup(ViewHolder holder, Group t, int groupPosition);
+
+ public abstract void convertChild(ViewHolder holder, Group group, Child child, int groupPosition, int childPosition);
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ /**
+ * 子类点击事件
+ *
+ * @param i groupPosition
+ * @param i1 childPosition
+ * @return
+ */
+ @Override
+ public boolean isChildSelectable(int i, int i1) {
+ return true;
+ }
+
+ public static boolean isEmpty(List sourceList) {
+ return (sourceList == null || sourceList.size() == 0);
+ }
+
+ @Override
+ public void onGroupExpanded(int groupPosition) {
+ super.onGroupExpanded(groupPosition);
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base/ViewHolder.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base/ViewHolder.java
new file mode 100644
index 0000000..a854af0
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base/ViewHolder.java
@@ -0,0 +1,142 @@
+package vip.devkit.debugkit.ui.base;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Adapter;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import androidx.annotation.IdRes;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.base
+ * File Name: ViewHolder
+ * Create Date: 2019/7/1 10:44
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class ViewHolder {
+ private SparseArray mViews;
+ private int mPosition;
+ private View mConvertView;
+ private Context mContext;
+
+ public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
+ this.mPosition = position;
+ this.mViews = new SparseArray();
+ this.mContext = context;
+ mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
+ mConvertView.setTag(this);
+ }
+
+ public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
+ if (convertView == null) {
+ return new ViewHolder(context, parent, layoutId, position);
+ } else {
+ ViewHolder holder = (ViewHolder) convertView.getTag();
+ holder.mPosition = position;
+ return holder;
+ }
+ }
+
+ /**
+ * 通过viewId获取控件,此方法返回的是View的一个子类
+ */
+ public T getView(int viewId) {
+ View view = mViews.get(viewId);
+ if (view == null) {
+ view = mConvertView.findViewById(viewId);
+ mViews.put(viewId, view);
+ }
+ return (T) view;
+ }
+
+ public View getConvertView() {
+ return mConvertView;
+ }
+
+ public ViewHolder setText(int viewId, String text) {
+ TextView tv = getView(viewId);
+ tv.setText(text);
+ return this;
+ }
+
+ /**
+ * @param viewId
+ * @param text
+ * @param flag Paint.STRIKE_THRU_TEXT_FLAG
+ * @return
+ */
+ public ViewHolder setText(int viewId, String text, int flag) {
+ TextView tv = getView(viewId);
+ tv.getPaint().setFlags(flag);
+ tv.setText(text);
+ return this;
+ }
+
+ /**
+ *
+ */
+ public ViewHolder setImageResource(int viewId, int resId) {
+ ImageView imageView = getView(viewId);
+ imageView.setImageResource(resId);
+ return this;
+ }
+
+
+ public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
+ ImageView imageView = getView(viewId);
+ imageView.setImageBitmap(bitmap);
+ return this;
+ }
+
+
+ public ViewHolder setCheckBox(int viewId, boolean c, boolean isShow) {
+ CheckBox mCheckBox = getView(viewId);
+ if (isShow == true) {
+ mCheckBox.setVisibility(View.VISIBLE);
+ } else {
+ mCheckBox.setVisibility(View.GONE);
+ }
+ mCheckBox.setChecked(c);
+ return this;
+ }
+
+ public ViewHolder setAdapter(int viewId, Adapter adapter) {
+ ListView listView = getView(viewId);
+ if (listView != null) {
+ listView.setAdapter((ListAdapter) adapter);
+ }
+ return this;
+ }
+
+ public ViewHolder setOnClickListener(@IdRes int viewId, View.OnClickListener listener) {
+ View view = getView(viewId);
+ view.setOnClickListener(listener);
+ return this;
+ }
+
+ public ViewHolder setVisibility(@IdRes int viewId, boolean isVisibility) {
+ View view = getView(viewId);
+ if (isVisibility) {
+ view.setVisibility(View.VISIBLE);
+ } else {
+ view.setVisibility(View.GONE);
+ }
+ return this;
+ }
+
+
+}
+
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlManager.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlManager.java
new file mode 100644
index 0000000..f207476
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlManager.java
@@ -0,0 +1,115 @@
+package vip.devkit.debugkit.ui.base_url;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * File Name: BaseUrlManager
+ * Create Date: 2019/6/14 11:53
+ * Describe :
+ * Author : By k
+ * E-mail : vip@devkit.vip
+ * VersionName: 1
+ * VersionCode: V 1.0
+ * Code Update:(author - time)
+ * Update Describe:
+ */
+public class BaseUrlManager implements IBaseUrlManager {
+ private Context context;
+
+ private List urlInfos;
+
+ private UrlInfo urlInfo;
+
+ private String baseUrl;
+
+
+ public BaseUrlManager(@NonNull Context context){
+ this.context = context;
+ refreshData();
+ }
+
+
+ @Override
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ @Override
+ public UrlInfo getUrlInfo() {
+ return urlInfo;
+ }
+
+ @Override
+ public void setUrlInfo(@NonNull UrlInfo urlInfo) {
+ this.urlInfo = urlInfo;
+ this.baseUrl = urlInfo.getBaseUrl();
+ if(urlInfos!=null){
+ if(urlInfos.contains(urlInfo)){
+ urlInfos.remove(urlInfo);
+ }
+ urlInfos.add(urlInfo);
+ BaseUrlUtil.put(context,urlInfo,true);
+ }
+ }
+
+ @Override
+ public void addUrlInfo(@NonNull UrlInfo urlInfo) {
+ if(urlInfos!=null){
+ if(urlInfos.contains(urlInfo)){
+ urlInfos.remove(urlInfo);
+ }
+ urlInfos.add(urlInfo);
+ BaseUrlUtil.put(context,urlInfo);
+
+ }
+ }
+
+ @Override
+ public void addUrlInfo(@NonNull Collection list) {
+ if(urlInfos!=null){
+ urlInfos.addAll(list);
+ BaseUrlUtil.put(context,list);
+ }
+ }
+
+ @Override
+ public void remove(@NonNull UrlInfo urlInfo) {
+ if(urlInfos!=null){
+ urlInfos.remove(urlInfo);
+ BaseUrlUtil.remove(context,urlInfo.getBaseUrl());
+ }
+ }
+
+ @Override
+ public void clear() {
+ if(urlInfos!=null){
+ urlInfos.clear();
+ }
+ urlInfo = null;
+ baseUrl = null;
+ BaseUrlUtil.clear(context);
+ }
+
+ @Override
+ public List getUrlInfos() {
+ return urlInfos;
+ }
+
+
+ @Override
+ public int getCount() {
+ return urlInfos != null ? urlInfos.size() : 0;
+ }
+
+ @Override
+ public void refreshData() {
+ baseUrl = BaseUrlUtil.getBaseUrl(context);
+ urlInfo = BaseUrlUtil.getUrlInfo(context,baseUrl);
+ urlInfos = BaseUrlUtil.getUrlInfos(context);
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlManagerActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlManagerActivity.java
new file mode 100644
index 0000000..85f0569
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlManagerActivity.java
@@ -0,0 +1,131 @@
+package vip.devkit.debugkit.ui.base_url;
+
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.adapter.BaseUrlManagerAdapter;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.ui.base.BaseActivity;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.base_url
+ * File Name: BaseUrlManagerActivity.java
+ * Create Date: 2019/7/3 9:47
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class BaseUrlManagerActivity extends BaseActivity implements View.OnClickListener,BaseUrlManagerAdapter.OnUrlCheckedListener {
+ private LinearLayout mLlTitleBack;
+ private TextView mTvTitle;
+ private TextView mTvTitleRight;
+ private LinearLayout mLlTitleRight;
+ private LinearLayout mLlCommonLayout;
+ private RecyclerView mRlList;
+ private EditText mEtContent;
+ private Button mBtnSubmit;
+
+ private BaseUrlManager mBaseUrlManager;
+ private UrlInfo mCheckUrlInfo;
+ private List mUrlList = new ArrayList<>();
+ private BaseUrlManagerAdapter mAdapter;
+
+ @Override
+ protected void initData() {
+
+ }
+
+ @Override
+ protected int setLayoutId() {
+ return R.layout.dk_activity_base_url;
+ }
+
+ @Override
+ protected void initView() {
+ mBaseUrlManager = new BaseUrlManager(this);
+ mLlTitleBack = (LinearLayout) findViewById(R.id.ll_title_back);
+ mTvTitle = (TextView) findViewById(R.id.tv_title);
+ mTvTitleRight = (TextView) findViewById(R.id.tv_title_right);
+ mLlTitleRight = (LinearLayout) findViewById(R.id.ll_title_right);
+ mLlCommonLayout = (LinearLayout) findViewById(R.id.ll_common_layout);
+ mRlList = (RecyclerView) findViewById(R.id.rl_list);
+ mEtContent = (EditText) findViewById(R.id.et_content);
+ mBtnSubmit = (Button) findViewById(R.id.btn_submit);
+ mLlTitleBack.setOnClickListener(this);
+ mBtnSubmit.setOnClickListener(this);
+ mLlTitleRight.setOnClickListener(this);
+
+ mTvTitle.setText("Base URL 管理");
+
+ mTvTitleRight.setText("保存");
+
+ mUrlList.clear();
+ mUrlList.addAll(mBaseUrlManager.getUrlInfos());
+
+
+ mAdapter = new BaseUrlManagerAdapter(R.layout.dk_item_base_url, mUrlList);
+ mAdapter.setOnUrlCheckedListener(this);
+ mRlList.setLayoutManager(new LinearLayoutManager(this));
+ mRlList.setAdapter(mAdapter);
+
+
+ }
+
+ @Override
+ protected void setListener() {
+
+ }
+
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ if (id == R.id.ll_title_back) {
+ finish();
+ } else if (id == R.id.btn_submit) {
+ String addUrl = mEtContent.getText().toString();
+ if (TextUtils.isEmpty(addUrl)) {
+ Toast.makeText(this, "请输入网络地址", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (!addUrl.startsWith("http")) {
+ Toast.makeText(this, "请输入正确的网络地址", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ mBaseUrlManager.addUrlInfo(new UrlInfo(addUrl));
+ mEtContent.setText("");
+ mEtContent.clearFocus();
+ mUrlList.clear();
+ mUrlList.addAll(mBaseUrlManager.getUrlInfos());
+ LogCat.i("mBaseUrlManager:"+mBaseUrlManager.getUrlInfos().size()+"/"+mUrlList);
+ mAdapter.notifyDataSetChanged();
+ }else if (id==R.id.ll_title_right){
+ if (mCheckUrlInfo!=null){
+ LogCat.i("mBaseUrlManager setUrlInfo :"+mCheckUrlInfo.getBaseUrl());
+ mBaseUrlManager.setUrlInfo(mCheckUrlInfo);
+ }
+ finish();
+ }
+ }
+
+ @Override
+ public void onChecked(UrlInfo urlInfo) {
+ mCheckUrlInfo= urlInfo;
+ mAdapter.notifyDataSetChanged();
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlUtil.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlUtil.java
new file mode 100644
index 0000000..46744dc
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/BaseUrlUtil.java
@@ -0,0 +1,221 @@
+package vip.devkit.debugkit.ui.base_url;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * File Name: BaseUrlUtil
+ * Create Date: 2019/6/14 11:48
+ * Describe :
+ * Author : By k
+ * E-mail : vip@devkit.vip
+ * VersionName: 1
+ * VersionCode: V 1.0
+ * Code Update:(author - time)
+ * Update Describe:
+ */
+public class BaseUrlUtil {
+ private static final String DEFAULT_PREF_NAME = "base_url_manager";
+ private static final String CURRENT_URL_PREF_NAME = "cur_base_url";
+ private static final String KEY_BASE_URL = "key_base_url";
+
+ private BaseUrlUtil(){
+ throw new AssertionError();
+ }
+
+ /**
+ * 缓存String
+ * @param context
+ * @param key
+ * @param value
+ */
+ public static void put(@NonNull Context context, @NonNull String key, Long value){
+ getSharedPreferences(context).edit()
+ .putLong(key,value)
+ .commit();
+ }
+
+ /**
+ * 缓存Map
+ * @param context
+ * @param map
+ */
+ public static void put(@NonNull Context context, Map map){
+ if(map!=null){
+ SharedPreferences.Editor editor = getSharedPreferences(context).edit();
+
+ for(Map.Entry entry: map.entrySet()){
+ if(!TextUtils.isEmpty(entry.getKey()))
+ editor.putLong(entry.getKey(), entry.getValue());
+ }
+
+ editor.commit();
+
+ }
+ }
+
+ /**
+ * 缓存UrlInfo
+ * @param context
+ * @param urlInfo
+ */
+ public static void put(@NonNull Context context,@NonNull UrlInfo urlInfo){
+ put(context,urlInfo,false);
+ }
+
+
+ /**
+ * 缓存一个UrlInfo
+ * @param context
+ * @param urlInfo
+ * @param isCurBaseUrl 是否设置为当前baseUrl
+ */
+ public static void put(@NonNull Context context,@NonNull UrlInfo urlInfo,boolean isCurBaseUrl){
+ put(context,urlInfo.getBaseUrl(),urlInfo.getTime());
+ if(isCurBaseUrl){
+ getSharedPreferences(context,CURRENT_URL_PREF_NAME)
+ .edit()
+ .putString(KEY_BASE_URL,urlInfo.getBaseUrl())
+ .commit();
+ }
+ }
+
+ /**
+ * 缓存UrlInfo结合
+ * @param context
+ * @param urlInfos
+ */
+ public static void put(@NonNull Context context, Collection urlInfos){
+ if(urlInfos!=null && !urlInfos.isEmpty()){
+ SharedPreferences.Editor editor = getSharedPreferences(context).edit();
+
+ for(UrlInfo urlInfo : urlInfos){
+ editor.putLong(urlInfo.getBaseUrl(),urlInfo.getTime());
+ }
+
+ editor.commit();
+
+ }
+ }
+
+ /**
+ * 移除指定的key
+ * @param context
+ * @param key
+ */
+ public static void remove(@NonNull Context context,String key){
+ getSharedPreferences(context).edit()
+ .remove(key)
+ .commit();
+ }
+
+ /**
+ * 清除缓存
+ * @param context
+ */
+ public static void clear(@NonNull Context context){
+ getSharedPreferences(context).edit().clear().commit();
+ getSharedPreferences(context,CURRENT_URL_PREF_NAME).edit().clear().commit();
+ }
+
+ /**
+ * 获取Long
+ * @param context
+ * @param key
+ * @return
+ */
+ public static long getLong(Context context,@NonNull String key){
+ SharedPreferences sp = getSharedPreferences(context);
+ return sp.getLong(key,0);
+ }
+
+ /**
+ * 获取UrlInfo
+ * @param context
+ * @param url
+ * @return
+ */
+ public static UrlInfo getUrlInfo(Context context,@NonNull String url){
+ long time = getLong(context,url);
+ if(time>0){
+ return new UrlInfo(url,time);
+ }
+ return new UrlInfo(url);
+ }
+
+ /**
+ * 获取BaseUrl
+ * @param context
+ * @return
+ */
+ public static String getBaseUrl(Context context){
+ return getSharedPreferences(context,CURRENT_URL_PREF_NAME).getString(KEY_BASE_URL,"");
+ }
+
+
+ /**
+ * 获取当前的UrlInfo
+ * @param context
+ * @return
+ */
+ public static UrlInfo getBseUrlInfo(Context context){
+ String baseUrl = getBaseUrl(context);
+
+ UrlInfo urlInfo = null;
+ if(!TextUtils.isEmpty(baseUrl)){
+ urlInfo = getUrlInfo(context,baseUrl);
+ }
+ return urlInfo;
+ }
+
+ /**
+ * 获取UrlInfo集合
+ * @param context
+ * @return
+ */
+ public static List getUrlInfos(@NonNull Context context){
+ SharedPreferences sp = getSharedPreferences(context);
+ List list = new ArrayList<>();
+ try{
+ Map map = (Map)sp.getAll();
+ if(map!=null){
+ for(Map.Entry entry : map.entrySet()){
+ list.add(new UrlInfo(entry.getKey(),entry.getValue()));
+ }
+ }
+ Collections.sort(list);
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+
+ return list;
+ }
+
+ /**
+ * 获取数据存储
+ * @param context
+ * @return
+ */
+ private static SharedPreferences getSharedPreferences(@NonNull Context context){
+ return context.getSharedPreferences(DEFAULT_PREF_NAME, Context.MODE_PRIVATE);
+ }
+
+ /**
+ * 获取数据存储
+ * @param context
+ * @param prefName
+ * @return
+ */
+ private static SharedPreferences getSharedPreferences(@NonNull Context context,String prefName){
+ return context.getSharedPreferences(prefName, Context.MODE_PRIVATE);
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/IBaseUrlManager.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/IBaseUrlManager.java
new file mode 100644
index 0000000..25ae09a
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/IBaseUrlManager.java
@@ -0,0 +1,79 @@
+package vip.devkit.debugkit.ui.base_url;
+
+
+import androidx.annotation.NonNull;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * File Name: IBaseUrlManager
+ * Create Date: 2019/6/14 11:41
+ * Describe :
+ * Author : By k
+ * E-mail : vip@devkit.vip
+ * VersionName: 1
+ * VersionCode: V 1.0
+ * Code Update:(author - time)
+ * Update Describe:
+ */
+public interface IBaseUrlManager {
+ /**
+ * 获取BaseUrl
+ * @return {@link String}
+ */
+ String getBaseUrl();
+
+ /**
+ * 获取UrlInfo
+ * @return {@link UrlInfo}
+ */
+ UrlInfo getUrlInfo();
+
+ /**
+ * 设置UrlInfo
+ * @param urlInfo
+ */
+ void setUrlInfo(@NonNull UrlInfo urlInfo);
+
+ /**
+ * 添加UrlInfo
+ * @param urlInfo
+ */
+ void addUrlInfo(@NonNull UrlInfo urlInfo);
+
+ /**
+ * 添加UrlInfo集合
+ * @param list
+ */
+ void addUrlInfo(@NonNull Collection list);
+
+
+ /**
+ * 移除UrlInfo
+ * @param urlInfo
+ */
+ void remove(@NonNull UrlInfo urlInfo);
+
+ /**
+ * 清除
+ */
+ void clear();
+
+ /**
+ * 获取UrlInfo集合
+ * @return {@link List}
+ */
+ List getUrlInfos();
+
+ /**
+ * 获取url数
+ * @return {@link int}
+ */
+ int getCount();
+
+ /**
+ * 刷新数据
+ */
+ void refreshData();
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/UrlInfo.java b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/UrlInfo.java
new file mode 100644
index 0000000..039261e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/base_url/UrlInfo.java
@@ -0,0 +1,138 @@
+package vip.devkit.debugkit.ui.base_url;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+/**
+ * File Name: UrlInfo
+ * Create Date: 2019/6/14 11:48
+ * Describe :
+ * Author : By k
+ * E-mail : vip@devkit.vip
+ * VersionName: 1
+ * VersionCode: V 1.0
+ * Code Update:(author - time)
+ * Update Describe:
+ */
+public class UrlInfo implements Parcelable,Comparable {
+
+ private String baseUrl;
+
+ private long time;
+
+ private String baseName;
+
+ public UrlInfo(@NonNull String baseUrl) {
+ this(baseUrl,System.currentTimeMillis());
+ }
+
+ public UrlInfo(@NonNull String baseUrl,long time) {
+ this.baseUrl = baseUrl;
+ this.time = time;
+ }
+
+
+ public UrlInfo(@NonNull String baseUrl,String baseName) {
+ this.baseUrl = baseUrl;
+ this.baseName = baseName;
+ }
+
+ public String getBaseUrl() {
+ if(TextUtils.isEmpty(baseUrl)){
+ return "";
+ }
+ return baseUrl;
+ }
+
+ public void setBaseUrl(@NonNull String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public void setTime(long time) {
+ this.time = time;
+ }
+
+ public String getBaseName() {
+ return baseName;
+ }
+
+ public void setBaseName(String baseName) {
+ this.baseName = baseName;
+ }
+
+ public static Creator getCREATOR() {
+ return CREATOR;
+ }
+
+ @Override
+ public String toString() {
+ return "UrlInfo{" +
+ "baseUrl='" + baseUrl + '\'' +
+ ", time=" + time +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ UrlInfo urlInfo = (UrlInfo) o;
+
+ return baseUrl.equals(urlInfo.baseUrl);
+ }
+
+ @Override
+ public int hashCode() {
+ return baseUrl.hashCode();
+ }
+
+
+ @Override
+ public int compareTo(@NonNull UrlInfo o) {
+ if(time > o.time){
+ return 1;
+ }
+ if(time < o.time){
+ return -1;
+ }
+ return 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(this.baseUrl);
+ dest.writeString(this.baseName);
+ dest.writeLong(this.time);
+ }
+
+ protected UrlInfo(Parcel in) {
+ this.baseUrl = in.readString();
+ this.time = in.readLong();
+ this.baseName = in.readString();
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public UrlInfo createFromParcel(Parcel source) {
+ return new UrlInfo(source);
+ }
+
+ @Override
+ public UrlInfo[] newArray(int size) {
+ return new UrlInfo[size];
+ }
+ };
+}
+
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/crash/CrashManagerActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/crash/CrashManagerActivity.java
new file mode 100644
index 0000000..de2e61a
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/crash/CrashManagerActivity.java
@@ -0,0 +1,103 @@
+package vip.devkit.debugkit.ui.crash;
+
+import android.app.ApplicationErrorReport;
+import android.os.Bundle;
+import android.text.format.Formatter;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.adapter.CrashListAdapter;
+import vip.devkit.debugkit.bean.CrashInfoBean;
+import vip.devkit.debugkit.kit.crash.CrashCaptureManager;
+import vip.devkit.debugkit.ui.base.BaseActivity;
+import vip.devkit.debugkit.util.FileUtil;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.crash
+ * File Name: CrashManagerActivity.java
+ * Create Date: 2019/7/9 9:54
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class CrashManagerActivity extends BaseActivity implements View.OnClickListener {
+ private LinearLayout mLlTitleBack;
+ private TextView mTvTitle;
+ private TextView mTvTitleRight;
+ private LinearLayout mLlTitleRight;
+ private LinearLayout mLlCommonLayout;
+ private Button mBtnAddCrash;
+ private RecyclerView mRlList;
+
+ private TextView mTvCrashSize;
+
+ private CrashListAdapter mAdapter;
+ private List mBeanList = new ArrayList<>();
+
+ @Override
+ protected void initData() {
+
+ }
+
+ @Override
+ protected int setLayoutId() {
+ return R.layout.dk_activity_crash;
+ }
+
+ @Override
+ protected void initView() {
+
+ mLlTitleBack = (LinearLayout) findViewById(R.id.ll_title_back);
+ mTvTitle = (TextView) findViewById(R.id.tv_title);
+ mTvTitleRight = (TextView) findViewById(R.id.tv_title_right);
+ mLlTitleRight = (LinearLayout) findViewById(R.id.ll_title_right);
+ mLlCommonLayout = (LinearLayout) findViewById(R.id.ll_common_layout);
+ mBtnAddCrash = (Button) findViewById(R.id.btn_add_crash);
+ mRlList = (RecyclerView) findViewById(R.id.rl_list);
+ mTvCrashSize = findViewById(R.id.tv_crash_size);
+ String s = Formatter.formatFileSize(this, FileUtil.getDirectorySize(CrashCaptureManager.getInstance().getCrashCacheDir()));
+ mTvCrashSize.setText(s);
+ mBtnAddCrash.setOnClickListener(this);
+ mLlTitleBack.setOnClickListener(this);
+
+
+ List caches = CrashCaptureManager.getInstance().getCrashCaches();
+ mBeanList.addAll(caches);
+ mAdapter = new CrashListAdapter(R.layout.dk_item_crash, mBeanList);
+ mRlList.setLayoutManager(new LinearLayoutManager(this));
+ mRlList.setAdapter(mAdapter);
+
+
+ }
+
+ @Override
+ protected void setListener() {
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ int i = v.getId();
+ if (i == R.id.ll_title_back) {
+ finish();
+ } else if (i == R.id.btn_add_crash) {
+ testCrash().length();
+ }
+ }
+
+ public String testCrash() {
+ return null;
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/debug/AppInfoM.java b/dklib/src/main/java/vip/devkit/debugkit/ui/debug/AppInfoM.java
new file mode 100644
index 0000000..2b2eba5
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/debug/AppInfoM.java
@@ -0,0 +1,127 @@
+package vip.devkit.debugkit.ui.debug;
+
+import android.content.Context;
+import android.content.pm.IPackageStatsObserver;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageStats;
+import android.content.pm.Signature;
+import android.os.Build;
+import android.os.RemoteException;
+import android.util.Log;
+
+import androidx.annotation.Keep;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.TreeMap;
+
+import vip.devkit.debugkit.BuildConfig;
+import vip.devkit.debugkit.util.AppUtil;
+import vip.devkit.debugkit.util.DeviceUtils;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.debug
+ * File Name: AppInfoM.java
+ * Create Date: 2019/7/2 15:14
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class AppInfoM {
+
+ @Keep // App 地址
+ private String sourceDir;
+ @Keep // APK 大小
+ private long apkSize;
+ public Map getAppInfo(Context context) {
+ Map map = new TreeMap();
+ PackageInfo pi = DeviceUtils.getPackageInfo(context);
+ map.put("包名", "" + pi.packageName);
+ map.put("包类型", "" + BuildConfig.BUILD_TYPE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ map.put("版本号", "" + pi.getLongVersionCode());
+ } else {
+ map.put("版本号", "" + pi.versionCode);
+ }
+ map.put("sharedUserId", "" + pi.sharedUserId);
+ map.put("版本名uid", "" + pi.applicationInfo.uid);
+ PackageInfo pia = DeviceUtils.getPackageInfo(context, PackageManager.GET_ACTIVITIES);
+ if (pia.activities != null) {
+ map.put("activities", "" + pia.activities.length);
+ for (int i = 0; i < pia.activities.length; i++) {
+ map.put("activities" + i, "" + pia.activities[i].name);
+ }
+ }
+ PackageInfo pip = DeviceUtils.getPackageInfo(context, PackageManager.GET_PERMISSIONS);
+ if (pip.permissions != null) {
+ map.put("permissions", "" + pip.permissions.length);
+ }
+
+ PackageInfo pirp = DeviceUtils.getPackageInfo(context, PackageManager.GET_PERMISSIONS);
+ if (pirp.requestedPermissions != null) {
+ map.put("requestedPermissions", "" + pirp.requestedPermissions.length);
+ }
+ if (Build.VERSION.SDK_INT >= 28) {
+ PackageInfo pis = DeviceUtils.getPackageInfo(context, PackageManager.GET_GIDS);
+ if (pis.signingInfo != null) {
+ }
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ map.put("baseRevisionCode", "" + pi.baseRevisionCode);
+ map.put("installLocation", "" + pi.installLocation);
+ }
+ map.put("SDK 目标版本号", "" + String.valueOf(context.getApplicationInfo().targetSdkVersion));
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ map.put("最小支持SDK版本", "" + String.valueOf(context.getApplicationInfo().minSdkVersion));
+ }
+ map.put("安装包大小", "");
+ map.put("安装包 SIGN MD5", "" + AppUtil.getSign(context, pi.packageName));
+ map.put("安装包文件MD5", "");
+ map.put("首次安装时间", "" + pi.firstInstallTime);
+ map.put("更新安装时间", "" + pi.lastUpdateTime);
+ map.put("缓存大小", "");
+
+ return map;
+ }
+
+ public void queryPacakgeSize(Context context, String pkgName) {
+ if (pkgName != null) {
+ //使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
+ PackageManager pm = context.getPackageManager(); //得到pm对象
+ try {
+ //通过反射机制获得该隐藏函数
+ Method getPackageSizeInfo = pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class);
+ //调用该函数,并且给其分配参数 ,待调用流程完成后会回调PkgSizeObserver类的函数
+ getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver());
+ } catch (Exception ex) {
+ Log.i("build", "NoSuchMethodException"+ex);
+ ex.printStackTrace();
+ }
+ }
+ }
+
+
+ //aidl文件形成的Bindler机制服务类
+ public class PkgSizeObserver extends IPackageStatsObserver.Stub {
+ /*** 回调函数,
+ * @param pStats ,返回数据封装在PackageStats对象中
+ * @param succeeded 代表回调成功
+ */
+ PackageStats mPackageStats;
+
+ @Override
+ public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ Log.i("build", "PackageStats"+pStats.codeSize);
+ Log.i("build", "PackageStats"+pStats.dataSize);
+ Log.i("build", "PackageStats"+pStats.cacheSize);
+ this.mPackageStats = pStats;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/permission/PermissionData.java b/dklib/src/main/java/vip/devkit/debugkit/ui/permission/PermissionData.java
new file mode 100644
index 0000000..216dc0b
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/permission/PermissionData.java
@@ -0,0 +1,171 @@
+package vip.devkit.debugkit.ui.permission;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.os.Build;
+import android.text.TextUtils;
+
+import androidx.core.app.ActivityCompat;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import vip.devkit.debugkit.util.DeviceUtils;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.permission
+ * File Name: PermissionData.java
+ * Create Date: 2019/7/3 13:52
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class PermissionData {
+
+
+ /**
+ * @param context
+ * @return 自定义权限组
+ */
+ public List getPermissions(Context context) {
+ List list = new ArrayList();
+ PackageInfo pip = DeviceUtils.getPackageInfo(context, PackageManager.GET_PERMISSIONS);
+ if (pip.permissions != null) {
+ list.addAll(Arrays.asList(pip.permissions));
+ }
+ return list;
+ }
+
+
+ public List getRequestedPermissions(Context context) {
+ List list = new ArrayList();
+ PackageInfo pip = DeviceUtils.getPackageInfo(context, PackageManager.GET_PERMISSIONS);
+ if (pip.requestedPermissions != null) {
+ list.addAll(Arrays.asList(pip.requestedPermissions));
+ }
+ return list;
+ }
+
+
+ public static String getPermissionName(String permission) {
+ Map map = new TreeMap();
+
+ //威胁需要申请的权限
+ map.put("android.permission.BIND_ACCESSIBILITY_SERVICE", "辅助");
+ map.put("android.permission.PACKAGE_USAGE_STATS", "应用使用情况");
+ map.put("android.permission.BIND_NOTIFICATION_LISTENER_SERVICE", "监听通知栏");
+ map.put("android.permission.WRITE_SETTINGS", "修改系统设置");
+ map.put("android.permission.SYSTEM_ALERT_WINDOW", "显示在其他应用上面");
+ map.put("android.permission.BIND_DEVICE_ADMIN", "设备管理器");
+ map.put("android.permission.WRITE_EXTERNAL_STORAGE", "读取/修改/删除SD卡内容");
+ map.put("android.permission.READ_EXTERNAL_STORAGE", "读取SD卡中的内容");
+ map.put("android.permission.READ_CELL_BROADCASTS", "读取小区广播消息");
+ map.put("android.permission.RECEIVE_MMS", "接收文字讯息 (彩信)");
+ map.put("android.permission.RECEIVE_WAP_PUSH", "接收文字讯息 (WAP)");
+ map.put("android.permission.READ_SMS", "读取您的文字讯息 (短信或彩信)");
+ map.put("android.permission.RECEIVE_SMS", "接收文字讯息 (短信)");
+ map.put("android.permission.SEND_SMS", "发送短信");
+ map.put("android.permission.BODY_SENSORS", "人体传感器 (如心跳速率检测器)");
+ map.put("android.permission.ANSWER_PHONE_CALLS", "接听来电");
+ map.put("android.permission.READ_PHONE_NUMBERS", "读取电话号码");
+ map.put("android.permission.PROCESS_OUTGOING_CALLS", "重新设置呼出的路径");
+ map.put("android.permission.USE_SIP", "拨打/接听互联网通话");
+ map.put("com.android.voicemail.permission.ADD_VOICEMAIL", "添加语音邮件");
+ map.put("android.permission.CALL_PHONE", "直接拨打电话号码");
+ map.put("android.permission.WRITE_CALL_LOG", "写入通话记录");
+ map.put("android.permission.READ_CALL_LOG", "读取通话记录");
+ map.put("android.permission.READ_PHONE_STATE", "设备信息:读取手机状态和身份");
+ map.put("android.permission.RECORD_AUDIO", "录音");
+ map.put("android.permission.ACCESS_COARSE_LOCATION", "(基于网络的) 大概位置");
+ map.put("android.permission.ACCESS_FINE_LOCATION", "精准的 (GPS) 位置");
+ map.put("android.permission.GET_ACCOUNTS", "查找设备上的帐户");
+ map.put("android.permission.WRITE_CONTACTS", "修改通讯录");
+ map.put("android.permission.READ_CONTACTS", "读取您的通讯录");
+ map.put("android.permission.CAMERA", "拍摄照片和视频");
+ map.put("android.permission.WRITE_CALENDAR", "写日历");
+ map.put("android.permission.READ_CALENDAR", "读日历");
+
+
+ map.put("android.permission.REQUEST_INSTALL_PACKAGES", "8.0+安装权限");
+ map.put("android.permission.SYSTEM_ALERT_WINDOW", "6.0+安装权限");
+
+ map.put("android.permission.ANSWER_PHONE_CALLS", "允许您的应用通过编程方式接听呼入电话");
+ map.put("android.permission.READ_PHONE_NUMBERS", "权限允许您的应用读取设备中存储的电话号码");
+
+ map.put("android.permission.SYSTEM_ALERT_WINDOW", "安装权限");
+ map.put("ACCESS_CHECKIN_PROPERTIES", "");
+ return map.get(permission);
+ }
+
+
+ /**
+ * 检查某些权限是否全部授予了
+ *
+ * @param context 上下文对象
+ * @param permissions 需要请求的权限组
+ */
+ public static boolean isHasPermission(Context context, String... permissions) {
+ ArrayList failPermissions = getFailPermissions(context, Arrays.asList(permissions));
+ return failPermissions == null || failPermissions.isEmpty();
+ }
+
+ /**
+ * 获取没有授予的权限
+ *
+ * @param context 上下文对象
+ * @param permissions 需要请求的权限组
+ */
+ static ArrayList getFailPermissions(Context context, List permissions) {
+ ArrayList failPermissions = null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ for (String permission : permissions) {
+ // 把没有授予过的权限加入到集合中
+ if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
+ if (failPermissions == null) failPermissions = new ArrayList<>();
+ failPermissions.add(permission);
+ }
+ }
+ } else {
+ failPermissions = new ArrayList<>();
+ }
+ return failPermissions;
+ }
+
+ public static boolean hasSelfPermission(Context context, List permissions) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
+ ArrayList failPermissions = null;
+ for (String permission : permissions) {
+ if (!hasSelfPermission(context, permission)) {
+ if (failPermissions == null) failPermissions = new ArrayList<>();
+ failPermissions.add(permission);
+ }
+ }
+ return failPermissions == null || failPermissions.isEmpty();
+ }
+
+ public static boolean hasSelfPermission(Context context, String permission) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
+ AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ String op = AppOpsManager.permissionToOp(permission);
+ if (!TextUtils.isEmpty(op)) {
+ int checkOp = appOpsManager.checkOp(op, android.os.Process.myUid(), context.getPackageName());
+ return checkOp == AppOpsManager.MODE_ALLOWED && ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
+ }
+ return true;
+ }
+
+ public static void ss(){
+
+
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/permission/PermissionManagerActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/permission/PermissionManagerActivity.java
new file mode 100644
index 0000000..9441e11
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/permission/PermissionManagerActivity.java
@@ -0,0 +1,150 @@
+package vip.devkit.debugkit.ui.permission;
+
+import android.Manifest;
+import android.content.ComponentName;
+import android.os.Build;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import vip.devkit.debugkit.R;
+import vip.devkit.debugkit.adapter.PermissionManagerAdapter;
+import vip.devkit.debugkit.kit.log.LogCat;
+import vip.devkit.debugkit.ui.base.BaseActivity;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui.permission
+ * File Name: PermissionManagerActivity.java
+ * Create Date: 2019/7/3 11:52
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class PermissionManagerActivity extends BaseActivity implements View.OnClickListener {
+
+
+ private LinearLayout mLlTitleBack;
+ private TextView mTvTitle;
+ private TextView mTvTitleRight;
+ private LinearLayout mLlTitleRight;
+ private LinearLayout mLlCommonLayout;
+ private RecyclerView mRlList;
+
+ private PermissionManagerAdapter mAdapter;
+ private List mList = new ArrayList<>();
+
+ private ComponentName mAdminName = null;
+
+
+ @Override
+ protected void initData() {
+
+ }
+
+ @Override
+ protected int setLayoutId() {
+ return R.layout.dk_activity_rv;
+ }
+
+ @Override
+ protected void initView() {
+ mLlTitleBack = (LinearLayout) findViewById(R.id.ll_title_back);
+ mTvTitle = (TextView) findViewById(R.id.tv_title);
+ mTvTitleRight = (TextView) findViewById(R.id.tv_title_right);
+ mLlTitleRight = (LinearLayout) findViewById(R.id.ll_title_right);
+ mLlCommonLayout = (LinearLayout) findViewById(R.id.ll_common_layout);
+ mRlList = (RecyclerView) findViewById(R.id.rl_list);
+ mLlTitleBack.setOnClickListener(this);
+ mLlTitleRight.setOnClickListener(this);
+ mTvTitle.setText("权限管理");
+ mTvTitleRight.setText("申请");
+
+ PermissionData data = new PermissionData();
+ mList.addAll(data.getRequestedPermissions(this));
+ for (int i = 0; i < data.getRequestedPermissions(this).size(); i++) {
+ String p = data.getRequestedPermissions(this).get(i);
+ LogCat.i("2:" + p);
+ LogCat.i("3:" + PermissionData.isHasPermission(this, p) + "/"
+ + PermissionData.hasSelfPermission(this, p) + "/"
+ + 0 + "/"
+ + 1);
+ }
+ mAdapter = new PermissionManagerAdapter(R.layout.dk_item_permission, mList);
+ mRlList.setLayoutManager(new LinearLayoutManager(this));
+ mRlList.setAdapter(mAdapter);
+ }
+
+ @Override
+ protected void setListener() {
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.ll_title_back) {
+ finish();
+ } else if (v.getId() == R.id.ll_title_right) {
+
+ LogCat.i("权限申请");
+ String[] permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
+ for (int i = 0; i = Build.VERSION_CODES.M) {
+// requestPermissions(permissions, 9999);
+
+ }
+
+ if (shouldShowRequestPermissionRationale(permissions[0])){
+
+ ActivityCompat.requestPermissions(PermissionManagerActivity.this,
+ permissions,
+ 9999);
+ }else {
+ Snackbar.make(getRootView(), "请开启权限", Snackbar.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ @Override
+ public boolean shouldShowRequestPermissionRationale(String permission) {
+ return super.shouldShowRequestPermissionRationale(permission);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ LogCat.i("requestCode:" + requestCode + "/" + permissions + "/" + grantResults);
+
+
+ for (int i = 0; i < permissions.length; i++) {
+ LogCat.i("permissions:" + permissions[i]);
+ }
+
+ for (int i = 0; i < grantResults.length; i++) {
+ LogCat.i("grantResults:" + grantResults[i]);
+ }
+
+ }
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/sysinfo/SysInfoActivity.java b/dklib/src/main/java/vip/devkit/debugkit/ui/sysinfo/SysInfoActivity.java
new file mode 100644
index 0000000..1315bc8
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/sysinfo/SysInfoActivity.java
@@ -0,0 +1,15 @@
+package vip.devkit.debugkit.ui.sysinfo;
+
+/**
+ * Package Name: vip.devkit.debugkit.ui
+ * File Name: SysInfoActivity.java
+ * Create Date: 2019/7/1 10:41
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class SysInfoActivity {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/ui/sysinfo/SysInfoKit.java b/dklib/src/main/java/vip/devkit/debugkit/ui/sysinfo/SysInfoKit.java
new file mode 100644
index 0000000..4cda493
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/ui/sysinfo/SysInfoKit.java
@@ -0,0 +1,197 @@
+package vip.devkit.debugkit.ui.sysinfo;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import androidx.annotation.RequiresApi;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import vip.devkit.debugkit.util.Comm;
+import vip.devkit.debugkit.util.NetUtils;
+
+/**
+ * Package Name: vip.ievkit.iebugkit.ui.sysinfo
+ * File Name: SysInfoKit.java
+ * Create Date: 2019/7/2 9:25
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class SysInfoKit {
+
+ public SysInfoKit() {
+
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ public Map getInfo() {
+ Map map = new HashMap();
+
+ String[] s=Build.SUPPORTED_ABIS;
+
+ String apis="";
+ for (String ss:s) {
+ apis=""+ss+"/";
+ }
+ apis=apis+Build.CPU_ABI+"/"+Build.CPU_ABI2;
+ map.put("品牌", Build.BRAND);
+ map.put("厂商", Build.MANUFACTURER);
+ map.put("型号", Build.DEVICE);
+ map.put("SDK版本", "" + Build.VERSION.SDK_INT);
+ map.put("CPU ABI", apis);
+ map.put("内核", Build.MANUFACTURER);
+ map.put("运行内存", Build.MANUFACTURER);
+ map.put("手机存储", Build.MANUFACTURER);
+ map.put("处理器", Build.HARDWARE);
+ map.put("无线电固件版本", Build.getRadioVersion());
+ map.put("硬件识别码", "" + Build.FINGERPRINT);
+ map.put("硬件名称", "" + Build.HARDWARE);
+ map.put("HOST", "" + Build.HOST);
+ map.put("版本", "" + Build.MODEL);
+ map.put("硬件序列号", "" + Build.SERIAL);
+ map.put("手机制作商", "" + Build.MANUFACTURER);
+ map.put("描述Build的标签", "" + Build.TAGS);
+ map.put("builder类型", "" + Build.TYPE);
+ map.put("USERs", "" + Build.USER);
+ map.put("USER", "" + Build.USER + "/" + Build.VERSION.RELEASE + "/");
+ map.put("USERs", "" + getNumberOfCPUCores()+"/"+Runtime.getRuntime().availableProcessors());
+
+
+ return map;
+ }
+
+
+ public Map getScreen(Context context) {
+
+ DisplayMetrics dm = context.getResources().getDisplayMetrics();
+ int height = dm.heightPixels;
+ int width = dm.widthPixels;
+ int sw = context.getResources().getConfiguration().smallestScreenWidthDp;
+ float density = dm.density;
+ int densityDPI = dm.densityDpi; // 屏幕密度(这里是系统密度)(每寸像素:120/160/240/320,480,640等)
+ float xdpi = dm.xdpi;
+ float ydpi = dm.ydpi;
+
+ float scaledDensity = dm.scaledDensity;
+ Map map = new HashMap();
+
+ String dpi = "ldpi";
+ if (density == 1.0) {
+ dpi = "mdpi";
+ } else if (density == 1.5) {
+ dpi = "hdpi";
+ } else if (density == 2.0) {
+ dpi = "xhdpi";
+ } else if (density == 3.0) {
+ dpi = "xxhdpi";
+ }
+ // 这样可以计算屏幕的物理尺寸
+ float width2 = (width / xdpi) * (width / xdpi);
+ float height2 = (height / ydpi) * (width / xdpi);
+
+ float xInch = width / xdpi;
+ float yInch = height / ydpi;
+ double screenInch = Math.sqrt(Math.pow(xInch, 2) + Math.pow(yInch, 2));
+ map.put("密度", "" + densityDPI + "dpi/" + dpi + "/" + density);
+ map.put("精确密度", "" + xdpi + "*" + ydpi + "dp");
+ map.put("屏幕分辨率", "" + width + "*" + height + "px");
+ map.put("可用屏幕分辨率", "" + width + "*" + height + "px");
+ map.put("屏幕尺寸", "" + formatDouble(screenInch, 1) + "英寸");
+ return map;
+ }
+
+ /**
+ * Double类型保留指定位数的小数,返回double类型(四舍五入)
+ * newScale 为指定的位数
+ */
+ private static double formatDouble(double d, int newScale) {
+ BigDecimal bd = new BigDecimal(d);
+ return bd.setScale(newScale, BigDecimal.ROUND_HALF_UP).doubleValue();
+ }
+
+
+ public Map getNetInfo(Context context) {
+ Map map = new TreeMap<>();
+ if (!NetUtils.isNetConnected(context)) {
+ map.put("网络类型:", "" + NetUtils.getNetworkStateName(context));
+ } else {
+ map.put("网络类型:", "" + NetUtils.getNetworkStateName(context));
+ int state = NetUtils.getNetworkState(context);
+ if (state == 0) {
+ } else if (state==1) {
+ int ipAddress=NetUtils.getWifiInfo(context).getIpAddress();
+ String ipString = ((ipAddress & 0xff) + "." + (ipAddress >> 8 & 0xff) + "." + (ipAddress >> 16 & 0xff) + "." + (ipAddress >> 24 & 0xff));
+ map.put("WIFI SSID:", "" + NetUtils.getWifiInfo(context).getSSID());
+ map.put("WIFI getBSSID:", "" + NetUtils.getWifiInfo(context).getBSSID());
+ map.put("WIFI Ip:", "" + ipString);
+ map.put("WIFI getLinkSpeed:", "" + NetUtils.getWifiInfo(context).getLinkSpeed());
+ map.put("WIFI getNetworkId:", "" + NetUtils.getWifiInfo(context).getNetworkId());
+ map.put("WIFI 型号强度:", "" + NetUtils.getWifiInfo(context).getRssi());
+
+ } else if (state == 2 || state == 3 || state == 4 || state == 5) {
+ map.put("运行商:", "" + NetUtils.getOperatorName(context));
+ }
+ map.put("local IP:", "" + NetUtils.getHostIp());
+ map.put("IPv4:", "");
+ map.put("IPv6:", "");
+ }
+ map.put("MAC地址:", "" + NetUtils.getMacAddress());
+ return map;
+ }
+ public Map getHardware(Context context) {
+ Map map = new TreeMap<>();
+
+
+ return map;
+ }
+
+ public static int getNumberOfCPUCores() {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
+ // Gingerbread doesn't support giving PermissionManagerActivity single application access to both cores, but PermissionManagerActivity
+ // handful of devices (Atrix 4G and Droid X2 for example) were released with PermissionManagerActivity dual-core
+ // chipset and Gingerbread; that can let an app in the background run without impacting
+ // the foreground application. But for our purposes, it makes them single core.
+ return 1; //上面的意思就是2.3以前不支持多核,有些特殊的设备有双核...不考虑,就当单核!!
+ }
+ int cores;
+ try {
+ cores = new File("/sys/devices/system/cpu/").listFiles(CPU_FILTER).length;
+ } catch (SecurityException e) {
+ cores = 0; //这个常量得自己约定
+ } catch (NullPointerException e) {
+ cores = 0;
+ }
+ return cores;
+ }
+
+ private static final FileFilter CPU_FILTER = new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ String path = pathname.getName();
+ //regex is slow, so checking char by char.
+ if (path.startsWith("cpu")) {
+ for (int i = 3; i < path.length(); i++) {
+ if (path.charAt(i) < '0' || path.charAt(i) > '9') {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/AppUtil.java b/dklib/src/main/java/vip/devkit/debugkit/util/AppUtil.java
new file mode 100644
index 0000000..f1a74f3
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/AppUtil.java
@@ -0,0 +1,58 @@
+package vip.devkit.debugkit.util;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import java.security.MessageDigest;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: AppUtil.java
+ * Create Date: 2019/7/2 15:46
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class AppUtil {
+ /**
+ * 获取App Sign 签名
+ * @param context
+ * @param pkgName
+ * @return
+ */
+ public static String getSign(Context context, String pkgName) {
+ try {
+ PackageInfo pis = context.getPackageManager().getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
+ return hexdigest(pis.signatures[0].toByteArray());
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException("s application not found" + e);
+ }
+ }
+
+
+ public static String hexdigest(byte[] paramArrayOfByte) {
+ final char[] hexDigits = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99,
+ 100, 101, 102};
+ try {
+ MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
+ localMessageDigest.update(paramArrayOfByte);
+ byte[] arrayOfByte = localMessageDigest.digest();
+ char[] arrayOfChar = new char[32];
+ for (int i = 0, j = 0; ; i++, j++) {
+ if (i >= 16) {
+ return new String(arrayOfChar);
+ }
+ int k = arrayOfByte[i];
+ arrayOfChar[j] = hexDigits[(0xF & k >>> 4)];
+ arrayOfChar[++j] = hexDigits[(k & 0xF)];
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/Comm.java b/dklib/src/main/java/vip/devkit/debugkit/util/Comm.java
new file mode 100644
index 0000000..a44e29c
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/Comm.java
@@ -0,0 +1,35 @@
+package vip.devkit.debugkit.util;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: Comm.java
+ * Create Date: 2019/7/2 11:27
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class Comm {
+ /**
+ * 检查网络状态
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isConnected(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo info = cm.getActiveNetworkInfo();
+ if (info != null && info.isConnected()) {
+ if (info.getState() == NetworkInfo.State.CONNECTED) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/DataCleanUtil.java b/dklib/src/main/java/vip/devkit/debugkit/util/DataCleanUtil.java
new file mode 100644
index 0000000..2a35b5e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/DataCleanUtil.java
@@ -0,0 +1,105 @@
+package vip.devkit.debugkit.util;
+
+import android.content.Context;
+import android.os.Environment;
+import android.text.format.Formatter;
+
+import java.io.File;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: DataCleanUtil.java
+ * Create Date: 2019/6/28 11:04
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class DataCleanUtil {
+ private DataCleanUtil() {
+ }
+
+ /**
+ * @param context
+ */
+ public static void cleanInternalCache(Context context) {
+ FileUtil.deleteDirectory(context.getCacheDir());
+ }
+
+ /**
+ * @param context
+ */
+ public static void cleanDatabases(Context context) {
+ FileUtil.deleteDirectory(new File(context.getFilesDir().getParent() + "/databases"));
+ }
+
+ /**
+ * @param context
+ */
+ public static void cleanSharedPreference(Context context) {
+ FileUtil.deleteDirectory(new File(context.getFilesDir().getParent() + "/shared_prefs"));
+ }
+
+ /**
+ * @param context
+ */
+ public static void cleanFiles(Context context) {
+ FileUtil.deleteDirectory(context.getFilesDir());
+ }
+
+ /**
+ * @param context
+ */
+ public static void cleanExternalCache(Context context) {
+ if (Environment.getExternalStorageState().equals(
+ Environment.MEDIA_MOUNTED)) {
+ FileUtil.deleteDirectory(context.getExternalCacheDir());
+ }
+ }
+
+ /**
+ * @param filePath
+ */
+ public static void cleanCustomCache(String filePath) {
+ FileUtil.deleteDirectory(new File(filePath));
+ }
+
+ /**
+ * clean app data
+ *
+ * @param context
+ * @param filepath
+ */
+ public static void cleanApplicationData(Context context, String... filepath) {
+ cleanInternalCache(context);
+ cleanExternalCache(context);
+ cleanDatabases(context);
+ cleanSharedPreference(context);
+ cleanFiles(context);
+ if (filepath == null) {
+ return;
+ }
+ for (String filePath : filepath) {
+ cleanCustomCache(filePath);
+ }
+ }
+
+ public static long getApplicationDataSize(Context context) {
+ long size = 0;
+ // internal cache
+ size += FileUtil.getDirectorySize(context.getCacheDir());
+ // databases
+ size += FileUtil.getDirectorySize(new File(context.getFilesDir().getParent() + "/databases"));
+ // shared preference
+ size += FileUtil.getDirectorySize(new File(context.getFilesDir().getParent() + "/shared_prefs"));
+ // files
+ size += FileUtil.getDirectorySize(context.getFilesDir());
+ return size;
+ }
+
+ public static String getApplicationDataSizeStr(Context context) {
+ return Formatter.formatFileSize(context, getApplicationDataSize(context));
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/DeviceUtils.java b/dklib/src/main/java/vip/devkit/debugkit/util/DeviceUtils.java
new file mode 100644
index 0000000..fc51ad5
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/DeviceUtils.java
@@ -0,0 +1,457 @@
+package vip.devkit.debugkit.util;
+
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.hardware.Camera;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.os.Environment;
+import android.os.StatFs;
+import android.telephony.CellLocation;
+import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaCellLocation;
+import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+import android.util.Log;
+
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.regex.Pattern;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: DeviceUtils.java
+ * Create Date: 2019/6/28 11:01
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class DeviceUtils {
+ private static final String TAG = "DeviceUtils";
+ private static final String PREF_DEVICE = "com.kuaidi.daijia.driver.device_pref";
+ private static final String KEY_UUID = "key_uuid";
+ private static final String BRAND_HUAWEI = "huawei";
+ private static final String BRAND_HONOR = "honor";
+ private static final String BRAND_SAMSUNG = "samsung";
+ private static final String BRAND_XIAOMI = "xiaomi";
+ private static final String BRAND_HONGMI = "hongmi";
+
+ private static String IMEI = "";
+ private static String IMSI = "";
+ private static String PHONE_NUMBER = null;
+ private static Boolean ROOTED = null;
+
+ /**
+ * 获取CPU个数
+ */
+ public static int getCoreNum() {
+ class CpuFilter implements FileFilter {
+ @Override
+ public boolean accept(File pathname) {
+ // Check if filename is "cpu", followed by PermissionManagerActivity single digit number
+ if (Pattern.matches("cpu[0-9]", pathname.getName())) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ try {
+ // Get directory containing CPU info
+ File dir = new File("/sys/devices/system/cpu/");
+ // Filter to only list the devices we care about
+ File[] files = dir.listFiles(new CpuFilter());
+ // Return the number of cores (virtual CPU devices)
+ return files.length;
+ } catch (Exception e) {
+ Log.e(TAG, "getCoreNum", e);
+ // Default to return 1 core
+ return 1;
+ }
+ }
+
+ /**
+ * @param context
+ * @return 手机总内存(兆)
+ */
+ public static long getTotalMemory(Context context) {
+ String str1 = "/proc/meminfo";// 系统内存信息文件
+ String str2;
+ String[] arrayOfString;
+ long initial_memory = 0;
+ try {
+ FileReader localFileReader = new FileReader(str1);
+ BufferedReader localBufferedReader = new BufferedReader(
+ localFileReader, 8192);
+ str2 = localBufferedReader.readLine();// 读取meminfo第一行,系统总内存大小
+ if (!TextUtils.isEmpty(str2)) {
+ arrayOfString = str2.split("\\s+");
+ initial_memory = Integer.valueOf(arrayOfString[1]).intValue() / 1024;// 获得系统总内存,单位是KB,乘以1024转换为Byte
+ }
+ localBufferedReader.close();
+ } catch (IOException e) {
+ }
+ return initial_memory;// Byte转换为KB或者MB,内存大小规格化
+ }
+
+ /**
+ * @param context
+ * @return 手机当前可用内存(兆)
+ */
+ public static long getAvailMemory(Context context) {// 获取android当前可用内存大小
+ ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
+ am.getMemoryInfo(mi);
+ return mi.availMem / 1024 / 1024;
+ }
+
+ /**
+ * 版本名
+ */
+ public static String getVersionName(Context context) {
+ PackageInfo pi = getPackageInfo(context);
+ if (pi != null) {
+ return pi.versionName;
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * 版本号
+ */
+ public static int getVersionCode(Context context) {
+ PackageInfo pi = getPackageInfo(context);
+ if (pi != null) {
+ return pi.versionCode;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * @desc GET_CONFIGURATIONS
+ * @param
+ * @return
+ * @author
+ * @time
+ */
+ public static PackageInfo getPackageInfo(Context context) {
+ PackageInfo pi = null;
+
+ try {
+ PackageManager pm = context.getPackageManager();
+ pi = pm.getPackageInfo(context.getPackageName(),
+ PackageManager.GET_CONFIGURATIONS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return pi;
+ }
+
+ public static PackageInfo getPackageInfo(Context context,int type) {
+ PackageInfo pi = null;
+
+ try {
+ PackageManager pm = context.getPackageManager();
+ pi = pm.getPackageInfo(context.getPackageName(),
+ type);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return pi;
+ }
+
+ public static PackageInfo getPackageInfoForPermission(Context context) {
+ PackageInfo pi = null;
+
+ try {
+ PackageManager pm = context.getPackageManager();
+ pi = pm.getPackageInfo(context.getPackageName(),
+ PackageManager.GET_PERMISSIONS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return pi;
+ }
+
+
+
+
+
+
+
+ /**
+ * @return 手机链接wifi的路由器的名字
+ */
+ public static String getWifiSSID(Context context) {
+ WifiManager mWifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ if (mWifi.isWifiEnabled()) {
+ WifiInfo wifiInfo = mWifi.getConnectionInfo();
+ return wifiInfo.getSSID();
+ }
+ return "";
+ }
+
+ /**
+ * @return 手机链接wifi的路由器的mac地址
+ */
+ public static String getWifiBSSID(Context context) {
+ WifiManager mWifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ if (mWifi.isWifiEnabled()) {
+ WifiInfo wifiInfo = mWifi.getConnectionInfo();
+ return wifiInfo.getBSSID();
+ }
+ return "";
+ }
+
+ /**
+ * @param permission
+ * @param defalutValue 如果检测不到()检测发生异常的默认值
+ * @return App是否拥有permission权限
+ */
+ public static boolean checkPermission(Context context, String permission, boolean defalutValue) {
+ boolean permit = false;
+ // 如果在判断的时候报错(有些机型),则默认不满足此权限
+ try {
+ permit = PackageManager.PERMISSION_GRANTED == context
+ .checkCallingOrSelfPermission(permission);
+ } catch (Exception e) {
+ permit = defalutValue;
+ }
+ return permit;
+ }
+
+
+ /**
+ * 判断wifi是否开启
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isWifiEnabled(Context context) {
+ WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ return (wm != null)
+ && (wm.getWifiState() == WifiManager.WIFI_STATE_ENABLED || wm.getWifiState() == WifiManager.WIFI_STATE_ENABLING);
+ }
+
+ /**
+ * Is wifi connected
+ *
+ * @param context
+ * @return
+ */
+ public static boolean isWifiConnected(Context context) {
+ ConnectivityManager connectivityManager = (ConnectivityManager) context.
+ getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
+ return activeNetInfo != null && activeNetInfo.isConnected()
+ && (activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI);
+ }
+
+ public static boolean hasJellyBeanMr2() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
+ }
+
+ public static boolean hasJellyBeanMr1() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
+ }
+
+ /**
+ * 判断是否为某品牌生产的手机
+ */
+ public static boolean isProduceByBrand(String brand) {
+ boolean result = false;
+ // 判断厂家
+ if (Build.MANUFACTURER != null) {
+ if (Build.MANUFACTURER.toLowerCase().contains(brand)) {
+ result = true;
+ }
+ }
+ // 判断品牌
+ if (!result && Build.BRAND != null) {
+ if (Build.BRAND.toLowerCase().contains(brand)) {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public static boolean isProduceByXiaomi() {
+ return isProductInBrands(BRAND_XIAOMI, BRAND_HONGMI);
+ }
+
+ public static boolean isProduceByHuaWei() {
+ return isProductInBrands(BRAND_HUAWEI, BRAND_HONOR);
+ }
+
+ public static boolean isProduceBySamsung() {
+ return isProduceByBrand(BRAND_SAMSUNG);
+ }
+
+ public static boolean isProductInBrands(String... brands) {
+ for (String brand : brands) {
+ if (isProduceByBrand(brand)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ public static boolean isSimReady(Context context) {
+ try {
+ TelephonyManager mgr = (TelephonyManager) context
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ Log.d(TAG, "[isSimReady]" + mgr.getSimState());
+ return TelephonyManager.SIM_STATE_READY == mgr.getSimState()
+ || TelephonyManager.SIM_STATE_NETWORK_LOCKED == mgr.getSimState();
+ } catch (Exception e) {
+ Log.e(TAG, "[isSimReady]" + e);
+ }
+ return false;
+ }
+
+ /**
+ * 判断当前手机是否有ROOT权限
+ *
+ * @return 是否ROOT
+ */
+ public static boolean isRoot(Context context) {
+ if (ROOTED != null) {
+ return ROOTED;
+ }
+ try {
+// RootBeer rootBeer = new RootBeer(context);
+// rootBeer.setLogging(true);
+// ROOTED = rootBeer.isRootedWithoutBusyBoxCheck();
+// if (ROOTED) {
+// Log.w(TAG, "Device rooted.");
+// }
+ } catch (Exception e) {
+ Log.e(TAG, "Check root failed.", e);
+ ROOTED = false;
+ }
+ return ROOTED;
+ }
+
+ public static boolean hasFrontCamera() {
+ int cameraCount = Camera.getNumberOfCameras();
+ Camera.CameraInfo info = new Camera.CameraInfo();
+ for (int i = 0; i < cameraCount; i++) {
+ Camera.getCameraInfo(i, info);
+ if (Camera.CameraInfo.CAMERA_FACING_FRONT == info.facing) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return Number of bytes available on external storage
+ */
+ public static long getExternalAvailableSpaceInBytes() {
+ long availableSpace = -1L;
+ try {
+ StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
+ .getPath());
+ availableSpace = (long) stat.getAvailableBlocks()
+ * (long) stat.getBlockSize();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return availableSpace;
+ }
+
+ /**
+ * 获得SD卡总大小
+ *
+ * @return
+ */
+ private static String getSDTotalSize(Context context) {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long totalBlocks = stat.getBlockCount();
+ return Formatter.formatFileSize(context, blockSize * totalBlocks);
+ }
+
+ /**
+ * 获得sd卡剩余容量,即可用大小
+ *
+ * @return
+ */
+ private static String getSDAvailableSize(Context context) {
+ File path = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long availableBlocks = stat.getAvailableBlocks();
+ return Formatter.formatFileSize(context, blockSize * availableBlocks);
+ }
+
+ /**
+ * 获得机身内存总大小
+ *
+ * @return
+ */
+ private static String getRomTotalSize(Context context) {
+ File path = Environment.getDataDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long totalBlocks = stat.getBlockCount();
+ return Formatter.formatFileSize(context, blockSize * totalBlocks);
+ }
+
+ /**
+ * 获得机身可用内存
+ *
+ * @return
+ */
+ private static String getRomAvailableSize(Context context) {
+ File path = Environment.getDataDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSize();
+ long availableBlocks = stat.getAvailableBlocks();
+ return Formatter.formatFileSize(context, blockSize * availableBlocks);
+ }
+
+
+ public static String getSDCardSpace(Context context) {
+ try {
+ String free = getSDAvailableSize(context);
+ String total = getSDTotalSize(context);
+ return free + "/" + total;
+ } catch (Exception e) {
+ return "-/-";
+ }
+ }
+
+ public static String getRomSpace(Context context) {
+ try {
+ String free = getRomAvailableSize(context);
+ String total = getRomTotalSize(context);
+ return free + "/" + total;
+ } catch (Exception e) {
+ return "-/-";
+ }
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/FileUtil.java b/dklib/src/main/java/vip/devkit/debugkit/util/FileUtil.java
new file mode 100644
index 0000000..ba20b65
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/FileUtil.java
@@ -0,0 +1,248 @@
+package vip.devkit.debugkit.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.text.format.Formatter;
+
+import androidx.core.content.FileProvider;
+
+import java.io.File;
+import java.util.Locale;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: FileUtil.java
+ * Create Date: 2019/6/28 11:05
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class FileUtil {
+ private static final String DATA_TYPE_ALL = "*/*";
+ private static final String DATA_TYPE_APK = "application/vnd.android.package-archive";
+ private static final String DATA_TYPE_VIDEO = "video/*";
+ private static final String DATA_TYPE_AUDIO = "audio/*";
+ private static final String DATA_TYPE_HTML = "text/html";
+ private static final String DATA_TYPE_IMAGE = "image/*";
+ private static final String DATA_TYPE_PPT = "application/vnd.ms-powerpoint";
+ private static final String DATA_TYPE_EXCEL = "application/vnd.ms-excel";
+ private static final String DATA_TYPE_WORD = "application/msword";
+ private static final String DATA_TYPE_CHM = "application/x-chm";
+ private static final String DATA_TYPE_TXT = "text/plain";
+ private static final String DATA_TYPE_PDF = "application/pdf";
+ private static final String DATA_TYPE_RTF = "application/rtf";
+
+ public static final String TXT = "txt";
+ public static final String JPG = "jpg";
+ public static final String PNG = "png";
+
+ public static final String DB = "db";
+ public static final String SHARED_PREFS = "shared_prefs";
+ public static final String XML = ".xml";
+ public static final String JSON = ".json";
+ private FileUtil() {
+ }
+
+ public static String getFileSize(Context context, File file) {
+ if (!file.exists() || !file.isFile()) {
+ return null;
+ }
+ return Formatter.formatFileSize(context, file.length());
+ }
+
+ public static String getSuffix(File file) {
+ if (file == null || !file.exists()) {
+ return "";
+ }
+ return file.getName()
+ .substring(file.getName().lastIndexOf(".") + 1)
+ .toLowerCase(Locale.getDefault());
+ }
+
+ public static void systemShare(Context context, File file) {
+ if (file == null || !file.exists()) {
+ return;
+ }
+ String suffix = getSuffix(file);
+ String type;
+ switch (suffix) {
+ case "doc":
+ case "docx":
+ type = DATA_TYPE_WORD;
+ break;
+ case "pdf":
+ type = DATA_TYPE_PDF;
+ break;
+ case "ppt":
+ case "pptx":
+ type = DATA_TYPE_PPT;
+ break;
+ case "xls":
+ case "xlsx":
+ type = DATA_TYPE_EXCEL;
+ break;
+ case "rtf":
+ type = DATA_TYPE_RTF;
+ break;
+ case "mpg":
+ case "mpeg":
+ case "3gp":
+ case "mp4":
+ type = DATA_TYPE_VIDEO;
+ break;
+ case "m4a":
+ case "mp3":
+ case "mid":
+ case "xmf":
+ case "ogg":
+ case "wav":
+ type = DATA_TYPE_AUDIO;
+ break;
+ case "gif":
+ case "jpg":
+ case "jpeg":
+ case "png":
+ case "bmp":
+ type = DATA_TYPE_IMAGE;
+ break;
+ case "txt":
+ case "sh":
+ type = DATA_TYPE_TXT;
+ break;
+ case "html":
+ type = DATA_TYPE_HTML;
+ break;
+ case "xml":
+ case "rss":
+ type = "application/rss+xml";
+ break;
+ case "js":
+ type = "application/javascript";
+ break;
+ case "chm":
+ type = DATA_TYPE_CHM;
+ break;
+ case "json":
+ type = "application/json";
+ break;
+ case "class":
+ type = "application/java-vm";
+ break;
+ case "jar":
+ type = "application/java-archive";
+ break;
+ case "gtar":
+ type = "application/x-gtar";
+ break;
+ case "tar":
+ type = "application/x-tar";
+ break;
+ case "css":
+ type = "text/css";
+ break;
+ case "7z":
+ type = "application/x-7z-compressed";
+ break;
+ case "swf":
+ type = "application/x-7z-compressed";
+ break;
+ case "zip":
+ type = "application/zip";
+ break;
+ case "csv":
+ type = "text/csv";
+ break;
+ case "apk":
+ type = DATA_TYPE_APK;
+ break;
+ default:
+ type = DATA_TYPE_ALL;
+ }
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ Uri uri;
+ uri = FileProvider.getUriForFile(context, context.getPackageName() + ".debugkitfileprovider", file);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setDataAndType(uri, type);
+ if (intent.resolveActivity(context.getPackageManager()) == null) {
+ intent.setDataAndType(uri, DATA_TYPE_ALL);
+ }
+ context.startActivity(intent);
+ }
+
+ public static boolean isImage(File file) {
+ if (file == null) {
+ return false;
+ }
+ String suffix = getSuffix(file);
+ return "jpg".equals(suffix) || "jpeg".equals(suffix) || "png".equals(suffix) || "bmp".equals(suffix);
+ }
+
+ public static boolean isVideo(File file) {
+ if (file == null) {
+ return false;
+ }
+ String suffix = getSuffix(file);
+ return "3gp".equals(suffix) || "mp4".equals(suffix) || "mkv".equals(suffix) || "webm".equals(suffix);
+ }
+
+ public static boolean isDB(File file) {
+ if (file == null) {
+ return false;
+ }
+ String suffix = getSuffix(file);
+ return "db".equals(suffix);
+ }
+
+ public static boolean isSp(File file) {
+ File parentFile = file.getParentFile();
+ if (parentFile != null && parentFile.getName().equals(SHARED_PREFS) && file.getName().contains(XML)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isTxt(File file) {
+ if (file == null) {
+ return false;
+ }
+ String suffix = getSuffix(file);
+
+ return TXT.equals(suffix);
+ }
+
+ /**
+ * @param file
+ */
+ public static void deleteDirectory(File file) {
+ if (file.isDirectory()) {
+ File[] listFiles = file.listFiles();
+ for (File f : listFiles) {
+ deleteDirectory(f);
+ }
+ file.delete();
+ } else {
+ file.delete();
+ }
+ }
+
+ public static long getDirectorySize(File directory) {
+ long size = 0;
+ File[] listFiles = directory.listFiles();
+ if (listFiles == null) {
+ return size;
+ }
+ for (File file : listFiles) {
+ if (file.isDirectory()) {
+ size += getDirectorySize(file);
+ } else {
+ size += file.length();
+ }
+ }
+ return size;
+ }
+}
+
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/NetUtils.java b/dklib/src/main/java/vip/devkit/debugkit/util/NetUtils.java
new file mode 100644
index 0000000..f901ff5
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/NetUtils.java
@@ -0,0 +1,283 @@
+package vip.devkit.debugkit.util;
+
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import static android.content.Context.WIFI_SERVICE;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: NetUtils.java
+ * Create Date: 2019/7/2 11:39
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class NetUtils {
+ public static final int NETWORK_NONE = 0; // 没有网络连接
+ public static final int NETWORK_WIFI = 1; // wifi连接
+ public static final int NETWORK_2G = 2; // 2G
+ public static final int NETWORK_3G = 3; // 3G
+ public static final int NETWORK_4G = 4; // 4G
+ public static final int NETWORK_5G = 5; // 5G
+
+ public static final int NETWORK_MOBILE = 10; // 手机流量
+
+ /**
+ * 获取运营商名字
+ *
+ * @param context context
+ * @return int
+ */
+ public static String getOperatorName(Context context) {
+ TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ // getSimOperatorName
+ return telephonyManager.getSimOperatorName();
+ }
+
+ public static String getNetworkStateName(Context context) {
+ int type = getNetworkState(context);
+ switch (type) {
+ case 0:
+ return "disconnect";
+ case 1:
+ return "WIFI";
+ case 2:
+ return "2G";
+ case 3:
+ return "3G";
+ case 4:
+ return "4G";
+ case 5:
+ return "4G";
+ case 10:
+ return "MOBILE";
+ }
+ return "disconnect";
+ }
+
+
+ /**
+ * 获取当前网络连接的类型
+ *
+ * @param context context
+ * @return int
+ */
+ public static int getNetworkState(Context context) {
+ ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // 获取网络服务
+ if (null == connManager) { // 为空则认为无网络
+ return NETWORK_NONE;
+ }
+ // 获取网络类型,如果为空,返回无网络
+ NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
+ if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
+ return NETWORK_NONE;
+ }
+ // 判断是否为WIFI
+ NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ if (null != wifiInfo) {
+ NetworkInfo.State state = wifiInfo.getState();
+ if (null != state) {
+ if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
+ return NETWORK_WIFI;
+ }
+ }
+ }
+ // 若不是WIFI,则去判断是2G、3G、4G网
+ TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ int networkType = telephonyManager.getNetworkType();
+ switch (networkType) {
+ /*
+ GPRS : 2G(2.5) General Packet Radia Service 114kbps
+ EDGE : 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
+ UMTS : 3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准
+ CDMA : 2G 电信 Code Division Multiple Access 码分多址
+ EVDO_0 : 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
+ EVDO_A : 3G 1.8mbps - 3.1mbps 属于3G过渡,3.5G
+ 1xRTT : 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
+ HSDPA : 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
+ HSUPA : 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
+ HSPA : 3G (分HSDPA,HSUPA) High Speed Packet Access
+ IDEN : 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科)
+ EVDO_B : 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
+ LTE : 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G
+ EHRPD : 3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
+ HSPAP : 3G HSPAP 比 HSDPA 快些
+ */
+ // 2G
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ return NETWORK_2G;
+ // 3G
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ return NETWORK_3G;
+ // 4G
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ return NETWORK_4G;
+ default:
+ return NETWORK_MOBILE;
+ }
+ }
+
+ /**
+ * 判断网络是否连接
+ *
+ * @param context context
+ * @return true/false
+ */
+ public static boolean isNetConnected(Context context) {
+ ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivity != null) {
+ NetworkInfo info = connectivity.getActiveNetworkInfo();
+ if (info != null && info.isConnected()) {
+ if (info.getState() == NetworkInfo.State.CONNECTED) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判断是否wifi连接
+ *
+ * @param context context
+ * @return true/false
+ */
+ public static synchronized boolean isWifiConnected(Context context) {
+ ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivityManager != null) {
+ NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
+ if (networkInfo != null) {
+ int networkInfoType = networkInfo.getType();
+ if (networkInfoType == ConnectivityManager.TYPE_WIFI || networkInfoType == ConnectivityManager.TYPE_ETHERNET) {
+ return networkInfo.isConnected();
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public static String getHostIp() {
+ String hostIp = null;
+
+ try {
+ Enumeration nis = NetworkInterface.getNetworkInterfaces();
+ InetAddress ia = null;
+ while (true) {
+ while (nis.hasMoreElements()) {
+ NetworkInterface ni = (NetworkInterface) nis.nextElement();
+ Enumeration ias = ni.getInetAddresses();
+
+ while (ias.hasMoreElements()) {
+ ia = (InetAddress) ias.nextElement();
+ if (!(ia instanceof Inet6Address)) {
+ String ip = ia.getHostAddress();
+ if (!"127.0.0.1".equals(ip)) {
+ hostIp = ia.getHostAddress();
+ break;
+ }
+ }
+ }
+ }
+
+ return hostIp;
+ }
+ } catch (SocketException var6) {
+ return "0.0.0.0";
+ }
+ }
+
+ public static boolean isIp(String str) {
+ if (TextUtils.isEmpty(str)) {
+ return false;
+ } else {
+ String[] addr = str.split("\\.");
+ return addr.length == 4;
+ }
+ }
+
+
+ public static WifiInfo getWifiInfo(Context context) {
+ WifiManager wifi_service = (WifiManager) context.getSystemService(WIFI_SERVICE);
+ WifiInfo wifiInfo = null;
+ if (isWifiConnected(context)) {
+ wifiInfo = wifi_service.getConnectionInfo();
+ }
+ return wifiInfo;
+ }
+
+ public static int inetAddressToInt(InetAddress inetAddr)
+ throws IllegalArgumentException {
+ byte [] addr = inetAddr.getAddress();
+ if (addr.length != 4) {
+ throw new IllegalArgumentException("Not an IPv4 address");
+ }
+ return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
+ ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
+
+ }
+ public static String getMacAddress() {
+ /*获取mac地址有一点需要注意的就是android 6.0版本后,以下注释方法不再适用,不管任何手机都会返回"02:00:00:00:00:00"这个默认的mac地址,这是googel官方为了加强权限管理而禁用了getSYstemService(Context.WIFI_SERVICE)方法来获得mac地址。*/
+ // String macAddress= "";
+// WifiManager wifiManager = (WifiManager) MyApp.getContext().getSystemService(Context.WIFI_SERVICE);
+// WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+// macAddress = wifiInfo.getMacAddress();
+// return macAddress;
+
+ String macAddress = null;
+ StringBuffer buf = new StringBuffer();
+ NetworkInterface networkInterface = null;
+ try {
+ networkInterface = NetworkInterface.getByName("eth1");
+ if (networkInterface == null) {
+ networkInterface = NetworkInterface.getByName("wlan0");
+ }
+ if (networkInterface == null) {
+ return "02:00:00:00:00:02";
+ }
+ byte[] addr = networkInterface.getHardwareAddress();
+ for (byte b : addr) {
+ buf.append(String.format("%02X:", b));
+ }
+ if (buf.length() > 0) {
+ buf.deleteCharAt(buf.length() - 1);
+ }
+ macAddress = buf.toString();
+ } catch (SocketException e) {
+ e.printStackTrace();
+ return "02:00:00:00:00:02";
+ }
+ return macAddress;
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/util/ResUtil.java b/dklib/src/main/java/vip/devkit/debugkit/util/ResUtil.java
new file mode 100644
index 0000000..0d92d23
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/util/ResUtil.java
@@ -0,0 +1,24 @@
+package vip.devkit.debugkit.util;
+
+import android.content.Context;
+
+/**
+ * Package Name: vip.devkit.debugkit.util
+ * File Name: ResUtil.java
+ * Create Date: 2019/7/1 15:48
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class ResUtil {
+ public static String getString(Context context, int resId, String s) {
+ String val = String.format(context.getString(resId), s);
+ return val;
+ }
+ public static String getString(Context context, int resId) {
+ return context.getString(resId);
+ }
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/widget/a.java b/dklib/src/main/java/vip/devkit/debugkit/widget/a.java
new file mode 100644
index 0000000..92e80f3
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/widget/a.java
@@ -0,0 +1,15 @@
+package vip.devkit.debugkit.widget;
+
+/**
+ * Package Name: vip.devkit.debugkit.widget
+ * File Name: PermissionManagerActivity.java
+ * Create Date: 2019/7/1 11:51
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class a {
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/BaseRecyclerAdapter.java b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/BaseRecyclerAdapter.java
new file mode 100644
index 0000000..33a3a4c
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/BaseRecyclerAdapter.java
@@ -0,0 +1,128 @@
+package vip.devkit.debugkit.widget.recyclerview;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+
+import androidx.annotation.IntRange;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter {
+ private static final String TAG = "BaseRecyclerAdapter";
+ protected List mData;
+ protected Context mContext;
+ protected int mLayoutResId;
+ protected LayoutInflater mLayoutInflater;
+
+
+ private RecyclerView mRecyclerView;
+ private OnItemClickListener mOnItemClickListener;
+ private OnItemChildClickListener mOnItemChildClickListener;
+
+ public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
+ mOnItemClickListener = onItemClickListener;
+ }
+
+ public void setOnItemChildClickListener(OnItemChildClickListener onItemChildClickListener) {
+ mOnItemChildClickListener = onItemChildClickListener;
+ }
+
+ protected RecyclerView getRecyclerView() {
+ return mRecyclerView;
+ }
+
+ private void setRecyclerView(RecyclerView recyclerView) {
+ mRecyclerView = recyclerView;
+ }
+
+ public BaseRecyclerAdapter(@LayoutRes int layoutResId, @Nullable List data) {
+ this.mData = data == null ? new ArrayList() : data;
+ if (layoutResId != 0) {
+ this.mLayoutResId = layoutResId;
+ }
+ }
+
+ @Override
+ public K onCreateViewHolder(ViewGroup parent, int viewType) {
+ K baseViewHolder = null;
+ this.mContext = parent.getContext();
+ this.mLayoutInflater = LayoutInflater.from(mContext);
+ baseViewHolder = (K) new BaseViewHolder(getItemView(mLayoutResId, parent));
+ bindViewClickListener(baseViewHolder);
+ baseViewHolder.setAdapter(this);
+ return baseViewHolder;
+
+ }
+
+
+ protected View getItemView(@LayoutRes int layoutResId, ViewGroup parent) {
+ return mLayoutInflater.inflate(layoutResId, parent, false);
+ }
+
+ private void bindViewClickListener(final BaseViewHolder baseViewHolder) {
+ if (baseViewHolder == null) {
+ return;
+ }
+ final View view = baseViewHolder.itemView;
+ if (view == null) {
+ return;
+ }
+ if (getOnItemClickListener() != null) {
+ view.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setOnItemClick(v, baseViewHolder.getLayoutPosition());
+ }
+ });
+ }
+ }
+ public void setOnItemClick(View v, int position) {
+ getOnItemClickListener().onItemClick(BaseRecyclerAdapter.this, v, position);
+ }
+
+ @Override
+ public void onBindViewHolder(K holder, int position) {
+ convert(holder, getItem(position));
+ }
+
+ @Nullable
+ public T getItem(@IntRange(from = 0) int position) {
+ if (position >= 0 && position < mData.size())
+ return mData.get(position);
+ else
+ return null;
+ }
+ @Override
+ public int getItemCount() {
+ return mData.size();
+ }
+
+ protected abstract void convert(K helper, T mItem);
+
+ public interface OnItemClickListener {
+ void onItemClick(BaseRecyclerAdapter adapter, View view, int position);
+ }
+
+ public interface OnItemChildClickListener {
+
+ void onItemChildClick(BaseRecyclerAdapter adapter, View view, int position);
+ }
+
+ public final OnItemClickListener getOnItemClickListener() {
+ return mOnItemClickListener;
+ }
+
+ @Nullable
+ public final OnItemChildClickListener getOnItemChildClickListener() {
+ return mOnItemChildClickListener;
+ }
+
+}
diff --git a/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/BaseViewHolder.java b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/BaseViewHolder.java
new file mode 100644
index 0000000..d45cc9e
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/BaseViewHolder.java
@@ -0,0 +1,519 @@
+package vip.devkit.debugkit.widget.recyclerview;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.text.util.Linkify;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.animation.AlphaAnimation;
+import android.widget.Adapter;
+import android.widget.AdapterView;
+import android.widget.Checkable;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RatingBar;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IdRes;
+import androidx.annotation.StringRes;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class BaseViewHolder extends RecyclerView.ViewHolder {
+ /**
+ * Views indexed with their IDs
+ */
+ private final SparseArray views;
+
+ public Set getNestViews() {
+ return nestViews;
+ }
+
+ private final HashSet nestViews;
+
+ private final LinkedHashSet childClickViewIds;
+
+ private final LinkedHashSet itemChildLongClickViewIds;
+ private BaseRecyclerAdapter adapter;
+ /**
+ * use itemView instead
+ */
+ @Deprecated
+ public View convertView;
+
+ /**
+ * Package private field to retain the associated user object and detect PermissionManagerActivity change
+ */
+ Object associatedObject;
+
+
+ public BaseViewHolder(final View view) {
+ super(view);
+ this.views = new SparseArray<>();
+ this.childClickViewIds = new LinkedHashSet<>();
+ this.itemChildLongClickViewIds = new LinkedHashSet<>();
+ this.nestViews = new HashSet<>();
+ convertView = view;
+
+
+ }
+
+ private int getClickPosition() {
+ return getLayoutPosition();
+ }
+
+ public HashSet getItemChildLongClickViewIds() {
+ return itemChildLongClickViewIds;
+ }
+
+ public HashSet getChildClickViewIds() {
+ return childClickViewIds;
+ }
+
+ /**
+ * use itemView instead
+ *
+ * @return the ViewHolder root view
+ */
+ @Deprecated
+ public View getConvertView() {
+
+ return convertView;
+ }
+
+ /**
+ * Will set the text of PermissionManagerActivity TextView.
+ *
+ * @param viewId The view id.
+ * @param value The text to put in the text view.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setText(@IdRes int viewId, CharSequence value) {
+ TextView view = getView(viewId);
+ view.setText(value);
+ return this;
+ }
+
+ public BaseViewHolder setText(@IdRes int viewId, @StringRes int strId) {
+ TextView view = getView(viewId);
+ view.setText(strId);
+ return this;
+ }
+
+ /**
+ * Will set the image of an ImageView from PermissionManagerActivity resource id.
+ *
+ * @param viewId The view id.
+ * @param imageResId The image resource id.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setImageResource(@IdRes int viewId, @DrawableRes int imageResId) {
+ ImageView view = getView(viewId);
+ view.setImageResource(imageResId);
+ return this;
+ }
+
+ /**
+ * Will set background color of PermissionManagerActivity view.
+ *
+ * @param viewId The view id.
+ * @param color A color, not PermissionManagerActivity resource id.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setBackgroundColor(@IdRes int viewId, @ColorInt int color) {
+ View view = getView(viewId);
+ view.setBackgroundColor(color);
+ return this;
+ }
+
+ /**
+ * Will set background of PermissionManagerActivity view.
+ *
+ * @param viewId The view id.
+ * @param backgroundRes A resource to use as PermissionManagerActivity background.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setBackgroundRes(@IdRes int viewId, @DrawableRes int backgroundRes) {
+ View view = getView(viewId);
+ view.setBackgroundResource(backgroundRes);
+ return this;
+ }
+
+ /**
+ * Will set text color of PermissionManagerActivity TextView.
+ *
+ * @param viewId The view id.
+ * @param textColor The text color (not PermissionManagerActivity resource id).
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setTextColor(@IdRes int viewId, @ColorInt int textColor) {
+ TextView view = getView(viewId);
+ view.setTextColor(textColor);
+ return this;
+ }
+
+
+ /**
+ * Will set the image of an ImageView from PermissionManagerActivity drawable.
+ *
+ * @param viewId The view id.
+ * @param drawable The image drawable.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setImageDrawable(@IdRes int viewId, Drawable drawable) {
+ ImageView view = getView(viewId);
+ view.setImageDrawable(drawable);
+ return this;
+ }
+
+ /**
+ * Add an action to set the image of an image view. Can be called multiple times.
+ */
+ public BaseViewHolder setImageBitmap(@IdRes int viewId, Bitmap bitmap) {
+ ImageView view = getView(viewId);
+ view.setImageBitmap(bitmap);
+ return this;
+ }
+
+ /**
+ * Add an action to set the alpha of PermissionManagerActivity view. Can be called multiple times.
+ * Alpha between 0-1.
+ */
+ public BaseViewHolder setAlpha(@IdRes int viewId, float value) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ getView(viewId).setAlpha(value);
+ } else {
+ // Pre-honeycomb hack to set Alpha value
+ AlphaAnimation alpha = new AlphaAnimation(value, value);
+ alpha.setDuration(0);
+ alpha.setFillAfter(true);
+ getView(viewId).startAnimation(alpha);
+ }
+ return this;
+ }
+
+ /**
+ * Set PermissionManagerActivity view visibility to VISIBLE (true) or GONE (false).
+ *
+ * @param viewId The view id.
+ * @param visible True for VISIBLE, false for GONE.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setGone(@IdRes int viewId, boolean visible) {
+ View view = getView(viewId);
+ view.setVisibility(visible ? View.VISIBLE : View.GONE);
+ return this;
+ }
+
+ /**
+ * Set PermissionManagerActivity view visibility to VISIBLE (true) or INVISIBLE (false).
+ *
+ * @param viewId The view id.
+ * @param visible True for VISIBLE, false for INVISIBLE.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setVisible(@IdRes int viewId, boolean visible) {
+ View view = getView(viewId);
+ view.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ return this;
+ }
+
+ /**
+ * Add links into PermissionManagerActivity TextView.
+ *
+ * @param viewId The id of the TextView to linkify.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder linkify(@IdRes int viewId) {
+ TextView view = getView(viewId);
+ Linkify.addLinks(view, Linkify.ALL);
+ return this;
+ }
+
+ /**
+ * Apply the typeface to the given viewId, and enable subpixel rendering.
+ */
+ public BaseViewHolder setTypeface(@IdRes int viewId, Typeface typeface) {
+ TextView view = getView(viewId);
+ view.setTypeface(typeface);
+ view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
+ return this;
+ }
+
+ /**
+ * Apply the typeface to all the given viewIds, and enable subpixel rendering.
+ */
+ public BaseViewHolder setTypeface(Typeface typeface, int... viewIds) {
+ for (int viewId : viewIds) {
+ TextView view = getView(viewId);
+ view.setTypeface(typeface);
+ view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the progress of PermissionManagerActivity ProgressBar.
+ *
+ * @param viewId The view id.
+ * @param progress The progress.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setProgress(@IdRes int viewId, int progress) {
+ ProgressBar view = getView(viewId);
+ view.setProgress(progress);
+ return this;
+ }
+
+ /**
+ * Sets the progress and max of PermissionManagerActivity ProgressBar.
+ *
+ * @param viewId The view id.
+ * @param progress The progress.
+ * @param max The max value of PermissionManagerActivity ProgressBar.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setProgress(@IdRes int viewId, int progress, int max) {
+ ProgressBar view = getView(viewId);
+ view.setMax(max);
+ view.setProgress(progress);
+ return this;
+ }
+
+ /**
+ * Sets the range of PermissionManagerActivity ProgressBar to 0...max.
+ *
+ * @param viewId The view id.
+ * @param max The max value of PermissionManagerActivity ProgressBar.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setMax(@IdRes int viewId, int max) {
+ ProgressBar view = getView(viewId);
+ view.setMax(max);
+ return this;
+ }
+
+ /**
+ * Sets the rating (the number of stars filled) of PermissionManagerActivity RatingBar.
+ *
+ * @param viewId The view id.
+ * @param rating The rating.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setRating(@IdRes int viewId, float rating) {
+ RatingBar view = getView(viewId);
+ view.setRating(rating);
+ return this;
+ }
+
+ /**
+ * Sets the rating (the number of stars filled) and max of PermissionManagerActivity RatingBar.
+ *
+ * @param viewId The view id.
+ * @param rating The rating.
+ * @param max The range of the RatingBar to 0...max.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setRating(@IdRes int viewId, float rating, int max) {
+ RatingBar view = getView(viewId);
+ view.setMax(max);
+ view.setRating(rating);
+ return this;
+ }
+
+ /**
+ * Sets the on click listener of the view.
+ *
+ * @param viewId The view id.
+ * @param listener The on click listener;
+ * @return The BaseViewHolder for chaining.
+ */
+ @Deprecated
+ public BaseViewHolder setOnClickListener(@IdRes int viewId, View.OnClickListener listener) {
+ View view = getView(viewId);
+ view.setOnClickListener(listener);
+ return this;
+ }
+
+
+
+
+
+
+ /**
+ * Sets the on touch listener of the view.
+ *
+ * @param viewId The view id.
+ * @param listener The on touch listener;
+ * @return The BaseViewHolder for chaining.
+ */
+ @Deprecated
+ public BaseViewHolder setOnTouchListener(@IdRes int viewId, View.OnTouchListener listener) {
+ View view = getView(viewId);
+ view.setOnTouchListener(listener);
+ return this;
+ }
+
+
+ /**
+ * Sets the listview or gridview's item long click listener of the view
+ *
+ * @param viewId The view id.
+ * @param listener The item long click listener;
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setOnItemLongClickListener(@IdRes int viewId, AdapterView.OnItemLongClickListener listener) {
+ AdapterView view = getView(viewId);
+ view.setOnItemLongClickListener(listener);
+ return this;
+ }
+
+ /**
+ * Sets the listview or gridview's item selected click listener of the view
+ *
+ * @param viewId The view id.
+ * @param listener The item selected click listener;
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setOnItemSelectedClickListener(@IdRes int viewId, AdapterView.OnItemSelectedListener listener) {
+ AdapterView view = getView(viewId);
+ view.setOnItemSelectedListener(listener);
+ return this;
+ }
+
+ /**
+ * Sets the on checked change listener of the view.
+ *
+ * @param viewId The view id.
+ * @param listener The checked change listener of compound button.
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setOnCheckedChangeListener(@IdRes int viewId, CompoundButton.OnCheckedChangeListener listener) {
+ CompoundButton view = getView(viewId);
+ view.setOnCheckedChangeListener(listener);
+ return this;
+ }
+
+
+ public BaseViewHolder addOnClickListener(@IdRes final int viewId) {
+ childClickViewIds.add(viewId);
+ final View view = getView(viewId);
+ if (view != null) {
+ if (!view.isClickable()) {
+ view.setClickable(true);
+ }
+ view.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (adapter.getOnItemChildClickListener() != null) {
+ adapter.getOnItemChildClickListener().onItemChildClick(adapter, v, getClickPosition());
+ }
+ }
+ });
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the tag of the view.
+ *
+ * @param viewId The view id.
+ * @param tag The tag;
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setTag(@IdRes int viewId, Object tag) {
+ View view = getView(viewId);
+ view.setTag(tag);
+ return this;
+ }
+
+ /**
+ * Sets the tag of the view.
+ *
+ * @param viewId The view id.
+ * @param key The key of tag;
+ * @param tag The tag;
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setTag(@IdRes int viewId, int key, Object tag) {
+ View view = getView(viewId);
+ view.setTag(key, tag);
+ return this;
+ }
+
+ /**
+ * Sets the checked status of PermissionManagerActivity checkable.
+ *
+ * @param viewId The view id.
+ * @param checked The checked status;
+ * @return The BaseViewHolder for chaining.
+ */
+ public BaseViewHolder setChecked(@IdRes int viewId, boolean checked) {
+ View view = getView(viewId);
+ // View unable cast to Checkable
+ if (view instanceof Checkable) {
+ ((Checkable) view).setChecked(checked);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the adapter of PermissionManagerActivity adapter view.
+ *
+ * @param viewId The view id.
+ * @param adapter The adapter;
+ * @return The BaseViewHolder for chaining.
+ */
+ @SuppressWarnings("unchecked")
+ public BaseViewHolder setAdapter(@IdRes int viewId, Adapter adapter) {
+ AdapterView view = getView(viewId);
+ view.setAdapter(adapter);
+ return this;
+ }
+
+ /**
+ * Sets the adapter of PermissionManagerActivity adapter view.
+ *
+ * @param adapter The adapter;
+ * @return The BaseViewHolder for chaining.
+ */
+ protected BaseViewHolder setAdapter(BaseRecyclerAdapter adapter) {
+ this.adapter = adapter;
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getView(@IdRes int viewId) {
+ View view = views.get(viewId);
+ if (view == null) {
+ view = itemView.findViewById(viewId);
+ views.put(viewId, view);
+ }
+ return (T) view;
+ }
+
+ /**
+ * Retrieves the last converted object on this view.
+ */
+ public Object getAssociatedObject() {
+ return associatedObject;
+ }
+
+ /**
+ * Should be called during convert
+ */
+ public void setAssociatedObject(Object associatedObject) {
+ this.associatedObject = associatedObject;
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/DividerItemDecoration.java b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/DividerItemDecoration.java
new file mode 100644
index 0000000..5ef7580
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/DividerItemDecoration.java
@@ -0,0 +1,138 @@
+package vip.devkit.debugkit.widget.recyclerview;
+
+import android.annotation.TargetApi;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+ public static final int HORIZONTAL = 0;
+ public static final int VERTICAL = 1;
+ private static final String TAG = "TitleItem";
+ private Drawable mDivider;
+ private int mOrientation;
+ private final Rect mBounds = new Rect();
+ private boolean mShowHeaderDivider;
+ private boolean mShowFooterDivider = true;
+
+ public DividerItemDecoration(int orientation) {
+ this.setOrientation(orientation);
+ }
+
+ public void setOrientation(int orientation) {
+ if (orientation != 0 && orientation != 1) {
+ throw new IllegalArgumentException("Invalid orientation. It should be either HORIZONTAL or VERTICAL");
+ } else {
+ this.mOrientation = orientation;
+ }
+ }
+
+ public void setDrawable(@NonNull Drawable drawable) {
+ this.mDivider = drawable;
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ if (parent.getLayoutManager() != null && this.mDivider != null) {
+ if (this.mOrientation == 1) {
+ this.drawVertical(c, parent);
+ } else {
+ this.drawHorizontal(c, parent);
+ }
+ }
+ }
+
+ public void showHeaderDivider(boolean show) {
+ mShowHeaderDivider = show;
+ }
+
+ public void showFooterDivider(boolean show) {
+ mShowFooterDivider = show;
+ }
+
+ private void drawVertical(Canvas canvas, RecyclerView parent) {
+ canvas.save();
+ int left;
+ int right;
+ if (parent.getClipToPadding()) {
+ left = parent.getPaddingLeft();
+ right = parent.getWidth() - parent.getPaddingRight();
+ int top = parent.getPaddingTop();
+ int bottom = parent.getHeight() - parent.getPaddingBottom();
+ canvas.clipRect(left, top, right, bottom);
+ } else {
+ left = 0;
+ right = parent.getWidth();
+ }
+
+ int childCount = parent.getChildCount();
+
+ for (int i = 0; i < childCount; ++i) {
+ View child = parent.getChildAt(i);
+ parent.getDecoratedBoundsWithMargins(child, this.mBounds);
+
+ int top;
+ int bottom;
+ if (i == 0 && mShowHeaderDivider) {
+ top = 0;
+ this.mDivider.setBounds(left, top, right, top + this.mDivider.getIntrinsicHeight());
+ this.mDivider.draw(canvas);
+ }
+
+ if (i != childCount - 1 || mShowFooterDivider) {
+ bottom = this.mBounds.bottom + Math.round(child.getTranslationY());
+ top = bottom - this.mDivider.getIntrinsicHeight();
+ this.mDivider.setBounds(left, top, right, bottom);
+ this.mDivider.draw(canvas);
+ }
+ }
+ canvas.restore();
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private void drawHorizontal(Canvas canvas, RecyclerView parent) {
+ canvas.save();
+ int top;
+ int bottom;
+ if (parent.getClipToPadding()) {
+ top = parent.getPaddingTop();
+ bottom = parent.getHeight() - parent.getPaddingBottom();
+ canvas.clipRect(parent.getPaddingLeft(), top, parent.getWidth() - parent.getPaddingRight(), bottom);
+ } else {
+ top = 0;
+ bottom = parent.getHeight();
+ }
+
+ int childCount = parent.getChildCount();
+
+ for (int i = 0; i < childCount; ++i) {
+ View child = parent.getChildAt(i);
+ parent.getLayoutManager().getDecoratedBoundsWithMargins(child, this.mBounds);
+ int right = this.mBounds.right + Math.round(child.getTranslationX());
+ int left = right - this.mDivider.getIntrinsicWidth();
+ this.mDivider.setBounds(left, top, right, bottom);
+ this.mDivider.draw(canvas);
+ }
+
+ canvas.restore();
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ if (this.mDivider == null) {
+ outRect.set(0, 0, 0, 0);
+ } else {
+ if (this.mOrientation == 1) {
+ outRect.set(0, 0, 0, this.mDivider.getIntrinsicHeight());
+ } else {
+ outRect.set(0, 0, this.mDivider.getIntrinsicWidth(), 0);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/S.java b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/S.java
new file mode 100644
index 0000000..cce24ca
--- /dev/null
+++ b/dklib/src/main/java/vip/devkit/debugkit/widget/recyclerview/S.java
@@ -0,0 +1,33 @@
+package vip.devkit.debugkit.widget.recyclerview;
+
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+/**
+ * Package Name: vip.devkit.debugkit.widget.recyclerview
+ * File Name: S.java
+ * Create Date: 2019/7/1 14:17
+ * Author : K
+ * E-mail : vip@devkit.vip
+ * VersionCode : V 1.0
+ * Describe :
+ * Code Update :(author - time)
+ * Update Describe:
+ */
+public class S extends BaseRecyclerAdapter {
+
+ public S(int layoutResId, @Nullable List data) {
+ super(layoutResId, data);
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, String mItem) {
+
+ }
+
+}
diff --git a/dklib/src/main/res/drawable/shape_group_kit_background.xml b/dklib/src/main/res/drawable/shape_group_kit_background.xml
new file mode 100644
index 0000000..70b4774
--- /dev/null
+++ b/dklib/src/main/res/drawable/shape_group_kit_background.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/act_kit_manager.xml b/dklib/src/main/res/layout/act_kit_manager.xml
new file mode 100644
index 0000000..5342846
--- /dev/null
+++ b/dklib/src/main/res/layout/act_kit_manager.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_activity_base_url.xml b/dklib/src/main/res/layout/dk_activity_base_url.xml
new file mode 100644
index 0000000..9fe4d2a
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_activity_base_url.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_activity_crash.xml b/dklib/src/main/res/layout/dk_activity_crash.xml
new file mode 100644
index 0000000..29f60ef
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_activity_crash.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_activity_file_explorer.xml b/dklib/src/main/res/layout/dk_activity_file_explorer.xml
new file mode 100644
index 0000000..b77f1d9
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_activity_file_explorer.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_activity_rv.xml b/dklib/src/main/res/layout/dk_activity_rv.xml
new file mode 100644
index 0000000..1fb55c8
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_activity_rv.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_base_url.xml b/dklib/src/main/res/layout/dk_item_base_url.xml
new file mode 100644
index 0000000..a68ad9c
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_base_url.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_crash.xml b/dklib/src/main/res/layout/dk_item_crash.xml
new file mode 100644
index 0000000..36dcdf4
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_crash.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_file.xml b/dklib/src/main/res/layout/dk_item_file.xml
new file mode 100644
index 0000000..996fc04
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_file.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_file_folder.xml b/dklib/src/main/res/layout/dk_item_file_folder.xml
new file mode 100644
index 0000000..be54860
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_file_folder.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_group_kit.xml b/dklib/src/main/res/layout/dk_item_group_kit.xml
new file mode 100644
index 0000000..4212526
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_group_kit.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_kit.xml b/dklib/src/main/res/layout/dk_item_kit.xml
new file mode 100644
index 0000000..a434263
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_kit.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_item_permission.xml b/dklib/src/main/res/layout/dk_item_permission.xml
new file mode 100644
index 0000000..77a33a2
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_item_permission.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_view_common_divider.xml b/dklib/src/main/res/layout/dk_view_common_divider.xml
new file mode 100644
index 0000000..c7a6c9d
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_view_common_divider.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/layout/dk_view_common_title.xml b/dklib/src/main/res/layout/dk_view_common_title.xml
new file mode 100644
index 0000000..f0a31c7
--- /dev/null
+++ b/dklib/src/main/res/layout/dk_view_common_title.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_app_info.png b/dklib/src/main/res/mipmap-xxhdpi/dk_app_info.png
new file mode 100644
index 0000000..64c2385
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_app_info.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_base_url.png b/dklib/src/main/res/mipmap-xxhdpi/dk_base_url.png
new file mode 100644
index 0000000..af6cb1c
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_base_url.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_crash_catch.png b/dklib/src/main/res/mipmap-xxhdpi/dk_crash_catch.png
new file mode 100644
index 0000000..1e1659b
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_crash_catch.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_crash_permission.png b/dklib/src/main/res/mipmap-xxhdpi/dk_crash_permission.png
new file mode 100644
index 0000000..cd3f969
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_crash_permission.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_data_clean.png b/dklib/src/main/res/mipmap-xxhdpi/dk_data_clean.png
new file mode 100644
index 0000000..10b376e
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_data_clean.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_data_export.png b/dklib/src/main/res/mipmap-xxhdpi/dk_data_export.png
new file mode 100644
index 0000000..e6a2034
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_data_export.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_file_db.png b/dklib/src/main/res/mipmap-xxhdpi/dk_file_db.png
new file mode 100644
index 0000000..ca1c174
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_file_db.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_file_explorer.png b/dklib/src/main/res/mipmap-xxhdpi/dk_file_explorer.png
new file mode 100644
index 0000000..b5dda7a
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_file_explorer.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_file_folder.png b/dklib/src/main/res/mipmap-xxhdpi/dk_file_folder.png
new file mode 100644
index 0000000..bb80744
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_file_folder.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_file_img.png b/dklib/src/main/res/mipmap-xxhdpi/dk_file_img.png
new file mode 100644
index 0000000..c7fbf76
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_file_img.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_file_ohter.png b/dklib/src/main/res/mipmap-xxhdpi/dk_file_ohter.png
new file mode 100644
index 0000000..9888e0a
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_file_ohter.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_file_txt.png b/dklib/src/main/res/mipmap-xxhdpi/dk_file_txt.png
new file mode 100644
index 0000000..ab00bfd
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_file_txt.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_log_info.png b/dklib/src/main/res/mipmap-xxhdpi/dk_log_info.png
new file mode 100644
index 0000000..6e64a16
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_log_info.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_more_down.png b/dklib/src/main/res/mipmap-xxhdpi/dk_more_down.png
new file mode 100644
index 0000000..dcf85a7
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_more_down.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_more_up.png b/dklib/src/main/res/mipmap-xxhdpi/dk_more_up.png
new file mode 100644
index 0000000..4360576
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_more_up.png differ
diff --git a/dklib/src/main/res/mipmap-xxhdpi/dk_right_more.png b/dklib/src/main/res/mipmap-xxhdpi/dk_right_more.png
new file mode 100644
index 0000000..79b0c13
Binary files /dev/null and b/dklib/src/main/res/mipmap-xxhdpi/dk_right_more.png differ
diff --git a/dklib/src/main/res/mipmap/dk_icon_back.png b/dklib/src/main/res/mipmap/dk_icon_back.png
new file mode 100644
index 0000000..c37fa67
Binary files /dev/null and b/dklib/src/main/res/mipmap/dk_icon_back.png differ
diff --git a/dklib/src/main/res/values/color.xml b/dklib/src/main/res/values/color.xml
new file mode 100644
index 0000000..7c9f6aa
--- /dev/null
+++ b/dklib/src/main/res/values/color.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ #ffffff
+
+ #ffffff
+
+ #ffffff
+
+ #ffffff
+
+ #ff0000
+
+ #292922
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/values/dimens.xml b/dklib/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..48c5a0c
--- /dev/null
+++ b/dklib/src/main/res/values/dimens.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ 16sp
+ 18sp
+ 14sp
+
+
+
+
+
+
+
+
+
+ - 10sp
+ - 12sp
+ - 20sp
+ - 40sp
+ - 100sp
+
+
+
\ No newline at end of file
diff --git a/dklib/src/main/res/values/strings.xml b/dklib/src/main/res/values/strings.xml
new file mode 100644
index 0000000..64e7d88
--- /dev/null
+++ b/dklib/src/main/res/values/strings.xml
@@ -0,0 +1,71 @@
+
+ DK
+
+
+
+ 系统信息
+ 系统
+ 硬件
+ 屏幕
+ 网络
+ 虚拟机
+ CPU
+ ID
+
+
+
+ 调试
+
+ APP信息
+ 权限管理
+ 日志
+ 清理
+ H5
+ Crash
+ 文件沙盒
+ Base URL
+
+ 数据导出
+
+ 环境模拟
+
+
+
+ 开发者选项
+ 系统设置
+ 不锁定屏幕
+ 不保留应用
+ 严格模式
+ USB调试
+ 运行中服务
+ 语言设置
+
+
+
+ 性能监控
+ 帧率
+ CPU
+ RAM
+ 电池温度
+ 流量监控
+ 耗时
+
+
+
+ UE/UI
+ 取色器
+ UE
+
+
+
+ 自定义
+
+
+
+ 记录Crash中...
+
+
+
+
+
+
diff --git a/dklib/src/test/java/vip/devkit/debugkit/ExampleUnitTest.java b/dklib/src/test/java/vip/devkit/debugkit/ExampleUnitTest.java
new file mode 100644
index 0000000..dd64dec
--- /dev/null
+++ b/dklib/src/test/java/vip/devkit/debugkit/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package vip.devkit.debugkit;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..199d16e
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# 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.
+org.gradle.jvmargs=-Xmx1536m
+# 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
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -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" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -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
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..0e9e576
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':dklib'