代码逻辑实现
我这里就以“图片”为例,其他都差不多
一、首先是将数据给“查”出来
具体查询代码如下,因为主要讲的是删除,就不详细说了。
我自己自定义的对象:
1、mFilePaths 查询数据的列表
2、ImageObejct 一个简单的数据实力对象
3、mHandler Handler因为我这里的查询是异步的,需要Handler同步一下
private void queryImages(boolean isUpdate) {
new Thread(new Runnable() {
@Override
public void run() {
// 先拿到图片数据表的uri
Uri tableUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// 需要获取数据表中的哪几列信息
String[] projection = new String[]{
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.MIME_TYPE};
// 查询条件,因为是查询全部图片,传null
// String selection = MediaStore.Images.Media.DISPLAY_NAME +"= \'138309016372535042.png\'";
// 条件参数 ,因为是查询全部图片,传null
//String[] args = new String[] {“test”}
// 排序:按id倒叙
String order = MediaStore.Files.FileColumns._ID+" DESC";
// 开始查询
Cursor cursor = getContentResolver().query(tableUri,projection,null,null, order);
if (mFilePaths == null || isUpdate){
mFilePaths = new ArrayList<>();
}
if (cursor != null) {
// 获取id字段是第几列,该方法最好在循环之前做好
int idIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID);
// 获取data字段是第几列,该方法最好在循环之前做好
int dataIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
int nameIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);
int typeIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.MIME_TYPE);
while (cursor.moveToNext()) {
long id = cursor.getLong(idIndex);
// 获取到每张图片的绝对路径
String path = cursor.getString(dataIndex);
String name = cursor.getString(nameIndex);
String type = cursor.getString(typeIndex);
// 获取到每张图片的uri
Uri imageUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,id);
// 后续工作
ImageObejct item = new ImageObejct(path,name,imageUri,id);
mFilePaths.add(item);
}
cursor.close();
}
Message msg = new Message();
if (isUpdate){
msg.what = UPDATE_FILE_FINISH;
}else{
msg.what = QUERY_FILE_FINISH;
}
mHandler.sendMessage(msg);
}
}).start();
}
二、删除操作
删除的操作主要分为三步:
一、删除系统数据库表对应的索引
private void actionDeleteItem(ImageObejct item) {
new Thread(new Runnable() {
@Override
public void run() {
File file = new File(item.getPath());
int flag = 0;
if (file.isFile() && file.exists()) {
String filePath = file.getPath();
//筛选条件,相当于sql:where xx = ?
String selectionClause = MediaStore.Images.Media.DATA + " = ?";
//筛选参数,填充到筛选条件对应?处
String[] selectionArgs = {filePath};
int res = MainActivity.this.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
selectionClause,
selectionArgs);
//delete的返回值是该操作所影响的行数,所以当res = 1,就是删除了一条记录,0 表示删除失败
if (res>0){
file.delete();
flag = 1;
}else{
showToast("actionDeleteItem 删除文件失败");
}
//删除多媒体数据库中的数据
}
Message msg = new Message();
msg.what = DELETE_FILE_FINISH;
msg.arg1 = flag;
msg.obj = file.getPath();
mHandler.sendMessage(msg);
}
}).start();
}
二、删除成功后需要更新MediaStore,不然下次查出来的数据有发现怎么删除了的还在
private void updateMediaStore(String filePath) {
MediaScannerConnection.scanFile(MainActivity.this ,
new String[]{filePath}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
//更新完后再判读一次是否已经删除
if (!TextUtils.isEmpty(path)){
File file = new File(path);
if (file.exists()){
showToast("updateMediaStore 删除失败");
}else {
showToast("updateMediaStore 删除成功");
}
}
}
});
}
三、(根据个人需求)重新查一遍数据,更新数据列表
查的代码上面已经展示,这里不再展示,这里是更新界面数据的逻辑。
private void upListDate() {
if (mFilePaths != null && mFilePaths.size()>0){
mFileListAdapter.setFilePaths(mFilePaths);
mFileListAdapter.notifyDataSetChanged();
loaddingFinish();
}else {
loaddingFail();
}
}
注意事项
权限
作为一个删除功能,肯定不能少的读写权限。
//Android 6及之后的版本
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
//Android 10及之后还需要在<application>中添加
//不使用 强制分区
android:requestLegacyExternalStorage="true"
//Android 11及之后必须强制分区
//获取 所有文件的控制权限,需要引导用户手动打开权限
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>