android Q beta中的文件操作

Nit*_*der 10 android fileoutputstream android-10.0

1)目标设定为Android Qandroid.permission.WRITE_EXTERNAL_STORAGE

2)使用getExternalStorageDirectorygetExternalStoragePublicDirectoryFileOutputStream(file)保存文件抛出

java.io.FileNotFoundException: /storage/emulated/0/myfolder/mytext.txt open failed: ENOENT (No such file or directory)

3)使用getExternalFilesDirapi并保存成功但即使之后也不会出现MediaScannerConnection.scanFile

     /storage/emulated/0/Android/data/my.com.ui/files/Download/myfolder/mytext.txt
Run Code Online (Sandbox Code Playgroud)

在android Q中将文件从内部存储器复制到SDCARD并刷新的最佳方法是什么。

小智 15

在 Android API 29 及更高版本中,您可以使用以下代码将文件、图像和视频存储到外部存储。

//首先,如果您使用“android.media.action.IMAGE_CAPTURE”选择文件,则将该文件存储在应用程序私有 Path(getExternalFilesDir()) 中,如下所示。

File destination = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);
Run Code Online (Sandbox Code Playgroud)

//然后使用内容提供程序访问媒体商店,如下所示。

 ContentValues values = new ContentValues(); 
 values.put(MediaStore.Images.Media.TITLE, fileName); 
 values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
Run Code Online (Sandbox Code Playgroud)

//如果您想要特定的 mime 类型,请在此处指定您的 mime 类型。否则将其留空,它将采用默认文件 mime 类型

values.put(MediaStore.Images.Media.MIME_TYPE, "MimeType"); 
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000); 
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); 
values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/" + "path"); // specify 
 storage path
Run Code Online (Sandbox Code Playgroud)

// 使用内容提供程序插入媒体存储,它将返回 URI。

Uri uri = cxt.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); 
Run Code Online (Sandbox Code Playgroud)

//使用该URI打开文件。

ParcelFileDescriptor descriptor = context.getContentResolver().openFileDescriptor(uri,"w"); //"w" specify's write mode
FileDescriptor fileDescriptor = descriptor.getFileDescriptor();
Run Code Online (Sandbox Code Playgroud)

// 从私有路径读取文件。

InputStream dataInputStream = cxt.openFileInput(privatePath_file_path);
Run Code Online (Sandbox Code Playgroud)

//将文件写入输出文件流。

 OutputStream output = new FileOutputStream(fileDescriptor);
 byte[] buf = new byte[1024];
 int bytesRead;
 while ((bytesRead = dataInputStream.read(buf)) > 0) 
 {
  output.write(buf, 0, bytesRead);
 }
 datanputStream.close();
 output.close();
}
Run Code Online (Sandbox Code Playgroud)

  • 私有文件路径是什么? (2认同)

gre*_*f82 13

在 Android Q 中,默认情况下禁用私有文件夹外的应用程序的直接文件访问。您可以使用以下几种策略:

  1. 使用 manifest 选项requestLegacyStorage具有旧行为,但它不再适用于 Android R,因此它确实是一个短期解决方案;
  2. 使用getExternalFilesDir()方法保存文件。这是你的私人文件夹,其他应用程序只有在他们有READ_EXTERNAL_STORAGE权限的情况下才能访问这些文件。在这种情况下,最好使用FileProvider授予对其他应用程序访问您的文件的权限。
  3. 使用MediaStoreAPI 直接插入您的媒体。这种方法适用于视频、音乐和照片。
  4. 使用getPrimaryStorageVolume().createOpenDocumentTreeIntent()类的方法StorageManager请求访问外部主卷。在这种情况下,您需要用户同意,并且File无论如何您都无法直接使用api,但是使用DocumentFileclass 您有一个非常相似的界面,因此这是更接近旧行为的解决方案。如果您需要在前台和后台执行操作,即没有用户交互,除了第一次请求权限的交互,它都可以工作。
  5. 用于ACTION_CREATE_DOCUMENT使用SAF. 如果您在前台执行此操作,则此选项有效,因为您将需要用户选择文件夹。

我为第 4 点链接了Flipper库,它有助于像在旧的 android 版本中一样管理文件。


Dar*_*han 5

添加android:requestLegacyExternalStorage="true"<application>标签在Android清单,这将允许您使用所有文件API,现在。

  • “没有其他办法”:您也可以放弃从 Android R+ 开始的支持并完全忽略该平台。总有一些选择......:)(我没有投反对票,但很高兴提到这个标志只是 Android Q 的临时标志,但另一个答案无论如何都更完整一点......尽管它可以有更明确地提到了 SAF(我只是在这里吃爆米花)) (2认同)