Android Q Beta中的文件操作

时间:2019-08-06 07:08:07

标签: android fileoutputstream android-10.0

1)使用““ android.permission.WRITE_EXTERNAL_STORAGE”“将目标设置为Android Q

2)使用getExternalStorageDirectory或getExternalStoragePublicDirectory和FileOutputStream(file)保存文件抛出

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

3)使用getExternalFilesDir api,保存成功,但即使在MediaScannerConnection.scanFile之后也不会显示。

 /storage/emulated/0/Android/data/my.com.ui/files/Download/myfolder/mytext.txt

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

6 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:4)

临时可能:您可以在Android清单的android:requestLegacyExternalStorage="true"标签中使用<application>

答案 2 :(得分:3)

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

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

File destination = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);

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

 ContentValues values = new ContentValues(); 
 values.put(MediaStore.Images.Media.TITLE, fileName); 
 values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);

///如果需要特定的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

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

Uri uri = cxt.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); 

//使用该URI打开文件。

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

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

InputStream dataInputStream = cxt.openFileInput(privatePath_file_path);

//将文件写入文件流。

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

答案 3 :(得分:2)

在Android Manifest的android:requestLegacyStorage="true"标签中添加<application>,现在您可以使用所有文件API。

答案 4 :(得分:1)

1)使用文档提供者https://developer.android.com/guide/topics/providers/document-provider#create

2)将要求用户保存(文件总数)并存储在documents文件夹中。 https://gist.github.com/neonankiti/05922cf0a44108a2e2732671ed9ef386

答案 5 :(得分:0)

如果使用preserveLegacyExternalStorage,则旧存储模型仅在用户卸载您的应用程序之前保持有效。如果用户在运行Android 11的设备上安装或重新安装您的应用程序,则无论keepLegacyExternalStorage的值如何,您的应用程序都不能选择范围内的存储模型。

使用此标志时要记住的事情。 know more