From 6398baaa6bda9a5a7a77be3bc4325370f33a64d5 Mon Sep 17 00:00:00 2001 From: Mathieu Moran Date: Wed, 12 Aug 2026 18:23:37 -0400 Subject: [PATCH] feat: in-app test file generator for upload testing adb-pushed files are invisible to the app due to scoped storage, so add a 'Create 120 MB test file' button in the Downloads tab that writes the file through the app's own uid (visible in its contribution set). --- .../java/com/yarisobd/app/DashcamViewModel.kt | 20 +++++++++++++++++++ .../java/com/yarisobd/app/DownloadsScreen.kt | 10 ++++++++++ .../java/com/yarisobd/app/MainActivity.kt | 1 + 3 files changed, 31 insertions(+) diff --git a/android/app/src/main/java/com/yarisobd/app/DashcamViewModel.kt b/android/app/src/main/java/com/yarisobd/app/DashcamViewModel.kt index fb8f9d0..4e73d42 100644 --- a/android/app/src/main/java/com/yarisobd/app/DashcamViewModel.kt +++ b/android/app/src/main/java/com/yarisobd/app/DashcamViewModel.kt @@ -19,7 +19,9 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import retrofit2.Retrofit import retrofit2.converter.kotlinx.serialization.asConverterFactory import okhttp3.MediaType.Companion.toMediaType @@ -257,6 +259,24 @@ class DashcamViewModel(application: Application) : AndroidViewModel(application) _downloadedFiles.value = files } + fun generateTestFile(sizeMb: Int = 120) { + viewModelScope.launch { + val f = File(getDownloadDir(), "test-upload-${sizeMb}mb.mp4") + try { + withContext(Dispatchers.IO) { + f.outputStream().use { out -> + val buf = ByteArray(1 shl 20) // 1MB + repeat(sizeMb) { out.write(buf) } + } + } + scanDownloads() + _downloadEvents.emit("✓ Created test file: ${f.name} (${sizeMb} MB)") + } catch (e: Exception) { + _downloadEvents.emit("✗ Could not create test file: ${e.message}") + } + } + } + fun deleteDownloaded(file: DownloadedFile) { _deletingNames.value = _deletingNames.value + file.name viewModelScope.launch { diff --git a/android/app/src/main/java/com/yarisobd/app/DownloadsScreen.kt b/android/app/src/main/java/com/yarisobd/app/DownloadsScreen.kt index bd98b91..119478c 100644 --- a/android/app/src/main/java/com/yarisobd/app/DownloadsScreen.kt +++ b/android/app/src/main/java/com/yarisobd/app/DownloadsScreen.kt @@ -67,6 +67,7 @@ fun DownloadsScreen( onCancel: (ActiveDownload) -> Unit, onUpload: (DownloadedFile) -> Unit, onCancelUpload: (ActiveDownload) -> Unit, + onGenerateTestFile: () -> Unit, onRefresh: () -> Unit, ) { val context = LocalContext.current @@ -83,6 +84,15 @@ fun DownloadsScreen( Text("Downloads", style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.primary) Spacer(Modifier.height(4.dp)) Text("${files.size} files · Movies/yaris-obd/", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + Spacer(Modifier.height(10.dp)) + Button( + onClick = onGenerateTestFile, + modifier = Modifier.height(34.dp), + shape = RoundedCornerShape(8.dp), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 0.dp) + ) { + Text("Create 120 MB test file", style = MaterialTheme.typography.bodySmall) + } } } diff --git a/android/app/src/main/java/com/yarisobd/app/MainActivity.kt b/android/app/src/main/java/com/yarisobd/app/MainActivity.kt index e59b31d..7212571 100644 --- a/android/app/src/main/java/com/yarisobd/app/MainActivity.kt +++ b/android/app/src/main/java/com/yarisobd/app/MainActivity.kt @@ -135,6 +135,7 @@ fun YarisMainScreen(client: OkHttpClient) { onCancel = { dashcamVm.cancelDownload(it) }, onUpload = { dashcamVm.uploadFile(it) }, onCancelUpload = { dashcamVm.cancelUpload(it) }, + onGenerateTestFile = { dashcamVm.generateTestFile() }, onRefresh = { dashcamVm.scanDownloads() }, ) 2 -> SettingsScreen(client = client)