Skip to content

Commit feb0ca4

Browse files
Axelen123oSumAtrIX
authored andcommitted
feat: add ability to share debug logs
1 parent 0383bd7 commit feb0ca4

3 files changed

Lines changed: 63 additions & 1 deletion

File tree

app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package app.revanced.manager.ui.screen.settings
22

33
import android.app.ActivityManager
44
import android.os.Build
5+
import androidx.activity.compose.rememberLauncherForActivityResult
6+
import androidx.activity.result.contract.ActivityResultContracts
57
import androidx.compose.foundation.clickable
68
import androidx.compose.foundation.layout.Arrangement
79
import androidx.compose.foundation.layout.Column
@@ -86,6 +88,15 @@ fun AdvancedSettingsScreen(
8688
}
8789
)
8890

91+
val exportDebugLogsLauncher =
92+
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) {
93+
it?.let(vm::exportDebugLogs)
94+
}
95+
SettingsListItem(
96+
headlineContent = stringResource(R.string.debug_logs_export),
97+
modifier = Modifier.clickable { exportDebugLogsLauncher.launch(vm.debugLogFileName) }
98+
)
99+
89100
GroupHeader(stringResource(R.string.patcher))
90101
BooleanItem(
91102
preference = vm.prefs.useProcessRuntime,

app/src/main/java/app/revanced/manager/ui/viewmodel/AdvancedSettingsViewModel.kt

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
11
package app.revanced.manager.ui.viewmodel
22

33
import android.app.Application
4+
import android.net.Uri
5+
import android.util.Log
46
import androidx.lifecycle.ViewModel
57
import androidx.lifecycle.viewModelScope
68
import app.revanced.manager.R
9+
import app.revanced.manager.domain.bundles.RemotePatchBundle
710
import app.revanced.manager.domain.manager.PreferencesManager
811
import app.revanced.manager.domain.repository.PatchBundleRepository
9-
import app.revanced.manager.domain.bundles.RemotePatchBundle
12+
import app.revanced.manager.util.tag
13+
import app.revanced.manager.util.toast
1014
import app.revanced.manager.util.uiSafe
15+
import com.github.pgreze.process.Redirect
16+
import com.github.pgreze.process.process
17+
import kotlinx.coroutines.CancellationException
1118
import kotlinx.coroutines.Dispatchers
19+
import kotlinx.coroutines.flow.collect
20+
import kotlinx.coroutines.flow.flowOn
21+
import kotlinx.coroutines.flow.onEach
1222
import kotlinx.coroutines.launch
23+
import kotlinx.coroutines.withContext
24+
import java.time.LocalDateTime
25+
import java.time.format.DateTimeFormatter
1326

1427
class AdvancedSettingsViewModel(
1528
val prefs: PreferencesManager,
1629
private val app: Application,
1730
private val patchBundleRepository: PatchBundleRepository
1831
) : ViewModel() {
32+
val debugLogFileName: String
33+
get() {
34+
val time = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())
35+
36+
return "revanced-manager_logcat_$time"
37+
}
38+
1939
fun setApiUrl(value: String) = viewModelScope.launch(Dispatchers.Default) {
2040
if (value == prefs.api.get()) return@launch
2141

@@ -32,4 +52,31 @@ class AdvancedSettingsViewModel(
3252
fun resetBundles() = viewModelScope.launch {
3353
patchBundleRepository.reset()
3454
}
55+
56+
fun exportDebugLogs(target: Uri) = viewModelScope.launch {
57+
val exitCode = try {
58+
withContext(Dispatchers.IO) {
59+
app.contentResolver.openOutputStream(target)!!.bufferedWriter().use { writer ->
60+
val consumer = Redirect.Consume { flow ->
61+
flow.onEach {
62+
writer.write(it)
63+
}.flowOn(Dispatchers.IO).collect()
64+
}
65+
66+
process("logcat", "-d", stdout = consumer).resultCode
67+
}
68+
}
69+
} catch (e: CancellationException) {
70+
throw e
71+
} catch (e: Exception) {
72+
Log.e(tag, "Got exception while exporting logs", e)
73+
app.toast(app.getString(R.string.debug_logs_export_failed))
74+
return@launch
75+
}
76+
77+
if (exitCode == 0)
78+
app.toast(app.getString(R.string.debug_logs_export_success))
79+
else
80+
app.toast(app.getString(R.string.debug_logs_export_read_failed, exitCode))
81+
}
3582
}

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@
137137
<string name="process_runtime_description">This is faster and allows Patcher to use more memory.</string>
138138
<string name="process_runtime_memory_limit">Patcher process memory limit</string>
139139
<string name="process_runtime_memory_limit_description">The max amount of memory that the Patcher process can use (in megabytes)</string>
140+
<string name="debug_logs_export">Export debug logs</string>
141+
<string name="debug_logs_export_read_failed">Failed to read logs (exit code %d)</string>
142+
<string name="debug_logs_export_failed">Failed to export logs</string>
143+
<string name="debug_logs_export_success">Exported logs</string>
140144
<string name="api_url">API URL</string>
141145
<string name="api_url_dialog_title">Set custom API URL</string>
142146
<string name="api_url_dialog_description">You may have issues with features when using a custom API URL.</string>

0 commit comments

Comments
 (0)