Android 10:通过MediaStore获取带有位置信息的图库 [英] Android 10: fetch the gallery via MediaStore with location information
问题描述
查看Android 10中引入的存储访问更改在此处,默认情况下,位置信息已被删除.
Looking at the storage access changes introduced in Android 10 here, location informations are now redacted by default.
Google要求我们在"MediaStore"页面上调用 setRequireOriginal()
.以媒体的uri作为参数的对象.当您一张一张地获取媒体时,此方法有效,但是当我们查询整个画廊的ContentResolver时该怎么办?
Google asks us to call setRequireOriginal()
on the "MediaStore" object with the media's uri as a parameter. This works when you fetch medias one by one, but what about when we query the ContentResolver for the whole gallery?
查看此示例:
String[] projection = {
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Images.Media.DATE_TAKEN,
MediaStore.Images.Media.WIDTH,
MediaStore.Images.Media.HEIGHT,
MediaStore.Images.Media.LATITUDE, // <----- THIS
MediaStore.Images.Media.LONGITUDE, // <----- THIS
MediaStore.Images.Media.MIME_TYPE,
};
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
Uri queryUri = MediaStore.Files.getContentUri("external");
Cursor cursor = null;
MediaStore a ;
try {
cursor = context.getContentResolver().query(queryUri, projection, selection,
null, MediaStore.Images.Media.DATE_TAKEN + " DESC");
}
catch (NullPointerException ex){
}
从Q开始,纬度和经度始终设置为0.如果在清单中添加了 ACCESS_MEDIA_LOCATION
权限,是否可以获取一批媒体的位置数据?
Starting Q the latitude and longitude are always set to 0. Is there a way to get the location data for a batch of medias assuming the ACCESS_MEDIA_LOCATION
permission is added in the Manifest?
推荐答案
不幸的是,MediaStore.Images.Media.LATITUDE和MediaStore.Images.Media.LONGITUDE是
Unfortunately, MediaStore.Images.Media.LATITUDE and MediaStore.Images.Media.LONGITUDE were deprecated in Android Q.
解决方法像这样使用 ExifInterface
:
Cursor cursor = null;
try {
String[] projection = {
MediaStore.Files.FileColumns._ID,
MediaStore.Images.Media.DATE_TAKEN,
MediaStore.Images.Media.WIDTH,
MediaStore.Images.Media.HEIGHT,
MediaStore.MediaColumns.TITLE,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.LATITUDE,
MediaStore.Images.Media.LONGITUDE
};
cursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
MediaStore.Images.Media.DATE_TAKEN + " DESC");
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID);
int titleColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.TITLE);
int latColumn = BuildCompat.isAtLeastQ() ? -1
: cursor.getColumnIndexOrThrow(MediaStore.Images.Media.LATITUDE);
int longColumn = BuildCompat.isAtLeastQ() ? -1
: cursor.getColumnIndexOrThrow(MediaStore.Images.Media.LONGITUDE);
while (cursor.moveToNext()) {
Uri photoUri = Uri.withAppendedPath(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
cursor.getString(idColumn));
String title = cursor.getString(titleColumn);
final double[] latLong;
if (BuildCompat.isAtLeastQ()) {
photoUri = MediaStore.setRequireOriginal(photoUri);
InputStream stream = getContentResolver().openInputStream(photoUri);
if (stream == null) {
Log.w(TAG, "Got a null input stream for " + photoUri);
continue;
}
ExifInterface exifInterface = new ExifInterface(stream);
double[] returnedLatLong = exifInterface.getLatLong();
// If it returns null, fall back to {0.0, 0.0}.
latLong = returnedLatLong != null ? returnedLatLong : new double[2];
// After using ExifInterface, the stream should not be reused.
stream.close();
} else {
latLong = new double[]{
cursor.getFloat(latColumn),
cursor.getFloat(longColumn)
};
}
Log.i(TAG, title + " | lat: " + latLong[0] + " | lng: " + latLong[1]);
}
} catch (NullPointerException | IOException ex) {
Log.e(TAG, "Caught exception", ex);
} finally {
if (cursor != null) {
cursor.close();
}
}
这是获得纬度&的唯一方法目前在Android Q上的照片经度.
This is the only way to get latitude & longitude of a photo on Android Q at the moment.
这需要持有 ACCESS_MEDIA_LOCATION
权限.注意,该许可不是用户在设置UI中可见".(源),这意味着用户即使看到弹出窗口也无法获得许可它是运行时权限.这意味着您必须在运行时请求许可(与清单文件不同),但用户不必同意.在此处添加此内容是因为您可能想知道为什么没有显示额外的UI弹出窗口.
This requires holding the ACCESS_MEDIA_LOCATION
permission. Note, this permission is not "user visible in the settings UI" (source), which means the user won't see a popup asking for permission, even though it is a runtime permission. This means you have to ask for permission during runtime (in contrast to just the manifest file) but the user won't have to consent to it. Adding this here because you might be wondering why no extra UI popups are shown.
这篇关于Android 10:通过MediaStore获取带有位置信息的图库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!