问题描述
到目前为止,我会检查文件是否存在,如果不存在,则将其保存到 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) 中的设备,但 Android 10 不支持该文件。
所以我尝试使用 mediastore API 来保存图像。
READ_STORAGE_PERMISSION -> 不允许
首先我使用以下代码查询 contentresolver 以检查文件是否存在:
Uri collection = null;
collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
String[] PROJECTION = new String[]{MediaStore.Images.Media.disPLAY_NAME,MediaStore.MediaColumns.RELATIVE_PATH};
String QUERY = MediaStore.Files.FileColumns.RELATIVE_PATH + " like ? and " +
MediaStore.Files.FileColumns.disPLAY_NAME + " like ?";
ContentResolver mContentResolver = this.getContentResolver();
Cursor cursor = mContentResolver.query(collection,PROJECTION,QUERY,new String[]{"%" + dirName + "%","%" + fname + "%"},null);
if (cursor != null) {
Log.d("upisdk","cursor != null");
if (cursor.getCount() > 0) {
} else {
}
}
ContentResolver contentResolver = getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.disPLAY_NAME,fname);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE,"image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH,dirName);
Uri imageUri =
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
fos = contentResolver.openOutputStream(Objects.requireNonNull(imageUri));
finalBitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);
Objects.requireNonNull(fos).close();
现在如果一切正常,直到我删除应用数据。
删除数据后,文件夹还在,之前保存的文件还在。现在,如果查询该文件的 contentresolver,则光标为空。如果不允许 READ_STORAGE_PERMISSION 则它正在发生。如果我允许 READ_STORAGE_PERMISSION 那么它给了我非空的游标。另一方面,如果我尝试保存一个新的不同图像并查询解析器,那么即使没有 READ_STORAGE_PERMISSION,我也会得到非空光标。
请告诉我我做错了什么。
解决方法
解决方案 1
private fun getUriFromPath(displayName: String): Uri? {
val photoId: Long
val photoUri = MediaStore.Images.Media.getContentUri("external")
val projection = arrayOf(MediaStore.Images.ImageColumns._ID)
val cursor = contentResolver.query(
photoUri,projection,MediaStore.Images.ImageColumns.DISPLAY_NAME + " LIKE ?",arrayOf(displayName),null
)!!
cursor.moveToFirst()
val columnIndex = cursor.getColumnIndex(projection[0])
photoId = cursor.getLong(columnIndex)
cursor.close()
return Uri.parse("$photoUri/$photoId")
}
如果您愿意,也可以添加相对路径以在特定位置查找
使用文件名检查
private fun isExist(){
val pathOfImage=getUriFromPath("myimage.png")
val isExist = try {
val i= pathOfImage?.let { contentResolver.openInputStream(it) }
i != null
}
catch (e: IOException) {
e.printStackTrace()
false
}
if (!isExist) {
// do whatever u want
}
}
当找不到文件并尝试打开流时,此解决方案会出现异常。
解决方案 2
在这个解决方案中,我确实将文件保存到 Android\media\com.yourpackge\
目录
private fun isExist(){
val path = this.externalMediaDirs.first()
val folder = File(path,getString(R.string.app_name))
if (!folder.exists()) folder.mkdirs()
val file = File(folder,"myimage.png")
if (!file.exists()) {
// save your files or do whatever you want
// use this for show files into gallery
MediaScannerConnection.scanFile(this,arrayOf(file.absolutePath),null,object : MediaScannerConnection.OnScanCompletedListener {
override fun onScanCompleted(path: String,uri: Uri?) {
Log.e("scann--","Finished scanning $path")
}
})
}
}
现在我想将我的文件从旧的 文件夹移动到 android 11 中的 getExternalStorageDirectory
Android\media\com.yourpackge\
目录,就像 whatsapp 所做的那样,无需征得任何许可。
编辑 - 1
我可以使用 kotlin Utils
类将我的文件夹移动到新文件夹
sourcefolder.copyRecursively(newfolder,true)
private fun copyFiles(){
val path = this.externalMediaDirs.first()
val folder = File(path,getString(R.string.app_name))
if (!folder.exists()) folder.mkdirs()
val sourcefolder = File(Environment.getExternalStorageDirectory().toString() + "/"
+"Supreme")
sourcefolder.copyRecursively(folder,true)
}