Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Access to External Storage in Android 10 (Android Q)?

I just migrated my sourcecode to Androidx, since I did that my share function to share a sound is no longer working. the Logcat says:

Failed to save file: /storage/emulated/0/appfolder/testsound.mp3 (Permission denied)

This is the part where it saves the sound:

            final String fileName = soundObject.getItemName() + ".mp3";
            File storage = Environment.getExternalStorageDirectory();
            File directory = new File(storage.getAbsolutePath() + "/appfolder/");
            directory.mkdirs();
            final File file = new File(directory, fileName);
            InputStream in = view.getContext().getResources().openRawResource(soundObject.getItemID());

            try{
                Log.i(LOG_TAG, "Saving sound " + soundObject.getItemName());
                OutputStream out = new FileOutputStream(file);
                byte[] buffer = new byte[1024];

                int len;
                while ((len = in.read(buffer, 0, buffer.length)) != -1){
                    out.write(buffer, 0 , len);
                }
                in.close();
                out.close();

            } catch (IOException e){

                Log.e(LOG_TAG, "Failed to save file: " + e.getMessage());
            }

And this is the code where it shares the sound:

try{
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){


                                if (ActivityCompat.checkSelfPermission(view.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
                                    ActivityCompat.requestPermissions((Activity) view.getContext(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);

                                }else {
                                    final String AUTHORITY = view.getContext().getPackageName() + ".fileprovider";
                                    Uri contentUri = FileProvider.getUriForFile(view.getContext(), AUTHORITY, file);
                                    final Intent intent = new Intent(Intent.ACTION_SEND);
                                    intent.putExtra(Intent.EXTRA_STREAM, contentUri);
                                    intent.setType("audio/mp3");
                                    view.getContext().startActivity(Intent.createChooser(intent, "Share sound via..."));
                                }


                            }
                            else {
                                final Intent intent = new Intent(Intent.ACTION_SEND);
                                Uri fileUri = Uri.parse(file.getAbsolutePath());
                                intent.putExtra(Intent.EXTRA_STREAM, fileUri);
                                intent.setType("audio/mp3");
                                view.getContext().startActivity(Intent.createChooser(intent, "Share sound via..."));
                            }

                        } catch (Exception e){
                            Log.e(LOG_TAG, "Failed to share sound: " + e.getMessage());
                        }
                    }

What do I have to change and how can I archieve that everyone no matter which Android Version he is using (minSdkVersion 16) can download and share the sound?

Sadly I'm getting many bad reviews atm because no one can share (Not even Android 9 and below eventhough they used to be able to) Thank you

like image 989
TheUseracc awd Avatar asked Oct 30 '19 12:10

TheUseracc awd


People also ask

How do I get write permission for external storage on Android?

To read and write data to external storage, the app required WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE system permission. These permissions are added to the AndroidManifest. xml file. Add these permissions just after the package name.

How do you access storage on Android?

You can also access free internal storage from your Android phone through Settings > System > Storage > Device storage. Here you can preview what data are using your internal storage and how much free storage you can use furtherly.

What is external storage in Android?

This article is continuation of the Android Internal Storage tutorial in the series of tutorials on structured data storage in android. External storage such as SD card can also store application data, there’s no security enforced upon files you save to the external storage. In general there are two types of External Storage:

How to check external storage availability in Android Studio?

External Storage Availability In Android Studio To avoid crashing app it is required to check before whether storage SD card is available for read & write operations. getExternalStorageState () method is used to determine the state of the storage media i.e SD card is mounted, is it readable, it is writable etc.. all this kind of information.

Why can't my Android app access files in external storage?

On Android 11, apps can no longer access files in any other app's dedicated, app-specific directory within external storage. To protect user privacy, on devices that run Android 11 or higher, the system further restricts your app's access to other apps' private directories.

How to add external storage permission in Android?

Important Note: It is necessary to add external storage the permission to read and write. For that you need to add permission in android Manifest file. Open AndroidManifest.xml file and add permissions to it just after the package name.


2 Answers

If you target Android 10 or higher, set the value of requestLegacyExternalStorage to true in your app's manifest file:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting
       Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Access files

To load media files, call one of the following methods from ContentResolver:

 Uri contentUri = ContentUris.withAppendedId(
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
        cursor.getLong(Integer.parseInt(BaseColumns._ID)));
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(uri, fileOpenMode);
if (parcelFd != null) {
    int fd = parcelFd.detachFd();
    // Pass the integer value "fd" into your native code. Remember to call
    // close(2) on the file descriptor when you're done using it.
}

On devices running Android 10 (API level 29) and higher, your app can get exclusive access to a media file as it's written to disk by using the IS_PENDING flag.

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.IS_PENDING, 1);

ContentResolver resolver = context.getContentResolver();
Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri item = resolver.insert(collection, values);

try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(item, "w", null)) {
    // Write data into the pending image.
} catch (IOException e) {
    e.printStackTrace();
}

// Now that we're finished, release the "pending" status, and allow other apps
// to view the image.
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(item, values, null, null);
like image 191
Jaspalsinh Gohil Avatar answered Oct 25 '22 22:10

Jaspalsinh Gohil


I have been stuck for a long time and this worked fine for me

  StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());
    File = new File(filepath);

and don't forget to request legacy Storage in manifest file.

  <application android:requestLegacyExternalStorage="true" >
like image 41
Mohamed AbdelraZek Avatar answered Oct 25 '22 23:10

Mohamed AbdelraZek