如何解决如何将包含内容的私有文件夹复制到 android q 及更高版本中的公共目录?
我有一个私人文件夹,其中包含包含图像和视频的子文件夹, 我需要将该文件夹复制到 Environment.DIRECTORY_PICTURES 以供公众使用
val fodler = getExternalFilesDir("Folder") // 包含图片和视频的子文件夹
val DESTINATION = Environment.getExternalStorageDirectory().toString() + File.separator + Environment.DIRECTORY_PICTURES
copyFileOrDirectory(fodler.absolutePath,DESTINATION)
private fun copyFileOrDirectory(srcDir: String,dstDir: String) {
try {
val src: File = File(srcDir)
val dst: File = File(dstDir,src.name)
if (src.isDirectory) {
val files = src.list()
val filesLength = files.size
for (i in 0 until filesLength) {
val src1 = File(src,files[i]).path
val dst1 = dst.path
copyFileOrDirectory(src1,dst1)
}
} else {
copyFile(src,dst)
}
} catch (e: Exception) {
e.printstacktrace()
}
}
private fun copyFile(sourceFile: File,destFile: File) {
if (!destFile.getParentFile().exists()) destFile.getParentFile().mkdirs()
if (!destFile.exists()) {
destFile.createNewFile()
}
var source: FileChannel? = null
var destination: FileChannel? = null
try {
source = FileInputStream(sourceFile).getChannel()
destination = FileOutputStream(destFile).getChannel()
destination.transferFrom(source,source.size())
} finally {
if (source != null) {
source.close()
}
if (destination != null) {
destination.close()
}
}
}
现在我在“图片”目录中得到文件“文件夹”(及其所有内容),所有人和公众都可以看到, 正是我需要的。
此解决方案适用于 api 级别 23-29(android:requestLegacyExternalStorage="true" 用于menifest 中的 api 级别 29) 但它在 api 级别 30 中不起作用,因为不推荐使用 getExternalStorageDirectory() 并且menifest 中的 android:requestLegacyExternalStorage="true" 不适用于 api 级别 30
api level 30 的解决方案是什么?
解决方法
我不知道如何使用 kotlin 向您展示示例,但是,如果您的问题是 sdk getExternalStorageDirectory() 已弃用,也许您应该使用 MediaStore 来保存文件(图像):
private void saveImage(Bitmap bitmap) {
if (android.os.Build.VERSION.SDK_INT >= 29) {
ContentValues values = contentValues(); //define your content values to save data
values.put(MediaStore.Images.Media.RELATIVE_PATH,"Pictures/" + "Example Folder"); //here your path
values.put(MediaStore.Images.Media.IS_PENDING,true);
Uri uri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values); //this to insert data
if (uri != null) {
try {
saveImageToStream(bitmap,this.getContentResolver().openOutputStream(uri)); //so save the image file
values.put(MediaStore.Images.Media.IS_PENDING,false);
Toast.makeText(this,"It works!!",Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
} else { //and if sdk < 29
File directory = new File(Environment.getExternalStorageDirectory().toString() + '/' + getString(R.string.app_name));
if (!directory.exists()) {
directory.mkdirs();
}
String fileName = "file" + ".jpg";
File file = new File(directory,fileName);
try {
saveImageToStream(bitmap,new FileOutputStream(file));
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA,file.getAbsolutePath());
this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
private ContentValues contentValues() { //here we do the some values to save in sdk>=29
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME,"fileImage" + ".jpg");
values.put(MediaStore.Images.Media.MIME_TYPE,"image/*");
values.put(MediaStore.Images.Media.DATE_ADDED,System.currentTimeMillis() / 1000);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(MediaStore.Images.Media.DATE_TAKEN,System.currentTimeMillis());
}
return values;
}
private void saveImageToStream(Bitmap bitmap,OutputStream outputStream) { //and this to give a format
if (outputStream != null) {
try {
bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
,
对于 api 30 设备,您可以像往常一样将文件夹复制到图片目录。
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) 有效,所以使用它。
但是……文件必须是图片。
对于 api 29 请求在清单文件的应用程序标签中的遗留外部存储复制到公共图片目录。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。