android Q beta 中的文件操作
File operations in android Q beta
1)目标设置为 Android Q
和 android.permission.WRITE_EXTERNAL_STORAGE
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 并刷新的最佳方法是什么。
在 Android 清单的 <application>
标签中添加 android:requestLegacyExternalStorage="true"
,这将允许您暂时使用所有文件 API。
In Android 默认情况下,Q direct 文件访问对于其私人文件夹之外的应用程序是禁用的。您可以使用以下几种策略:
- 使用清单选项
requestLegacyStorage
来获得旧的行为,但它不再适用于 Android R,因此它确实是一个短期解决方案;
- 使用
getExternalFilesDir()
方法保存文件。这是您的私人文件夹,其他应用只有在拥有 READ_EXTERNAL_STORAGE
权限的情况下才能访问这些文件。在这种情况下,最好使用 FileProvider
授予其他应用访问您的文件的权限。
- 使用
MediaStore
API 直接插入您的媒体。这种方法适用于视频、音乐和照片。
- 使用class
StorageManager
的方法getPrimaryStorageVolume().createOpenDocumentTreeIntent()
请求访问外部主卷。在这种情况下,您需要用户同意,并且您将无法直接使用 File
api,但是使用 DocumentFile
class 您有一个非常相似的界面,所以这个是更接近旧行为的解决方案。如果您需要在前台和后台执行操作,即没有用户交互,但第一次交互请求权限时除外。
- 使用
ACTION_CREATE_DOCUMENT
使用 SAF
创建文件。如果您在前台执行此操作,则此选项有效,因为您将需要用户选择文件夹。
我 link Flipper 第 4 点的库,它有助于像旧 android 版本一样管理文件。
1)使用文档提供者https://developer.android.com/guide/topics/providers/document-provider#create
2) 用户将被要求保存(文件总数)并存储在文档文件夹中。
https://gist.github.com/neonankiti/05922cf0a44108a2e2732671ed9ef386
在Android API 29及以上你可以使用下面的代码将文件、图片和视频存储到外部存储。
//首先,如果您使用 "android.media.action.IMAGE_CAPTURE" 选择文件
然后将该文件存储在应用程序私有路径(getExternalFilesDir())中,如下所示。
File destination = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);
//然后使用content provider获取对Media-store的访问,如下所示。
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
// 使用内容提供程序插入媒体存储,它将 return 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();
}
临时可能性:您可以在 Android 清单中的 <application>
标签中使用 android:requestLegacyExternalStorage="true"
。
如果您使用 preserveLegacyExternalStorage,则旧存储模型仅在用户卸载您的应用程序之前一直有效。如果用户在运行 Android 11 的设备上安装或重新安装您的应用程序,那么无论 preserveLegacyExternalStorage 的值如何,您的应用程序都不能选择退出范围存储模型。
使用这个标志时要记住一些事情。 know more
1)目标设置为 Android Q
和 android.permission.WRITE_EXTERNAL_STORAGE
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 并刷新的最佳方法是什么。
在 Android 清单的 <application>
标签中添加 android:requestLegacyExternalStorage="true"
,这将允许您暂时使用所有文件 API。
In Android 默认情况下,Q direct 文件访问对于其私人文件夹之外的应用程序是禁用的。您可以使用以下几种策略:
- 使用清单选项
requestLegacyStorage
来获得旧的行为,但它不再适用于 Android R,因此它确实是一个短期解决方案; - 使用
getExternalFilesDir()
方法保存文件。这是您的私人文件夹,其他应用只有在拥有READ_EXTERNAL_STORAGE
权限的情况下才能访问这些文件。在这种情况下,最好使用FileProvider
授予其他应用访问您的文件的权限。 - 使用
MediaStore
API 直接插入您的媒体。这种方法适用于视频、音乐和照片。 - 使用class
StorageManager
的方法getPrimaryStorageVolume().createOpenDocumentTreeIntent()
请求访问外部主卷。在这种情况下,您需要用户同意,并且您将无法直接使用File
api,但是使用DocumentFile
class 您有一个非常相似的界面,所以这个是更接近旧行为的解决方案。如果您需要在前台和后台执行操作,即没有用户交互,但第一次交互请求权限时除外。 - 使用
ACTION_CREATE_DOCUMENT
使用SAF
创建文件。如果您在前台执行此操作,则此选项有效,因为您将需要用户选择文件夹。
我 link Flipper 第 4 点的库,它有助于像旧 android 版本一样管理文件。
1)使用文档提供者https://developer.android.com/guide/topics/providers/document-provider#create
2) 用户将被要求保存(文件总数)并存储在文档文件夹中。 https://gist.github.com/neonankiti/05922cf0a44108a2e2732671ed9ef386
在Android API 29及以上你可以使用下面的代码将文件、图片和视频存储到外部存储。
//首先,如果您使用 "android.media.action.IMAGE_CAPTURE" 选择文件 然后将该文件存储在应用程序私有路径(getExternalFilesDir())中,如下所示。
File destination = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);
//然后使用content provider获取对Media-store的访问,如下所示。
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
// 使用内容提供程序插入媒体存储,它将 return 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();
}
临时可能性:您可以在 Android 清单中的 <application>
标签中使用 android:requestLegacyExternalStorage="true"
。
如果您使用 preserveLegacyExternalStorage,则旧存储模型仅在用户卸载您的应用程序之前一直有效。如果用户在运行 Android 11 的设备上安装或重新安装您的应用程序,那么无论 preserveLegacyExternalStorage 的值如何,您的应用程序都不能选择退出范围存储模型。
使用这个标志时要记住一些事情。 know more