I tried to load images from a directory using Intent.ACTION_OPEN_DOCUMENT_TREE and it worked fine until I tried to save the URI I got to preferences. Then I could read it but there were no files in the directory (tree.listFiles() from the chosen folder was of size 0). I thought that the issue was that there was no access to that directory from the start, because when I chose a folder using startActivityForResult() it asked if I wanted to give the app permission to read files from that directory. But that wasn't the case, as I understood from asking for READ_EXTERNAL_STORAGE permission as it didn't solve the problem.
I worked out a minimal example that demonstrates what isn't working:
package com.example.loadingtest
import android.Manifest
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.DocumentsContract
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile
class FullscreenActivity : AppCompatActivity(), View.OnClickListener {
lateinit var preferences: SharedPreferences
var text = ""
val pickCode = 1
lateinit var textField:TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fullscreen)
val permissionStorage = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
val requestExternalStorage = 1
val permission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
if(permission != PackageManager.PERMISSION_GRANTED){
requestPermissions(permissionStorage, requestExternalStorage)
}
textField = findViewById(R.id.texttest)
text = getString(R.string.txt_amount)
val btn = findViewById<Button>(R.id.btntest)
btn.setOnClickListener(this)
preferences = getPreferences(MODE_PRIVATE)
val path = preferences.getString("path","")
if(path != null && path != ""){
loadImages(path.toUri())
}
}
fun loadImages(uri: Uri){
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, DocumentsContract.getTreeDocumentId(uri))
val tree = DocumentFile.fromTreeUri(this, childrenUri) ?: return
val files = tree.listFiles()
textField.text = String.format(text, files.size)
}
override fun onClick(v: View?) {
if(v == null) return
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, pickCode)
}
override fun onActivityResult(requestCode:Int, resultCode:Int, data: Intent?){
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == pickCode){
if(resultCode == RESULT_OK){
data?.data.also{
uri ->
if(uri!=null){
loadImages(uri)
val editor = preferences.edit()
val str = uri.toString()
editor.putString("path", str)
editor.apply()
}
}
}
}
}
}
The layout is as simple as a button to pick the folder and a TextView to show the amount of files in that chosen directory. The TextView should also show that there are files in the directory that I loaded from preferences, but it does not. Layout file (not necessary to the problem, I suppose):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/fullscreenBackgroundColor"
android:theme="@style/ThemeOverlay.GuidedAttempt.FullscreenContainer"
tools:context=".FullscreenActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/btntest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<TextView
android:id="@+id/texttest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</FrameLayout>
The android manifest file also includes
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
, so the app should(?) have access to external storage when the permission is granted.
You do not need READ_EXTERNAL_STORAGE.
Just take persistable uri permission in onActivityResult in order to use the obtained uri later.