Reputation:
I wish to select an image or a video from the Gallery of an Android Device. Store it in a variable of typeFile and upload to server. but when I selected a file csv for upload from adnroid 11 then seen error: targetAPI 29
AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=75535, result=-1, data=Intent { dat=content://com.android.providers.media.documents/document/document:4987 flg=0x1 }} to activity {MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:5457)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5498)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
Caused by: java.lang.NullPointerException
Here is the code get File:
@SuppressLint("NewApi")
fun getRealPathFromURI_API19(context: Context, uri: Uri): String? {
val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
}
// TODO handle non-primary volumes
} else if (isDownloadsDocument(uri)) {
val fileName = getFilePath(context, uri)
if (fileName != null) {
return Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName
}
val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)
)
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if ("image" == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if ("video" == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if ("audio" == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri, selection, selectionArgs)
} else if (isGoogleDriverUri(uri))
return uri.toString()
else if (isGoogleDriverUriDoc(uri))
return uri.toString()// MediaProvider
// DownloadsProvider
} else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.lastPathSegment
if (isGoogleDriverUri(uri))
return uri.toString()
return if (isGoogleDriverUriDoc(uri)) uri.toString() else getDataColumn(context, uri, null, null)
} else if ("file".equals(uri.scheme!!, ignoreCase = true)) {
return uri.path
}// File
// MediaStore (and general)
return null
}
I added requestLegacyExternalStorage in manifest file:
android:requestLegacyExternalStorage="true"
Upvotes: 2
Views: 3797
Reputation: 151
I use to get files and crash the same as you. I fixed:
val contentUri: Uri? = when (split[0]) {
"image" -> {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
"video" -> {
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
"audio" -> {
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
"document" -> {
MediaStore.Files.getContentUri("external")
}
else -> null
}
you can try it
Upvotes: 9
Reputation: 8360
If you target Android 11, requestLegacyExternalStorage
won't be used. That's probably the reason your code doesn't work on Android 11.
https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage
If you want the user to select a file your application should have read access to you should use the Storage Access Framework. When a user picks a file through that one, your app gets read access to that file.
Upvotes: 1