0

I using the the following code to get open the image picker:

val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
        type = "image/*"
    }
startActivityForResult(intent, REQUEST_IMAGE_PICK)

I then use a standard piece of code to get the image from the URI which is as follows (it is in onActivity result):

val uri:Uri = data.data
            val imageP = getPath(context!!,uri)
//              Glide.with(this)
//                      .load(data.data)
//                      .apply(GlobalSiteRecords.options)
//                      .into(companyImageView)
//              return
            **imagePath = Uri.parse(imageP).toString()// NULL POINTER EXCEPTION HERE**
// following function loads the image and saves the path
                loadImageAndStoreImagePath(imagePath)
            } catch(e:Exception){
                e.printStackTrace()
                val a = Toast.makeText(activity,"Error reading file, please try a different file!",Toast.LENGTH_SHORT)
                a.setGravity(Gravity.FILL_HORIZONTAL,0,0)
                a.show()
            }

Get path function is the following:

        fun getPath(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() + File.separator + split[1]
                }

                // TODO handle non-primary volumes
            } else if (isDownloadsDocument(uri)) {

                val id:String = DocumentsContract.getDocumentId(uri)
                val contentUri:Uri = 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:String = 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)
            }// MediaProvider
            // DownloadsProvider
        } else if ("content".equals(uri.getScheme(), ignoreCase = true)) {

            // Return the remote address
            return if (isGooglePhotosUri(uri)) uri.getLastPathSegment() else getDataColumn(context, uri, null, null)

        } else if ("file".equals(uri.getScheme(), ignoreCase = true)) {
            return uri.getPath()
        }// File
        // MediaStore (and general)

        return null
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    fun getDataColumn(context: Context, uri: Uri?, selection: String?,
                      selectionArgs: Array<String>?): String? {

        var cursor: Cursor? = null
        val column = "_data"
        val projection = arrayOf(column)

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null)
            if (cursor != null && cursor.moveToFirst()) {
                val index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(index)
            }
        } finally {
            if (cursor != null)
                cursor.close()
        }
        return null
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents".equals(uri.getAuthority())
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority())
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents".equals(uri.getAuthority())
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    fun isGooglePhotosUri(uri: Uri): Boolean {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority())
    }
 }
}

I am not sure what the problem is here. I tried loading the image using URI and Glide directly before processing for imagepath and it works fine but unfortunately if I don't have imagepath I cannot save a copy of the image which is what I want to do.

Ashish
  • 6,791
  • 3
  • 26
  • 48
Damandroid
  • 756
  • 9
  • 31
  • 1
    "if I don't have imagepath I cannot save a copy of the image" – Yes you can. Use the [`ContentResolver#openInputStream(Uri)` method](https://developer.android.com/reference/android/content/ContentResolver.html#openInputStream(android.net.Uri)) to open an `InputStream`, and then copy that using basic file I/O. – Mike M. Jan 08 '19 at 19:27
  • Is it possible to have a more code based example for your suggestion please? – Damandroid Jan 08 '19 at 19:41
  • 1
    https://stackoverflow.com/q/13133579, https://stackoverflow.com/q/21960650, https://stackoverflow.com/a/52095352, https://stackoverflow.com/a/45520771 – Mike M. Jan 08 '19 at 19:50
  • Thanks. Also I would like to know what is going wrong in the code above please? – Damandroid Jan 10 '19 at 10:39
  • Well, it's just fundamentally wrong code, mainly because a `Uri` is not a `File`, and there is no guarantee that the data backing that `Uri` is a file with an accessible file path. – Mike M. Jan 10 '19 at 16:06

0 Answers0