如何在 Android 10 (Android Q) 中访问外部存储?

用户访问权限

我刚刚将我的源代码迁移到了 Androidx,因为我这样做了我的共享功能来共享声音不再工作。Logcat 说:

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)都可以下载和分享声音?

可悲的是,我收到了很多差评,因为没有人可以分享(即使 Android 9 及以下版本也无法分享,尽管他们曾经可以)谢谢

贾斯帕辛戈希尔

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

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

访问文件

要加载媒体文件,请从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 标志获得对写入磁盘的媒体文件的独占访问权限。

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Android 10中访问外部存储?

从Android Q中的外部存储访问照片

如何在Android Q中请求外部文件访问权限?

如何在Android Q(10)中以编程方式访问剪贴板数据?

如何在Android中访问外部存储卡

无法访问 Android Q 中的存储

如何直接从Android 10(Q)上的外部下载目录中读取文件

如何直接将文件下载到Android Q(Android 10)的下载目录中

如何在Android Q中从Mediastore获取专辑?

Android Q范围存储和外部库

以编程方式测试是否在Android 10+中禁用了旧版外部存储访问

如何访问Android Q中的所有图片?

如何在Android Q上设置闹钟?

我们如何在Android Q中访问扩展文件?

如何从Android Q中的图库获取图像?

如何拍照并保存在Android Q中?

在Android API中访问外部存储29

如何获取android q中android文档目录的路径?

如何将文件从应用程序的内部存储移动到Android Q(10)中手机的下载目录中?

在Android Q中替换ContentResolver查询中的“ GROUP BY”(对Android 10,API 29进行了更改)

如何在Android中安全存储访问令牌和机密?

如何在Android NDK中访问USB大容量存储

访问存储在 Android Q 内部存储器中的数据库

如何在Android 10中获取图像的方向信息?

如何在Android 10中打开活动(传入的voip呼叫)

如何在Android 10中显示每日离线通知?

如何在Android 10中打开APK文件

如何在Android中检查日期在10天内

如何在android 10中通过意图共享图像