parent
0fdd3b6fbd
commit
87217696dd
@ -1,26 +0,0 @@ |
|||||||
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() |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,38 @@ |
|||||||
|
package top.niunaijun.blackboxa.app |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import android.app.Application |
||||||
|
import android.content.Context |
||||||
|
import top.niunaijun.blackdex.app.AppManager |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @Description: |
||||||
|
* @Author: wukaicheng |
||||||
|
* @CreateDate: 2021/4/29 21:21 |
||||||
|
*/ |
||||||
|
class App : Application() { |
||||||
|
|
||||||
|
companion object { |
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak") |
||||||
|
@Volatile |
||||||
|
private lateinit var mContext: Context |
||||||
|
|
||||||
|
@JvmStatic |
||||||
|
fun getContext(): Context { |
||||||
|
return mContext |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun attachBaseContext(base: Context?) { |
||||||
|
super.attachBaseContext(base) |
||||||
|
mContext = base!! |
||||||
|
AppManager.doAttachBaseContext(base) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreate() { |
||||||
|
super.onCreate() |
||||||
|
AppManager.doOnCreate(mContext) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package top.niunaijun.blackdex.app |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
|
||||||
|
object AppManager { |
||||||
|
@JvmStatic |
||||||
|
val mBlackBoxLoader by lazy { |
||||||
|
BlackDexLoader() |
||||||
|
} |
||||||
|
|
||||||
|
fun doAttachBaseContext(context: Context) { |
||||||
|
try { |
||||||
|
mBlackBoxLoader.attachBaseContext(context) |
||||||
|
mBlackBoxLoader.addLifecycleCallback() |
||||||
|
} catch (e: Exception) { |
||||||
|
e.printStackTrace() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun doOnCreate(context: Context) { |
||||||
|
mBlackBoxLoader.doOnCreate(context) |
||||||
|
initThirdService(context) |
||||||
|
} |
||||||
|
|
||||||
|
private fun initThirdService(context: Context) {} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
package top.niunaijun.blackdex.app |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import top.niunaijun.blackbox.BlackDexCore |
||||||
|
import top.niunaijun.blackbox.app.configuration.ClientConfiguration |
||||||
|
import top.niunaijun.blackbox.utils.FileUtils |
||||||
|
import top.niunaijun.blackbox.utils.compat.BuildCompat |
||||||
|
import top.niunaijun.blackboxa.app.App |
||||||
|
import top.niunaijun.blackdex.biz.cache.AppSharedPreferenceDelegate |
||||||
|
import java.io.File |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @Description: |
||||||
|
* @Author: wukaicheng |
||||||
|
* @CreateDate: 2021/5/6 23:38 |
||||||
|
*/ |
||||||
|
class BlackDexLoader { |
||||||
|
|
||||||
|
|
||||||
|
private var mSavePath by AppSharedPreferenceDelegate(App.getContext(), "") |
||||||
|
|
||||||
|
private var mSaveEnable by AppSharedPreferenceDelegate(App.getContext(), false) |
||||||
|
|
||||||
|
private var mDir = if (mSaveEnable) { |
||||||
|
getDexDumpDir(App.getContext()) |
||||||
|
} else { |
||||||
|
mSavePath |
||||||
|
} |
||||||
|
|
||||||
|
fun addLifecycleCallback() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
fun attachBaseContext(context: Context) { |
||||||
|
BlackDexCore.get().doAttachBaseContext(context, object : ClientConfiguration() { |
||||||
|
override fun getHostPackageName(): String { |
||||||
|
return context.packageName |
||||||
|
} |
||||||
|
|
||||||
|
override fun getDexDumpDir(): String { |
||||||
|
return mDir |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
fun doOnCreate(context: Context) { |
||||||
|
BlackDexCore.get().doCreate() |
||||||
|
} |
||||||
|
|
||||||
|
fun saveEnable(): Boolean { |
||||||
|
return mSaveEnable |
||||||
|
} |
||||||
|
|
||||||
|
fun saveEnable(state: Boolean) { |
||||||
|
this.mSaveEnable = state |
||||||
|
} |
||||||
|
|
||||||
|
fun getSavePath(): String { |
||||||
|
return mSavePath |
||||||
|
} |
||||||
|
|
||||||
|
fun setSavePath(path: String) { |
||||||
|
this.mSavePath = path |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
companion object { |
||||||
|
|
||||||
|
val TAG: String = BlackDexLoader::class.java.simpleName |
||||||
|
|
||||||
|
fun getDexDumpDir(context: Context): String { |
||||||
|
return if (BuildCompat.isR()) { |
||||||
|
val dump = File( |
||||||
|
context.externalCacheDir?.parentFile?.parentFile?.parentFile?.parentFile, |
||||||
|
"hupu/dexDump" |
||||||
|
) |
||||||
|
FileUtils.mkdirs(dump) |
||||||
|
dump.absolutePath |
||||||
|
} else { |
||||||
|
val dump = File(context.externalCacheDir?.parentFile, "dump") |
||||||
|
FileUtils.mkdirs(dump) |
||||||
|
dump.absolutePath |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
package top.niunaijun.blackdex.biz.cache |
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import android.text.TextUtils |
||||||
|
import androidx.core.content.edit |
||||||
|
import kotlin.properties.ReadWriteProperty |
||||||
|
import kotlin.reflect.KProperty |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @desc:目前只支持 5种基本数据类型,如果要支持obj,请继承该类并重写他的相关方法 findData/putData |
||||||
|
* |
||||||
|
* @author: mini |
||||||
|
* @created by 2021/5/10 |
||||||
|
*/ |
||||||
|
open class AppSharedPreferenceDelegate<Data>(context: Context, private val default: Data, spName: String? = null) : ReadWriteProperty<Any, Data?> { |
||||||
|
|
||||||
|
private val mSharedPreferences by lazy { |
||||||
|
val tmpCacheName = if (TextUtils.isEmpty(spName)) { |
||||||
|
AppSharedPreferenceDelegate::class.java.simpleName |
||||||
|
} else { |
||||||
|
spName |
||||||
|
} |
||||||
|
return@lazy context.getSharedPreferences(tmpCacheName, Context.MODE_PRIVATE) |
||||||
|
} |
||||||
|
|
||||||
|
override fun getValue(thisRef: Any, property: KProperty<*>): Data { |
||||||
|
return findData(property.name, default) |
||||||
|
} |
||||||
|
|
||||||
|
override fun setValue(thisRef: Any, property: KProperty<*>, value: Data?) { |
||||||
|
putData(property.name, value) |
||||||
|
} |
||||||
|
|
||||||
|
protected fun findData(key: String, default: Data): Data { |
||||||
|
with(mSharedPreferences) { |
||||||
|
val result: Any? = when (default) { |
||||||
|
is Int -> getInt(key, default) |
||||||
|
is Long -> getLong(key, default) |
||||||
|
is Float -> getFloat(key, default) |
||||||
|
is String -> getString(key, default) |
||||||
|
is Boolean -> getBoolean(key, default) |
||||||
|
else -> throw IllegalArgumentException("This type $default can not be saved into sharedPreferences") |
||||||
|
} |
||||||
|
return result as? Data ?: default |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected fun putData(key: String, value: Data?) { |
||||||
|
mSharedPreferences.edit { |
||||||
|
if (value == null) { |
||||||
|
remove(key) |
||||||
|
} else { |
||||||
|
when (value) { |
||||||
|
is Int -> putInt(key, value) |
||||||
|
is Long -> putLong(key, value) |
||||||
|
is Float -> putFloat(key, value) |
||||||
|
is String -> putString(key, value) |
||||||
|
is Boolean -> putBoolean(key, value) |
||||||
|
else -> throw IllegalArgumentException("This type $default can not be saved into Preferences") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,41 +0,0 @@ |
|||||||
package top.niunaijun.blackdex.data |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import top.niunaijun.blackbox.app.configuration.ClientConfiguration |
|
||||||
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:04 |
|
||||||
*/ |
|
||||||
class BlackDexConfiguration(private val context: Context) : ClientConfiguration() { |
|
||||||
|
|
||||||
companion object { |
|
||||||
fun getDexDumpDir(context: Context): String { |
|
||||||
return if (BuildCompat.isR()) { |
|
||||||
val dump = File(context.externalCacheDir?.parentFile?.parentFile?.parentFile?.parentFile, "Download/dexDump") |
|
||||||
FileUtils.mkdirs(dump) |
|
||||||
dump.absolutePath |
|
||||||
} else { |
|
||||||
val dump = File(context.externalCacheDir?.parentFile, "dump") |
|
||||||
FileUtils.mkdirs(dump) |
|
||||||
dump.absolutePath |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private val dir = getDexDumpDir(context) |
|
||||||
|
|
||||||
override fun getHostPackageName(): String { |
|
||||||
return context.packageName |
|
||||||
} |
|
||||||
|
|
||||||
override fun getDexDumpDir(): String { |
|
||||||
return dir |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,19 @@ |
|||||||
|
package top.niunaijun.blackdex.view.setting |
||||||
|
|
||||||
|
import android.os.Bundle |
||||||
|
import top.niunaijun.blackdex.R |
||||||
|
import top.niunaijun.blackdex.databinding.ActivitySettingBinding |
||||||
|
import top.niunaijun.blackdex.util.inflate |
||||||
|
import top.niunaijun.blackdex.view.base.BaseActivity |
||||||
|
|
||||||
|
class SettingActivity : BaseActivity() { |
||||||
|
|
||||||
|
private val viewBinding: ActivitySettingBinding by inflate() |
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) { |
||||||
|
super.onCreate(savedInstanceState) |
||||||
|
setContentView(viewBinding.root) |
||||||
|
initToolbar(viewBinding.toolbarLayout.toolbar, R.string.app_setting,true) |
||||||
|
supportFragmentManager.beginTransaction().replace(R.id.fragment,SettingFragment()).commit() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
package top.niunaijun.blackdex.view.setting |
||||||
|
|
||||||
|
import android.os.Bundle |
||||||
|
import android.os.Environment |
||||||
|
import androidx.preference.Preference |
||||||
|
import androidx.preference.PreferenceFragmentCompat |
||||||
|
import androidx.preference.SwitchPreferenceCompat |
||||||
|
import com.afollestad.materialdialogs.MaterialDialog |
||||||
|
import com.afollestad.materialdialogs.files.folderChooser |
||||||
|
import top.niunaijun.blackdex.R |
||||||
|
import top.niunaijun.blackdex.app.AppManager |
||||||
|
import java.io.File |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @Description: |
||||||
|
* @Author: wukaicheng |
||||||
|
* @CreateDate: 2021/5/28 19:55 |
||||||
|
*/ |
||||||
|
class SettingFragment : PreferenceFragmentCompat() { |
||||||
|
|
||||||
|
private lateinit var savePathPreference: Preference |
||||||
|
|
||||||
|
private lateinit var saveEnablePreference: SwitchPreferenceCompat |
||||||
|
|
||||||
|
private val initialDirectory = AppManager.mBlackBoxLoader.getSavePath() |
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { |
||||||
|
addPreferencesFromResource(R.xml.setting) |
||||||
|
savePathPreference = findPreference("save_path")!! |
||||||
|
savePathPreference.onPreferenceClickListener = mSavedPathClick |
||||||
|
savePathPreference.summary = initialDirectory |
||||||
|
|
||||||
|
saveEnablePreference = findPreference("save_enable")!! |
||||||
|
saveEnablePreference.onPreferenceChangeListener = mSaveEnableChange |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private val mSavedPathClick = Preference.OnPreferenceClickListener { |
||||||
|
val initialFile = with(initialDirectory) { |
||||||
|
if (initialDirectory.isEmpty()) { |
||||||
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) |
||||||
|
} else { |
||||||
|
File(this) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
MaterialDialog(requireContext()).show { |
||||||
|
folderChooser(requireContext(), initialDirectory = initialFile,allowFolderCreation = true) { _, file -> |
||||||
|
AppManager.mBlackBoxLoader.setSavePath(file.absolutePath) |
||||||
|
savePathPreference.summary = file.absolutePath |
||||||
|
} |
||||||
|
} |
||||||
|
return@OnPreferenceClickListener true |
||||||
|
} |
||||||
|
|
||||||
|
private val mSaveEnableChange = Preference.OnPreferenceChangeListener { _, newValue -> |
||||||
|
AppManager.mBlackBoxLoader.saveEnable(newValue as Boolean) |
||||||
|
return@OnPreferenceChangeListener true |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:orientation="vertical" |
||||||
|
tools:context=".view.setting.SettingActivity"> |
||||||
|
|
||||||
|
<include |
||||||
|
android:id="@+id/toolbar_layout" |
||||||
|
layout="@layout/view_toolbar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
app:layout_constraintTop_toTopOf="parent" /> |
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView |
||||||
|
android:id="@+id/fragment" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" /> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,15 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
|
||||||
|
<PreferenceCategory android:title="文件储存"> |
||||||
|
<SwitchPreferenceCompat |
||||||
|
android:disableDependentsState="true" |
||||||
|
android:key="save_enable" |
||||||
|
android:title="使用默认储存路径" /> |
||||||
|
|
||||||
|
<Preference |
||||||
|
android:dependency="save_enable" |
||||||
|
android:key="save_path" |
||||||
|
android:title="自定义储存路径" /> |
||||||
|
</PreferenceCategory> |
||||||
|
</PreferenceScreen> |
Loading…
Reference in new issue