1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.util; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.location.Address; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.location.Geocoder; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.location.Location; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.location.LocationManager; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.ConnectivityManager; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.NetworkInfo; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 272b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.BlobCache; 282b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.ByteArrayInputStream; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.ByteArrayOutputStream; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.DataInputStream; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.DataOutputStream; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.IOException; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.List; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Locale; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class ReverseGeocoder { 387817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @SuppressWarnings("unused") 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "ReverseGeocoder"; 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int EARTH_RADIUS_METERS = 6378137; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int LAT_MIN = -90; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int LAT_MAX = 90; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int LON_MIN = -180; 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final int LON_MAX = 180; 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int MAX_COUNTRY_NAME_LENGTH = 8; 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // If two points are within 20 miles of each other, use 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // "Around Palo Alto, CA" or "Around Mountain View, CA". 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // instead of directly jumping to the next level and saying 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // "California, US". 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int MAX_LOCALITY_MILE_RANGE = 20; 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String GEO_CACHE_FILE = "rev_geocoding"; 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int GEO_CACHE_MAX_ENTRIES = 1000; 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int GEO_CACHE_MAX_BYTES = 500 * 1024; 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int GEO_CACHE_VERSION = 0; 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static class SetLatLong { 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The latitude and longitude of the min latitude point. 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMinLatLatitude = LAT_MAX; 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMinLatLongitude; 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The latitude and longitude of the max latitude point. 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMaxLatLatitude = LAT_MIN; 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMaxLatLongitude; 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The latitude and longitude of the min longitude point. 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMinLonLatitude; 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMinLonLongitude = LON_MAX; 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The latitude and longitude of the max longitude point. 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMaxLonLatitude; 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public double mMaxLonLongitude = LON_MIN; 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Context mContext; 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Geocoder mGeocoder; 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private BlobCache mGeoCache; 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private ConnectivityManager mConnectivityManager; 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static Address sCurrentAddress; // last known address 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ReverseGeocoder(Context context) { 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContext = context; 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mGeocoder = new Geocoder(mContext); 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mGeoCache = CacheManager.getCache(context, GEO_CACHE_FILE, 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GEO_CACHE_MAX_ENTRIES, GEO_CACHE_MAX_BYTES, 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin GEO_CACHE_VERSION); 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mConnectivityManager = (ConnectivityManager) 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin context.getSystemService(Context.CONNECTIVITY_SERVICE); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public String computeAddress(SetLatLong set) { 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The overall min and max latitudes and longitudes of the set. 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin double setMinLatitude = set.mMinLatLatitude; 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin double setMinLongitude = set.mMinLatLongitude; 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin double setMaxLatitude = set.mMaxLatLatitude; 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin double setMaxLongitude = set.mMaxLatLongitude; 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (Math.abs(set.mMaxLatLatitude - set.mMinLatLatitude) 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin < Math.abs(set.mMaxLonLongitude - set.mMinLonLongitude)) { 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setMinLatitude = set.mMinLonLatitude; 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setMinLongitude = set.mMinLonLongitude; 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setMaxLatitude = set.mMaxLonLatitude; 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setMaxLongitude = set.mMaxLonLongitude; 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Address addr1 = lookupAddress(setMinLatitude, setMinLongitude, true); 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Address addr2 = lookupAddress(setMaxLatitude, setMaxLongitude, true); 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr1 == null) 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr1 = addr2; 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr2 == null) 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr2 = addr1; 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr1 == null || addr2 == null) { 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Get current location, we decide the granularity of the string based 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // on this. 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin LocationManager locationManager = 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Location location = null; 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin List<String> providers = locationManager.getAllProviders(); 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < providers.size(); ++i) { 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String provider = providers.get(i); 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin location = (provider != null) ? locationManager.getLastKnownLocation(provider) : null; 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (location != null) 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String currentCity = ""; 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String currentAdminArea = ""; 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String currentCountry = Locale.getDefault().getCountry(); 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (location != null) { 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Address currentAddress = lookupAddress( 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin location.getLatitude(), location.getLongitude(), true); 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (currentAddress == null) { 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin currentAddress = sCurrentAddress; 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sCurrentAddress = currentAddress; 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (currentAddress != null && currentAddress.getCountryCode() != null) { 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin currentCity = checkNull(currentAddress.getLocality()); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin currentCountry = checkNull(currentAddress.getCountryCode()); 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin currentAdminArea = checkNull(currentAddress.getAdminArea()); 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String closestCommonLocation = null; 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr1Locality = checkNull(addr1.getLocality()); 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr2Locality = checkNull(addr2.getLocality()); 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr1AdminArea = checkNull(addr1.getAdminArea()); 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr2AdminArea = checkNull(addr2.getAdminArea()); 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr1CountryCode = checkNull(addr1.getCountryCode()); 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr2CountryCode = checkNull(addr2.getCountryCode()); 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (currentCity.equals(addr1Locality) || currentCity.equals(addr2Locality)) { 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String otherCity = currentCity; 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (currentCity.equals(addr1Locality)) { 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin otherCity = addr2Locality; 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (otherCity.length() == 0) { 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin otherCity = addr2AdminArea; 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!currentCountry.equals(addr2CountryCode)) { 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin otherCity += " " + addr2CountryCode; 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr2Locality = addr1Locality; 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr2AdminArea = addr1AdminArea; 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr2CountryCode = addr1CountryCode; 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin otherCity = addr1Locality; 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (otherCity.length() == 0) { 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin otherCity = addr1AdminArea; 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!currentCountry.equals(addr1CountryCode)) { 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin otherCity += " " + addr1CountryCode; 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr1Locality = addr2Locality; 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr1AdminArea = addr2AdminArea; 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr1CountryCode = addr2CountryCode; 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = valueIfEqual(addr1.getAddressLine(0), addr2.getAddressLine(0)); 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) { 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!currentCity.equals(otherCity)) { 177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation += " - " + otherCity; 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Compare thoroughfare (street address) next. 183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = valueIfEqual(addr1.getThoroughfare(), addr2.getThoroughfare()); 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) { 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Compare the locality. 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = valueIfEqual(addr1Locality, addr2Locality); 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null && !("".equals(closestCommonLocation))) { 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String adminArea = addr1AdminArea; 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String countryCode = addr1CountryCode; 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (adminArea != null && adminArea.length() > 0) { 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!countryCode.equals(currentCountry)) { 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation += ", " + adminArea + " " + countryCode; 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation += ", " + adminArea; 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // If the admin area is the same as the current location, we hide it and 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // instead show the city name. 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (currentAdminArea.equals(addr1AdminArea) && currentAdminArea.equals(addr2AdminArea)) { 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if ("".equals(addr1Locality)) { 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr1Locality = addr2Locality; 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if ("".equals(addr2Locality)) { 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr2Locality = addr1Locality; 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!"".equals(addr1Locality)) { 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr1Locality.equals(addr2Locality)) { 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = addr1Locality + ", " + currentAdminArea; 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = addr1Locality + " - " + addr2Locality; 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Just choose one of the localities if within a MAX_LOCALITY_MILE_RANGE 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mile radius. 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float[] distanceFloat = new float[1]; 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Location.distanceBetween(setMinLatitude, setMinLongitude, 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin setMaxLatitude, setMaxLongitude, distanceFloat); 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int distance = (int) GalleryUtils.toMile(distanceFloat[0]); 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (distance < MAX_LOCALITY_MILE_RANGE) { 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Try each of the points and just return the first one to have a 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // valid address. 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = getLocalityAdminForAddress(addr1, true); 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null) { 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = getLocalityAdminForAddress(addr2, true); 237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null) { 238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 241f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Check the administrative area. 243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = valueIfEqual(addr1AdminArea, addr2AdminArea); 244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null && !("".equals(closestCommonLocation))) { 245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String countryCode = addr1CountryCode; 246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!countryCode.equals(currentCountry)) { 247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (countryCode != null && countryCode.length() > 0) { 248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation += " " + countryCode; 249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 254f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Check the country codes. 255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = valueIfEqual(addr1CountryCode, addr2CountryCode); 256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (closestCommonLocation != null && !("".equals(closestCommonLocation))) { 257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // There is no intersection, let's choose a nicer name. 260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr1Country = addr1.getCountryName(); 261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String addr2Country = addr2.getCountryName(); 262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr1Country == null) 263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr1Country = addr1CountryCode; 264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr2Country == null) 265f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin addr2Country = addr2CountryCode; 266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr1Country == null || addr2Country == null) 267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr1Country.length() > MAX_COUNTRY_NAME_LENGTH || addr2Country.length() > MAX_COUNTRY_NAME_LENGTH) { 269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = addr1CountryCode + " - " + addr2CountryCode; 270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin closestCommonLocation = addr1Country + " - " + addr2Country; 272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return closestCommonLocation; 274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private String checkNull(String locality) { 277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (locality == null) 278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return ""; 279f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (locality.equals("null")) 280f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return ""; 281f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return locality; 282f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private String getLocalityAdminForAddress(final Address addr, final boolean approxLocation) { 285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (addr == null) 286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return ""; 287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String localityAdminStr = addr.getLocality(); 288f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (localityAdminStr != null && !("null".equals(localityAdminStr))) { 289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (approxLocation) { 290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // TODO: Uncomment these lines as soon as we may translations 291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // for Res.string.around. 292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // localityAdminStr = 293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mContext.getResources().getString(Res.string.around) + " " + 294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // localityAdminStr; 295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String adminArea = addr.getAdminArea(); 297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (adminArea != null && adminArea.length() > 0) { 298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin localityAdminStr += ", " + adminArea; 299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return localityAdminStr; 301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Address lookupAddress(final double latitude, final double longitude, 306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean useCache) { 307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long locationKey = (long) (((latitude + LAT_MAX) * 2 * LAT_MAX 309f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin + (longitude + LON_MAX)) * EARTH_RADIUS_METERS); 310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin byte[] cachedLocation = null; 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (useCache && mGeoCache != null) { 312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cachedLocation = mGeoCache.lookup(locationKey); 313f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 314f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Address address = null; 315f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); 316f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (cachedLocation == null || cachedLocation.length == 0) { 317f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (networkInfo == null || !networkInfo.isConnected()) { 318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin List<Address> addresses = mGeocoder.getFromLocation(latitude, longitude, 1); 321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!addresses.isEmpty()) { 322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address = addresses.get(0); 323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ByteArrayOutputStream bos = new ByteArrayOutputStream(); 324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin DataOutputStream dos = new DataOutputStream(bos); 325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Locale locale = address.getLocale(); 326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, locale.getLanguage()); 327f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, locale.getCountry()); 328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, locale.getVariant()); 329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getThoroughfare()); 331f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int numAddressLines = address.getMaxAddressLineIndex(); 332f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dos.writeInt(numAddressLines); 333f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < numAddressLines; ++i) { 334f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getAddressLine(i)); 335f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 336f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getFeatureName()); 337f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getLocality()); 338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getAdminArea()); 339f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getSubAdminArea()); 340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 341f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getCountryName()); 342f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getCountryCode()); 343f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getPostalCode()); 344f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getPhone()); 345f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin writeUTF(dos, address.getUrl()); 346f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 347f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dos.flush(); 348f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mGeoCache != null) { 349f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mGeoCache.insert(locationKey, bos.toByteArray()); 350f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 351f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dos.close(); 352f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 353f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 354f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Parsing the address from the byte stream. 355f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin DataInputStream dis = new DataInputStream( 356f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new ByteArrayInputStream(cachedLocation)); 357f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String language = readUTF(dis); 358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String country = readUTF(dis); 359f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String variant = readUTF(dis); 360f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Locale locale = null; 361f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (language != null) { 362f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (country == null) { 363f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin locale = new Locale(language); 364f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (variant == null) { 365f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin locale = new Locale(language, country); 366f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 367f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin locale = new Locale(language, country, variant); 368f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 369f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 370f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (!locale.getLanguage().equals(Locale.getDefault().getLanguage())) { 371f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dis.close(); 372f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return lookupAddress(latitude, longitude, false); 373f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 374f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address = new Address(locale); 375f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 376f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setThoroughfare(readUTF(dis)); 377f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int numAddressLines = dis.readInt(); 378f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < numAddressLines; ++i) { 379f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setAddressLine(i, readUTF(dis)); 380f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 381f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setFeatureName(readUTF(dis)); 382f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setLocality(readUTF(dis)); 383f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setAdminArea(readUTF(dis)); 384f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setSubAdminArea(readUTF(dis)); 385f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 386f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setCountryName(readUTF(dis)); 387f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setCountryCode(readUTF(dis)); 388f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setPostalCode(readUTF(dis)); 389f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setPhone(readUTF(dis)); 390f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin address.setUrl(readUTF(dis)); 391f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dis.close(); 392f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return address; 394f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Exception e) { 395f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // Ignore. 396f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 397f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 398f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 399f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 400f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private String valueIfEqual(String a, String b) { 401f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return (a != null && b != null && a.equalsIgnoreCase(b)) ? a : null; 402f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 403f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 404f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final void writeUTF(DataOutputStream dos, String string) throws IOException { 405f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (string == null) { 406f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dos.writeUTF(""); 407f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 408f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin dos.writeUTF(string); 409f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 410f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 411f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 412f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static final String readUTF(DataInputStream dis) throws IOException { 413f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String retVal = dis.readUTF(); 414f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (retVal.length() == 0) 415f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 416f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return retVal; 417f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 418f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 419