Ficheros usando MediaStore en Kotlin
Escribir y leer ficheros usando MediaStore.
Para versiones de Android 10 (API 29) o superiores
Crear un nuevo proyecto en Kotlin: MemoriaExternaMediaStoreKotlin
Añadir el permiso al manifiesto:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
build.gradle
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.example.memoriaexternakotlin"
compileSdk = 34
buildFeatures {
viewBinding = true
}
strings.xml
<resources>
<string name="app_name">Memoria Externa en Kotlin</string>
<string name="texto">una prueba de escritura en memoria externa</string>
<string name="botonEsc">Guardar</string>
<string name="botonLee">Leer</string>
<string name="propiedades">Propiedades del fichero</string>
</resources>
activity_main.xml
<?xml version = "1.0" encoding = "utf-8" ?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText"
android:layout_width="270dp"
android:layout_height="156dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="68dp"
android:ems="10"
android:gravity="top|left"
android:text="@string/texto"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.04" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/swExplorer"
android:layout_width="170dp"
android:layout_height="48dp"
android:layout_marginBottom="20dp"
android:checked="false"
android:text="Explorador"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="265dp" />
<Button
android:id="@+id/btnWrite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="36dp"
android:layout_marginEnd="236dp"
android:text="@string/botonEscribir"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline"
app:layout_constraintVertical_bias="0.025" />
<Button
android:id="@+id/btnRead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="49dp"
android:layout_marginEnd="68dp"
android:text="@string/botonLeer"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@+id/btnWrite"
app:layout_constraintTop_toTopOf="@+id/guideline"
app:layout_constraintVertical_bias="0.025" />
<TextView
android:id="@+id/textView"
android:layout_width="310dp"
android:layout_height="236dp"
android:text="@string/propiedades"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText"
app:layout_constraintVertical_bias="0.599" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity(), View.OnClickListener {
lateinit var binding: ActivityMainBinding
companion object {
const val FICHERO = "ficheroExterna.txt"
val RELATIVE_PATH = Environment.DIRECTORY_DOCUMENTS + "/"
// val RELATIVE_PATH = Environment.DIRECTORY_DOCUMENTS + "/ficheros/" //end "/" is not mandatory
val TYPE = "text/plain"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
val view: View = binding.root
setContentView(view)
binding.btnWrite.setOnClickListener(this)
binding.btnRead.setOnClickListener(this)
}
override fun onClick(view: View) {
if (view === binding.btnWrite)
if (!binding.swExplorer.isChecked)
writeTextFileToMediaStore(FICHERO)
else
saveFileExplorer()
else if (view === binding.btnRead)
if (!binding.swExplorer.isChecked)
readTextFileFromMediaStore(FICHERO)
else
openAndReadFile()
}
// write and read the file
}
Ask Gemini
For Android 10 and higher, give me the code in Kotlin to write a text file to the user’s «Documents» directory using the Storage Access Framework (SAF)
private fun saveFileExplorer() {
val fileName = FICHERO //"my_document.txt"
val mimeType = TYPE
// Create an intent to create a new document
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mimeType
putExtra(Intent.EXTRA_TITLE, fileName)
}
// Launch the activity to create the document
createDocumentLauncher.launch(intent)
}
private val createDocumentLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.let { uri ->
// Write the data to the file
writeFile(uri, binding.editText.text.toString())
}
} else {
Log.e("MyTag", "Error creating file")
}
}
private fun writeFile(uri: Uri, data: String) {
//val fileUri: Uri = uri
uri.let { fileUri ->
try {
contentResolver.openOutputStream(fileUri)?.use { outputStream ->
outputStream.write(data.toByteArray())
Log.d("MyTag", "File written successfully to: $fileUri")
}
} catch (e: IOException) {
Log.e("MyTag", "Error writing to file: $fileUri", e)
}
}
}
Ask Gemini
For Android 10 and higher, give me the code in Kotlin to read a text file using the Storage Access Framework (SAF)
private fun openAndReadFile() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/plain" // Filter for text files
}
openFileLauncher.launch(intent)
}
private val openFileLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.let { uri ->
readFileContent(uri)
}
} else {
Log.e("MyTag", "File not selected")
}
}
private fun readFileContent(uri: Uri) {
try {
contentResolver.openInputStream(uri)?.use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
val fileContent = reader.readText()
binding.editText.setText(fileContent)
Log.d("MyTag", "File content: $fileContent")
}
}
showMessage("File read successfully:\n $FICHERO")
} catch (e: IOException) {
binding.editText.setText("Error reading file")
showMessage("Fail to read the file:\n $FICHERO \n" + e.message.toString())
Log.e("MyTag", "Error reading file" + e.message.toString())
}
}
private fun showMessage(texto: String) {
Toast.makeText(this, texto, Toast.LENGTH_SHORT).show()
}
Ask Gemini:
give me the code to write a text file in kotlin using MediaStore
fun writeTextFileToMediaStore(fileName: String) {
val relativePath = RELATIVE_PATH
val type = TYPE
try {
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName) //file name
values.put(MediaStore.MediaColumns.MIME_TYPE, type) //file extension, will automatically add to file
values.put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath)
val uri = contentResolver.insert(MediaStore.Files.getContentUri("external"), values) //important!
val outputStream = contentResolver.openOutputStream(uri!!)
outputStream!!.write(binding.editText.text.toString().toByteArray())
outputStream.close()
getFileProperties(uri)
showMessage("File created successfully: $FICHERO")
} catch (e: IOException) {
showMessage("Fail to create file: " + e.message.toString())
}
}
Ask Gemini:
give me the code in Kotlin to get the properties of the file (path and creation date) after I write it
private fun getFileProperties(uri: Uri) {
val projection = arrayOf(
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DATE_ADDED
)
val query = contentResolver.query(
uri,
projection,
null,
null,
null
)
query?.use { cursor ->
val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA)
val dateAddedColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATE_ADDED)
if (cursor.moveToFirst()) {
val path = cursor.getString(dataColumn)
val dateAddedTimestamp = cursor.getLong(dateAddedColumn)
val dateFormat = SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault())
val creationDate = dateFormat.format(Date(dateAddedTimestamp * 1000))
binding.textView.text = "File Path: $path\n Creation Date: $creationDate"
Log.d("MyTag", "File Path: $path")
Log.d("MyTag", "Creation Date: $creationDate")
} else {
binding.textView.text = "File properties not found"
Log.e("MyTag", "File properties not found")
}
}
}
Ask Gemini:
give me the code to read a text file in kotlin using MediaStore, the file relative path is Environment.DIRECTORY_ DOCUMENTS
private fun readTextFileFromMediaStore(fileName: String) {
val relativePath = RELATIVE_PATH
val collection =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
MediaStore.Files.getContentUri("external")
}
val projection = arrayOf(
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.RELATIVE_PATH
)
val selection = "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ? AND ${MediaStore.Files.FileColumns.RELATIVE_PATH} = ?"
val selectionArgs = arrayOf(fileName, relativePath)
val query = contentResolver.query(
collection,
projection,
selection,
selectionArgs,
null
)
query?.use { cursor ->
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)
val relativePathColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.RELATIVE_PATH)
if (cursor.moveToFirst()) {
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val path = cursor.getString(relativePathColumn)
val contentUri: Uri = Uri.withAppendedPath(collection, id.toString())
Log.d("MyTag", "Found file: $name, Path: $path, Uri: $contentUri")
readFileContent(contentUri)
} else {
showMessage("File not found: $FICHERO")
Log.e("MyTag", "File not found")
}
}
}
/*
private fun readFileContent(uri: Uri) {
try {
contentResolver.openInputStream(uri)?.use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
val fileContent = reader.readText()
binding.editText.setText(fileContent)
Log.d("MyTag", "File content: $fileContent")
}
}
showMessage("File read successfully:\n $FICHERO")
} catch (e: IOException) {
binding.editText.setText("Error reading file")
showMessage("Fail to read the file:\n $FICHERO \n" + e.message.toString())
Log.e("MyTag", "Error reading file" + e.message.toString())
}
}
*/
Más información:
Access media files from shared storage
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.