user15365603
user15365603

Reputation:

How to select file on android 11

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

Answers (2)

Tuan Dang Van
Tuan Dang Van

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

Peppe L-G
Peppe L-G

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

Related Questions