diff --git a/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt b/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt index 11084934..0503b42f 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt @@ -5,6 +5,7 @@ import coil.Coil import coil.ImageLoader import me.zhanghai.android.appiconloader.coil.AppIconFetcher import me.zhanghai.android.appiconloader.coil.AppIconKeyer +import java.io.File lateinit var ksuApp: KernelSUApplication @@ -24,6 +25,11 @@ class KernelSUApplication : Application() { } .build() ) + + val webroot = File(dataDir, "webroot") + if (!webroot.exists()) { + webroot.mkdir() + } } diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/WebScreen.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/WebScreen.kt index e38ea11b..a39f5558 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/WebScreen.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/WebScreen.kt @@ -15,34 +15,26 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import androidx.lifecycle.lifecycleScope import com.google.accompanist.web.WebView import com.google.accompanist.web.rememberWebViewState import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.topjohnwu.superuser.ShellUtils -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import me.weishu.kernelsu.ui.util.createRootShell import me.weishu.kernelsu.ui.util.serveModule -import java.net.ServerSocket @SuppressLint("SetJavaScriptEnabled") @Destination @Composable fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: String) { - val port = 8080 LaunchedEffect(Unit) { - serveModule(moduleId, port) + serveModule(moduleId) } - val lifecycleOwner = LocalLifecycleOwner.current val context = LocalContext.current DisposableEffect(Unit) { @@ -50,15 +42,12 @@ fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: St if (WebViewInterface.isHideSystemUI && context is Activity) { showSystemUI(context.window) } - lifecycleOwner.lifecycleScope.launch { - stopServer(port) - } } } Scaffold { innerPadding -> WebView( - state = rememberWebViewState(url = "http://localhost:$port"), + state = rememberWebViewState(url = "file:///data/data/me.weishu.kernelsu/webroot/index.html"), Modifier .fillMaxSize() .padding(innerPadding), @@ -66,6 +55,7 @@ fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: St android.webkit.WebView(context).apply { settings.javaScriptEnabled = true settings.domStorageEnabled = true + settings.allowFileAccess = true addJavascriptInterface(WebViewInterface(context), "ksu") } }) @@ -100,22 +90,6 @@ class WebViewInterface(val context: Context) { } -private suspend fun getFreePort(): Int { - return withContext(Dispatchers.IO) { - ServerSocket(0).use { socket -> socket.localPort } - } -} - -private suspend fun stopServer(port: Int) { - withContext(Dispatchers.IO) { - runCatching { - okhttp3.OkHttpClient() - .newCall(okhttp3.Request.Builder().url("http://localhost:$port/stop").build()) - .execute() - } - } -} - private fun hideSystemUI(window: Window) { WindowCompat.setDecorFitsSystemWindows(window, false) WindowInsetsControllerCompat(window, window.decorView).let { controller -> diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt index e61eaf99..087f246d 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt @@ -131,13 +131,13 @@ fun installModule( } } -fun serveModule(id: String, port: Int): Process { +fun serveModule(id: String): Boolean { // we should use a new root shell to avoid blocking the global shell - val process = Runtime.getRuntime().exec("${getKsuDaemonPath()} debug su") - val builder = Shell.Builder.create() - val shell = builder.build(process) - shell.newJob().add("${getKsuDaemonPath()} module serve $id $port").submit() - return process + val shell = createRootShell() + return ShellUtils.fastCmdResult( + shell, + "${getKsuDaemonPath()} module link-manager $id ${android.os.Process.myPid()} ${BuildConfig.APPLICATION_ID}" + ) } fun reboot(reason: String = "") {