mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-25 17:17:23 +00:00
Copy APK from external storage in stub
Much faster and easier development
This commit is contained in:
parent
b76a3614da
commit
de3747d65e
@ -11,7 +11,7 @@ paranoid {
|
|||||||
android {
|
android {
|
||||||
val canary = !Config.version.contains(".")
|
val canary = !Config.version.contains(".")
|
||||||
|
|
||||||
val url = Config["DEV_CHANNEL"] ?: if (canary) null
|
val url = if (canary) null
|
||||||
else "https://cdn.jsdelivr.net/gh/topjohnwu/magisk-files@${Config.version}/app-release.apk"
|
else "https://cdn.jsdelivr.net/gh/topjohnwu/magisk-files@${Config.version}/app-release.apk"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
@ -12,17 +12,12 @@ import io.michaelrocks.paranoid.Obfuscate;
|
|||||||
@Obfuscate
|
@Obfuscate
|
||||||
public class DelegateApplication extends Application {
|
public class DelegateApplication extends Application {
|
||||||
|
|
||||||
static boolean dynLoad = false;
|
|
||||||
|
|
||||||
private Application receiver;
|
private Application receiver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void attachBaseContext(Context base) {
|
protected void attachBaseContext(Context base) {
|
||||||
super.attachBaseContext(base);
|
super.attachBaseContext(base);
|
||||||
|
|
||||||
// Only dynamic load full APK if hidden
|
|
||||||
dynLoad = !base.getPackageName().equals(BuildConfig.APPLICATION_ID);
|
|
||||||
|
|
||||||
receiver = InjectAPK.setup(this);
|
receiver = InjectAPK.setup(this);
|
||||||
if (receiver != null) try {
|
if (receiver != null) try {
|
||||||
// Call attachBaseContext without ContextImpl to show it is being wrapped
|
// Call attachBaseContext without ContextImpl to show it is being wrapped
|
||||||
|
@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
|
|||||||
import static android.R.string.no;
|
import static android.R.string.no;
|
||||||
import static android.R.string.ok;
|
import static android.R.string.ok;
|
||||||
import static android.R.string.yes;
|
import static android.R.string.yes;
|
||||||
import static com.topjohnwu.magisk.DelegateApplication.dynLoad;
|
|
||||||
import static com.topjohnwu.magisk.R2.string.dling;
|
import static com.topjohnwu.magisk.R2.string.dling;
|
||||||
import static com.topjohnwu.magisk.R2.string.no_internet_msg;
|
import static com.topjohnwu.magisk.R2.string.no_internet_msg;
|
||||||
import static com.topjohnwu.magisk.R2.string.relaunch_app;
|
import static com.topjohnwu.magisk.R2.string.relaunch_app;
|
||||||
@ -49,12 +48,16 @@ public class DownloadActivity extends Activity {
|
|||||||
private String apkLink = BuildConfig.APK_URL;
|
private String apkLink = BuildConfig.APK_URL;
|
||||||
private Context themed;
|
private Context themed;
|
||||||
private ProgressDialog dialog;
|
private ProgressDialog dialog;
|
||||||
|
private boolean dynLoad;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
themed = new ContextThemeWrapper(this, android.R.style.Theme_DeviceDefault);
|
themed = new ContextThemeWrapper(this, android.R.style.Theme_DeviceDefault);
|
||||||
|
|
||||||
|
// Only download and dynamic load full APK if hidden
|
||||||
|
dynLoad = getPackageName().equals(BuildConfig.APPLICATION_ID);
|
||||||
|
|
||||||
// Inject resources
|
// Inject resources
|
||||||
loadResources();
|
loadResources();
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ import android.os.Build;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -29,6 +31,17 @@ public class InjectAPK {
|
|||||||
return (DelegateComponentFactory) componentFactory;
|
return (DelegateComponentFactory) componentFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void copy(InputStream src, OutputStream dest) throws IOException {
|
||||||
|
try (InputStream s = src) {
|
||||||
|
try (OutputStream o = dest) {
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
for (int read; (read = s.read(buf)) >= 0;) {
|
||||||
|
o.write(buf, 0, read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
static Application setup(Context context) {
|
static Application setup(Context context) {
|
||||||
// Get ContextImpl
|
// Get ContextImpl
|
||||||
@ -38,25 +51,44 @@ public class InjectAPK {
|
|||||||
|
|
||||||
File apk = DynAPK.current(context);
|
File apk = DynAPK.current(context);
|
||||||
File update = DynAPK.update(context);
|
File update = DynAPK.update(context);
|
||||||
if (update.exists())
|
|
||||||
|
if (update.exists()) {
|
||||||
|
// Rename from update
|
||||||
update.renameTo(apk);
|
update.renameTo(apk);
|
||||||
if (!apk.exists()) {
|
}
|
||||||
// Try copying APK
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
// Copy from external for easier development
|
||||||
|
File external = new File(context.getExternalFilesDir(null), "magisk.apk");
|
||||||
|
if (external.exists()) {
|
||||||
|
try {
|
||||||
|
copy(new FileInputStream(external), new FileOutputStream(apk));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(InjectAPK.class.getSimpleName(), "", e);
|
||||||
|
apk.delete();
|
||||||
|
} finally {
|
||||||
|
external.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!apk.exists() && !context.getPackageName().equals(BuildConfig.APPLICATION_ID)) {
|
||||||
|
// Copy from previous app
|
||||||
Uri uri = new Uri.Builder().scheme("content")
|
Uri uri = new Uri.Builder().scheme("content")
|
||||||
.authority("com.topjohnwu.magisk.provider")
|
.authority("com.topjohnwu.magisk.provider")
|
||||||
.encodedPath("apk_file").build();
|
.encodedPath("apk_file").build();
|
||||||
ContentResolver resolver = context.getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
try (InputStream src = resolver.openInputStream(uri)) {
|
try {
|
||||||
|
InputStream src = resolver.openInputStream(uri);
|
||||||
if (src != null) {
|
if (src != null) {
|
||||||
try (OutputStream out = new FileOutputStream(apk)) {
|
copy(src, new FileOutputStream(apk));
|
||||||
byte[] buf = new byte[4096];
|
|
||||||
for (int read; (read = src.read(buf)) >= 0;) {
|
|
||||||
out.write(buf, 0, read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {}
|
} catch (IOException e) {
|
||||||
|
Log.e(InjectAPK.class.getSimpleName(), "", e);
|
||||||
|
apk.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apk.exists()) {
|
if (apk.exists()) {
|
||||||
ClassLoader cl = new InjectedClassLoader(apk);
|
ClassLoader cl = new InjectedClassLoader(apk);
|
||||||
PackageManager pm = context.getPackageManager();
|
PackageManager pm = context.getPackageManager();
|
||||||
@ -124,5 +156,4 @@ public class InjectAPK {
|
|||||||
data.classToComponent = Mapping.inverseMap;
|
data.classToComponent = Mapping.inverseMap;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user