Sitelet https://github.com/script-or-script/FlutterTap/commit/5a2eff34f9f85c812fd56ee44d2d3fa6f43bc004
Skip to content

Commit 5a2eff3

Browse files
manager-app: root retry button, combined module status, Burp Invisible Proxy note
Adds a "grant root access" button in the Status card, shown only when root wasn't granted -- closes any cached non-root shell and asks again, covering the case where the user dismissed the automatic prompt on first launch. Collapses the module install/enable state into a single accurate flag (checks the standard `disable` marker file alongside the module directory, the same convention Magisk/ KernelSU/APatch all use) instead of only reporting "installed" regardless of whether it's actually active. Adds a small-print reminder in the Proxy card to enable Invisible Proxying in Burp Suite's listener settings.
1 parent 271aae1 commit 5a2eff3

9 files changed

Lines changed: 69 additions & 22 deletions

File tree

‎manager-app/src/main/java/com/eduardolopes/fluttertap/data/RootManager.kt‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ enum class RootBackend { MAGISK, KERNELSU, APATCH, UNKNOWN }
99
data class RootStatus(
1010
val granted: Boolean,
1111
val backend: RootBackend,
12-
val moduleInstalled: Boolean,
12+
/** True only when the module directory exists AND has no `disable` marker file. */
13+
val moduleActive: Boolean,
1314
)
1415

1516
/** All root shell I/O for FlutterTap: root/backend detection and config.json read/write. */
@@ -21,16 +22,27 @@ object RootManager {
2122
// Runs on a background thread; callers are expected to launch it off the main thread.
2223
fun queryStatus(): RootStatus {
2324
val granted = Shell.getShell().isRoot
24-
if (!granted) return RootStatus(granted = false, backend = RootBackend.UNKNOWN, moduleInstalled = false)
25+
if (!granted) return RootStatus(granted = false, backend = RootBackend.UNKNOWN, moduleActive = false)
2526

2627
val backend = when {
2728
exists("/data/adb/ksu") || Shell.cmd("ksud --version").exec().isSuccess -> RootBackend.KERNELSU
2829
exists("/data/adb/ap") -> RootBackend.APATCH
2930
Shell.cmd("magisk -v").exec().isSuccess -> RootBackend.MAGISK
3031
else -> RootBackend.UNKNOWN
3132
}
32-
val moduleInstalled = exists(MODULE_DIR)
33-
return RootStatus(granted = true, backend = backend, moduleInstalled = moduleInstalled)
33+
val moduleActive = exists(MODULE_DIR) && !exists("$MODULE_DIR/disable")
34+
return RootStatus(granted = true, backend = backend, moduleActive = moduleActive)
35+
}
36+
37+
/**
38+
* Closes the cached shell if it's not root and asks again -- covers the case where the
39+
* user dismissed or denied the automatic prompt on first launch and now wants to retry
40+
* (e.g. after fixing the app's permission in their root manager). A prior hard "deny"
41+
* recorded by the root manager itself still won't re-prompt; only it can undo that.
42+
*/
43+
fun requestRoot(): RootStatus {
44+
Shell.getCachedShell()?.let { if (!it.isRoot) it.close() }
45+
return queryStatus()
3446
}
3547

3648
fun readConfig(): ConfigData {

‎manager-app/src/main/java/com/eduardolopes/fluttertap/ui/HomeScreen.kt‎

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import androidx.compose.ui.platform.LocalContext
4747
import androidx.compose.ui.res.stringResource
4848
import androidx.compose.ui.text.style.TextOverflow
4949
import androidx.compose.ui.unit.dp
50+
import androidx.compose.ui.unit.sp
5051
import androidx.appcompat.app.AppCompatDelegate
5152
import com.eduardolopes.fluttertap.R
5253
import com.eduardolopes.fluttertap.data.AppInfo
@@ -100,6 +101,15 @@ fun HomeScreen(onLanguageSelected: (String?) -> Unit) {
100101
}
101102
}
102103

104+
fun retryRoot() {
105+
scope.launch {
106+
status = withContext(Dispatchers.IO) { RootManager.requestRoot() }
107+
if (status?.granted == true) {
108+
config = withContext(Dispatchers.IO) { RootManager.readConfig() }
109+
}
110+
}
111+
}
112+
103113
Scaffold(
104114
topBar = { TopAppBar(title = { Text(stringResource(R.string.app_name)) }) },
105115
snackbarHost = { SnackbarHost(snackbarHostState) },
@@ -117,7 +127,7 @@ fun HomeScreen(onLanguageSelected: (String?) -> Unit) {
117127
verticalArrangement = Arrangement.spacedBy(16.dp),
118128
) {
119129
item { LanguageCard(onLanguageSelected = onLanguageSelected) }
120-
item { StatusCard(status!!) }
130+
item { StatusCard(status = status!!, onRetryRoot = ::retryRoot) }
121131
item { ProxyCard(config = config, onSave = { newConfig -> persist(newConfig, notify = true) }) }
122132
item {
123133
AppsCard(
@@ -137,7 +147,7 @@ fun HomeScreen(onLanguageSelected: (String?) -> Unit) {
137147
}
138148

139149
@Composable
140-
private fun StatusCard(status: RootStatus) {
150+
private fun StatusCard(status: RootStatus, onRetryRoot: () -> Unit) {
141151
Card(modifier = Modifier.fillMaxWidth()) {
142152
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) {
143153
Text(stringResource(R.string.status_title), style = MaterialTheme.typography.titleMedium)
@@ -158,10 +168,14 @@ private fun StatusCard(status: RootStatus) {
158168
)
159169
Text(
160170
stringResource(
161-
if (status.moduleInstalled) R.string.status_module_installed
162-
else R.string.status_module_not_installed
171+
if (status.moduleActive) R.string.status_module_active
172+
else R.string.status_module_inactive
163173
)
164174
)
175+
} else {
176+
TextButton(onClick = onRetryRoot, modifier = Modifier.padding(top = 4.dp)) {
177+
Text(stringResource(R.string.status_grant_root_button))
178+
}
165179
}
166180
}
167181
}
@@ -233,6 +247,13 @@ private fun ProxyCard(config: ConfigData, onSave: (ConfigData) -> Unit) {
233247
) {
234248
Text(stringResource(R.string.proxy_save_button))
235249
}
250+
251+
Text(
252+
stringResource(R.string.proxy_burp_invisible_note),
253+
style = MaterialTheme.typography.labelSmall.copy(fontSize = 9.sp),
254+
color = MaterialTheme.colorScheme.onSurfaceVariant,
255+
modifier = Modifier.padding(top = 4.dp),
256+
)
236257
}
237258
}
238259
}

‎manager-app/src/main/res/values-ar/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">المدير: KernelSU</string>
1010
<string name="status_backend_apatch">المدير: APatch</string>
1111
<string name="status_backend_unknown">المدير: غير معروف</string>
12-
<string name="status_module_installed">وحدة FlutterTap: مثبَّتة</string>
13-
<string name="status_module_not_installed">وحدة FlutterTap: غير مثبَّتة</string>
12+
<string name="status_module_active">وحدة FlutterTap: مثبَّتة ومفعَّلة</string>
13+
<string name="status_module_inactive">وحدة FlutterTap: غير مثبَّتة أو معطَّلة</string>
14+
<string name="status_grant_root_button">منح صلاحية الروت</string>
1415

1516
<string name="proxy_title">البروكسي</string>
1617
<string name="proxy_master_switch">تفعيل الاعتراض</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">تم حفظ الإعدادات</string>
2122
<string name="proxy_invalid_ip">أدخل عنوان IPv4 صالحًا</string>
2223
<string name="proxy_invalid_port">أدخل منفذًا بين 1 و65535</string>
24+
<string name="proxy_burp_invisible_note">تذكَّر تفعيل خيار "Invisible Proxying" في إعدادات مستمع البروكسي في Burp Suite.</string>
2325

2426
<string name="apps_title">التطبيقات المستهدَفة</string>
2527
<string name="apps_subtitle">اختر التطبيقات المثبَّتة التي يجب على FlutterTap اعتراضها</string>

‎manager-app/src/main/res/values-es/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">Gestor: KernelSU</string>
1010
<string name="status_backend_apatch">Gestor: APatch</string>
1111
<string name="status_backend_unknown">Gestor: desconocido</string>
12-
<string name="status_module_installed">Módulo FlutterTap: instalado</string>
13-
<string name="status_module_not_installed">Módulo FlutterTap: no instalado</string>
12+
<string name="status_module_active">Módulo FlutterTap: instalado y habilitado</string>
13+
<string name="status_module_inactive">Módulo FlutterTap: no instalado o deshabilitado</string>
14+
<string name="status_grant_root_button">Conceder acceso root</string>
1415

1516
<string name="proxy_title">Proxy</string>
1617
<string name="proxy_master_switch">Activar interceptación</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">Configuración guardada</string>
2122
<string name="proxy_invalid_ip">Introduce una dirección IPv4 válida</string>
2223
<string name="proxy_invalid_port">Introduce un puerto entre 1 y 65535</string>
24+
<string name="proxy_burp_invisible_note">Recuerda activar "Invisible Proxying" en la configuración del listener de proxy de Burp Suite.</string>
2325

2426
<string name="apps_title">Apps objetivo</string>
2527
<string name="apps_subtitle">Elige qué apps instaladas debe interceptar FlutterTap</string>

‎manager-app/src/main/res/values-fr/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">Gestionnaire : KernelSU</string>
1010
<string name="status_backend_apatch">Gestionnaire : APatch</string>
1111
<string name="status_backend_unknown">Gestionnaire : inconnu</string>
12-
<string name="status_module_installed">Module FlutterTap : installé</string>
13-
<string name="status_module_not_installed">Module FlutterTap : non installé</string>
12+
<string name="status_module_active">Module FlutterTap : installé et activé</string>
13+
<string name="status_module_inactive">Module FlutterTap : non installé ou désactivé</string>
14+
<string name="status_grant_root_button">Accorder l\'accès root</string>
1415

1516
<string name="proxy_title">Proxy</string>
1617
<string name="proxy_master_switch">Activer l\'interception</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">Configuration enregistrée</string>
2122
<string name="proxy_invalid_ip">Saisissez une adresse IPv4 valide</string>
2223
<string name="proxy_invalid_port">Saisissez un port entre 1 et 65535</string>
24+
<string name="proxy_burp_invisible_note">Pensez à activer l\'"Invisible Proxying" dans les paramètres de l\'écouteur proxy de Burp Suite.</string>
2325

2426
<string name="apps_title">Apps ciblées</string>
2527
<string name="apps_subtitle">Choisissez les apps installées que FlutterTap doit intercepter</string>

‎manager-app/src/main/res/values-hi/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">मैनेजर: KernelSU</string>
1010
<string name="status_backend_apatch">मैनेजर: APatch</string>
1111
<string name="status_backend_unknown">मैनेजर: अज्ञात</string>
12-
<string name="status_module_installed">FlutterTap मॉड्यूल: इंस्टॉल है</string>
13-
<string name="status_module_not_installed">FlutterTap मॉड्यूल: इंस्टॉल नहीं है</string>
12+
<string name="status_module_active">FlutterTap मॉड्यूल: इंस्टॉल और सक्षम है</string>
13+
<string name="status_module_inactive">FlutterTap मॉड्यूल: इंस्टॉल नहीं है या अक्षम है</string>
14+
<string name="status_grant_root_button">रूट एक्सेस प्रदान करें</string>
1415

1516
<string name="proxy_title">प्रॉक्सी</string>
1617
<string name="proxy_master_switch">हुकिंग सक्षम करें</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">कॉन्फ़िगरेशन सहेजा गया</string>
2122
<string name="proxy_invalid_ip">एक मान्य IPv4 पता दर्ज करें</string>
2223
<string name="proxy_invalid_port">1 से 65535 के बीच एक पोर्ट दर्ज करें</string>
24+
<string name="proxy_burp_invisible_note">Burp Suite की प्रॉक्सी लिसनर सेटिंग्स में "Invisible Proxying" सक्षम करना न भूलें।</string>
2325

2426
<string name="apps_title">लक्ष्य ऐप्स</string>
2527
<string name="apps_subtitle">चुनें कि FlutterTap को किन इंस्टॉल किए गए ऐप्स को इंटरसेप्ट करना चाहिए</string>

‎manager-app/src/main/res/values-pt-rBR/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">Gerenciador: KernelSU</string>
1010
<string name="status_backend_apatch">Gerenciador: APatch</string>
1111
<string name="status_backend_unknown">Gerenciador: desconhecido</string>
12-
<string name="status_module_installed">Módulo FlutterTap: instalado</string>
13-
<string name="status_module_not_installed">Módulo FlutterTap: não instalado</string>
12+
<string name="status_module_active">Módulo FlutterTap: instalado e habilitado</string>
13+
<string name="status_module_inactive">Módulo FlutterTap: não instalado ou desabilitado</string>
14+
<string name="status_grant_root_button">Conceder acesso root</string>
1415

1516
<string name="proxy_title">Proxy</string>
1617
<string name="proxy_master_switch">Ativar interceptação</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">Configuração salva</string>
2122
<string name="proxy_invalid_ip">Informe um endereço IPv4 válido</string>
2223
<string name="proxy_invalid_port">Informe uma porta entre 1 e 65535</string>
24+
<string name="proxy_burp_invisible_note">Lembre-se de habilitar o "Invisible Proxying" nas configurações do listener de proxy do Burp Suite.</string>
2325

2426
<string name="apps_title">Apps alvo</string>
2527
<string name="apps_subtitle">Escolha quais apps instalados o FlutterTap deve interceptar</string>

‎manager-app/src/main/res/values-zh/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">管理器:KernelSU</string>
1010
<string name="status_backend_apatch">管理器:APatch</string>
1111
<string name="status_backend_unknown">管理器:未知</string>
12-
<string name="status_module_installed">FlutterTap 模块:已安装</string>
13-
<string name="status_module_not_installed">FlutterTap 模块:未安装</string>
12+
<string name="status_module_active">FlutterTap 模块:已安装并已启用</string>
13+
<string name="status_module_inactive">FlutterTap 模块:未安装或已禁用</string>
14+
<string name="status_grant_root_button">授予 Root 权限</string>
1415

1516
<string name="proxy_title">代理</string>
1617
<string name="proxy_master_switch">启用拦截</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">配置已保存</string>
2122
<string name="proxy_invalid_ip">请输入有效的 IPv4 地址</string>
2223
<string name="proxy_invalid_port">请输入 1 到 65535 之间的端口</string>
24+
<string name="proxy_burp_invisible_note">别忘了在 Burp Suite 的代理监听器设置中启用"Invisible Proxying"。</string>
2325

2426
<string name="apps_title">目标应用</string>
2527
<string name="apps_subtitle">选择 FlutterTap 需要拦截的已安装应用</string>

‎manager-app/src/main/res/values/strings.xml‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
<string name="status_backend_kernelsu">Manager: KernelSU</string>
1010
<string name="status_backend_apatch">Manager: APatch</string>
1111
<string name="status_backend_unknown">Manager: unknown</string>
12-
<string name="status_module_installed">FlutterTap module: installed</string>
13-
<string name="status_module_not_installed">FlutterTap module: not installed</string>
12+
<string name="status_module_active">FlutterTap module: installed and enabled</string>
13+
<string name="status_module_inactive">FlutterTap module: not installed or disabled</string>
14+
<string name="status_grant_root_button">Grant root access</string>
1415

1516
<string name="proxy_title">Proxy</string>
1617
<string name="proxy_master_switch">Enable hooking</string>
@@ -20,6 +21,7 @@
2021
<string name="proxy_saved_confirmation">Configuration saved</string>
2122
<string name="proxy_invalid_ip">Enter a valid IPv4 address</string>
2223
<string name="proxy_invalid_port">Enter a port between 1 and 65535</string>
24+
<string name="proxy_burp_invisible_note">Remember to enable "Invisible Proxying" in Burp Suite\'s proxy listener settings.</string>
2325

2426
<string name="apps_title">Target apps</string>
2527
<string name="apps_subtitle">Choose which installed apps FlutterTap should hook</string>

0 commit comments

Comments
 (0)