如何在Android 10(Android Q)中访问外部存储? [英] How to get Access to External Storage in Android 10 (Android Q)?

查看:2163
本文介绍了如何在Android 10(Android Q)中访问外部存储?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚将源代码迁移到Androidx,因为这样做是因为共享声音的共享功能不再起作用. Logcat说:

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)

这是保存声音的部分:

            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());
            }

这是共享声音的代码:

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());
                        }
                    }

我必须更改什么?如何归档每个人,无论他使用的是哪个Android版本(minSdkVersion 16),都可以下载并共享声音?

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?

可悲的是,我收到了很多atm不好的评论,因为没有人可以分享(即使以前只有Android 9及更低版本也没有) 谢谢

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

推荐答案

如果您定位的是Android 10或更高版本,请在应用的清单文件中将requestLegacyExternalStorage的值设置为true:

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>

访问文件

要加载媒体文件,请从 ContentResolver 中调用以下方法之一:

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.
}

在运行Android 10(API级别29)及更高版本的设备上,您的应用可以通过使用IS_PENDING标志在写入磁盘时获得对媒体文件的独占访问权限.

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);

这篇关于如何在Android 10(Android Q)中访问外部存储?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆