From f8e7c1852188e4dc16c2bb4716af37d18013a249 Mon Sep 17 00:00:00 2001
From: kai-city <1830170041@qq.com>
Date: Sun, 23 May 2021 23:38:25 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0UI?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
app/build.gradle | 41 ++-
.../blackdex/ExampleInstrumentedTest.java | 26 --
.../blackdex/ExampleInstrumentedTest.kt | 24 ++
app/src/main/AndroidManifest.xml | 23 +-
.../main/java/top/niunaijun/blackdex/App.java | 43 ---
.../main/java/top/niunaijun/blackdex/App.kt | 26 ++
.../top/niunaijun/blackdex/MainActivity.java | 45 ---
.../blackdex/data/BlackDexConfiguration.kt | 18 +
.../blackdex/data/DexDumpRepository.kt | 88 +++++
.../niunaijun/blackdex/data/entity/AppInfo.kt | 15 +
.../blackdex/data/entity/DumpInfo.kt | 22 ++
.../top/niunaijun/blackdex/util/FileUtil.kt | 27 ++
.../niunaijun/blackdex/util/InjectionUtil.kt | 22 ++
.../niunaijun/blackdex/util/LoadingUtil.kt | 30 ++
.../top/niunaijun/blackdex/util/ToastEx.kt | 17 +
.../niunaijun/blackdex/util/ViewBindingEx.kt | 41 +++
.../blackdex/view/base/BaseActivity.kt | 29 ++
.../blackdex/view/base/BaseAdapter.kt | 115 ++++++
.../blackdex/view/base/BaseViewModel.kt | 34 ++
.../blackdex/view/main/MainActivity.kt | 211 +++++++++++
.../blackdex/view/main/MainAdapter.kt | 27 ++
.../blackdex/view/main/MainFactory.kt | 19 +
.../blackdex/view/main/MainViewModel.kt | 40 +++
.../main/res/drawable-anydpi/ic_folder.xml | 11 +
.../main/res/drawable-anydpi/ic_search.xml | 11 +
app/src/main/res/drawable-hdpi/ic_folder.png | Bin 0 -> 248 bytes
app/src/main/res/drawable-hdpi/ic_search.png | Bin 0 -> 425 bytes
app/src/main/res/drawable-mdpi/ic_folder.png | Bin 0 -> 163 bytes
app/src/main/res/drawable-mdpi/ic_search.png | Bin 0 -> 247 bytes
.../drawable-v24/ic_launcher_foreground.xml | 38 +-
app/src/main/res/drawable-xhdpi/ic_folder.png | Bin 0 -> 318 bytes
app/src/main/res/drawable-xhdpi/ic_search.png | Bin 0 -> 462 bytes
.../main/res/drawable-xxhdpi/ic_folder.png | Bin 0 -> 421 bytes
.../main/res/drawable-xxhdpi/ic_search.png | Bin 0 -> 810 bytes
.../res/drawable/ic_launcher_background.xml | 334 +++++++++---------
app/src/main/res/drawable/splash.xml | 14 +
app/src/main/res/layout/activity_main.xml | 64 +++-
app/src/main/res/layout/item_package.xml | 37 ++
app/src/main/res/layout/view_toolbar.xml | 12 +
app/src/main/res/menu/menu_main.xml | 17 +
app/src/main/res/values-night/themes.xml | 16 +-
app/src/main/res/values/colors.xml | 12 +-
app/src/main/res/values/strings.xml | 5 +
app/src/main/res/values/themes.xml | 24 +-
.../niunaijun/blackdex/ExampleUnitTest.java | 17 -
.../top/niunaijun/blackdex/ExampleUnitTest.kt | 17 +
build.gradle | 25 +-
settings.gradle | 2 +-
49 files changed, 1273 insertions(+), 368 deletions(-)
delete mode 100644 app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.java
create mode 100644 app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.kt
delete mode 100644 app/src/main/java/top/niunaijun/blackdex/App.java
create mode 100644 app/src/main/java/top/niunaijun/blackdex/App.kt
delete mode 100644 app/src/main/java/top/niunaijun/blackdex/MainActivity.java
create mode 100644 app/src/main/java/top/niunaijun/blackdex/data/BlackDexConfiguration.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/data/DexDumpRepository.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/data/entity/AppInfo.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/data/entity/DumpInfo.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/util/FileUtil.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/util/InjectionUtil.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/util/LoadingUtil.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/util/ToastEx.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/util/ViewBindingEx.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/base/BaseActivity.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/base/BaseAdapter.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/base/BaseViewModel.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/main/MainActivity.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/main/MainAdapter.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/main/MainFactory.kt
create mode 100644 app/src/main/java/top/niunaijun/blackdex/view/main/MainViewModel.kt
create mode 100644 app/src/main/res/drawable-anydpi/ic_folder.xml
create mode 100644 app/src/main/res/drawable-anydpi/ic_search.xml
create mode 100644 app/src/main/res/drawable-hdpi/ic_folder.png
create mode 100644 app/src/main/res/drawable-hdpi/ic_search.png
create mode 100644 app/src/main/res/drawable-mdpi/ic_folder.png
create mode 100644 app/src/main/res/drawable-mdpi/ic_search.png
create mode 100644 app/src/main/res/drawable-xhdpi/ic_folder.png
create mode 100644 app/src/main/res/drawable-xhdpi/ic_search.png
create mode 100644 app/src/main/res/drawable-xxhdpi/ic_folder.png
create mode 100644 app/src/main/res/drawable-xxhdpi/ic_search.png
create mode 100644 app/src/main/res/drawable/splash.xml
create mode 100644 app/src/main/res/layout/item_package.xml
create mode 100644 app/src/main/res/layout/view_toolbar.xml
create mode 100644 app/src/main/res/menu/menu_main.xml
delete mode 100644 app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.java
create mode 100644 app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.kt
diff --git a/README.md b/README.md
index 674bc65..61cb757 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
![](https://img.shields.io/badge/language-java-brightgreen.svg)
-BlackDex是一个运行在Android手机上的脱壳工具,支持5.0~12,无需依赖任何环境任何手机都可以使用,包括模拟器。只需5秒,即可对已安装包括未安装的APK进行脱壳。
+BlackDex是一个运行在Android手机上的脱壳工具,支持5.0~12,无需依赖任何环境任何手机都可以使用,包括模拟器。只需数秒,即可对已安装包括未安装的APK进行脱壳。
## 项目声明
- 由于 [黑盒BlackBox](https://github.com/nnjun/BlackBox) 已被抄家,多的不想说了,请关注本项目或者其他未来项目吧。
diff --git a/app/build.gradle b/app/build.gradle
index d4eceb0..8710ded 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,6 @@
plugins {
id 'com.android.application'
+ id 'kotlin-android'
}
android {
@@ -14,10 +15,12 @@ android {
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
ndk {
// 设置支持的SO库架构
abiFilters 'armeabi-v7a', 'x86'
}
+
}
buildTypes {
@@ -26,20 +29,50 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
+
+ buildFeatures{
+ viewBinding true
+ }
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
}
dependencies {
- implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'androidx.core:core-ktx:1.5.0'
+ implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
- testImplementation 'junit:junit:4.+'
- androidTestImplementation 'androidx.test.ext:junit:1.1.2'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation project(':Bcore')
+
+ //coroutines
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2"
+
+ //viewModel liveData lifecycle
+ implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
+ implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
+ implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
+
+ //third
+
+ implementation 'com.afollestad.material-dialogs:core:3.3.0'
+ //dialog
+ implementation 'com.github.nukc.stateview:kotlin:2.2.0'
+ //状态控制控件
+ implementation 'com.roger.catloadinglibrary:catloadinglibrary:1.0.9'
+ //加载dialog
+ implementation 'com.github.Ferfalk:SimpleSearchView:0.2.0'
+ //searchView
+
+
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
\ No newline at end of file
diff --git a/app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.java b/app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.java
deleted file mode 100644
index a3fec20..0000000
--- a/app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package top.niunaijun.blackdex;
-
-import android.content.Context;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.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.getInstrumentation().getTargetContext();
- assertEquals("top.niunaijun.blackdex", appContext.getPackageName());
- }
-}
\ No newline at end of file
diff --git a/app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.kt b/app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..69060a5
--- /dev/null
+++ b/app/src/androidTest/java/top/niunaijun/blackdex/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package top.niunaijun.blackdex
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("top.niunaijun.blackdex", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 75000f6..ad12602 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,16 +1,21 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ package="top.niunaijun.blackdex">
+
+
+
-
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:name=".App"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.BlackDex">
+
diff --git a/app/src/main/java/top/niunaijun/blackdex/App.java b/app/src/main/java/top/niunaijun/blackdex/App.java
deleted file mode 100644
index 7aa367f..0000000
--- a/app/src/main/java/top/niunaijun/blackdex/App.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package top.niunaijun.blackdex;
-
-import android.app.Application;
-import android.content.Context;
-
-import java.io.File;
-
-import top.niunaijun.blackbox.BlackDexCore;
-import top.niunaijun.blackbox.app.configuration.ClientConfiguration;
-
-/**
- * Created by Milk on 2021/5/20.
- * * ∧_∧
- * (`・ω・∥
- * 丶 つ0
- * しーJ
- * 此处无Bug
- */
-public class App extends Application {
- @Override
- protected void attachBaseContext(Context base) {
- super.attachBaseContext(base);
- String dir = new File(base.getExternalCacheDir().getParent(), "dump").getAbsolutePath();
- BlackDexCore.get().doAttachBaseContext(base, new ClientConfiguration() {
- @Override
- public String getHostPackageName() {
- return base.getPackageName();
- }
-
- @Override
- public String getDexDumpDir() {
- // 此处一定要给固定值,可以在doAttachBaseContext之前就把路径确定好。否则doAttachBaseContext后可能会遭到hook。
- return dir;
- }
- });
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- BlackDexCore.get().doCreate();
- }
-}
diff --git a/app/src/main/java/top/niunaijun/blackdex/App.kt b/app/src/main/java/top/niunaijun/blackdex/App.kt
new file mode 100644
index 0000000..1ba0721
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/App.kt
@@ -0,0 +1,26 @@
+package top.niunaijun.blackdex
+
+import android.app.Application
+import android.content.Context
+import top.niunaijun.blackbox.BlackDexCore
+import top.niunaijun.blackbox.app.configuration.ClientConfiguration
+import top.niunaijun.blackdex.data.BlackDexConfiguration
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:00
+ */
+class App : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ super.attachBaseContext(base)
+ BlackDexCore.get().doAttachBaseContext(base,BlackDexConfiguration(base!!))
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+ BlackDexCore.get().doCreate()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/MainActivity.java b/app/src/main/java/top/niunaijun/blackdex/MainActivity.java
deleted file mode 100644
index 2bcf1c3..0000000
--- a/app/src/main/java/top/niunaijun/blackdex/MainActivity.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package top.niunaijun.blackdex;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import android.os.Bundle;
-import android.util.Log;
-
-import java.io.File;
-
-import top.niunaijun.blackbox.BlackDexCore;
-import top.niunaijun.blackbox.core.system.dump.IBDumpMonitor;
-import top.niunaijun.blackbox.entity.dump.DumpResult;
-
-public class MainActivity extends AppCompatActivity {
- public static final String TAG = "MainActivity";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- // 注册dump监听
- BlackDexCore.get().registerDumpMonitor(mMonitor);
-
- findViewById(R.id.btn_click).setOnClickListener(v -> {
- // 此方法会阻塞
- boolean b = BlackDexCore.get().dumpDex("com.hicorenational.antifraud");
- if (!b) {
- Log.d(TAG, "dumpDex: error.");
- }
- });
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- BlackDexCore.get().unregisterDumpMonitor(mMonitor);
- }
-
- private final IBDumpMonitor mMonitor = new IBDumpMonitor.Stub() {
- @Override
- public void onDump(DumpResult result) {
- Log.d(TAG, "onDump: " + result.toString());
- }
- };
-}
diff --git a/app/src/main/java/top/niunaijun/blackdex/data/BlackDexConfiguration.kt b/app/src/main/java/top/niunaijun/blackdex/data/BlackDexConfiguration.kt
new file mode 100644
index 0000000..62fba09
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/data/BlackDexConfiguration.kt
@@ -0,0 +1,18 @@
+package top.niunaijun.blackdex.data
+
+import android.content.Context
+import top.niunaijun.blackbox.app.configuration.ClientConfiguration
+
+/**
+ *
+ * @Description: 启动配置文件
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:04
+ */
+class BlackDexConfiguration(private val context: Context) : ClientConfiguration() {
+ override fun getHostPackageName(): String {
+ return context.packageName
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/data/DexDumpRepository.kt b/app/src/main/java/top/niunaijun/blackdex/data/DexDumpRepository.kt
new file mode 100644
index 0000000..c02956e
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/data/DexDumpRepository.kt
@@ -0,0 +1,88 @@
+package top.niunaijun.blackdex.data
+
+import android.content.pm.ApplicationInfo
+import android.net.Uri
+import android.webkit.URLUtil
+import androidx.lifecycle.MutableLiveData
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import top.niunaijun.blackbox.BlackBoxCore
+import top.niunaijun.blackbox.BlackBoxCore.getPackageManager
+import top.niunaijun.blackbox.BlackDexCore
+import top.niunaijun.blackbox.utils.AbiUtils
+import top.niunaijun.blackbox.utils.FileUtils
+import top.niunaijun.blackdex.data.entity.AppInfo
+import top.niunaijun.blackdex.data.entity.DumpInfo
+import java.io.File
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:29
+ */
+class DexDumpRepository {
+
+ private var dumpTaskId = 0
+
+ fun getAppList(mAppListLiveData: MutableLiveData>) {
+
+ val installedApplications: List = getPackageManager().getInstalledApplications(0)
+ val installedList = mutableListOf()
+
+ for (installedApplication in installedApplications) {
+ val file = File(installedApplication.sourceDir)
+
+ if ((installedApplication.flags and ApplicationInfo.FLAG_SYSTEM) != 0) continue
+
+ if (!AbiUtils.isSupport(file)) continue
+
+
+ val info = AppInfo(
+ installedApplication.loadLabel(getPackageManager()).toString(),
+ installedApplication.packageName,
+ installedApplication.loadIcon(getPackageManager())
+ )
+ installedList.add(info)
+ }
+
+ mAppListLiveData.postValue(installedList)
+ }
+
+ fun dumpDex(source: String, dexDumpLiveData: MutableLiveData) {
+
+ dexDumpLiveData.postValue(DumpInfo(DumpInfo.LOADING))
+
+ val result = if (URLUtil.isValidUrl(source)) {
+ BlackDexCore.get().dumpDex(Uri.parse(source))
+ } else {
+ BlackDexCore.get().dumpDex(source)
+ }
+
+ if(result){
+ dumpTaskId++
+ startCountdown(dexDumpLiveData)
+ }else{
+ dexDumpLiveData.postValue(DumpInfo(DumpInfo.TIMEOUT))
+ }
+
+ }
+
+
+ fun dumpSuccess(){
+ dumpTaskId++
+ }
+
+ private fun startCountdown(dexDumpLiveData: MutableLiveData){
+ GlobalScope.launch {
+ val tempId = dumpTaskId
+ delay(10000)
+
+ if(tempId == dumpTaskId){
+ dexDumpLiveData.postValue(DumpInfo(DumpInfo.TIMEOUT))
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/data/entity/AppInfo.kt b/app/src/main/java/top/niunaijun/blackdex/data/entity/AppInfo.kt
new file mode 100644
index 0000000..5b5dea4
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/data/entity/AppInfo.kt
@@ -0,0 +1,15 @@
+package top.niunaijun.blackdex.data.entity
+
+import android.graphics.drawable.Drawable
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:36
+ */
+data class AppInfo(
+ val name:String,
+ val packageName:String,
+ val icon:Drawable
+)
diff --git a/app/src/main/java/top/niunaijun/blackdex/data/entity/DumpInfo.kt b/app/src/main/java/top/niunaijun/blackdex/data/entity/DumpInfo.kt
new file mode 100644
index 0000000..47d1ced
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/data/entity/DumpInfo.kt
@@ -0,0 +1,22 @@
+package top.niunaijun.blackdex.data.entity
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:36
+ */
+data class DumpInfo(
+ val state: Int,
+ val msg: String = ""
+) {
+ companion object {
+ const val SUCCESS = 200
+
+ const val FAIL = 404
+
+ const val LOADING = 300
+
+ const val TIMEOUT = 500
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/util/FileUtil.kt b/app/src/main/java/top/niunaijun/blackdex/util/FileUtil.kt
new file mode 100644
index 0000000..c78a117
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/util/FileUtil.kt
@@ -0,0 +1,27 @@
+package top.niunaijun.blackdex.util
+
+import top.niunaijun.blackbox.BlackBoxCore
+import top.niunaijun.blackbox.utils.FileUtils
+import top.niunaijun.blackbox.utils.compat.BuildCompat
+import java.io.File
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:54
+ */
+object FileUtil {
+
+ fun getDexDumpDir(): String {
+ if (BuildCompat.isR()) {
+ val dump = File(BlackBoxCore.getContext().externalCacheDir?.parentFile?.parentFile?.parentFile, "Download/dexDump")
+ FileUtils.mkdirs(dump)
+ return dump.absolutePath
+ }else{
+ val dump = File(BlackBoxCore.getContext().externalCacheDir?.parentFile, "dump")
+ FileUtils.mkdirs(dump)
+ return dump.absolutePath
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/util/InjectionUtil.kt b/app/src/main/java/top/niunaijun/blackdex/util/InjectionUtil.kt
new file mode 100644
index 0000000..08556b5
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/util/InjectionUtil.kt
@@ -0,0 +1,22 @@
+package top.niunaijun.blackdex.util
+
+import top.niunaijun.blackdex.data.DexDumpRepository
+import top.niunaijun.blackdex.view.main.MainFactory
+
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/4/29 22:38
+ */
+object InjectionUtil {
+
+ private val dexDumpRepository = DexDumpRepository()
+
+
+ fun getMainFactory() : MainFactory {
+ return MainFactory(dexDumpRepository)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/util/LoadingUtil.kt b/app/src/main/java/top/niunaijun/blackdex/util/LoadingUtil.kt
new file mode 100644
index 0000000..d6d91d3
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/util/LoadingUtil.kt
@@ -0,0 +1,30 @@
+package top.niunaijun.blackdex.util
+
+import android.view.KeyEvent
+import androidx.fragment.app.FragmentManager
+import com.roger.catloadinglibrary.CatLoadingView
+import top.niunaijun.blackdex.R
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/4/30 23:04
+ */
+object LoadingUtil {
+
+ fun showLoading(loadingView: CatLoadingView, fragmentManager: FragmentManager) {
+ if (!loadingView.isAdded) {
+ loadingView.setBackgroundColor(R.color.primary)
+ loadingView.show(fragmentManager, "")
+ fragmentManager.executePendingTransactions()
+ loadingView.setClickCancelAble(false)
+ loadingView.dialog?.setOnKeyListener { _, keyCode, _ ->
+ if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
+ return@setOnKeyListener true
+ }
+ false
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/util/ToastEx.kt b/app/src/main/java/top/niunaijun/blackdex/util/ToastEx.kt
new file mode 100644
index 0000000..3931cd0
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/util/ToastEx.kt
@@ -0,0 +1,17 @@
+package top.niunaijun.blackdex.util
+
+import android.content.Context
+import android.widget.Toast
+import androidx.viewbinding.ViewBinding
+import com.google.android.material.snackbar.Snackbar
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/2 0:13
+ */
+
+fun Context.toast(msg:String){
+ Toast.makeText(this,msg,Toast.LENGTH_LONG).show()
+}
diff --git a/app/src/main/java/top/niunaijun/blackdex/util/ViewBindingEx.kt b/app/src/main/java/top/niunaijun/blackdex/util/ViewBindingEx.kt
new file mode 100644
index 0000000..ee4e835
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/util/ViewBindingEx.kt
@@ -0,0 +1,41 @@
+package top.niunaijun.blackdex.util
+
+import android.app.Activity
+import android.app.Dialog
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.viewbinding.ViewBinding
+
+/**
+ *
+ * @Description: viewBinding 扩展类
+ * @Author: wukaicheng
+ * @CreateDate: 2021/4/29 21:23
+ */
+
+inline fun Activity.inflate(): Lazy = lazy {
+ inflateBinding(layoutInflater)
+}
+
+inline fun Fragment.inflate(): Lazy = lazy {
+ inflateBinding(layoutInflater)
+}
+
+inline fun Dialog.inflate(): Lazy = lazy {
+ inflateBinding(layoutInflater)
+}
+
+
+inline fun inflateBinding(layoutInflater: LayoutInflater): T {
+ val method = T::class.java.getMethod("inflate", LayoutInflater::class.java)
+ return method.invoke(null, layoutInflater) as T
+}
+
+inline fun newBindingViewHolder(viewGroup: ViewGroup, attachToParent:Boolean = false): T {
+ val method = T::class.java.getMethod("inflate",
+ LayoutInflater::class.java,
+ ViewGroup::class.java,
+ Boolean::class.java)
+ return method.invoke(null,LayoutInflater.from(viewGroup.context),viewGroup,attachToParent) as T
+}
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/base/BaseActivity.kt b/app/src/main/java/top/niunaijun/blackdex/view/base/BaseActivity.kt
new file mode 100644
index 0000000..be3359d
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/base/BaseActivity.kt
@@ -0,0 +1,29 @@
+package top.niunaijun.blackdex.view.base
+
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.Toolbar
+
+/**
+ *
+ * @Description:BaseActivity
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/4 15:58
+ */
+open class BaseActivity : AppCompatActivity() {
+
+ protected fun initToolbar(toolbar: Toolbar,title:Int, showBack: Boolean = false, onBack: (() -> Unit)? = null) {
+ setSupportActionBar(toolbar)
+ toolbar.setTitle(title)
+ if (showBack) {
+ supportActionBar?.let {
+ it.setDisplayHomeAsUpEnabled(true)
+ toolbar.setNavigationOnClickListener {
+ if (onBack != null) {
+ onBack()
+ }
+ finish()
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/base/BaseAdapter.kt b/app/src/main/java/top/niunaijun/blackdex/view/base/BaseAdapter.kt
new file mode 100644
index 0000000..1056432
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/base/BaseAdapter.kt
@@ -0,0 +1,115 @@
+ package top.niunaijun.blackdex.view.base
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import androidx.viewbinding.ViewBinding
+
+/**
+ *
+ * @Description: 抽象adapter
+ * @Author: wukaicheng
+ * @CreateDate: 2021/4/29 21:42
+ */
+abstract class BaseAdapter : RecyclerView.Adapter>() {
+
+ var dataList: MutableList = ArrayList()
+
+ private var onItemClick: ((position: Int, binding: T, data: D) -> Unit)? = null
+
+ private var onLongClick: ((position: Int, binding: T, data: D) -> Unit)? = null
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(getViewBinding(parent))
+ }
+
+
+ override fun getItemCount(): Int {
+ return dataList.size
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val bean = dataList[position]
+ val binding = holder.bindIng
+ initView(binding, position, bean)
+
+ binding.root.setOnClickListener {
+ if (onItemClick != null) {
+ onItemClick!!(position, holder.bindIng, bean)
+ }
+ }
+ binding.root.setOnLongClickListener {
+ if (onLongClick != null) {
+ onLongClick!!(position, holder.bindIng, bean)
+ }
+ true
+ }
+ }
+
+ open fun replaceData(newDataList: List) {
+ this.dataList = arrayListOf().apply {
+ newDataList.forEach {
+ this.add(it)
+ }
+ }
+ notifyDataSetChanged()
+ }
+
+ open fun addData(list: List) {
+ val index = this.dataList.size
+ this.dataList.addAll(list)
+ notifyItemRangeInserted(index, list.size)
+ }
+
+ open fun addData(bean: D) {
+ val index = this.dataList.size
+ this.dataList.add(bean)
+ notifyItemRangeInserted(index, 1)
+ }
+
+ open fun updateData(bean: D, position: Int) {
+ if (dataList.size > position) {
+ dataList[position] = bean
+ notifyItemChanged(position)
+ }
+ }
+
+ open fun removeData(bean: D): Int {
+ val position: Int = this.dataList.indexOf(bean)
+ if (position >= 0) {
+ removeDataAt(position)
+ }
+ return position
+ }
+
+ open fun removeDataAt(position: Int) {
+ if (position >= 0) {
+ this.dataList.removeAt(position)
+ notifyItemRemoved(position)
+ notifyItemRangeChanged(position, dataList.size - position)
+ }
+ }
+
+ fun setOnItemClick(function: (position: Int, binding: T, data: D) -> Unit) {
+ this.onItemClick = function
+
+ }
+
+ fun setOnItemLongClick(function: (position: Int, binding: T, data: D) -> Unit) {
+ this.onLongClick = function
+
+ }
+
+ fun getLayoutInflater(parent: ViewGroup): LayoutInflater {
+ return LayoutInflater.from(parent.context)
+ }
+
+ abstract fun getViewBinding(parent: ViewGroup): T
+
+ abstract fun initView(binding: T, position: Int, data: D)
+
+
+ class ViewHolder(val bindIng: T) : RecyclerView.ViewHolder(bindIng.root)
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/base/BaseViewModel.kt b/app/src/main/java/top/niunaijun/blackdex/view/base/BaseViewModel.kt
new file mode 100644
index 0000000..a5b7b8b
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/base/BaseViewModel.kt
@@ -0,0 +1,34 @@
+package top.niunaijun.blackdex.view.base
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.*
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/4/29 23:33
+ */
+open class BaseViewModel : ViewModel() {
+
+ fun launchOnUI(block: suspend CoroutineScope.() -> Unit) {
+ viewModelScope.launch {
+ withContext(Dispatchers.IO) {
+ try {
+ block()
+ } catch (e: Throwable) {
+ e.printStackTrace()
+ }
+
+ }
+ }
+ }
+
+
+ override fun onCleared() {
+ super.onCleared()
+ viewModelScope.cancel()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/main/MainActivity.kt b/app/src/main/java/top/niunaijun/blackdex/view/main/MainActivity.kt
new file mode 100644
index 0000000..748bad7
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/main/MainActivity.kt
@@ -0,0 +1,211 @@
+package top.niunaijun.blackdex.view.main
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuItem
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.afollestad.materialdialogs.MaterialDialog
+import com.ferfalk.simplesearchview.SimpleSearchView
+import com.roger.catloadinglibrary.CatLoadingView
+import top.niunaijun.blackbox.BlackDexCore
+import top.niunaijun.blackbox.core.system.dump.IBDumpMonitor
+import top.niunaijun.blackbox.entity.dump.DumpResult
+import top.niunaijun.blackdex.R
+import top.niunaijun.blackdex.data.entity.AppInfo
+import top.niunaijun.blackdex.data.entity.DumpInfo
+import top.niunaijun.blackdex.databinding.ActivityMainBinding
+import top.niunaijun.blackdex.util.InjectionUtil
+import top.niunaijun.blackdex.util.LoadingUtil
+import top.niunaijun.blackdex.util.inflate
+import top.niunaijun.blackdex.view.base.BaseActivity
+
+class MainActivity : BaseActivity() {
+
+ private val viewBinding: ActivityMainBinding by inflate()
+
+ private lateinit var viewModel: MainViewModel
+
+ private lateinit var mAdapter: MainAdapter
+
+ private lateinit var loadingView: CatLoadingView
+
+ private var appList: List = ArrayList()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(viewBinding.root)
+
+ initToolbar(viewBinding.toolbarLayout.toolbar, R.string.app_name)
+
+ initView()
+
+ initViewModel()
+
+ initSearchView()
+
+ BlackDexCore.get().registerDumpMonitor(mMonitor)
+ }
+
+ private fun initView() {
+ mAdapter = MainAdapter()
+ viewBinding.recyclerView.adapter = mAdapter
+ viewBinding.recyclerView.layoutManager = LinearLayoutManager(this)
+
+ mAdapter.setOnItemClick { _, _, data ->
+ viewModel.startDexDump(data.packageName)
+ }
+
+ viewBinding.fab.setOnClickListener {
+ openDocumentedResult.launch("application/vnd.android.package-archive")
+ }
+ }
+
+ private fun initViewModel() {
+ viewModel = ViewModelProvider(this, InjectionUtil.getMainFactory()).get(MainViewModel::class.java)
+ viewModel.getAppList()
+
+ viewBinding.stateView.showLoading()
+
+ viewModel.mAppListLiveData.observe(this) {
+ it?.let {
+ this.appList = it
+ viewBinding.searchView.setQuery("", false)
+ filterApp("")
+ if (it.isNotEmpty()) {
+ viewBinding.stateView.showContent()
+ } else {
+ viewBinding.stateView.showEmpty()
+ }
+ }
+ }
+
+ viewModel.mDexDumpLiveData.observe(this) {
+ it?.let {
+ when (it.state) {
+ DumpInfo.LOADING -> {
+ showLoading()
+ }
+ DumpInfo.TIMEOUT -> {
+ loadingView.dismiss()
+ MaterialDialog(this).show {
+ title(text = "脱壳失败")
+ message(text = "未知错误,可前往GitHub(https://github.com/CodingGay/BlackDex)提Issue")
+ negativeButton(text = "Github"){
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/CodingGay/BlackDex/issues"))
+ startActivity(intent)
+ }
+ positiveButton(text = "确定")
+
+ }
+ }
+ else -> {
+ viewModel.dexDumpSuccess()
+ val title = if (it.state == DumpInfo.SUCCESS) {
+ "脱壳成功"
+ } else {
+ "脱壳失败"
+ }
+ loadingView.dismiss()
+ MaterialDialog(this).show {
+ title(text = title)
+ message(text = it.msg)
+ positiveButton(text = "确定")
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ private val mMonitor = object: IBDumpMonitor.Stub(){
+ override fun onDump(result: DumpResult?) {
+ result?.let {
+ if(result.success){
+ viewModel.mDexDumpLiveData.postValue(DumpInfo(DumpInfo.SUCCESS,"DEX文件储存在:${result.dir}"))
+ }else{
+
+ viewModel.mDexDumpLiveData.postValue(DumpInfo(DumpInfo.FAIL,"错误原因:${result.msg}"))
+ }
+ }
+ }
+
+ }
+
+
+ private fun initSearchView() {
+ viewBinding.searchView.setOnQueryTextListener(object : SimpleSearchView.OnQueryTextListener {
+ override fun onQueryTextChange(newText: String): Boolean {
+ filterApp(newText)
+ return true
+ }
+
+ override fun onQueryTextCleared(): Boolean {
+ return true
+ }
+
+ override fun onQueryTextSubmit(query: String): Boolean {
+ return true
+ }
+
+ })
+ }
+
+
+ private fun filterApp(newText: String) {
+ val newList = this.appList.filter {
+ it.name.contains(newText, true) or it.packageName.contains(newText, true)
+ }
+ mAdapter.replaceData(newList)
+ }
+
+ private fun showLoading() {
+ if (!this::loadingView.isInitialized) {
+ loadingView = CatLoadingView()
+ }
+
+ LoadingUtil.showLoading(loadingView, supportFragmentManager)
+ }
+
+
+ private val openDocumentedResult = registerForActivityResult(ActivityResultContracts.GetContent()) {
+ it?.run {
+ viewModel.startDexDump(it.toString())
+ }
+ }
+
+
+ override fun onBackPressed() {
+ if (viewBinding.searchView.isSearchOpen) {
+ viewBinding.searchView.closeSearch()
+ } else {
+ super.onBackPressed()
+ }
+ }
+
+
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.menu_main, menu)
+ val item = menu!!.findItem(R.id.main_search)
+ viewBinding.searchView.setMenuItem(item)
+
+ return true
+ }
+
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when(item.itemId){
+ R.id.main_git->{
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/CodingGay/BlackDex"))
+ startActivity(intent)
+ }
+ }
+
+ return super.onOptionsItemSelected(item)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/main/MainAdapter.kt b/app/src/main/java/top/niunaijun/blackdex/view/main/MainAdapter.kt
new file mode 100644
index 0000000..0e89517
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/main/MainAdapter.kt
@@ -0,0 +1,27 @@
+package top.niunaijun.blackdex.view.main
+
+import android.view.ViewGroup
+import top.niunaijun.blackdex.data.entity.AppInfo
+import top.niunaijun.blackdex.databinding.ItemPackageBinding
+import top.niunaijun.blackdex.util.newBindingViewHolder
+import top.niunaijun.blackdex.view.base.BaseAdapter
+
+/**
+ *
+ * @Description: 软件显示界面适配器
+ * @Author: wukaicheng
+ * @CreateDate: 2021/4/29 21:52
+ */
+
+class MainAdapter : BaseAdapter() {
+ override fun getViewBinding(parent: ViewGroup): ItemPackageBinding {
+ return newBindingViewHolder(parent, false)
+
+ }
+
+ override fun initView(binding: ItemPackageBinding, position: Int, data: AppInfo) {
+ binding.icon.setImageDrawable(data.icon)
+ binding.name.text = data.name
+ binding.packageName.text = data.packageName
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/main/MainFactory.kt b/app/src/main/java/top/niunaijun/blackdex/view/main/MainFactory.kt
new file mode 100644
index 0000000..3c43d4b
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/main/MainFactory.kt
@@ -0,0 +1,19 @@
+package top.niunaijun.blackdex.view.main
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import top.niunaijun.blackdex.data.DexDumpRepository
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:29
+ */
+@Suppress("UNCHECKED_CAST")
+class MainFactory(private val repo:DexDumpRepository): ViewModelProvider.NewInstanceFactory() {
+
+ override fun create(modelClass: Class): T {
+ return MainViewModel(repo) as T
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/niunaijun/blackdex/view/main/MainViewModel.kt b/app/src/main/java/top/niunaijun/blackdex/view/main/MainViewModel.kt
new file mode 100644
index 0000000..aca3139
--- /dev/null
+++ b/app/src/main/java/top/niunaijun/blackdex/view/main/MainViewModel.kt
@@ -0,0 +1,40 @@
+package top.niunaijun.blackdex.view.main
+
+import androidx.lifecycle.MutableLiveData
+import top.niunaijun.blackdex.data.DexDumpRepository
+import top.niunaijun.blackdex.data.entity.AppInfo
+import top.niunaijun.blackdex.data.entity.DumpInfo
+import top.niunaijun.blackdex.view.base.BaseViewModel
+
+/**
+ *
+ * @Description:
+ * @Author: wukaicheng
+ * @CreateDate: 2021/5/23 14:29
+ */
+class MainViewModel(private val repo: DexDumpRepository) : BaseViewModel() {
+
+ val mAppListLiveData = MutableLiveData>()
+
+ val mDexDumpLiveData = MutableLiveData()
+
+
+ fun getAppList() {
+ launchOnUI {
+ repo.getAppList(mAppListLiveData)
+ }
+ }
+
+ fun startDexDump(source: String) {
+ launchOnUI {
+ repo.dumpDex(source, mDexDumpLiveData)
+ }
+ }
+
+ fun dexDumpSuccess() {
+ launchOnUI {
+ repo.dumpSuccess()
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_folder.xml b/app/src/main/res/drawable-anydpi/ic_folder.xml
new file mode 100644
index 0000000..a39ab19
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_folder.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_search.xml b/app/src/main/res/drawable-anydpi/ic_search.xml
new file mode 100644
index 0000000..44dcb4a
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_search.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_folder.png b/app/src/main/res/drawable-hdpi/ic_folder.png
new file mode 100644
index 0000000000000000000000000000000000000000..82a87a74424e461d59b2f472ac99107ce87cc95b
GIT binary patch
literal 248
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB_ItWGhE&A8opzeH*+77Gx(yn(?(W2xe-@%36WgL95o16
zOp-r4gA1zol)Qa7Ik{Qe+9hW9ll!H=kKK6Lyrb@>eKHU()97N{!x;JC
Wj(+LP^9De#FnGH9xvX=kFgZIhO#YR9#k`{+UE#K1!~PU-+t%iv
z*k267O*yhZh2*SFe)fhwMW4(RU9tZel)GksFA&br8JVjuaa)sj!B{U_E#wQ{t`3Pm
zITABocUn{ciBj9ayg1R%
T_HplA00000NkvXXu0mjf#aXy(
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable-mdpi/ic_folder.png b/app/src/main/res/drawable-mdpi/ic_folder.png
new file mode 100644
index 0000000000000000000000000000000000000000..e7e2306c5ff3a4cc6a7b645575d6b7fea4903dca
GIT binary patch
literal 163
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjS)MMAAr*0Nr)=bHFyLX?9L$!o
zJcW_%gx@i}jB}k00-Rj?OJsLW)|eCY#$0&f8j+>EH-0?37!qI|WF-IcMB2vv6JEwk
z8gTtx&D{Hs!{SAMLokWf241`&rb94Z9VhyrPy9Nx
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ android:endX="85.84757"
+ android:endY="92.4963"
+ android:startX="42.9492"
+ android:startY="49.59793"
+ android:type="linear">
+ android:color="#44000000"
+ android:offset="0.0" />
+ android:color="#00000000"
+ android:offset="1.0" />
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable-xhdpi/ic_folder.png b/app/src/main/res/drawable-xhdpi/ic_folder.png
new file mode 100644
index 0000000000000000000000000000000000000000..099e909d9985565280ee8542d41faed2f45077ca
GIT binary patch
literal 318
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezr3(FtU2OIEGZjy`6DTu*pGy#q$7*
zM;P;k6a@yJ19Q&p{d9fvv;)k`PQ6|A&+rEOK8dzP8eNMR)^0W2(;oce){Cj%t*3D8
zXz>=>cJwo!pnaWp)3=IqinsRdKWpA^?;=#V?Qi3~!xPtPp5%>*xi!mK#aUhcjp(F_
zlZC5WQ&Lo`S^4gytUu5=`;DkY!Q{P6?0K8Q9~|)g#wD}kWLzV&`AzMD2WsRfa*Fx#
zvs$FHgVQ}(2<*j*ldp&@?
zTV*MTA!6R8PcuZKr+i*Yuec7q67`DfKyKUXv4tMery2ACU*hT8=!k=?dRzVrxhsa&
zT6&d`ZMpi5Mj`*IWfc(+4=a9~S&;ua4M9->@Ck??bDg%3yOpeA{EOTlG#CrbfhE7e
zCLm!%P^ne7<}Ap+ol*^Ru@G{6co9{9t9YJ|F9Oi(oWNlRfy-+LK4T2eoIVe+o&we>
zq7*G+D`*j0L5tW5fgIm
zCTfoj7*SN?taN!N<@0U5PAPS;A-DT^}BFPNt+Du3_f$L*!Z
zpSg-G?(1{Tz4=e%=#16s+w5HppS+p(cT&=kn@{}%4U=?#tI8Bi|0~3|<8&P-`<>MN
zEzIvW#UElUzp4MQVfUNq1qWikd0RZtqrb9W{Btdn-pu?v>Dx{5ll$L(3je_N)_&fi
zr~c>XmiEO?Rp$@-IBZe^8DJRbl2Ce1qBx<%+{O}tuBgd{>GnQ2Mm4&Pgg&e
IbxsLQ077@h5&!@I
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable-xxhdpi/ic_search.png b/app/src/main/res/drawable-xxhdpi/ic_search.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8a2af509b86e03ea1936c58c8a92121160dfbde
GIT binary patch
literal 810
zcmV+_1J(SAP)x2Ce}Lpn%%~pp7d43Lpg>1yBIAku89pbpF`B@qFaOo3mqQPjBWAY$8jt
zuB;HMX?FTdgx9!^`>?xZA6JQ+=)Kc#Dn_X=?w);K
z1(=xl6~U9=>e;qlYh1^D*zs7_9LEn$nA}=hVZy(7>=LjK5`Wrok`Ol5O?%E7@EiPdOz4&EyAcxQ1f#0976boE%%~=Rn2T|V
zoRs9CGuyTRag^B5iEX~l!)(%aiY+1e
z=b&94_Yp^l4Gr@gbW)Oonjf>`_n%pb4eiq6tAr#uxu|aM#n`qhl3(VtG&;@TH~8n6
z(8Ts#k^D&ly|8@^;8%$iHAZ`-Nd7c~s^C@2!{{l5hQ3q`WxM3f>~ahRk?
oR-7E6NLC!fFbu;m48z!!Kk@wrxBvhE
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index 07d5da9..6ae213e 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,170 +1,170 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/splash.xml b/app/src/main/res/drawable/splash.xml
new file mode 100644
index 0000000..3dd706a
--- /dev/null
+++ b/app/src/main/res/drawable/splash.xml
@@ -0,0 +1,14 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
\ 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
index 636b9c7..903e339 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,15 +1,55 @@
-
-
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_package.xml b/app/src/main/res/layout/item_package.xml
new file mode 100644
index 0000000..3033b5f
--- /dev/null
+++ b/app/src/main/res/layout/item_package.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_toolbar.xml b/app/src/main/res/layout/view_toolbar.xml
new file mode 100644
index 0000000..6bb72e0
--- /dev/null
+++ b/app/src/main/res/layout/view_toolbar.xml
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..d13cc84
--- /dev/null
+++ b/app/src/main/res/menu/menu_main.xml
@@ -0,0 +1,17 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 9031696..e379302 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,16 +1,18 @@
-
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127..9facc85 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,10 +1,10 @@
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
+ #3F3F3F
+ #3F3F3F
+ #3F3F3F
+ #ffffff
+ #212121
+ #757575
#FFFFFFFF
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1137f0b..b2c6e6c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,8 @@
+
BlackDex
+ 过滤
+ 选择
+ 软件日志
+ 开源地址
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index e92af38..d39d830 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,16 +1,28 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.java b/app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.java
deleted file mode 100644
index 8f7c2c9..0000000
--- a/app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package top.niunaijun.blackdex;
-
-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/app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.kt b/app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.kt
new file mode 100644
index 0000000..b6ff238
--- /dev/null
+++ b/app/src/test/java/top/niunaijun/blackdex/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package top.niunaijun.blackdex
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 23136ba..fa9fc45 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,21 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext {
+ kotlin_version = '1.5.0'
+ }
repositories {
- google()
- mavenCentral()
+ maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ jcenter { url 'https://maven.aliyun.com/repository/jcenter' }
+ jcenter { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+ maven { url 'https://dl.bintray.com/umsdk/release' }
+ maven { url 'https://jitpack.io' }
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.0"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -14,9 +24,14 @@ buildscript {
allprojects {
repositories {
- google()
- mavenCentral()
- jcenter() // Warning: this repository is going to shut down soon
+ maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ jcenter { url 'https://maven.aliyun.com/repository/jcenter' }
+ jcenter { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+ maven { url 'https://dl.bintray.com/umsdk/release' }
+ maven { url 'https://jitpack.io' }
}
}
diff --git a/settings.gradle b/settings.gradle
index 40dbe7b..11ae613 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,5 +1,5 @@
rootProject.name = "BlackDex"
-include ':app'
include ':Bcore:black-hook'
include ':Bcore:black-fake'
include ':Bcore'
+include ':app'