Can't get file uri from intent onActivityResult
I would like to receive normal file path from onActivityResult like this:
My guess is that you are using ACTION_OPEN_DOCUMENT
, or perhaps ACTION_GET_CONTENT
. You are getting a content
Uri
, which is exactly what those Intent
actions are documented to return. Such a Uri
might be backed by:
- A local file on external storage, which you probably cannot access on Android 10+
- A local file on internal storage for the other app
- A local file on removable storage
- A local file that is encrypted and needs to be decrypted on the fly
- A stream of bytes held in a
BLOB
column in a database - A piece of content on the Internet that needs to be downloaded by the other app first
- Content that is generated on the fly
- ...and so on
this exception comes from method which converts my file to string
I assume that by "converts my file to string", you mean read the file contents in as a String
. In that case:
- Get a
ContentResolver
by callinggetContentResolver()
on aContext
, such as yourActivity
- Call
openInputStream()
on theContentResolver
, passing in yourUri
, to get anInputStream
on the content identified by theUri
- Call
reader().readText()
on theInputStream
to get aString
representing the file contents
Combined, that should be something like:
val string = data.data?.let { contentResolver.openInputStream(it).use { it.reader().readText() } }
onActivityResult's intent.getPath() doesn't give me the correct filename
I am trying to fetch a file
Not with that code. That code is asking the user to pick a piece of content. This may or may not be a file.
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath()
That was never correct, though it tended to work on older versions of Android.
So what to do?
Well, that depends.
If you wish to only accept files, integrate a file chooser library instead of using (UPDATE 2019-04-06: since Android Q is banning most filesystem access, this solution is no longer practical)ACTION_GET_CONTENT
.
If you are willing to allow the user to pick a piece of content using ACTION_GET_CONTENT
, please understand that it does not have to be a file and it does not have to have something that resembles a filename. The closest that you will get:
If
getScheme()
of theUri
returnsfile
, your original algorithm will workIf
getScheme()
of theUri
returnscontent
, useDocumentFile.fromSingleUri()
to create aDocumentFile
, then callgetName()
on thatDocumentFile
— this should return a "display name" which should be recognizable to the user
onActivityResult Uri - create subfolder and get DocumentUri of new subfolder
DocumentFile subfolderDf = DocumentFile.fromTreeUri(this,uri);
subfolderDf.createDirectory("TestFolder");
Change to:
DocumentFile folder = DocumentFile.fromTreeUri(this, uri);
DocumentFile subfolder = folder.createDirectory("TestFolder");
if ( subfolder == null )
{
Toast.makeText(context, "Sorry, could not create a subfolder with name TestFolder", Toast.LENGTH_LONG).show();
return;
}
Toast.makeText(context, "Created a subfolder with name TestFolder: " + subfolder.getUri().toString(), Toast.LENGTH_LONG).show();
Android: Converting a URI to File
I would simply like to take the file from the app's internal storage and save it to whatever directory the user selected
The user didn't select a directory. The user is creating a document, where the Uri
points to that document.
How do I convert the returned Uri into a File so I can write data more easily?
You don't, any more than you convert an HTTPS URL into a File
so you can write data more easily.
Use ContentResolver
and openOutputStream()
to open an OutputStream
on the (empty) document created by ACTION_CREATE_DOCUMENT
and identified by the returned Uri
. Then, use standard Java I/O to copy the bytes from your file (e.g., via a FileInputStream
) to the OutputStream
.
Get PDF from MediaStore after receiving content:// Uri in onActivityResult?
This is how I'm getting pdf as file :
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
type = "application/pdf"
addCategory(Intent.CATEGORY_OPENABLE)
flags = flags or Intent.FLAG_GRANT_READ_URI_PERMISSION
}
startActivityForResult(intent, 111)
Inside your OnActivityResult(requestCode:Int,resultCode:Int,data:Intent?)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
// 101 -> {
// data?.data?.also { uri ->
// Log.i(TAG, "Uri: $uri")
// baseAdapter?.add(ImageArray(null, null, uri.toString()))
// }
// }
111 -> {
data?.data?.also { documentUri ->
baseActivity.contentResolver?.takePersistableUriPermission(
documentUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val file = DocumentUtils.getFile(baseActivity,documentUri)//use pdf as file
}
}
}
}
Singleton class to covert Uri to file:
object DocumentUtils {
fun getFile(mContext: BaseActivity?, documentUri: Uri): File {
val inputStream = mContext?.contentResolver?.openInputStream(documentUri)
var file = File("")
inputStream.use { input ->
file =
File(mContext?.cacheDir, System.currentTimeMillis().toString()+".pdf")
FileOutputStream(file).use { output ->
val buffer =
ByteArray(4 * 1024) // or other buffer size
var read: Int = -1
while (input?.read(buffer).also {
if (it != null) {
read = it
}
} != -1) {
output.write(buffer, 0, read)
}
output.flush()
}
}
return file
}
}
P.S: Do not forget to ask permission at runtime
Manifest.permission.WRITE_EXTERNAL_STORAGE
Manifest.permission.READ_EXTERNAL_STORAGE
Related Topics
Play Sound Using Soundpool Example
Android Studio Fails to Build New Project, Timed Out While Wating for Slave Aapt Process
Using Onsaveinstancestate with Fragments in Backstack
How to Use Front and Back Camera at Same Time in Android
How to Write a Custom Filter for Listview with Arrayadapter
How to Get Number of Lines of Textview
Get Image from the Gallery and Show in Imageview
Android Studio: Creating Landscape Layouts
Editing Functionality of Host Card Emulation in Android
Android Background Drawable Not Working in Button Since Android Studio 4.1
How to Run a Service Every Day at Noon, and on Every Boot
Horizontalscrollview: Auto-Scroll to End When New Views Are Added
How to to Check If a User Has Rated Your App on the Google Play