@@ -3,8 +3,8 @@ package com.voicenotes
33import android.Manifest
44import android.content.Intent
55import android.content.pm.PackageManager
6+ import android.net.Uri
67import android.os.Bundle
7- import android.os.Environment
88import android.speech.RecognizerIntent
99import android.speech.SpeechRecognizer
1010import android.widget.Button
@@ -13,8 +13,6 @@ import android.widget.Toast
1313import androidx.appcompat.app.AppCompatActivity
1414import androidx.core.app.ActivityCompat
1515import androidx.core.content.ContextCompat
16- import java.io.File
17- import java.io.FileWriter
1816import java.text.SimpleDateFormat
1917import java.time.LocalDateTime
2018import java.time.format.DateTimeFormatter
@@ -27,6 +25,7 @@ class MainActivity : AppCompatActivity() {
2725 private lateinit var notesTextView: TextView
2826 private val RECORD_AUDIO_PERMISSION_CODE = 1
2927 private val SPEECH_REQUEST_CODE = 0
28+ private val CREATE_FILE_REQUEST_CODE = 2
3029
3130 companion object {
3231 private const val ISO_8601_FILENAME_PATTERN = " yyyy-MM-dd'T'HH-mm-ss"
@@ -113,6 +112,10 @@ class MainActivity : AppCompatActivity() {
113112 }
114113 notesTextView.text = newText
115114 }
115+ } else if (requestCode == CREATE_FILE_REQUEST_CODE && resultCode == RESULT_OK ) {
116+ data?.data?.let { uri ->
117+ writeNotesToUri(uri)
118+ }
116119 }
117120 }
118121
@@ -146,45 +149,61 @@ class MainActivity : AppCompatActivity() {
146149 return
147150 }
148151
152+ // Generate ISO 8601 timestamp for filename (filename-safe format)
153+ val filenameTimestamp = if (android.os.Build .VERSION .SDK_INT >= android.os.Build .VERSION_CODES .O ) {
154+ LocalDateTime .now().format(DateTimeFormatter .ofPattern(ISO_8601_FILENAME_PATTERN ))
155+ } else {
156+ SimpleDateFormat (ISO_8601_FILENAME_PATTERN , Locale .getDefault()).format(Date ())
157+ }
158+
159+ // Use Storage Access Framework to let user choose location
160+ val intent = Intent (Intent .ACTION_CREATE_DOCUMENT ).apply {
161+ addCategory(Intent .CATEGORY_OPENABLE )
162+ type = " text/markdown"
163+ putExtra(Intent .EXTRA_TITLE , " voice-notes-$filenameTimestamp .md" )
164+ }
165+
166+ try {
167+ startActivityForResult(intent, CREATE_FILE_REQUEST_CODE )
168+ } catch (e: Exception ) {
169+ Toast .makeText(
170+ this ,
171+ getString(R .string.export_error, e.message),
172+ Toast .LENGTH_LONG
173+ ).show()
174+ }
175+ }
176+
177+ private fun writeNotesToUri (uri : Uri ) {
178+ val currentText = notesTextView.text.toString()
179+
149180 try {
150- // Generate ISO 8601 timestamp for filename (filename-safe format)
151- val filenameTimestamp = if (android.os.Build .VERSION .SDK_INT >= android.os.Build .VERSION_CODES .O ) {
152- LocalDateTime .now().format(DateTimeFormatter .ofPattern(ISO_8601_FILENAME_PATTERN ))
153- } else {
154- SimpleDateFormat (ISO_8601_FILENAME_PATTERN , Locale .getDefault()).format(Date ())
155- }
156-
157181 // Generate human-readable timestamp for content
158182 val readableTimestamp = if (android.os.Build .VERSION .SDK_INT >= android.os.Build .VERSION_CODES .O ) {
159183 LocalDateTime .now().format(DateTimeFormatter .ofPattern(" yyyy-MM-dd HH:mm:ss" ))
160184 } else {
161185 SimpleDateFormat (" yyyy-MM-dd HH:mm:ss" , Locale .getDefault()).format(Date ())
162186 }
163187
164- // Create VoiceNotes directory in Documents
165- val documentsDir = Environment .getExternalStoragePublicDirectory(Environment .DIRECTORY_DOCUMENTS )
166- val voiceNotesDir = File (documentsDir, " VoiceNotes" )
167-
168- if (! voiceNotesDir.exists()) {
169- voiceNotesDir.mkdirs()
188+ // Build the complete markdown content
189+ val markdownContent = buildString {
190+ append(" # Voice Notes Export\n\n " )
191+ append(" **Exported on:** $readableTimestamp \n\n " )
192+ append(" ---\n\n " )
193+ append(currentText)
194+ append(" \n " )
170195 }
171196
172- // Create the markdown file
173- val filename = " voice-notes-$filenameTimestamp .md"
174- val file = File (voiceNotesDir, filename)
175-
176197 // Write content to the file with markdown formatting
177- FileWriter (file).use { writer ->
178- writer.write(" # Voice Notes Export\n\n " )
179- writer.write(" **Exported on:** $readableTimestamp \n\n " )
180- writer.write(" ---\n\n " )
181- writer.write(currentText)
182- writer.write(" \n " )
198+ contentResolver.openOutputStream(uri)?.use { outputStream ->
199+ outputStream.write(markdownContent.toByteArray())
200+ } ? : run {
201+ throw Exception (" Failed to open output stream" )
183202 }
184203
185204 Toast .makeText(
186205 this ,
187- getString(R .string.export_success, file.absolutePath ),
206+ getString(R .string.export_success_new ),
188207 Toast .LENGTH_LONG
189208 ).show()
190209
0 commit comments