Android 11: Primary directory (invalid) not allowed for content://media/external/file allowed directories are [Download, Documents]

14,564

I finally found a solution. I can't say it's a best solution but it works perfectly.

folderPath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + File.separator + "appFolderName";

to

folderPath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + File.separator + "appFolderName";

I suppose in Android 11, they allowed to create folder/file in DOWNLOADS folder but not DOCUMENTS. Best regards.

Note for Huawei Developers: You just keep the current file writing strategy. No need to Android 11 special code for now. I tried the new file writing method and it crashed. Apperantly, they didn't fully implemented Android 11.

Share:
14,564

Related videos on Youtube

Aykut Uludağ
Author by

Aykut Uludağ

Education: BSc in Mechanical Engineering in Çankaya University. Current works: Android&System Developer in Turkish State Railways (TCDD). Mainly working on a tablet app which control/manage rail transportation system. Android&Huawei Developer in e-Nabız Project. Official health app in Turkey, has more than 20 million user. I sometimes work with other projects of Ministry of Health of Turkey. --Android App: https://play.google.com/store/apps/details?id=tr.gov.saglik.enabiz --Huawei App: https://appgallery.huawei.com/#/app/C101184181 Some other private/goverment projects. Developing Android apps since 2011. Published many apps/games on GooglePlay/HuaweiAppGallery/AppleAppstore. You can see some of them in Github. I like to work with: Java, XML, Kotlin, Swift Unity, C#, PHP-SQL-HTML-CSS, Wordpress, Arduino etc. I don't like to work with: C++, Objective-C

Updated on June 02, 2022

Comments

  • Aykut Uludağ
    Aykut Uludağ about 2 years

    I am trying to create PDF file from base64 string. Because of Storage Update in Android 11, I have to change my code but I'm getting following error in Android 11 devices:

    java.lang.IllegalArgumentException: Primary directory (invalid) not allowed for content://media/external/file; allowed directories are [Download, Documents]
       at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
       at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
       at android.content.ContentProviderProxy.insert(ContentProviderNative.java:549)
       at android.content.ContentResolver.insert(ContentResolver.java:2149)
       at android.content.ContentResolver.insert(ContentResolver.java:2111)
    

    This code create a PDF file and save it into folder.

    public static void createPDF(Context mContext, String fileName, String base64) {
        try {
            String folderPath;
            File dwldsPath;
    
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
                folderPath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + File.separator + "appFolderName";
                dwldsPath = new File(folderPath + "/" + fileName);
    
                File folder = new File(folderPath);
                folder.mkdirs();
    
                ContentValues values = new ContentValues();
                values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName); // file name
                values.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf"); // file extension, will automatically add to file
                values.put(MediaStore.DownloadColumns.RELATIVE_PATH, folderPath); // end "/" is not mandatory
                Uri uriFile = mContext.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); // important!
                OutputStream outputStream = mContext.getContentResolver().openOutputStream(uriFile);
                outputStream.write(Base64.decode(base64, 0));
                outputStream.close();
            } else {
                folderPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + File.separator + "appFolderName";
                dwldsPath = new File(folderPath + "/" + fileName);
    
                File folder = new File(folderPath);
                folder.mkdirs();
    
                FileOutputStream os = new FileOutputStream(dwldsPath, false);
                os.write(Base64.decode(base64, 0));
                os.flush();
                os.close();
            }
    
            openPDF(mContext, dwldsPath);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ActivityNotFoundException e) {
            Toast.makeText(mContext, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
        }
    }
    

    This code is working for opening file

      public static void openPDF(Context mContext, File dwldsPath) {
            Intent intentUrl = new Intent(Intent.ACTION_VIEW);
            Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".provider", dwldsPath);
            intentUrl.setDataAndType(uri, "application/pdf");
            intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intentUrl.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            mContext.startActivity(intentUrl);
        }
    

    In addition to this error, folder.mkdirs() returns false in Android 11. Here is provider_paths.xml and defined in AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-path
            name="external"
            path="." />
        <external-files-path
            name="external_files"
            path="." />
        <files-path
            name="files"
            path="." />
    </paths>
    

    I google it but I couldn't find any working solution to fix problem. Thanks in advance.

    • Thomas
      Thomas about 3 years
      I'm no expert here but values.put(MediaStore.DownloadColumns.RELATIVE_PATH, folderPath); looks like you might have to put a path relative to the downloads directory, i.e. "appFolderName" in your case. Just a guess though.
    • Thomas
      Thomas about 3 years
      I can't tell about the new error but on the previous one I'd have a question: what do Environment.DIRECTORY_DOCUMENTS and mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS‌​) return? I'd assume the former acutally already describes the "Documents" directory you're working with while the latter might return null or an empty string thus resulting in a path like "/appFolderName".
    • Aykut Uludağ
      Aykut Uludağ about 3 years
      I found a solution. Apperantly there is no permission to write in documents in Android 11. But apperantly downloads folder are permissed to write folder/file.
  • valerybodak
    valerybodak almost 3 years
    But the function mContext.getExternalFilesDir(...) returns File. Not string.