1d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian/* 2d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Copyright (C) 2017 The Android Open Source Project 3d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 4d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 5d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * you may not use this file except in compliance with the License. 6d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * You may obtain a copy of the License at 7d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 8d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 9d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 10d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Unless required by applicable law or agreed to in writing, software 11d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 12d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * See the License for the specific language governing permissions and 14d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * limitations under the License 15d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 16d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 17d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianpackage com.android.incallui.calllocation.impl; 18d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 19d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.Context; 20d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.Intent; 21d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.content.res.Resources; 22d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.location.Location; 23d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.net.Uri; 24d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.support.annotation.Nullable; 25d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport android.support.annotation.VisibleForTesting; 26d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport java.util.Locale; 27d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 28d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianclass LocationUrlBuilder { 29d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 30d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian // Static Map API path constants. 31d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String HTTPS_SCHEME = "https"; 32d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MAPS_API_DOMAIN = "maps.googleapis.com"; 33d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MAPS_PATH = "maps"; 34d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String API_PATH = "api"; 35d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String STATIC_MAP_PATH = "staticmap"; 36d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String GEOCODE_PATH = "geocode"; 37d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String GEOCODE_OUTPUT_TYPE = "json"; 38d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 39d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian // Static Map API parameter constants. 40d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String KEY_PARAM_KEY = "key"; 41d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String CENTER_PARAM_KEY = "center"; 42d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String ZOOM_PARAM_KEY = "zoom"; 43d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String SCALE_PARAM_KEY = "scale"; 44d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String SIZE_PARAM_KEY = "size"; 45d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MARKERS_PARAM_KEY = "markers"; 46d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 47d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String ZOOM_PARAM_VALUE = Integer.toString(16); 48d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 49d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String LAT_LONG_DELIMITER = ","; 50d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 51d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MARKER_DELIMITER = "|"; 52d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MARKER_STYLE_DELIMITER = ":"; 53d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MARKER_STYLE_COLOR = "color"; 54d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String MARKER_STYLE_COLOR_RED = "red"; 55d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 56d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String LAT_LNG_PARAM_KEY = "latlng"; 57d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 58d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String ANDROID_API_KEY_VALUE = "AIzaSyAXdDnif6B7sBYxU8hzw9qAp3pRPVHs060"; 59d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private static final String BROWSER_API_KEY_VALUE = "AIzaSyBfLlvWYndiQ3RFEHli65qGQH36QIxdyCI"; 60d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 61d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian /** 62d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Generates the URL to a static map image for the given location. 63d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 64d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * <p>This image has the following characteristics: 65d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 66d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * <p>- It is centered at the given latitude and longitutde. - It is scaled according to the 67d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * device's pixel density. - There is a red marker at the given latitude and longitude. 68d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 69d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * <p>Source: https://developers.google.com/maps/documentation/staticmaps/ 70d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 71d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param contxt The context. 72d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param Location A location. 73d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @return The URL of a static map image url of the given location. 74d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 75d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian public static String getStaticMapUrl(Context context, Location location) { 76d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian final Uri.Builder builder = new Uri.Builder(); 77d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian Resources res = context.getResources(); 78d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian String size = 79d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian res.getDimensionPixelSize(R.dimen.location_map_width) 80d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + "x" 81d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + res.getDimensionPixelSize(R.dimen.location_map_height); 82d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 83d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian builder 84d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .scheme(HTTPS_SCHEME) 85d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .authority(MAPS_API_DOMAIN) 86d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(MAPS_PATH) 87d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(API_PATH) 88d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(STATIC_MAP_PATH) 89d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(CENTER_PARAM_KEY, getFormattedLatLng(location)) 90d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(ZOOM_PARAM_KEY, ZOOM_PARAM_VALUE) 91d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(SIZE_PARAM_KEY, size) 92d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(SCALE_PARAM_KEY, Float.toString(res.getDisplayMetrics().density)) 93d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(MARKERS_PARAM_KEY, getMarkerUrlParamValue(location)) 94d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(KEY_PARAM_KEY, ANDROID_API_KEY_VALUE); 95d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 96d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return builder.build().toString(); 97d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 98d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 99d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian /** 100d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Generates the URL for a request to reverse geocode the given location. 101d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 102d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * <p>Source: https://developers.google.com/maps/documentation/geocoding/#ReverseGeocoding 103d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 104d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param Location A location. 105d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 106d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian public static String getReverseGeocodeUrl(Location location) { 107d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian final Uri.Builder builder = new Uri.Builder(); 108d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 109d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian builder 110d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .scheme(HTTPS_SCHEME) 111d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .authority(MAPS_API_DOMAIN) 112d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(MAPS_PATH) 113d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(API_PATH) 114d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(GEOCODE_PATH) 115d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendPath(GEOCODE_OUTPUT_TYPE) 116d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(LAT_LNG_PARAM_KEY, getFormattedLatLng(location)) 117d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .appendQueryParameter(KEY_PARAM_KEY, BROWSER_API_KEY_VALUE); 118d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 119d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return builder.build().toString(); 120d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 121d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 122d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian public static Intent getShowMapIntent( 123d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian Location location, @Nullable CharSequence addressLine1, @Nullable CharSequence addressLine2) { 124d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 125d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian String latLong = getFormattedLatLng(location); 126d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian String url = String.format(Locale.US, "geo: %s?q=%s", latLong, latLong); 127d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 128d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian // Add a map label 129d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (addressLine1 != null) { 130d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (addressLine2 != null) { 131d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian url += 132d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian String.format(Locale.US, "(%s, %s)", addressLine1.toString(), addressLine2.toString()); 133d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } else { 134d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian url += String.format(Locale.US, "(%s)", addressLine1.toString()); 135d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 136d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } else { 13710ae593a59aa50963e1d3159747da2d65ca79bedEric Erfanian // TODO: i18n 138d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian url += 139d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian String.format( 140d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian Locale.US, 141d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian "(Latitude: %f, Longitude: %f)", 142d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian location.getLatitude(), 143d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian location.getLongitude()); 144d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 145d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 146d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 147d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian intent.setPackage("com.google.android.apps.maps"); 148d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return intent; 149d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 150d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 151d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian /** 152d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Returns a comma-separated latitude and longitude pair, formatted for use as a URL parameter 153d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * value. 154d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 155d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param location A location. 156d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @return The comma-separated latitude and longitude pair of that location. 157d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 158d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian @VisibleForTesting 159d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian static String getFormattedLatLng(Location location) { 160d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return location.getLatitude() + LAT_LONG_DELIMITER + location.getLongitude(); 161d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 162d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 163d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian /** 164d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * Returns the URL parameter value for the marker, specifying its style and position. 165d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * 166d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @param location A location. 167d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian * @return The URL parameter value for the marker. 168d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian */ 169d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian @VisibleForTesting 170d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian static String getMarkerUrlParamValue(Location location) { 171d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian return MARKER_STYLE_COLOR 172d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + MARKER_STYLE_DELIMITER 173d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + MARKER_STYLE_COLOR_RED 174d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + MARKER_DELIMITER 175d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian + getFormattedLatLng(location); 176d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 177d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian} 178