Google不幸地计划破坏存储权限,以使应用程序无法使用标准File API(和文件路径)访问文件系统。许多人反对它,因为它改变了应用程序访问存储的方式,并且在许多方面都是受限制的有限API。
因此,如果我们想处理各种问题,我们将需要在将来的某些Android版本上完全使用SAF(存储访问框架)(在Android Q上,我们至少可以暂时使用一个标志来使用常规存储权限)。存储卷并到达那里的所有文件。
因此,例如,假设您要创建一个文件管理器并显示设备的所有存储卷,以显示用户可以授予访问权限的内容,并且如果您已经可以访问每个文件,则只需输入该文件即可。这样的事情看起来很合理,但是由于我找不到解决方法。
从API 24(此处)开始,我们终于可以列出所有存储卷,如下所示:
val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
Run Code Online (Sandbox Code Playgroud)
而且,这是有史以来第一次,我们可以有一个Intent请求访问storageVolume(在此)。因此,例如,如果我们要请求用户授予对主数据库的访问权限(实际上是从那里开始,实际上并没有真正询问任何内容),则可以使用以下方法:
startActivityForResult(storageManager.primaryStorageVolume.createOpenDocumentTreeIntent(), REQUEST_CODE__DIRECTORTY_PERMISSION)
Run Code Online (Sandbox Code Playgroud)
代替startActivityForResult(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), REQUEST_CODE__DIRECTORTY_PERMISSION),希望用户在那里选择正确的东西。
为了最终获得用户选择的内容,我们需要执行以下操作:
@TargetApi(Build.VERSION_CODES.KITKAT)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE__DIRECTORTY_PERMISSION && resultCode == Activity.RESULT_OK && data != null) {
val treeUri = data.data ?: return
contentResolver.takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
val pickedDir = DocumentFile.fromTreeUri(this, treeUri)
...
Run Code Online (Sandbox Code Playgroud)
到目前为止,我们可以请求对各种存储卷的许可... …
我想保存 Whatsapp 的状态。通过使用此代码,我可以保存图像
public void saveImage(Bitmap bitmap, String name) {
OutputStream fileOutputStream;
Uri imageUri;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver contentResolver = context.getApplicationContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "" + name);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/V Troid/WhatsApp");
imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
fileOutputStream = (FileOutputStream) contentResolver.openOutputStream(Objects.requireNonNull(imageUri));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
Objects.requireNonNull(fileOutputStream);
Toast.makeText(context.getApplicationContext(), "Image Saved", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Toast.makeText(context.getApplicationContext(), "Error \n" + e, Toast.LENGTH_SHORT).show();
}
}
Run Code Online (Sandbox Code Playgroud)
但现在我也想保存视频文件,为此我正在使用此代码,但它对我不起作用,此代码损坏后我得到的文件
public void saveVideo(String name, Uri vidUri) {
OutputStream …Run Code Online (Sandbox Code Playgroud)