Display nearest address for Geotagged files
Bug: 64298047
Test: MediaViewTest.java
Change-Id: I114b5fb57d86cfc2c5992c6f248437e0f2c4db1b
diff --git a/res/values/inspector_strings.xml b/res/values/inspector_strings.xml
index 8a426e3..d02ae0c 100644
--- a/res/values/inspector_strings.xml
+++ b/res/values/inspector_strings.xml
@@ -83,6 +83,8 @@
<string name="metadata_composer">Composer</string>
<!--The album the file is in, Note this is probably MP3 ID3 tags-->
<string name="metadata_album">Album</string>
+ <!-- The address nearest to where a photo was taken -->
+ <string name="metadata_address">Location</string>
<!-- String label for developer/debug file details, specifying which stream types are available. -->
<string name="debug_stream_types">Stream types</string>
diff --git a/src/com/android/documentsui/inspector/MediaView.java b/src/com/android/documentsui/inspector/MediaView.java
index 8fc179e..b2ae758 100644
--- a/src/com/android/documentsui/inspector/MediaView.java
+++ b/src/com/android/documentsui/inspector/MediaView.java
@@ -17,8 +17,11 @@
import android.content.Context;
import android.content.res.Resources;
+import android.location.Address;
+import android.location.Geocoder;
import android.media.ExifInterface;
import android.media.MediaMetadata;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.support.annotation.VisibleForTesting;
@@ -31,6 +34,9 @@
import com.android.documentsui.inspector.InspectorController.MediaDisplay;
import com.android.documentsui.inspector.InspectorController.TableDisplay;
+import java.io.IOException;
+import java.util.function.Consumer;
+
import javax.annotation.Nullable;
/**
@@ -41,6 +47,7 @@
public class MediaView extends TableView implements MediaDisplay {
private final Resources mResources;
+ private final Context mContext;
public MediaView(Context context) {
this(context, null);
@@ -52,6 +59,7 @@
public MediaView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ mContext = context;
mResources = context.getResources();
}
@@ -61,7 +69,7 @@
Bundle exif = metadata.getBundle(DocumentsContract.METADATA_EXIF);
if (exif != null) {
- showExifData(this, mResources, doc, exif, geoClickListener);
+ showExifData(this, mResources, doc, exif, geoClickListener, this::getAddress);
}
Bundle video = metadata.getBundle(Shared.METADATA_KEY_VIDEO);
@@ -126,7 +134,8 @@
Resources resources,
DocumentInfo doc,
Bundle tags,
- @Nullable Runnable geoClickListener) {
+ @Nullable Runnable geoClickListener,
+ Consumer<float[]> geoAddressFetcher) {
addDimensionsRow(table, resources, tags);
@@ -135,11 +144,6 @@
table.put(R.string.metadata_date_time, date);
}
- if (MetadataUtils.hasExifGpsFields(tags)) {
- float[] coords = MetadataUtils.getExifGpsCoords(tags);
- showCoordiantes(table, resources, coords, geoClickListener);
- }
-
if (tags.containsKey(ExifInterface.TAG_GPS_ALTITUDE)) {
double altitude = tags.getDouble(ExifInterface.TAG_GPS_ALTITUDE);
table.put(R.string.metadata_altitude, String.valueOf(altitude));
@@ -178,6 +182,11 @@
String.format(resources.getString(R.string.metadata_iso_format), iso));
}
+ if (MetadataUtils.hasExifGpsFields(tags)) {
+ float[] coords = MetadataUtils.getExifGpsCoords(tags);
+ showCoordiantes(table, resources, coords, geoClickListener);
+ geoAddressFetcher.accept(coords);
+ }
}
private static void showCoordiantes(
@@ -202,6 +211,53 @@
}
/**
+ * Attempts to retrieve an approximate address and displays the address if it can find one.
+ * @param coords the coordinates that gets an address.
+ */
+ private void getAddress(float[] coords) {
+ new AsyncTask<Float, Void, Address>() {
+ @Override
+ protected Address doInBackground(Float... coords) {
+ assert (coords.length == 2);
+ Geocoder geocoder = new Geocoder(mContext);
+ try {
+ Address address = geocoder.getFromLocation(coords[0], // latitude
+ coords[1], // longitude
+ 1 // amount of results returned
+ ).get(0);
+ return address;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ @Override
+ protected void onPostExecute(@Nullable Address address) {
+ if (address != null) {
+ TableDisplay table = MediaView.this;
+ if (address.getMaxAddressLineIndex() >= 0) {
+ String formattedAddress;
+ StringBuilder addressBuilder = new StringBuilder("");
+ addressBuilder.append(address.getAddressLine(0));
+ for (int i = 1; i < address.getMaxAddressLineIndex(); i++) {
+ addressBuilder.append("\n");
+ addressBuilder.append(address.getAddressLine(i));
+ }
+ formattedAddress = addressBuilder.toString();
+ table.put(R.string.metadata_address, formattedAddress);
+ } else if (address.getLocality() != null) {
+ table.put(R.string.metadata_address, address.getLocality());
+ } else if (address.getSubAdminArea() != null) {
+ table.put(R.string.metadata_address, address.getSubAdminArea());
+ } else if (address.getAdminArea() != null) {
+ table.put(R.string.metadata_address, address.getAdminArea());
+ } else if (address.getCountryName() != null) {
+ table.put(R.string.metadata_address, address.getCountryName());
+ } }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, coords[0], coords[1]);
+ }
+
+ /**
* @param speed a value n, where shutter speed equals 1/(2^n)
* @return a String containing either a fraction that displays 1 over a positive integer, or a
* double rounded to one decimal, depending on if 1/(2^n) is less than or greater than 1,
diff --git a/src/com/android/documentsui/inspector/TableView.java b/src/com/android/documentsui/inspector/TableView.java
index b112980..41a3165 100644
--- a/src/com/android/documentsui/inspector/TableView.java
+++ b/src/com/android/documentsui/inspector/TableView.java
@@ -83,15 +83,16 @@
}
/**
- * Puts or updates an value in the table view.
+ * Puts or updates a value in the table view.
*/
@Override
public void put(@StringRes int keyId, CharSequence value) {
put(mRes.getString(keyId), value);
}
+
/**
- * Puts or updates an value in the table view.
+ * Puts or updates a value in the table view.
*/
protected KeyValueRow put(CharSequence key, CharSequence value) {
KeyValueRow row = mRows.get(key);
diff --git a/tests/unit/com/android/documentsui/inspector/MediaViewTest.java b/tests/unit/com/android/documentsui/inspector/MediaViewTest.java
index 224ae30..7cf7b21 100644
--- a/tests/unit/com/android/documentsui/inspector/MediaViewTest.java
+++ b/tests/unit/com/android/documentsui/inspector/MediaViewTest.java
@@ -31,6 +31,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.function.Consumer;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MediaViewTest {
@@ -38,6 +40,10 @@
private TestResources mResources;
private TestTable mTable;
private Bundle mMetadata;
+ private Consumer<float[]> mGeo = (float[] coords) -> {
+ mTable.put(R.string.metadata_address, "1234 Street Street\n"
+ + "City, State, 56789");
+ };
@Before
public void setUp() {
@@ -63,7 +69,7 @@
mResources.strings.put(R.string.metadata_focal_format, "%.2f mm");
mResources.strings.put(R.string.metadata_iso_format, "ISO %d");
Bundle exif = mMetadata.getBundle(DocumentsContract.METADATA_EXIF);
- MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, exif, null);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, exif, null, mGeo);
mTable.assertHasRow(R.string.metadata_dimensions, "3840 x 2160, 8.3MP");
mTable.assertHasRow(R.string.metadata_date_time, "Jan 01, 1970, 12:16 AM");
@@ -74,6 +80,8 @@
mTable.assertHasRow(R.string.metadata_aperture, "f/2.0");
mTable.assertHasRow(R.string.metadata_iso_speed_ratings, "ISO 120");
mTable.assertHasRow(R.string.metadata_focal_length, "4.27 mm");
+ mTable.assertHasRow(R.string.metadata_address, "1234 Street Street\n"
+ + "City, State, 56789");
}
/**
@@ -87,7 +95,7 @@
data.putDouble(ExifInterface.TAG_GPS_LATITUDE, 37.7749);
mMetadata.putBundle(DocumentsContract.METADATA_EXIF, data);
- MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null, mGeo);
mTable.assertEmpty();
}
@@ -102,7 +110,7 @@
data.putInt(ExifInterface.TAG_IMAGE_WIDTH, 3840);
mMetadata.putBundle(DocumentsContract.METADATA_EXIF, data);
- MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null, mGeo);
mTable.assertEmpty();
}
@@ -142,4 +150,17 @@
mTable.assertHasRow(R.string.metadata_duration, "6:01:00");
}
+
+ @Test
+ public void testGetAddress() throws Exception {
+ Consumer<float[]> badAddress = (float[] coords) -> {
+ };
+ Bundle data = new Bundle();
+ data.putInt(ExifInterface.TAG_IMAGE_WIDTH, 3840);
+ data.putInt(ExifInterface.TAG_IMAGE_LENGTH, 2160);
+
+ mMetadata.getBundle(DocumentsContract.METADATA_EXIF);
+ MediaView.showExifData(mTable, mResources, TestEnv.FILE_JPG, mMetadata, null, badAddress);
+ mTable.assertNotInTable(R.string.metadata_address);
+ }
}
diff --git a/tests/unit/com/android/documentsui/inspector/TestTable.java b/tests/unit/com/android/documentsui/inspector/TestTable.java
index c3665e4..f1bd0b7 100644
--- a/tests/unit/com/android/documentsui/inspector/TestTable.java
+++ b/tests/unit/com/android/documentsui/inspector/TestTable.java
@@ -17,6 +17,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import android.view.View.OnClickListener;
@@ -42,6 +43,10 @@
assertEquals(expected, mRows.get(keyId));
}
+ public void assertNotInTable (int keyId) {
+ assertNull(mRows.get(keyId));
+ }
+
@Override
public void put(int keyId, CharSequence value) {
mRows.put(keyId, value);