I want to use some .pdf files in my app which are located in external storage. For using those files in android 10&11 I am going to copy files into internal storage. My code is working well in Android 10 but not in Android 11
Exception: java.io.FileNotFoundException: open failed: EACCES (Permission denied)
error is coming.
My code is as below;
manifest
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.packagename"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
<files-path
name="."
path="/"/>
</paths>
in fragment
val contentUri = FileProvider.getUriForFile(
context,
"com.packagename",
File("/sdcard/Documents/PDFConverter/my_file.pdf")
)
ScopeStoreUtils.copyFileIntoFiles(context, contentUri)
util class
object ScopeStoreUtils {
fun copyFileIntoFilesDir(context: Context, fileUri: Uri) {
if (Build.VERSION.SDK_INT >= 29) {
// r for read
try {
val parcelFileDescriptor =
context.contentResolver.openFileDescriptor(fileUri, "r", null)
val inputStream = FileInputStream(parcelFileDescriptor?.fileDescriptor)
val destinationFile = File(context.filesDir,
context.contentResolver.getFileName(fileUri))
val outputStream = FileOutputStream(destinationFile)
copy(inputStream, outputStream)
} catch (e: Exception) {
Log.e("ScopeStoreUtils", "copyFileIntoFilesDir: Exception: $e")
}
}
}
private fun ContentResolver.getFileName(fileUri: Uri): String {
var name = ""
val returnCursor = this.query(fileUri, null, null, null, null)
if (returnCursor != null) {
val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
returnCursor.moveToFirst()
name = returnCursor.getString(nameIndex)
returnCursor.close()
}
return name
}
@Throws(IOException::class)
fun copy(input: InputStream?, output: OutputStream?): Int {
val count = copyLarge(input!!, output!!)
return if (count > Int.MAX_VALUE) {
-1
} else count.toInt()
}
private const val DEFAULT_BUFFER_SIZE = 1024 * 4
@Throws(IOException::class)
fun copyLarge(input: InputStream, output: OutputStream): Long {
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
var count: Long = 0
var n: Int
while (-1 != input.read(buffer).also { n = it }) {
output.write(buffer, 0, n)
count += n.toLong()
}
return count
}
}