Primary directory not allowed for content://media/external/images/media/296; allowed directories are [DCIM, Pictures]

Viewed 2247

I was trying to rename a photo file in android api level > 28 (Pie) and getting java.lang.IllegalArgumentException: Primary directory WhatsApp not allowed for content://media/external/images/media/296; allowed directories are [DCIM, Pictures] exception

Below is the code for fetching images from storage

private fun getAllImages(): List<ImageModel>? {
    val allImagesUri = getExternalUriForImages()
    val columns = arrayOf(
            MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.DATE_ADDED, MediaStore.Images.Media.DATE_MODIFIED,
            MediaStore.Images.Media.HEIGHT, MediaStore.Images.Media.WIDTH)
    val cursor = application.contentResolver.query(allImagesUri, columns, null, null, null)
    return prepareImageModel(cursor)
}

private fun prepareImageModel(cursor: Cursor?):List<ImageModel>?{
    var images :MutableList<ImageModel>? = null
    if (cursor != null && cursor.count > 0) {
        images = mutableListOf()
        val idColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media._ID)
        val nameIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
        val dateAddedIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED)
        val dateModifiedIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)

        for (i in 0 until cursor.count) {
            cursor.moveToPosition(i)
            val id = cursor.getLong(idColumnIndex)
            if (id != -1L) {
                val name = cursor.getString(nameIndex)
                val dateAdded = cursor.getString(dateAddedIndex)
                val dateModified = cursor.getString(dateModifiedIndex)
                val uri = ContentUris.withAppendedId(getExternalUriForImages(), id)
                val imageModel = ImageModel(id, name, dateAdded, dateModified, uri = uri)
                images.add(imageModel)
            }
        }
    }
    return images
}

fun getExternalUriForImages(): Uri {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
        MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL) else {
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    }
}

data class ImageModel(var id: Long, var name: String?, var dateAdded: String? = "",
                      var dateModified: String? = "", var resolution: String? = "", var uri: Uri)

Below is the code for renaming a file

private fun renameFile(imageModel: ImageModel?) {
    if(imageModel != null){
        try {
            // When performing a single item update, prefer using the ID
            val selection = "${MediaStore.MediaColumns._ID} = ?"
            // By using selection + args we protect against improper escaping of // values.
            val selectionArgs = arrayOf(imageModel.id.toString())
            // Update an existing file.
            val contentValues = ContentValues().apply {
                put(MediaStore.MediaColumns.DISPLAY_NAME, "New name ${System.currentTimeMillis()}")
            }

            // Use the individual song's URI to represent the collection that's
            // updated.
            val rowsUpdated = contentResolver.update(imageModel.uri, contentValues, selection, selectionArgs)
            Toast.makeText(this, if(rowsUpdated > 0) "Rename success" else "Rename failed", Toast.LENGTH_SHORT).show()
        } catch (securityException: SecurityException) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                val recoverableSecurityException = securityException as?
                        RecoverableSecurityException ?:
                throw RuntimeException(securityException.message, securityException)
                val intentSender = recoverableSecurityException.userAction.actionIntent.intentSender
                intentSender?.let {
                    pendingImageModel = imageModel
                    startIntentSenderForResult(intentSender, REQUEST_RENAME_FILE, null, 0, 0, 0, null)
                }
            } else {
                throw RuntimeException(securityException.message, securityException)
            }
        }
    }
}

AndroidManifest file

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:requestLegacyExternalStorage="true"
    android:theme="@style/Theme.SimplePhotoApp">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
0 Answers
Related