android 10(Q, api29), getContent
做本地图库,通过getContentResolver方法获取媒体文件,
private final static String[] QUERY_Columns = {
MediaStore.Files.FileColumns.DATA + " FROM (SELECT *"
};
getContentResolver().query(
MediaStore.Files.getContentUri("external"),
QUERY_Columns, ...
在android10(Q)上遇到crash:
Error : java.lang.IllegalArgumentException: Invalid column _data FROM (SELECT * at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140) at android.content.ContentProviderProxy.query(ContentProviderNative.java:423) at android.content.ContentResolver.query(ContentResolver.java:951) at android.content.ContentResolver.query(ContentResolver.java:887) at android.content.ContentResolver.query(ContentResolver.java:843) at com.dhq.album.model.ImageScannerModelImpl2.startScanImage2(ImageScannerModelImpl2.java:69) at com.dhq.album.ui.fragment.OneAlbumFolderFragment2$2.run(OneAlbumFolderFragment2.java:181) at java.lang.Thread.run(Thread.java:919)
问题在于:
MediaStore.Files.FileColumns.DATAMediaStore.Files.FileColumns.DATA 在 android 10(Q,api29)会不能被访问
/** * Path to the file on disk. * <p> * Note that apps may not have filesystem permissions to directly access * this path. Instead of trying to open this path directly, apps should * use {@link ContentResolver#openFileDescriptor(Uri, String)} to gain * access. * <p> * Type: TEXT */ public static final String DATA = "_data";
但是,我target api设的是28(android 9),为什么会有问题的?不管了,既然String path拿不到,就用它文档建议的获取uri,再去解析一下。
文档:
https://developer.android.com/training/data-storage/shared/media#java
如video:
class Video {
private final Uri uri;
private final String name;
private final int duration;
private final int size;
public Video(Uri uri, String name, int duration, int size) {
this.uri = uri;
this.name = name;
this.duration = duration;
this.size = size;
}
}
List<Video> videoList = new ArrayList<Video>();
String[] projection = new String[] {
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.SIZE
};
String selection = MediaStore.Video.Media.DURATION +
" >= ?";
String[] selectionArgs = new String[] {
String.valueOf(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
};
String sortOrder = MediaStore.Video.Media.DISPLAY_NAME + " ASC";
try (Cursor cursor = getApplicationContext().getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
selectionArgs,
sortOrder
)) {
// Cache column indices.
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
int nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
int durationColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION);
int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);
while (cursor.moveToNext()) {
// Get values of columns for a given video.
long id = cursor.getLong(idColumn);
String name = cursor.getString(nameColumn);
int duration = cursor.getInt(durationColumn);
int size = cursor.getInt(sizeColumn);
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
// Stores column values and the contentUri in a local object
// that represents the media file.
videoList.add(new Video(contentUri, name, duration, size));
}
}