add user custom select lkm file button on install screen top bar (#1491)
This commit is contained in:
@@ -140,7 +140,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
sealed class FlashIt : Parcelable {
|
sealed class FlashIt : Parcelable {
|
||||||
data class FlashBoot(val bootUri: Uri? = null, val ota: Boolean) : FlashIt()
|
data class FlashBoot(val bootUri: Uri? = null, val lkmUri: Uri? = null, val ota: Boolean) : FlashIt()
|
||||||
|
|
||||||
data class FlashModule(val uri: Uri) : FlashIt()
|
data class FlashModule(val uri: Uri) : FlashIt()
|
||||||
}
|
}
|
||||||
@@ -153,6 +153,7 @@ fun flashIt(
|
|||||||
when (flashIt) {
|
when (flashIt) {
|
||||||
is FlashIt.FlashBoot -> installBoot(
|
is FlashIt.FlashBoot -> installBoot(
|
||||||
flashIt.bootUri,
|
flashIt.bootUri,
|
||||||
|
flashIt.lkmUri,
|
||||||
flashIt.ota,
|
flashIt.ota,
|
||||||
onFinish,
|
onFinish,
|
||||||
onStdout,
|
onStdout,
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package me.weishu.kernelsu.ui.screen
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
|
import android.webkit.DownloadListener
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
@@ -14,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.FileUpload
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -35,8 +38,11 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.core.net.toFile
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
@@ -61,20 +67,41 @@ fun InstallScreen(navigator: DestinationsNavigator) {
|
|||||||
mutableStateOf<InstallMethod?>(null)
|
mutableStateOf<InstallMethod?>(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lkmFileUri = null as Uri?
|
||||||
|
|
||||||
val onClickInstall = {
|
val onClickInstall = {
|
||||||
installMethod?.let { method ->
|
installMethod?.let { method ->
|
||||||
val flashIt = FlashIt.FlashBoot(
|
val flashIt = FlashIt.FlashBoot(
|
||||||
if (method is InstallMethod.SelectFile) method.uri else null,
|
bootUri = if (method is InstallMethod.SelectFile) method.uri else null,
|
||||||
method is InstallMethod.DirectInstallToInactiveSlot
|
lkmUri = lkmFileUri,
|
||||||
|
ota = method is InstallMethod.DirectInstallToInactiveSlot
|
||||||
)
|
)
|
||||||
navigator.navigate(FlashScreenDestination(flashIt))
|
navigator.navigate(FlashScreenDestination(flashIt))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(topBar = {
|
val selectLkmLauncher =
|
||||||
TopBar {
|
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
|
||||||
navigator.popBackStack()
|
if (it.resultCode == Activity.RESULT_OK) {
|
||||||
|
it.data?.data?.let { uri ->
|
||||||
|
lkmFileUri = uri
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val onLkmUpload = {
|
||||||
|
selectLkmLauncher.launch(
|
||||||
|
Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||||
|
type = "application/octet-stream"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(topBar = {
|
||||||
|
TopBar(
|
||||||
|
onBack = { navigator.popBackStack() },
|
||||||
|
onLkmUpload = onLkmUpload
|
||||||
|
)
|
||||||
}) {
|
}) {
|
||||||
Column(modifier = Modifier.padding(it)) {
|
Column(modifier = Modifier.padding(it)) {
|
||||||
SelectInstallMethod { method ->
|
SelectInstallMethod { method ->
|
||||||
@@ -217,7 +244,7 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(onBack: () -> Unit = {}) {
|
private fun TopBar(onBack: () -> Unit = {}, onLkmUpload: () -> Unit = {}) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(stringResource(R.string.install)) },
|
title = { Text(stringResource(R.string.install)) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
@@ -225,6 +252,11 @@ private fun TopBar(onBack: () -> Unit = {}) {
|
|||||||
onClick = onBack
|
onClick = onBack
|
||||||
) { Icon(Icons.Filled.ArrowBack, contentDescription = null) }
|
) { Icon(Icons.Filled.ArrowBack, contentDescription = null) }
|
||||||
},
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(onClick = onLkmUpload) {
|
||||||
|
Icon(Icons.Filled.FileUpload, contentDescription = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,10 +143,11 @@ fun installModule(
|
|||||||
|
|
||||||
fun installBoot(
|
fun installBoot(
|
||||||
bootUri: Uri?,
|
bootUri: Uri?,
|
||||||
|
lkmUri: Uri?,
|
||||||
ota: Boolean,
|
ota: Boolean,
|
||||||
onFinish: (Boolean) -> Unit,
|
onFinish: (Boolean) -> Unit,
|
||||||
onStdout: (String) -> Unit,
|
onStdout: (String) -> Unit,
|
||||||
onStderr: (String) -> Unit
|
onStderr: (String) -> Unit,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val resolver = ksuApp.contentResolver
|
val resolver = ksuApp.contentResolver
|
||||||
|
|
||||||
@@ -161,6 +162,17 @@ fun installBoot(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val lkmFile = lkmUri?.let { uri ->
|
||||||
|
with(resolver.openInputStream(uri)) {
|
||||||
|
val lkmFile = File(ksuApp.cacheDir, "kernelsu-tmp-lkm.ko")
|
||||||
|
lkmFile.outputStream().use { output ->
|
||||||
|
this?.copyTo(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
lkmFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so")
|
||||||
var cmd = "boot-patch --magiskboot ${magiskboot.absolutePath}"
|
var cmd = "boot-patch --magiskboot ${magiskboot.absolutePath}"
|
||||||
|
|
||||||
@@ -175,6 +187,10 @@ fun installBoot(
|
|||||||
cmd += " -u"
|
cmd += " -u"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lkmFile?.let {
|
||||||
|
cmd += " -m ${it.absolutePath}"
|
||||||
|
}
|
||||||
|
|
||||||
// output dir
|
// output dir
|
||||||
val downloadsDir =
|
val downloadsDir =
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||||
@@ -200,6 +216,7 @@ fun installBoot(
|
|||||||
Log.i("KernelSU", "install boot result: ${result.isSuccess}")
|
Log.i("KernelSU", "install boot result: ${result.isSuccess}")
|
||||||
|
|
||||||
bootFile?.delete()
|
bootFile?.delete()
|
||||||
|
lkmFile?.delete()
|
||||||
|
|
||||||
// if boot uri is empty, it is direct install, when success, we should show reboot button
|
// if boot uri is empty, it is direct install, when success, we should show reboot button
|
||||||
onFinish(bootUri == null && result.isSuccess)
|
onFinish(bootUri == null && result.isSuccess)
|
||||||
|
|||||||
Reference in New Issue
Block a user