Introduce DynamicClassLoader
This commit is contained in:
parent
41134466ed
commit
010e4de4e1
@ -9,10 +9,10 @@ import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore
|
|||||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade
|
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.ui.SplashActivity
|
import com.topjohnwu.magisk.ui.SplashActivity
|
||||||
|
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||||
import com.topjohnwu.magisk.utils.PatchAPK
|
import com.topjohnwu.magisk.utils.PatchAPK
|
||||||
import com.topjohnwu.magisk.utils.RootUtils
|
import com.topjohnwu.magisk.utils.RootUtils
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import dalvik.system.DexClassLoader
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ private fun RemoteFileService.patchPackage(apk: File, id: Int): File {
|
|||||||
val patched = File(apk.parent, "patched.apk")
|
val patched = File(apk.parent, "patched.apk")
|
||||||
try {
|
try {
|
||||||
// Try using the new APK to patch itself
|
// Try using the new APK to patch itself
|
||||||
val loader = DexClassLoader(apk.path, apk.parent, null, ClassLoader.getSystemClassLoader())
|
val loader = DynamicClassLoader(apk)
|
||||||
loader.loadClass("a.a")
|
loader.loadClass("a.a")
|
||||||
.getMethod("patchAPK", String::class.java, String::class.java, String::class.java)
|
.getMethod("patchAPK", String::class.java, String::class.java, String::class.java)
|
||||||
.invoke(null, apk.path, patched.path, packageName)
|
.invoke(null, apk.path, patched.path, packageName)
|
||||||
|
@ -18,10 +18,10 @@ import com.topjohnwu.magisk.model.events.*
|
|||||||
import com.topjohnwu.magisk.ui.base.MagiskActivity
|
import com.topjohnwu.magisk.ui.base.MagiskActivity
|
||||||
import com.topjohnwu.magisk.ui.base.MagiskFragment
|
import com.topjohnwu.magisk.ui.base.MagiskFragment
|
||||||
import com.topjohnwu.magisk.utils.ISafetyNetHelper
|
import com.topjohnwu.magisk.utils.ISafetyNetHelper
|
||||||
|
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||||
import com.topjohnwu.magisk.view.dialogs.*
|
import com.topjohnwu.magisk.view.dialogs.*
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import dalvik.system.DexClassLoader
|
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@ -97,8 +97,7 @@ class HomeFragment : MagiskFragment<HomeViewModel, FragmentMagiskBinding>(),
|
|||||||
|
|
||||||
private fun updateSafetyNet(dieOnError: Boolean) {
|
private fun updateSafetyNet(dieOnError: Boolean) {
|
||||||
try {
|
try {
|
||||||
val loader = DexClassLoader(EXT_APK.path, EXT_APK.parent, null,
|
val loader = DynamicClassLoader(EXT_APK)
|
||||||
ISafetyNetHelper::class.java.classLoader)
|
|
||||||
val clazz = loader.loadClass("com.topjohnwu.snet.Snet")
|
val clazz = loader.loadClass("com.topjohnwu.snet.Snet")
|
||||||
val helper = clazz.getMethod("newHelper",
|
val helper = clazz.getMethod("newHelper",
|
||||||
Class::class.java, String::class.java, Activity::class.java, Any::class.java)
|
Class::class.java, String::class.java, Activity::class.java, Any::class.java)
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import dalvik.system.DexClassLoader
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
inline fun <reified T> T.DynamicClassLoader(apk: File) = DynamicClassLoader(apk, T::class.java.classLoader)
|
||||||
|
|
||||||
|
class DynamicClassLoader(apk: File, parent: ClassLoader?)
|
||||||
|
: DexClassLoader(apk.path, apk.parent, null, parent) {
|
||||||
|
|
||||||
|
private val base by lazy { Any::class.java.classLoader!! }
|
||||||
|
|
||||||
|
@Throws(ClassNotFoundException::class)
|
||||||
|
override fun loadClass(name: String, resolve: Boolean) : Class<*>
|
||||||
|
= findLoadedClass(name) ?: runCatching {
|
||||||
|
base.loadClass(name)
|
||||||
|
}.getOrElse {
|
||||||
|
runCatching {
|
||||||
|
findClass(name)
|
||||||
|
}.getOrElse { err ->
|
||||||
|
runCatching {
|
||||||
|
parent.loadClass(name)
|
||||||
|
}.getOrElse { throw err }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getResource(name: String) = base.getResource(name)
|
||||||
|
?: findResource(name)
|
||||||
|
?: parent?.getResource(name)
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun getResources(name: String): Enumeration<URL> {
|
||||||
|
val resources = mutableListOf(
|
||||||
|
base.getResources(name),
|
||||||
|
findResources(name), parent.getResources(name))
|
||||||
|
return object : Enumeration<URL> {
|
||||||
|
override fun hasMoreElements(): Boolean {
|
||||||
|
while (true) {
|
||||||
|
if (resources.isEmpty())
|
||||||
|
return false
|
||||||
|
if (!resources[0].hasMoreElements()) {
|
||||||
|
resources.removeAt(0)
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun nextElement(): URL {
|
||||||
|
if (!hasMoreElements())
|
||||||
|
throw NoSuchElementException()
|
||||||
|
return resources[0].nextElement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user