Android 10: fetch the gallery via MediaStore with location information

二次信任 提交于 2020-07-04 13:50:30

问题


Looking at the storage access changes introduced in Android 10 here, location informations are now redacted by default.

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?

See this sample:

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){
}

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?


回答1:


Unfortunately, MediaStore.Images.Media.LATITUDE and MediaStore.Images.Media.LONGITUDE were deprecated in Android Q.

The work around for this is to use ExifInterface like this:

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();
    }
}

This is the only way to get latitude & longitude of a photo on Android Q at the moment.

This requires holding the ACCESS_MEDIA_LOCATION permission.



来源:https://stackoverflow.com/questions/55186255/android-10-fetch-the-gallery-via-mediastore-with-location-information

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!