mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2024-11-10 01:01:56 +01:00
feat: add ability to share debug logs
This commit is contained in:
parent
d8248cc915
commit
8d3d500b7b
3 changed files with 63 additions and 1 deletions
|
@ -2,6 +2,8 @@ package app.revanced.manager.ui.screen.settings
|
||||||
|
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
@ -86,6 +88,15 @@ fun AdvancedSettingsScreen(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val exportDebugLogsLauncher =
|
||||||
|
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) {
|
||||||
|
it?.let(vm::exportDebugLogs)
|
||||||
|
}
|
||||||
|
SettingsListItem(
|
||||||
|
headlineContent = stringResource(R.string.debug_logs_export),
|
||||||
|
modifier = Modifier.clickable { exportDebugLogsLauncher.launch(vm.debugLogFileName) }
|
||||||
|
)
|
||||||
|
|
||||||
GroupHeader(stringResource(R.string.patcher))
|
GroupHeader(stringResource(R.string.patcher))
|
||||||
BooleanItem(
|
BooleanItem(
|
||||||
preference = vm.prefs.useProcessRuntime,
|
preference = vm.prefs.useProcessRuntime,
|
||||||
|
|
|
@ -1,21 +1,41 @@
|
||||||
package app.revanced.manager.ui.viewmodel
|
package app.revanced.manager.ui.viewmodel
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
|
import app.revanced.manager.domain.bundles.RemotePatchBundle
|
||||||
import app.revanced.manager.domain.manager.PreferencesManager
|
import app.revanced.manager.domain.manager.PreferencesManager
|
||||||
import app.revanced.manager.domain.repository.PatchBundleRepository
|
import app.revanced.manager.domain.repository.PatchBundleRepository
|
||||||
import app.revanced.manager.domain.bundles.RemotePatchBundle
|
import app.revanced.manager.util.tag
|
||||||
|
import app.revanced.manager.util.toast
|
||||||
import app.revanced.manager.util.uiSafe
|
import app.revanced.manager.util.uiSafe
|
||||||
|
import com.github.pgreze.process.Redirect
|
||||||
|
import com.github.pgreze.process.process
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
class AdvancedSettingsViewModel(
|
class AdvancedSettingsViewModel(
|
||||||
val prefs: PreferencesManager,
|
val prefs: PreferencesManager,
|
||||||
private val app: Application,
|
private val app: Application,
|
||||||
private val patchBundleRepository: PatchBundleRepository
|
private val patchBundleRepository: PatchBundleRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
val debugLogFileName: String
|
||||||
|
get() {
|
||||||
|
val time = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())
|
||||||
|
|
||||||
|
return "revanced-manager_logcat_$time"
|
||||||
|
}
|
||||||
|
|
||||||
fun setApiUrl(value: String) = viewModelScope.launch(Dispatchers.Default) {
|
fun setApiUrl(value: String) = viewModelScope.launch(Dispatchers.Default) {
|
||||||
if (value == prefs.api.get()) return@launch
|
if (value == prefs.api.get()) return@launch
|
||||||
|
|
||||||
|
@ -32,4 +52,31 @@ class AdvancedSettingsViewModel(
|
||||||
fun resetBundles() = viewModelScope.launch {
|
fun resetBundles() = viewModelScope.launch {
|
||||||
patchBundleRepository.reset()
|
patchBundleRepository.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun exportDebugLogs(target: Uri) = viewModelScope.launch {
|
||||||
|
val exitCode = try {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
app.contentResolver.openOutputStream(target)!!.bufferedWriter().use { writer ->
|
||||||
|
val consumer = Redirect.Consume { flow ->
|
||||||
|
flow.onEach {
|
||||||
|
writer.write(it)
|
||||||
|
}.flowOn(Dispatchers.IO).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
process("logcat", "-d", stdout = consumer).resultCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: CancellationException) {
|
||||||
|
throw e
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(tag, "Got exception while exporting logs", e)
|
||||||
|
app.toast(app.getString(R.string.debug_logs_export_failed))
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exitCode == 0)
|
||||||
|
app.toast(app.getString(R.string.debug_logs_export_success))
|
||||||
|
else
|
||||||
|
app.toast(app.getString(R.string.debug_logs_export_read_failed, exitCode))
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -137,6 +137,10 @@
|
||||||
<string name="process_runtime_description">This is faster and allows Patcher to use more memory.</string>
|
<string name="process_runtime_description">This is faster and allows Patcher to use more memory.</string>
|
||||||
<string name="process_runtime_memory_limit">Patcher process memory limit</string>
|
<string name="process_runtime_memory_limit">Patcher process memory limit</string>
|
||||||
<string name="process_runtime_memory_limit_description">The max amount of memory that the Patcher process can use (in megabytes)</string>
|
<string name="process_runtime_memory_limit_description">The max amount of memory that the Patcher process can use (in megabytes)</string>
|
||||||
|
<string name="debug_logs_export">Export debug logs</string>
|
||||||
|
<string name="debug_logs_export_read_failed">Failed to read logs (exit code %d)</string>
|
||||||
|
<string name="debug_logs_export_failed">Failed to export logs</string>
|
||||||
|
<string name="debug_logs_export_success">Exported logs</string>
|
||||||
<string name="api_url">API URL</string>
|
<string name="api_url">API URL</string>
|
||||||
<string name="api_url_dialog_title">Set custom API URL</string>
|
<string name="api_url_dialog_title">Set custom API URL</string>
|
||||||
<string name="api_url_dialog_description">You may have issues with features when using a custom API URL.</string>
|
<string name="api_url_dialog_description">You may have issues with features when using a custom API URL.</string>
|
||||||
|
|
Loading…
Reference in a new issue