为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

互换的青春 2024-01-17 20:52:13
我刚刚将源代码迁移到 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);                                }我需要改变什么?如何让每个人无论使用哪个 Android 版本(minSdkVersion 16)都可以下载和分享声音?
查看完整描述

2 回答

?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

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


<manifest ... >

  <!-- This attribute is "false" by default on apps targeting

       Android 10 or higher. -->

  <application android:requestLegacyExternalStorage="true" ... >

    ...

  </application>

</manifest>

访问文件


(以下两个代码块来自developer.android.com文档。)


要加载媒体文件,请从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);


查看完整回答
反对 回复 2024-01-17
?
慕运维8079593

TA贡献1876条经验 获得超5个赞

我被困了很长时间,这对我来说效果很好

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

并且不要忘记在清单文件中请求旧存储。

  <application android:requestLegacyExternalStorage="true" >


查看完整回答
反对 回复 2024-01-17
  • 2 回答
  • 0 关注
  • 45 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信