Rewrite FlashZip in Kotlin
This commit is contained in:
parent
8b7144c986
commit
a0cfce7cbc
@ -1,85 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.tasks;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.App;
|
|
||||||
import com.topjohnwu.magisk.Const;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
import com.topjohnwu.magisk.utils.ZipUtilsKt;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class FlashZip {
|
|
||||||
|
|
||||||
private Uri mUri;
|
|
||||||
private File tmpFile;
|
|
||||||
private List<String> console, logs;
|
|
||||||
|
|
||||||
public FlashZip(Uri uri, List<String> out, List<String> err) {
|
|
||||||
mUri = uri;
|
|
||||||
console = out;
|
|
||||||
logs = err;
|
|
||||||
tmpFile = new File(App.self.getCacheDir(), "install.zip");
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean unzipAndCheck() throws IOException {
|
|
||||||
ZipUtilsKt.unzip(tmpFile, tmpFile.getParentFile(), "META-INF/com/google/android", true);
|
|
||||||
return Shell.su("grep -q '#MAGISK' " + new File(tmpFile.getParentFile(), "updater-script"))
|
|
||||||
.exec().isSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean flash() throws IOException {
|
|
||||||
console.add("- Copying zip to temp directory");
|
|
||||||
try (InputStream in = App.self.getContentResolver().openInputStream(mUri);
|
|
||||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(tmpFile))) {
|
|
||||||
if (in == null) throw new FileNotFoundException();
|
|
||||||
InputStream buf= new BufferedInputStream(in);
|
|
||||||
ShellUtils.pump(buf, out);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
console.add("! Invalid Uri");
|
|
||||||
throw e;
|
|
||||||
} catch (IOException e) {
|
|
||||||
console.add("! Cannot copy to cache");
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (!unzipAndCheck()) {
|
|
||||||
console.add("! This zip is not a Magisk Module!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
console.add("! Unzip error");
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
console.add("- Installing " + Utils.getNameFromUri(App.self, mUri));
|
|
||||||
return Shell.su("cd " + tmpFile.getParent(),
|
|
||||||
"BOOTMODE=true sh update-binary dummy 1 " + tmpFile)
|
|
||||||
.to(console, logs)
|
|
||||||
.exec().isSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exec() {
|
|
||||||
App.THREAD_POOL.execute(() -> {
|
|
||||||
boolean success = false;
|
|
||||||
try {
|
|
||||||
success = flash();
|
|
||||||
} catch (IOException ignored) {}
|
|
||||||
Shell.su("cd /", "rm -rf " + tmpFile.getParent() + " " + Const.TMP_FOLDER_PATH).submit();
|
|
||||||
boolean finalSuccess = success;
|
|
||||||
UiThreadHandler.run(() -> onResult(finalSuccess));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void onResult(boolean success);
|
|
||||||
}
|
|
73
app/src/main/java/com/topjohnwu/magisk/tasks/FlashZip.kt
Normal file
73
app/src/main/java/com/topjohnwu/magisk/tasks/FlashZip.kt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package com.topjohnwu.magisk.tasks
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.App
|
||||||
|
import com.topjohnwu.magisk.Const
|
||||||
|
import com.topjohnwu.magisk.utils.*
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
abstract class FlashZip(private val mUri: Uri,
|
||||||
|
private val console: MutableList<String>,
|
||||||
|
private val logs: MutableList<String>) {
|
||||||
|
|
||||||
|
private val tmpFile: File = File(App.self.cacheDir, "install.zip")
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun unzipAndCheck(): Boolean {
|
||||||
|
unzip(tmpFile, tmpFile.parentFile!!, "META-INF/com/google/android", true)
|
||||||
|
return Shell.su("grep -q '#MAGISK' ${File(tmpFile.parentFile, "updater-script")}")
|
||||||
|
.exec().isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun flash(): Boolean {
|
||||||
|
console.add("- Copying zip to temp directory")
|
||||||
|
try {
|
||||||
|
App.self.readUri(mUri).use { input ->
|
||||||
|
tmpFile.outputStream().use { out -> input.copyTo(out) }
|
||||||
|
}
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
console.add("! Invalid Uri")
|
||||||
|
throw e
|
||||||
|
} catch (e: IOException) {
|
||||||
|
console.add("! Cannot copy to cache")
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!unzipAndCheck()) {
|
||||||
|
console.add("! This zip is not a Magisk Module!")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
console.add("! Unzip error")
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
console.add("- Installing ${mUri.fileName}")
|
||||||
|
return Shell.su("cd " + tmpFile.parent!!,
|
||||||
|
"BOOTMODE=true sh update-binary dummy 1 $tmpFile")
|
||||||
|
.to(console, logs)
|
||||||
|
.exec().isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exec() {
|
||||||
|
App.THREAD_POOL.execute {
|
||||||
|
val success = try {
|
||||||
|
flash()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Shell.su("cd /", "rm -rf ${tmpFile.parent} ${Const.TMP_FOLDER_PATH}").submit()
|
||||||
|
UiThreadHandler.run { onResult(success) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun onResult(success: Boolean)
|
||||||
|
}
|
@ -58,24 +58,6 @@ public class Utils {
|
|||||||
return getPrefsInt(prefs, key, 0);
|
return getPrefsInt(prefs, key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNameFromUri(Context context, Uri uri) {
|
|
||||||
String name = null;
|
|
||||||
try (Cursor c = context.getContentResolver().query(uri, null, null, null, null)) {
|
|
||||||
if (c != null) {
|
|
||||||
int nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
||||||
if (nameIndex != -1) {
|
|
||||||
c.moveToFirst();
|
|
||||||
name = c.getString(nameIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name == null) {
|
|
||||||
int idx = uri.getPath().lastIndexOf('/');
|
|
||||||
name = uri.getPath().substring(idx + 1);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int dpInPx(int dp) {
|
public static int dpInPx(int dp) {
|
||||||
float scale = App.self.getResources().getDisplayMetrics().density;
|
float scale = App.self.getResources().getDisplayMetrics().density;
|
||||||
return (int) (dp * scale + 0.5);
|
return (int) (dp * scale + 0.5);
|
||||||
|
@ -6,6 +6,10 @@ import android.content.pm.ComponentInfo
|
|||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.PackageManager.*
|
import android.content.pm.PackageManager.*
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.OpenableColumns
|
||||||
|
import com.topjohnwu.magisk.App
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
|
||||||
val PackageInfo.processes
|
val PackageInfo.processes
|
||||||
get() = activities?.processNames.orEmpty() +
|
get() = activities?.processNames.orEmpty() +
|
||||||
@ -38,6 +42,22 @@ val ApplicationInfo.packageInfo: PackageInfo?
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Uri.fileName: String get() {
|
||||||
|
var name: String? = null
|
||||||
|
App.self.contentResolver.query(this, null, null, null, null)?.use { c ->
|
||||||
|
val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||||
|
if (nameIndex != -1) {
|
||||||
|
c.moveToFirst()
|
||||||
|
name = c.getString(nameIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name == null && path != null) {
|
||||||
|
val idx = path!!.lastIndexOf('/')
|
||||||
|
name = path!!.substring(idx + 1)
|
||||||
|
}
|
||||||
|
return name.orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
fun PackageManager.activities(packageName: String) =
|
fun PackageManager.activities(packageName: String) =
|
||||||
getPackageInfo(packageName, GET_ACTIVITIES)
|
getPackageInfo(packageName, GET_ACTIVITIES)
|
||||||
|
|
||||||
@ -51,3 +71,6 @@ fun PackageManager.providers(packageName: String) =
|
|||||||
getPackageInfo(packageName, GET_PROVIDERS).providers
|
getPackageInfo(packageName, GET_PROVIDERS).providers
|
||||||
|
|
||||||
fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
||||||
|
|
||||||
|
fun Context.readUri(uri: Uri) = contentResolver.openInputStream(uri) ?: throw FileNotFoundException()
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import java.util.zip.ZipEntry
|
|||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
@JvmOverloads
|
|
||||||
fun unzip(zip: File, folder: File, path: String = "", junkPath: Boolean = false) {
|
fun unzip(zip: File, folder: File, path: String = "", junkPath: Boolean = false) {
|
||||||
zip.inputStream().buffered().use {
|
zip.inputStream().buffered().use {
|
||||||
unzip(it, folder, path, junkPath)
|
unzip(it, folder, path, junkPath)
|
||||||
|
@ -5,11 +5,11 @@ import android.net.Uri;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.XAndroidKt;
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
|
|
||||||
public class SnackbarMaker {
|
public class SnackbarMaker {
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ public class SnackbarMaker {
|
|||||||
|
|
||||||
public static void showUri(Activity activity, Uri uri) {
|
public static void showUri(Activity activity, Uri uri) {
|
||||||
make(activity, activity.getString(R.string.internal_storage,
|
make(activity, activity.getString(R.string.internal_storage,
|
||||||
"/Download/" + Utils.getNameFromUri(activity, uri)),
|
"/Download/" + XAndroidKt.getFileName(uri)),
|
||||||
Snackbar.LENGTH_LONG)
|
Snackbar.LENGTH_LONG)
|
||||||
.setAction(R.string.ok, (v)->{}).show();
|
.setAction(R.string.ok, (v)->{}).show();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user