Commit 346a4a16 authored by Deployer's avatar Deployer

- Updated Support Library, Build Tools, okhttp to the latest version available

- Removed CedarMapsTestApp. A new version called CedarMapsSampleApp is being written. - Added Directions API. - Added JavaDocs
parent 500d4915
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'signing'
apply plugin: 'com.github.dcendents.android-maven' apply plugin: 'com.github.dcendents.android-maven'
group = "com.cedarmaps" group = "com.cedarmaps"
version = "1.0.0" version = "2.0.0"
def siteUrl = 'http://cedarmaps.com' def siteUrl = 'http://cedarmaps.com'
def gitUrl = 'http://cedarmaps.com/git' def gitUrl = 'http://cedarmaps.com/git'
android { android {
compileSdkVersion 23 compileSdkVersion 26
buildToolsVersion "23.0.3" buildToolsVersion '26.0.2'
defaultConfig { defaultConfig {
minSdkVersion 9 minSdkVersion 15 //IceCream Sandwich 4.0.3
targetSdkVersion 23 targetSdkVersion 26 //Oreo
} }
} }
dependencies { dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs') compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'org.osmdroid:osmdroid-android:5.2@aar' compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1' compile 'com.squareup.okhttp3:okhttp-urlconnection:3.9.0'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1' compile 'com.google.code.gson:gson:2.8.0'
compile ('com.cedarmaps:mapbox-android-sdk:5.1.4@aar') {
transitive = true
}
}
// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/gradle-mvn-push.gradle
def isReleaseBuild() {
return VERSION_NAME.contains("SNAPSHOT") == false
} }
apply from: 'gradle-javadoc.gradle'
install { install {
repositories.mavenInstaller { repositories.mavenInstaller {
// This generates POM.xml with proper parameters // This generates POM.xml with proper parameters
...@@ -45,7 +56,7 @@ install { ...@@ -45,7 +56,7 @@ install {
developer { developer {
id 'cedarstudios' id 'cedarstudios'
name 'CedarStudios' name 'CedarStudios'
email 'info@cedarstudios.com' email 'info@cedarmaps.com'
} }
} }
scm { scm {
...@@ -58,3 +69,30 @@ install { ...@@ -58,3 +69,30 @@ install {
} }
} }
} }
signing {
required { isReleaseBuild() }
sign configurations.archives
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.sourceFiles
classpath = files(android.bootClasspath)
failOnError false
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.sourceFiles
}
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
}
android.libraryVariants.all { variant ->
def name = variant.name
// noinspection GroovyAssignabilityCheck
task "javadoc$name"(type: Javadoc) {
description = "Generates javadoc for build $name"
failOnError = false
destinationDir = new File(destinationDir, variant.baseName)
source = files(variant.javaCompile.source)
classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath)
options.windowTitle("CedarMaps Android SDK $VERSION_NAME Reference")
options.docTitle("CedarMaps Android SDK $VERSION_NAME")
options.header("CedarMaps Android SDK $VERSION_NAME Reference")
options.bottom("© 2017–2017 Cedar Studios. All rights reserved.")
options.links("http://docs.oracle.com/javase/7/docs/api/")
options.linksOffline("http://d.android.com/reference/", "$System.env.ANDROID_HOME/docs/reference")
options.overview("src/main/java/overview.html")
options.group("CedarMaps Android SDK", "com.cedarmaps.*")
exclude '**/R.java', '**/BuildConfig.java'
}
}
package com.cedarstudios.cedarmapssdk;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import com.cedarstudios.cedarmapssdk.listeners.AccessTokenListener;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.http.HTTPRequest;
import org.json.JSONObject;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
final class AuthenticationManager {
static final String ACCESS_TOKEN_READY_INTENT = "ACCESS_TOKEN_READY_INTENT";
private static final String defaultBaseURL = "https://api.cedarmaps.com/v1/";
private static final String SAVED_ACCESS_TOKEN_KEY = "com.cedarstudios.cedarmapssdk.saved_access_token";
private static AuthenticationManager instance;
private String mClientID;
private String mClientSecret;
private String mAccessToken;
private String mBaseURL;
private Context mContext = null;
private boolean isFetchingNewAccessToken = false;
private BroadcastReceiver mapViewError401BroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
regenerateAccessToken();
}
};
private AuthenticationManager() {
mBaseURL = defaultBaseURL;
}
public static AuthenticationManager getInstance() {
if (instance == null) {
instance = new AuthenticationManager();
}
return instance;
}
void setClientID(@NonNull String clientID) {
mClientID = clientID;
}
void setClientSecret(@NonNull String clientSecret) {
mClientSecret = clientSecret;
}
void getAccessToken(final @Nullable AccessTokenListener completionHandler) {
Handler handler = new Handler(Looper.getMainLooper());
if (TextUtils.isEmpty(mAccessToken)) {
String result;
try {
result = getSavedAccessToken();
if (TextUtils.isEmpty(result)) {
fetchAccessTokenFromServer(completionHandler);
} else {
mAccessToken = result;
if (completionHandler == null) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
completionHandler.onSuccess(mAccessToken);
}
});
}
} catch (final CedarMapsException e) {
if (completionHandler == null) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
completionHandler.onFailure(e.getMessage());
}
});
}
} else {
if (completionHandler == null) {
return;
}
handler.post(new Runnable() {
@Override
public void run() {
completionHandler.onSuccess(mAccessToken);
}
});
}
}
void setContext(@NonNull Context context) {
mContext = context.getApplicationContext();
LocalBroadcastManager.getInstance(mContext)
.registerReceiver(instance.mapViewError401BroadcastReceiver,
new IntentFilter(HTTPRequest.MAP_TILE_401_INTENT));
}
Context getContext() {
return mContext;
}
private void invalidateCredentials() {
mAccessToken = null;
if (mContext != null) {
SharedPreferences sharedPreferences = mContext.getSharedPreferences(SAVED_ACCESS_TOKEN_KEY, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.remove(SAVED_ACCESS_TOKEN_KEY);
editor.apply();
}
}
void regenerateAccessToken() {
if (isFetchingNewAccessToken) {
return;
}
isFetchingNewAccessToken = true;
invalidateCredentials();
fetchAccessTokenFromServer(new AccessTokenListener() {
@Override
public void onSuccess(@NonNull String accessToken) {
isFetchingNewAccessToken = false;
if (!TextUtils.isEmpty(accessToken)) {
Mapbox.getInstance(getContext(), accessToken);
Intent intent = new Intent(ACCESS_TOKEN_READY_INTENT);
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
}
}
@Override
public void onFailure(@NonNull String error) {
isFetchingNewAccessToken = false;
}
});
}
private boolean saveAccessToken() throws CedarMapsException {
if (TextUtils.isEmpty(mAccessToken)) {
throw new CedarMapsException("AccessToken is not available to save. Try calling 'getAccessToken' first.");
}
if (mContext == null) {
throw new CedarMapsException("Context is not set. Please call 'setContext' method on CedarMaps.getInstance()");
}
SharedPreferences sharedPreferences = mContext.getSharedPreferences(SAVED_ACCESS_TOKEN_KEY, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(SAVED_ACCESS_TOKEN_KEY, mAccessToken);
editor.apply();
return true;
}
@Nullable
private String getSavedAccessToken() throws CedarMapsException {
if (mContext == null) {
throw new CedarMapsException("Context is not set. Please call 'setContext' method on CedarMaps.getInstance()");
}
SharedPreferences sharedPreferences = mContext.getSharedPreferences(SAVED_ACCESS_TOKEN_KEY, Context.MODE_PRIVATE);
return sharedPreferences.getString(SAVED_ACCESS_TOKEN_KEY, null);
}
String getAPIBaseURL() {
return mBaseURL;
}
void setAPIBaseURL(@Nullable String baseURL) {
if (baseURL == null) {
this.mBaseURL = defaultBaseURL;
} else {
if ((baseURL.substring(baseURL.length() - 1)).equals("/")) {
this.mBaseURL = baseURL;
} else {
this.mBaseURL = baseURL + "/";
}
}
}
private void fetchAccessTokenFromServer(final AccessTokenListener completionHandler) {
CedarOkHttpClient client = CedarOkHttpClient.getInstance();
final Handler handler = new Handler(Looper.getMainLooper());
String url = mBaseURL + "token";
RequestBody formBody = new FormBody.Builder()
.add("client_id", mClientID)
.add("client_secret", mClientSecret)
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onFailure(e.getMessage());
}
}
});
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
ResponseBody body = response.body();
if (body == null) {
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onFailure("Response body was null. HTTP code: " + response.code());
}
}
});
} else {
try {
JSONObject responseObject = new JSONObject(body.string());
if (response.code() == 200) {
try {
mAccessToken = URLDecoder.decode(responseObject.optString("access_token"), "UTF-8");
saveAccessToken();
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onSuccess(mAccessToken);
}
}
});
} catch (final UnsupportedEncodingException ignore) {
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onFailure(ignore.getMessage());
}
}
});
}
} else if (response.code() == 401) {
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onFailure("Client Secret or Client ID is wrong. HTTP code: "
+ response.code());
}
}
});
} else {
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onFailure("Obtaining Bearer Token failed. HTTP code: "
+ response.code());
}
}
});
}
} catch (final Exception e) {
handler.post(new Runnable() {
@Override
public void run() {
if (completionHandler != null) {
completionHandler.onFailure(e.getMessage());
}
}
});
}
}
}
});
}
}
package com.cedarstudios.cedarmapssdk; package com.cedarstudios.cedarmapssdk;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Pair; import com.cedarstudios.cedarmapssdk.listeners.AccessTokenListener;
import com.cedarstudios.cedarmapssdk.listeners.ForwardGeocodeResultsListener;
import com.cedarstudios.cedarmapssdk.listeners.GeoRoutingResultListener;
import com.cedarstudios.cedarmapssdk.listeners.OnTilesConfigured;
import com.cedarstudios.cedarmapssdk.listeners.ReverseGeocodeResultListener;
import com.cedarstudios.cedarmapssdk.listeners.StaticMapImageResultListener;
import com.cedarstudios.cedarmapssdk.model.geocoder.forward.ForwardGeocodeResponse;
import com.cedarstudios.cedarmapssdk.model.geocoder.reverse.ReverseGeocodeResponse;
import com.cedarstudios.cedarmapssdk.model.routing.GeoRoutingResponse;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Support; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Locale;
import org.json.JSONObject; import okhttp3.Call;
import org.osmdroid.api.IGeoPoint; import okhttp3.Callback;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public interface CedarMaps extends OAuth2Support, CedarMapsBase { public class CedarMaps {
//region Constants
private static final String defaultMapID = "cedarmaps.streets";
private static final String defaultDirectionID = "cedarmaps.driving";
//endregion
//region Properties
private String mMapID;
private String mDirectionID;
private static CedarMaps instance;
//endregion
//region Initializers
public static CedarMaps getInstance() {
if (instance == null) {
instance = new CedarMaps();
}
return instance;
}
private CedarMaps() {
mMapID = defaultMapID;
mDirectionID = defaultDirectionID;
}
/**
* Preparing Tiles for using in a mapView.
* Make sure to call setClientID , setClientSecret and setContext before calling this method.
* @param completionHandler The handler to notify when preparing tiles was finished with success or error.
*/
public void prepareTiles(OnTilesConfigured completionHandler) {
TileConfigurator.prepare(completionHandler);
}
//endregion
//region Setters & Getters
String getMapID() {
return mMapID;
}
void setMapID(String mapID) {
this.mMapID = mapID;
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Setting your clientID for using CedarMaps API.
* This method should be called during setup before using any of the CedarMaps methods.
* @param clientID The client ID you received for using CedarMaps SDK.
* @return AuthenticationManager singleton object; You could use this to continue setting the other parameters such as clientSecret and context.
*/
public AuthenticationManager setClientID(@NonNull String clientID) {
AuthenticationManager.getInstance().setClientID(clientID);
return AuthenticationManager.getInstance();
}
/**
* Setting your clientSecret for using CedarMaps API.
* This method should be called during setup before using any of the CedarMaps methods.
* @param clientSecret The client secret you received for using CedarMaps SDK.
* @return AuthenticationManager singleton object; You could use this to continue setting the other parameters such as context.
*/
public AuthenticationManager setClientSecret(@NonNull String clientSecret) {
AuthenticationManager.getInstance().setClientSecret(clientSecret);
return AuthenticationManager.getInstance();
}
/**
* Setting the context for using CedarMaps API.
* This method should be called during setup before using any of the CedarMaps methods.
* @param context You can pass your MainActivity as the context.
* We will use applicationContext extracted from what you pass.
* This needs to be set only once in the lifetime of your application.
* @return AuthenticationManager singleton object.
*/
public AuthenticationManager setContext(@NonNull Context context) {
AuthenticationManager.getInstance().setContext(context);
return AuthenticationManager.getInstance();
}
/**
* Setting the baseURL for using CedarMaps API.
* If you are given a different baseURL for using CedarMaps API, set it here.
* This method should be called during setup before using any of the CedarMaps methods.
* @param url If you pass null, the SDK uses the default baseURL.
* @return AuthenticationManager singleton object.
*/
public AuthenticationManager setAPIBaseURL(@Nullable String url) {
AuthenticationManager.getInstance().setAPIBaseURL(url);
return AuthenticationManager.getInstance();
}
//endregion
/**
* Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler is called on UIThread.
*/ */
JSONObject geocode(String searchTerm) throws CedarMapsException; public void forwardGeocode(@NonNull String searchTerm, @NonNull ForwardGeocodeResultsListener completionHandler) {
forwardGeocode(searchTerm, null, completionHandler);
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",") * @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",")
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject geocode(String searchTerm, String type) throws CedarMapsException; public void forwardGeocode(@NonNull String searchTerm, String type, @NonNull ForwardGeocodeResultsListener completionHandler) {
forwardGeocode(searchTerm, type, 30, completionHandler);
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",") * @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",")
* @param limit Number of results * @param limit Number of results
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject geocode(String searchTerm, String type, int limit) throws CedarMapsException; public void forwardGeocode(String searchTerm, String type, int limit, @NonNull ForwardGeocodeResultsListener completionHandler) {
forwardGeocode(searchTerm, null, -1, null, type, limit, completionHandler);
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @param location Center point. should be accompanied with distance param * @param location Center point. should be accompanied with distance param
* @param distance Distance from location. Unit is km, 0.1 means 100 meters * @param distance GeoRouting from location. Unit is km, 0.1 means 100 meters
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject geocode(String searchTerm, IGeoPoint location, float distance) throws CedarMapsException; public void forwardGeocode(String searchTerm, LatLng location, float distance, @NonNull ForwardGeocodeResultsListener completionHandler) {
forwardGeocode(searchTerm, location, distance, null, null, 30, completionHandler);
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @param location Center point. should be accompanied with distance param * @param location Center point. should be accompanied with distance param
* @param distance Distance from location. Unit is km, 0.1 means 100 meters * @param distance GeoRouting from location. Unit is km, 0.1 means 100 meters
* @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",") * @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",")
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject geocode(String searchTerm, IGeoPoint location, float distance, String type) throws CedarMapsException; public void forwardGeocode(String searchTerm, LatLng location, float distance, String type, @NonNull ForwardGeocodeResultsListener completionHandler) {
forwardGeocode(searchTerm, location, distance, null, type, 30, completionHandler);
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @param location Center point. should be accompanied with distance param * @param location Center point. should be accompanied with distance param
* @param distance Distance from location. Unit is km, 0.1 means 100 meters * @param distance GeoRouting from location. Unit is km, 0.1 means 100 meters
* @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",") * @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",")
* @param limit Number of results * @param limit Number of results
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject geocode(String searchTerm, IGeoPoint location, float distance, String type, int limit) throws CedarMapsException; public void forwardGeocode(String searchTerm, LatLng location, float distance, String type, int limit, @NonNull ForwardGeocodeResultsListener completionHandler) {
forwardGeocode(searchTerm, location, distance, null, type, limit, completionHandler);
}
/** /**
* Forward Geocoding. This API call needs a valid access token. * Forward Geocoding. You can use this method to obtain address info about the entered query.
* This method works asynchronously and returns immediately.
* *
* @param searchTerm Wherever you want to get info about * @param searchTerm Wherever you want to get info about
* @param location Center point. should be accompanied with distance param * @param location Center point. should be accompanied with distance param
* @param distance Distance from location. Unit is km, 0.1 means 100 meters * @param distance GeoRouting from location. Unit is km, 0.1 means 100 meters
* @param ne Specifies north east of the bounding box - should be accompanied with sw param * @param bounds Specifies the bounding box to search inside.
* @param sw Specifies south west of the bounding box - should be accompanied with ne param
* @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",") * @param type Possible values are: locality, roundabout, street, freeway, expressway, boulevard (You can mix types by separating them with ",")
* @param limit Number of results * @param limit Number of results
* @return Results as JSONObject * @param completionHandler The handler to notify when Forward Geocode results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject geocode(String searchTerm, IGeoPoint location, float distance, IGeoPoint ne, IGeoPoint sw, String type, int limit) throws CedarMapsException; public void forwardGeocode(String searchTerm, LatLng location, float distance, LatLngBounds bounds, String type, int limit, @NonNull final ForwardGeocodeResultsListener completionHandler) {
String term;
try {
term = URLEncoder.encode(searchTerm, "UTF-8");
} catch (UnsupportedEncodingException e) {
completionHandler.onFailure(e.getMessage());
return;
}
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "geocode/%s/%s.json",
mMapID,
term);
url += String.format(Locale.ENGLISH, "?limit=%s", limit);
if (location != null) {
url += String.format(Locale.ENGLISH, "&location=%1$s,%2$s&distance=%3$s", location.getLatitude(), location.getLongitude(), distance);
}
if (bounds != null) {
url += String.format(Locale.ENGLISH, "&ne=%1$s,%2$s", bounds.getNorthEast().getLatitude(), bounds.getNorthEast().getLongitude());
url += String.format(Locale.ENGLISH, "&sw=%1$s,%2$s", bounds.getSouthWest().getLatitude(), bounds.getSouthWest().getLongitude());
}
if (!TextUtils.isEmpty(type)) {
url += String.format(Locale.ENGLISH, "&type=%s", type);
}
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(ResponseBody responseBody) {
ForwardGeocodeResponse forwardGeocodeResponse = ForwardGeocodeResponse.parseJSON(responseBody.charStream());
if (forwardGeocodeResponse.results == null) {
completionHandler.onFailure(forwardGeocodeResponse.status);
} else {
completionHandler.onSuccess(forwardGeocodeResponse.results);
}
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/** /**
* Gives an address based on a provided IGeoPoint pair. This API call needs a valid access token. * Gives an address based on a provided coordinate.
* This method works asynchronously and returns immediately.
* *
* @param lat * @param coordinate The coordinate to get the address from.
* @param lng * @param completionHandler The handler to notify when Reverse Geocode results are ready with success or error.
* @return Results as JSONObject * The handler methods are called on UIThread.
* @throws CedarMapsException
*/ */
JSONObject geocode(double lat, double lng) throws CedarMapsException; public void reverseGeocode(LatLng coordinate, final ReverseGeocodeResultListener completionHandler) {
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "geocode/%1$s/%2$s,%3$s.json",
mMapID,
coordinate.getLatitude(), coordinate.getLongitude());
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(ResponseBody responseBody) {
ReverseGeocodeResponse reverseGeocodeResponse = ReverseGeocodeResponse.parseJSON(responseBody.charStream());
if (reverseGeocodeResponse.result == null) {
completionHandler.onFailure(reverseGeocodeResponse.status);
} else {
completionHandler.onSuccess(reverseGeocodeResponse.result);
}
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/** /**
* This method calculates the distance between points in meters. It can be called with up to 50 different points in a single request. * This method calculates the distance between two points in meters.
* This API call needs a valid access token.
* *
* @param location1 Starting point * @param start Starting coordinate
* @param location2 Ending point * @param end Ending coordinate
* @return Results as JSONObject * @param completionHandler The handler to notify when Geo Routing results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/ */
JSONObject distance(IGeoPoint location1, IGeoPoint location2) throws CedarMapsException; public void distance(LatLng start, LatLng end, final GeoRoutingResultListener completionHandler) {
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "distance/%1$s/%2$s,%3$s;%4$s,%5$s",
mDirectionID,
start.getLatitude(), start.getLongitude(), end.getLatitude(), end.getLongitude());
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(ResponseBody responseBody) {
GeoRoutingResponse geoRoutingResponse = GeoRoutingResponse.parseJSON(responseBody.charStream());
if (geoRoutingResponse.result == null) {
completionHandler.onFailure(geoRoutingResponse.status);
} else {
completionHandler.onSuccess(geoRoutingResponse.result);
}
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/** /**
* This method calculates the distance between points in meters. It can be called with up to 15 pairs * This method calculates the distance between points in meters. It can be called with up to 15 pairs
* This API call needs a valid access token. * This API call needs a valid access token.
* *
* @param locationPairs Set up to 15 pairs * @param coordinatePairs Set up to 15 pairs of (Start, End).
* @return Results as JSONObject * @param completionHandler The handler to notify when Geo Routing results are ready with success or error.
* @throws CedarMapsException * The handler methods are called on UIThread.
*/
public void distance(Pair<LatLng, LatLng>[] coordinatePairs, final GeoRoutingResultListener completionHandler) {
String pairs = "";
String delimiter = "";
for (Pair<LatLng, LatLng> locationPair : coordinatePairs) {
pairs += delimiter + String.format(Locale.ENGLISH, "%1$s,%2$s;%3$s,%4$s", locationPair.first.getLatitude(),
locationPair.first.getLongitude(), locationPair.second.getLatitude(), locationPair.second.getLatitude());
delimiter = "/";
}
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "distance/%1$s/%2$s",
mDirectionID, pairs);
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(ResponseBody responseBody) {
GeoRoutingResponse geoRoutingResponse = GeoRoutingResponse.parseJSON(responseBody.charStream());
if (geoRoutingResponse.result == null) {
completionHandler.onFailure(geoRoutingResponse.status);
} else {
completionHandler.onSuccess(geoRoutingResponse.result);
}
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/**
* This method calculates the detailed coordinates of the route between two points.
*
* @param start Starting coordinate
* @param end Ending coordinate
* @param completionHandler The handler to notify when Geo Routing results are ready with success or error.
* The handler methods are called on UIThread.
*/ */
JSONObject distance(Pair<IGeoPoint, IGeoPoint>[] locationPairs) throws CedarMapsException; public void direction(LatLng start, LatLng end, final GeoRoutingResultListener completionHandler) {
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "direction/%1$s/%2$s,%3$s;%4$s,%5$s",
mDirectionID,
start.getLatitude(), start.getLongitude(), end.getLatitude(), end.getLongitude());
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(ResponseBody responseBody) {
GeoRoutingResponse geoRoutingResponse = GeoRoutingResponse.parseJSON(responseBody.charStream());
if (geoRoutingResponse.result == null) {
completionHandler.onFailure(geoRoutingResponse.status);
} else {
completionHandler.onSuccess(geoRoutingResponse.result);
}
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/** /**
* Gives all localities in a city wih geometry in GeoJSON format. * This method calculates the detailed coordinates of the route between two consecutive points. It can be called with up to 50 pairs
* @param city City name in English or Persian *
* @return Results as JSONObject * @param coordinatePairs Set up to 50 pairs of (Start, End).
* @throws CedarMapsException * @param completionHandler The handler to notify when Geo Routing results are ready with success or error.
* The handler methods are called on UIThread.
*/ */
JSONObject locality(String city) throws CedarMapsException; public void direction(Pair<LatLng, LatLng>[] coordinatePairs, final GeoRoutingResultListener completionHandler) {
String pairs = "";
String delimiter = "";
for (Pair<LatLng, LatLng> locationPair : coordinatePairs) {
pairs += delimiter + String.format(Locale.ENGLISH, "%1$s,%2$s;%3$s,%4$s", locationPair.first.getLatitude(),
locationPair.first.getLongitude(), locationPair.second.getLatitude(), locationPair.second.getLatitude());
delimiter = "/";
}
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "direction/%1$s/%2$s",
mDirectionID, pairs);
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(ResponseBody responseBody) {
GeoRoutingResponse geoRoutingResponse = GeoRoutingResponse.parseJSON(responseBody.charStream());
if (geoRoutingResponse.result == null) {
completionHandler.onFailure(geoRoutingResponse.status);
} else {
completionHandler.onSuccess(geoRoutingResponse.result);
}
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/**
* This method creates a static image of map for the entered location.
*
* @param dimension The wrapper for the width and height of the required image. The width and height should be specified in pixels. (not dp)
* @param zoomLevel An integer for the required zoom level. Valid from 6 to 17.
* @param centerPoint The center of the map in the image. If you pass null, make sure to fill the markers array. The boundary will be automatically set to show all the markers.
* @param markers An array of StaticMarker objects. The markers will be drawn on the resulting image.
* @param completionHandler The handler to notify when static image Bitmap is ready with success or error.
* The handler methods are called on UIThread.
*/
public void staticMap(@NonNull Dimension dimension, int zoomLevel, @Nullable LatLng centerPoint, @Nullable ArrayList<StaticMarker> markers, final @NonNull StaticMapImageResultListener completionHandler) {
int validZoomLevel = Math.min(17, Math.max(zoomLevel, 6));
String paramPosition = centerPoint != null ? String.format(Locale.ENGLISH, "%f,%f,%d", centerPoint.getLatitude(), centerPoint.getLongitude(), validZoomLevel) : "auto";
String paramDimension = dimension.toStringUsingDp(true);
String paramScale = "";
if (Resources.getSystem().getDisplayMetrics().densityDpi > DisplayMetrics.DENSITY_MEDIUM) {
paramScale = "@2x";
}
String paramMarkers = "";
if (markers != null && markers.size() > 0) {
paramMarkers = "?markers=";
for (StaticMarker marker: markers) {
String item = String.format(Locale.ENGLISH, "%s|%f,%f|",
marker.markerUri == null ? "marker-default" : marker.markerUri.toString(),
marker.coordinate.getLatitude(),
marker.coordinate.getLongitude());
paramMarkers += item;
}
paramMarkers = paramMarkers.substring(0, paramMarkers.length() - 1);
}
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL() + "static/light/%s/%s%s%s", paramPosition, paramDimension, paramScale, paramMarkers);
getResponseBodyFromURL(url, new NetworkResponseBodyCompletionHandler() {
@Override
public void onSuccess(final ResponseBody responseBody) {
final Handler mainHandler = new Handler(Looper.getMainLooper());
AsyncTask.execute(new Runnable() {
@Override
public void run() {
final Bitmap bitmap = BitmapFactory.decodeStream(responseBody.byteStream());
mainHandler.post(new Runnable() {
@Override
public void run() {
if (bitmap == null) {
completionHandler.onFailure("Bitmap decoding failed");
} else {
completionHandler.onSuccess(bitmap);
}
}
});
}
});
}
@Override
public void onFailure(String errorMessage) {
completionHandler.onFailure(errorMessage);
}
});
}
/**
* The wrapper class whose instances are used for showing markers on the static map.
* @see #staticMap(Dimension, int, LatLng, ArrayList, StaticMapImageResultListener)
*/
public static class StaticMarker {
@NonNull
private LatLng coordinate;
@Nullable
private Uri markerUri;
/**
*
* @param coordinate The coordinate of the marker
* @param markerUri The remote address of the image you want to use for the marker
*/
public StaticMarker(@NonNull LatLng coordinate, @Nullable Uri markerUri) {
this.coordinate = coordinate;
this.markerUri = markerUri;
}
}
private interface NetworkResponseBodyCompletionHandler {
void onSuccess(ResponseBody responseBody);
void onFailure(String errorMessage);
}
private void getResponseBodyFromURL(final String url, final NetworkResponseBodyCompletionHandler completionHandler) {
final Handler handler = new Handler(Looper.getMainLooper());
AuthenticationManager.getInstance().getAccessToken(new AccessTokenListener() {
@Override
public void onSuccess(@NonNull String accessToken) {
CedarOkHttpClient client = CedarOkHttpClient.getInstance();
Request request = new Request.Builder()
.url(url)
.tag(url)
.addHeader("Authorization", "Bearer " + accessToken)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, final Response response) throws IOException {
handler.post(new Runnable() {
@Override
public void run() {
if (response.code() == 400) {
completionHandler.onFailure(new CedarMapsException("Invalid Request. Missing Parameters.", response).getMessage());
} else if (response.code() == 401) {
AuthenticationManager.getInstance().regenerateAccessToken();
completionHandler.onFailure(new CedarMapsException("Obtaining Bearer Token Failed.", response).getMessage());
} else if (response.code() == 500) {
completionHandler.onFailure(new CedarMapsException("Internal Server Error.", response).getMessage());
} else {
ResponseBody body = response.body();
if (body == null) {
completionHandler.onFailure(new CedarMapsException("Response body can't be parsed.", response).getMessage());
} else {
completionHandler.onSuccess(body);
}
}
}
});
}
@Override
public void onFailure(final Call call, final IOException e) {
handler.post(new Runnable() {
@Override
public void run() {
completionHandler.onFailure(new CedarMapsException(call.toString(), e).getMessage());
}
});
}
});
}
@Override
public void onFailure(final @NonNull String error) {
handler.post(new Runnable() {
@Override
public void run() {
completionHandler.onFailure(error);
}
});
}
});
}
} }
package com.cedarstudios.cedarmapssdk;
import com.cedarstudios.cedarmapssdk.auth.Authorization;
import com.cedarstudios.cedarmapssdk.config.Configuration;
public interface CedarMapsBase {
/**
* Returns the authorization scheme for this instance.<br>
* The returned type will be either of OAuthAuthorization or NullAuthorization
*
* @return the authorization scheme for this instance
*/
Authorization getAuthorization();
/**
* Returns the configuration associated with this instance
*
* @return configuration associated with this instance
* @since CedarMaps 0.5
*/
Configuration getConfiguration();
}
package com.cedarstudios.cedarmapssdk;
import com.cedarstudios.cedarmapssdk.auth.Authorization;
import com.cedarstudios.cedarmapssdk.auth.NullAuthorization;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Authorization;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Support;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Token;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
abstract class CedarMapsBaseImpl implements CedarMapsBase, Serializable, OAuth2Support {
Configuration conf;
Authorization auth;
CedarMapsBaseImpl(Configuration conf, Authorization auth) {
this.conf = conf;
this.auth = auth;
init();
}
private void init() {
if (null == auth) {
// try to populate OAuthAuthorization if available in the configuration
String clientId = conf.getOAuthClientId();
String clientSecret = conf.getOAuthClientSecret();
// try to find oauth tokens in the configuration
if (clientId != null && clientSecret != null) {
OAuth2Authorization oauth2 = new OAuth2Authorization(conf);
String tokenType = conf.getOAuth2TokenType();
String accessToken = conf.getOAuth2AccessToken();
if (tokenType != null && accessToken != null) {
oauth2.setOAuth2Token(new OAuth2Token(tokenType, accessToken));
}
this.auth = oauth2;
} else {
this.auth = NullAuthorization.getInstance();
}
}
}
@Override
public final Authorization getAuthorization() {
return auth;
}
@Override
public Configuration getConfiguration() {
return this.conf;
}
final void ensureAuthorizationEnabled() {
if (!auth.isEnabled()) {
throw new IllegalStateException("Authentication credentials are missing. ");
}
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
// http://docs.oracle.com/javase/6/docs/platform/serialization/spec/output.html#861
out.putFields();
out.writeFields();
out.writeObject(conf);
out.writeObject(auth);
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
// http://docs.oracle.com/javase/6/docs/platform/serialization/spec/input.html#2971
stream.readFields();
conf = (Configuration) stream.readObject();
auth = (Authorization) stream.readObject();
}
// methods declared in OAuthSupport interface
@Override
public synchronized OAuth2Token getOAuth2Token() throws CedarMapsException {
return getOAuth2().getOAuth2Token();
}
@Override
public void setOAuth2Token(OAuth2Token oauth2Token) {
getOAuth2().setOAuth2Token(oauth2Token);
}
@Override
public synchronized void invalidateOAuth2Token() throws CedarMapsException {
getOAuth2().invalidateOAuth2Token();
}
private OAuth2Support getOAuth2() {
if (!(auth instanceof OAuth2Support)) {
throw new IllegalStateException("OAuth client id/secret combination not supplied");
}
return (OAuth2Support) auth;
}
}
package com.cedarstudios.cedarmapssdk;
import com.cedarstudios.cedarmapssdk.auth.Authorization;
import com.cedarstudios.cedarmapssdk.auth.AuthorizationFactory;
import com.cedarstudios.cedarmapssdk.config.Configuration;
public class CedarMapsFactory {
private static CedarMaps singleton;
private final Configuration configuration;
public CedarMaps getInstance() {
return getInstance(AuthorizationFactory.getInstance(configuration));
}
public CedarMaps getInstance(Authorization auth) {
return new CedarMapsImpl(configuration, auth);
}
public CedarMapsFactory(Configuration configuration) {
this.configuration = configuration;
}
}
package com.cedarstudios.cedarmapssdk;
import android.text.TextUtils;
import android.util.Pair;
import com.cedarstudios.cedarmapssdk.auth.Authorization;
import com.cedarstudios.cedarmapssdk.auth.NullAuthorization;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Authorization;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import org.json.JSONException;
import org.json.JSONObject;
import org.osmdroid.api.IGeoPoint;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Locale;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
class CedarMapsImpl extends CedarMapsBaseImpl implements CedarMaps {
CedarMapsImpl(Configuration conf, Authorization auth) {
super(conf, auth);
}
@Override
public JSONObject geocode(String searchTerm) throws CedarMapsException {
return geocode(searchTerm, null);
}
@Override
public JSONObject geocode(String searchTerm, String type) throws CedarMapsException {
return geocode(searchTerm, type, 30);
}
@Override
public JSONObject geocode(String searchTerm, String type, int limit) throws CedarMapsException {
return geocode(searchTerm, null, -1, null, null, type, limit);
}
@Override
public JSONObject geocode(String searchTerm, IGeoPoint location, float distance) throws CedarMapsException {
return geocode(searchTerm, location, distance, null, null, null, 30);
}
@Override
public JSONObject geocode(String searchTerm, IGeoPoint location, float distance, String type) throws CedarMapsException {
return geocode(searchTerm, location, distance, null, null, type, 30);
}
@Override
public JSONObject geocode(String searchTerm, IGeoPoint location, float distance, String type, int limit) throws CedarMapsException {
return geocode(searchTerm, location, distance, null, null, type, limit);
}
@Override
public JSONObject geocode(String searchTerm, IGeoPoint location, float distance, IGeoPoint ne, IGeoPoint sw, String type, int limit)
throws CedarMapsException {
String term;
if (TextUtils.isEmpty(conf.getMapId())) {
throw new CedarMapsException(new NullPointerException("mapId is null. please provide a mapId in configuration"));
}
try {
term = URLEncoder.encode(searchTerm, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new CedarMapsException(e);
}
String url = String.format(Locale.ENGLISH, conf.getAPIBaseURL() + "geocode/%s/%s.json", conf.getMapId(), term);
url += String.format(Locale.ENGLISH, "?limit=%s", limit);
if (location != null) {
url += String.format(Locale.ENGLISH, "&location=%1$s,%2$s&distance=%3$s", location.getLatitude(), location.getLongitude(), distance);
}
if (ne != null) {
url += String.format(Locale.ENGLISH, "&ne=%1$s,%2$s", ne.getLatitude(), ne.getLongitude());
}
if (sw != null) {
url += String.format(Locale.ENGLISH, "&sw=%1$s,%2$s", sw.getLatitude(), sw.getLongitude());
}
if (!TextUtils.isEmpty(type)) {
url += String.format(Locale.ENGLISH, "&type=%s", type);
}
try {
return new JSONObject(getDataFromAPI(url));
} catch (JSONException e) {
throw new CedarMapsException(e);
}
}
@SuppressWarnings("SpellCheckingInspection")
@Override
public JSONObject geocode(double lat, double lng) throws CedarMapsException {
if (TextUtils.isEmpty(conf.getMapId())) {
throw new CedarMapsException(new NullPointerException("mapId is null. please provide a mapId in configuration"));
}
String url = String.format(Locale.ENGLISH, conf.getAPIBaseURL() + "geocode/%1$s/%2$s,%3$s.json", conf.getMapId(), lat, lng);
try {
return new JSONObject(getDataFromAPI(url));
} catch (JSONException e) {
throw new CedarMapsException(e);
}
}
@Override
public JSONObject distance(IGeoPoint location1, IGeoPoint location2) throws CedarMapsException {
if (TextUtils.isEmpty(conf.getMapId())) {
throw new CedarMapsException(new NullPointerException("mapId is null. please provide a mapId in configuration"));
}
String url = String.format(Locale.ENGLISH, conf.getAPIBaseURL() + "distance/%1$s/%2$s,%3$s;%4$s,%5$s", conf.getMapId(),
location1.getLatitude(), location1.getLongitude(), location2.getLatitude(), location2.getLongitude());
try {
return new JSONObject(getDataFromAPI(url));
} catch (JSONException e) {
throw new CedarMapsException(e);
}
}
@Override
public JSONObject distance(Pair<IGeoPoint, IGeoPoint>[] locationPairs) throws CedarMapsException {
if (TextUtils.isEmpty(conf.getMapId())) {
throw new CedarMapsException(new NullPointerException("mapId is null. please provide a mapId in configuration"));
}
String pairs = "";
String delimiter = "";
for (Pair<IGeoPoint, IGeoPoint> locationPair : locationPairs) {
pairs += delimiter + String.format(Locale.ENGLISH, "%1$s,%2$s;%3$s,%4$s", locationPair.first.getLatitude(),
locationPair.first.getLongitude(), locationPair.second.getLatitude(), locationPair.second.getLatitude());
delimiter = "/";
}
String url = String.format(Locale.ENGLISH, conf.getAPIBaseURL() + "distance/%1$s/%2$s", conf.getMapId(), pairs);
try {
return new JSONObject(getDataFromAPI(url));
} catch (JSONException e) {
throw new CedarMapsException(e);
}
}
@Override
public JSONObject locality(String city) throws CedarMapsException {
String url = String.format(Locale.ENGLISH, conf.getAPIBaseURL() + "locality/%s.json", city);
try {
return new JSONObject(getDataFromAPI(url));
} catch (JSONException e) {
throw new CedarMapsException(e);
}
}
private String getDataFromAPI(String url) throws CedarMapsException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", "Bearer " + conf.getOAuth2AccessToken())
.build();
Response response;
String responseString;
try {
response = client.newCall(request).execute();
responseString = response.body().string();
} catch (Exception e) {
throw new CedarMapsException(e);
}
if (response.code() == 400) {
throw new CedarMapsException("Invalid Request. missing parameter.", response);
} else if (response.code() == 401) {
throw new CedarMapsException("OAuth2 Bearer Token failed.", response);
} else if (response.code() == 500) {
throw new CedarMapsException("Internal Error", response);
}
return responseString;
}
@Override
public void setOAuthClient(String clientId, String clientSecret) {
if (null == clientId) {
throw new NullPointerException("client key is null");
}
if (null == clientSecret) {
throw new NullPointerException("client secret is null");
}
if (auth instanceof NullAuthorization) {
OAuth2Authorization oauth2 = new OAuth2Authorization(conf);
oauth2.setOAuthClient(clientId, clientSecret);
auth = oauth2;
} else if (auth instanceof OAuth2Authorization) {
throw new IllegalStateException("client id/secret pair already set.");
}
}
}
package com.cedarstudios.cedarmapssdk;
import com.cedarstudios.cedarmapssdk.tileprovider.tilesource.CedarMapsTileSourceInfo;
public interface CedarMapsTileLayerListener {
void onPrepared(CedarMapsTileSourceInfo tileLayer);
}
package com.cedarstudios.cedarmapssdk;
import okhttp3.OkHttpClient;
final class CedarOkHttpClient extends OkHttpClient {
private static CedarOkHttpClient client = new CedarOkHttpClient();
public static CedarOkHttpClient getInstance() {
return client;
}
}
package com.cedarstudios.cedarmapssdk;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import java.util.Locale;
/**
* A wrapper class for the width and height of the required image.
*/
public class Dimension {
private int width;
private int height;
public Dimension(int width, int height) {
this.width = width;
this.height = height;
}
int getWidthUsingDp(boolean usingDp) {
if (usingDp) {
return pixelToDp(width);
} else {
return width;
}
}
int getHeightUsingDp(boolean usingDp) {
if (usingDp) {
return pixelToDp(height);
} else {
return height;
}
}
public String toString() {
return toStringUsingDp(false);
}
String toStringUsingDp(boolean usingDp) {
return String.format(Locale.ENGLISH, "%dx%d", getWidthUsingDp(usingDp), getHeightUsingDp(usingDp));
}
int pixelToDp(int pixel) {
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
return Math.round(pixel / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
int dpToPixel(int dp) {
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
}
package com.cedarstudios.cedarmapssdk;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.AttributeSet;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import java.util.Locale;
public class MapView extends com.mapbox.mapboxsdk.maps.MapView {
private BroadcastReceiver mBroadcastReceiver = null;
public MapView(@NonNull Context context) {
super(context);
setupBroadcastReceiver();
setupStyleURL();
}
public MapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setupBroadcastReceiver();
setupStyleURL();
}
public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupBroadcastReceiver();
setupStyleURL();
}
public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
super(context, options);
setupBroadcastReceiver();
setupStyleURL();
}
private void setupBroadcastReceiver() {
if (mBroadcastReceiver == null) {
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setupStyleURL();
}
};
LocalBroadcastManager.getInstance(Mapbox.getApplicationContext())
.registerReceiver(mBroadcastReceiver, new IntentFilter(AuthenticationManager.ACCESS_TOKEN_READY_INTENT));
}
}
private void setupStyleURL() {
String url = String.format(Locale.ENGLISH,
AuthenticationManager.getInstance().getAPIBaseURL()
+ "tiles/light.json?access_token=%s",
Mapbox.getAccessToken());
this.setStyleUrl(url);
}
@Override
public void onDestroy() {
LocalBroadcastManager.getInstance(Mapbox.getApplicationContext()).unregisterReceiver(mBroadcastReceiver);
super.onDestroy();
}
}
package com.cedarstudios.cedarmapssdk;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.cedarstudios.cedarmapssdk.listeners.AccessTokenListener;
import com.cedarstudios.cedarmapssdk.listeners.OnTilesConfigured;
import com.mapbox.mapboxsdk.Mapbox;
final class TileConfigurator {
static void prepare(@Nullable final OnTilesConfigured completionHandler) {
final Context context = AuthenticationManager.getInstance().getContext();
Handler handler = new Handler(Looper.getMainLooper());
if (context == null) {
if (completionHandler != null) {
handler.post(new Runnable() {
@Override
public void run() {
completionHandler.onFailure("Context is not set. Please call 'setContext' method on CedarMaps.getInstance()");
}
});
}
} else {
AuthenticationManager.getInstance().getAccessToken(new AccessTokenListener() {
@Override
public void onSuccess(@NonNull String accessToken) {
Mapbox.getInstance(context, accessToken);
if (completionHandler != null) {
completionHandler.onSuccess();
}
}
@Override
public void onFailure(@NonNull String error) {
if (completionHandler != null) {
completionHandler.onFailure(error);
}
}
});
}
}
}
package com.cedarstudios.cedarmapssdk.auth;
public interface Authorization {
boolean isEnabled();
}
package com.cedarstudios.cedarmapssdk.auth;
public interface AuthorizationConfiguration {
String getOAuth2TokenType();
String getOAuth2AccessToken();
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.auth;
import com.cedarstudios.cedarmapssdk.config.Configuration;
public final class AuthorizationFactory {
/**
* @param conf configuration
* @since CedarMaps 0.5
*/
public static Authorization getInstance(Configuration conf) {
Authorization auth = null;
String clientId = conf.getOAuthClientId();
String clientSecret = conf.getOAuthClientSecret();
if (clientId != null && clientSecret != null) {
OAuth2Authorization oauth2 = new OAuth2Authorization(conf);
String tokenType = conf.getOAuth2TokenType();
String accessToken = conf.getOAuth2AccessToken();
if (tokenType != null && accessToken != null) {
oauth2.setOAuth2Token(new OAuth2Token(tokenType, accessToken));
}
auth = oauth2;
}
if (null == auth) {
auth = NullAuthorization.getInstance();
}
return auth;
}
}
package com.cedarstudios.cedarmapssdk.auth;
import java.io.Serializable;
public class NullAuthorization implements Authorization, Serializable {
private static final NullAuthorization SINGLETON = new NullAuthorization();
private NullAuthorization() {
}
public static NullAuthorization getInstance() {
return SINGLETON;
}
@Override
public boolean isEnabled() {
return false;
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.auth;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import org.json.JSONObject;
import java.io.Serializable;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class OAuth2Authorization implements Authorization, Serializable, OAuth2Support {
private final Configuration conf;
private String clientId;
private String clientSecret;
private OAuth2Token token;
public OAuth2Authorization(Configuration conf) {
this.conf = conf;
setOAuthClient(conf.getOAuthClientId(), conf.getOAuthClientSecret());
}
@Override
public void setOAuthClient(String clientId, String clientSecret) {
this.clientId = clientId != null ? clientId : "";
this.clientSecret = clientSecret != null ? clientSecret : "";
}
@Override
public OAuth2Token getOAuth2Token() throws CedarMapsException {
if (token != null) {
throw new IllegalStateException("OAuth 2 Bearer Token is already available.");
}
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("client_id", clientId)
.add("client_secret", clientSecret)
.build();
Request request = new Request.Builder()
.url(conf.getOAuth2TokenURL())
.post(formBody)
.build();
JSONObject responseObject;
Response response;
try {
response = client.newCall(request).execute();
responseObject = new JSONObject(response.body().string());
} catch (Exception e) {
throw new CedarMapsException(e);
}
if (response.code() != 200) {
throw new CedarMapsException("Obtaining OAuth2 Bearer Token failed.", response);
}
token = new OAuth2Token(responseObject);
return token;
}
@Override
public void setOAuth2Token(OAuth2Token oauth2Token) {
this.token = oauth2Token;
}
@Override
public void invalidateOAuth2Token() throws CedarMapsException {
//TODO
}
@Override
public boolean isEnabled() {
return token != null;
}
}
package com.cedarstudios.cedarmapssdk.auth;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
public interface OAuth2Support {
/**
* Sets the OAuth client id and client secret.
*
* @param clientId OAuth client id
* @param clientSecret OAuth client secret
* @throws IllegalStateException when OAuth client has already been set, or the instance is
* using basic authorization.
*/
void setOAuthClient(String clientId, String clientSecret);
/**
* Obtains an OAuth 2 Bearer token.
*
* @return OAuth 2 Bearer token
* @throws CedarMapsException when service or network is unavailable, or connecting
* non-SSL endpoints.
* @throws IllegalStateException when Bearer token is already available, or OAuth client is
* not available.
*/
OAuth2Token getOAuth2Token() throws CedarMapsException;
/**
* Sets the OAuth 2 Bearer token.
*
* @param oauth2Token OAuth 2 Bearer token
*/
void setOAuth2Token(OAuth2Token oauth2Token);
/**
* Revokes an issued OAuth 2 Bearer Token.
*
* @throws CedarMapsException when service or network is unavailable, or connecting
* non-SSL endpoints.
* @throws IllegalStateException when Bearer token is not available.
*/
void invalidateOAuth2Token() throws CedarMapsException;
}
package com.cedarstudios.cedarmapssdk.auth;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import org.json.JSONObject;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class OAuth2Token implements Serializable {
private String tokenType;
private String accessToken;
OAuth2Token(JSONObject json) throws CedarMapsException {
tokenType = json.optString("token_type");
try {
accessToken = URLDecoder.decode(json.optString("access_token"), "UTF-8");
} catch (UnsupportedEncodingException ignore) {
}
}
public OAuth2Token(String tokenType, String accessToken) {
this.tokenType = tokenType;
this.accessToken = accessToken;
}
public String getTokenType() {
return tokenType;
}
public String getAccessToken() {
return accessToken;
}
String generateAuthorizationHeader() {
String encoded = "";
try {
encoded = URLEncoder.encode(accessToken, "UTF-8");
} catch (UnsupportedEncodingException ignore) {
}
return "Bearer " + encoded;
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.config;
class CedarMapsConstants {
public final static String CEDARMAPS_BASE_URL_V1 = "http://api.cedarmaps.com/v1/";
}
package com.cedarstudios.cedarmapssdk.config;
import com.cedarstudios.cedarmapssdk.auth.AuthorizationConfiguration;
import java.io.Serializable;
public interface Configuration extends AuthorizationConfiguration, Serializable {
String getOAuth2TokenType();
String getOAuth2AccessToken();
String getAPIBaseURL();
String getOAuth2Scope();
String getOAuth2TokenURL();
String getOAuthClientId();
String getOAuthClientSecret();
String getMapId();
}
package com.cedarstudios.cedarmapssdk.config;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
class ConfigurationBase implements Configuration, Serializable {
private String oAuthClientId;
private String oAuthClientSecret;
private String oAuth2TokenType;
private String oAuth2AccessToken;
private String oAuth2Scope;
private String mapId;
private String restBaseURL = CedarMapsConstants.CEDARMAPS_BASE_URL_V1;
private String oAuth2TokenURL = restBaseURL + "token";
public void setOAuthClientId(String oAuthClientId) {
this.oAuthClientId = oAuthClientId;
}
public void setClientSecret(String clientSecret) {
this.oAuthClientSecret = clientSecret;
}
public void setMapId(String mapId) {
this.mapId = mapId;
}
public void setAPIBaseUrl(String baseUrl) {
restBaseURL = baseUrl;
setOAuth2TokenURL(restBaseURL + "token");
}
@Override
public String getAPIBaseURL() {
return restBaseURL;
}
protected final void setRestBaseURL(String restBaseURL) {
this.restBaseURL = restBaseURL;
}
@Override
public String getOAuth2TokenType() {
return oAuth2TokenType;
}
protected final void setOAuth2TokenType(String oAuth2TokenType) {
this.oAuth2TokenType = oAuth2TokenType;
}
@Override
public String getOAuth2AccessToken() {
return oAuth2AccessToken;
}
@Override
public String getOAuth2Scope() {
return oAuth2Scope;
}
protected final void setOAuth2AccessToken(String oAuth2AccessToken) {
this.oAuth2AccessToken = oAuth2AccessToken;
}
protected final void setOAuth2Scope(String oAuth2Scope) {
this.oAuth2Scope = oAuth2Scope;
}
@Override
public String getOAuth2TokenURL() {
return oAuth2TokenURL;
}
@Override
public String getOAuthClientId() {
return oAuthClientId;
}
@Override
public String getOAuthClientSecret() {
return oAuthClientSecret;
}
@Override
public String getMapId() {
return mapId;
}
protected final void setOAuth2TokenURL(String oAuth2TokenURL) {
this.oAuth2TokenURL = oAuth2TokenURL;
}
private static final List<ConfigurationBase> instances = new ArrayList<ConfigurationBase>();
private static void cacheInstance(ConfigurationBase conf) {
if (!instances.contains(conf)) {
instances.add(conf);
}
}
protected void cacheInstance() {
cacheInstance(this);
}
private static ConfigurationBase getInstance(ConfigurationBase configurationBase) {
int index;
if ((index = instances.indexOf(configurationBase)) == -1) {
instances.add(configurationBase);
return configurationBase;
} else {
return instances.get(index);
}
}
// assures equality after deserialization
protected Object readResolve() throws ObjectStreamException {
return getInstance(this);
}
}
package com.cedarstudios.cedarmapssdk.config;
public final class ConfigurationBuilder {
private ConfigurationBase configurationBase = new ConfigurationBase();
public ConfigurationBuilder setAPIBaseURL(String baseURL) {
checkNotBuilt();
configurationBase.setAPIBaseUrl(baseURL);
return this;
}
public ConfigurationBuilder setClientId(String clientId) {
checkNotBuilt();
configurationBase.setOAuthClientId(clientId);
return this;
}
public ConfigurationBuilder setClientSecret(String clientSecret) {
checkNotBuilt();
configurationBase.setClientSecret(clientSecret);
return this;
}
public ConfigurationBuilder setMapId(String mapId) {
checkNotBuilt();
configurationBase.setMapId(mapId);
return this;
}
public ConfigurationBuilder setOAuth2TokenType(String oAuth2TokenType) {
checkNotBuilt();
configurationBase.setOAuth2TokenType(oAuth2TokenType);
return this;
}
public ConfigurationBuilder setOAuth2AccessToken(String oAuth2AccessToken) {
checkNotBuilt();
configurationBase.setOAuth2AccessToken(oAuth2AccessToken);
return this;
}
public ConfigurationBuilder setOAuth2Scope(String oAuth2Scope) {
checkNotBuilt();
configurationBase.setOAuth2Scope(oAuth2Scope);
return this;
}
public ConfigurationBuilder setOAuth2TokenURL(String oAuth2TokenURL) {
checkNotBuilt();
configurationBase.setOAuth2TokenURL(oAuth2TokenURL);
return this;
}
public ConfigurationBuilder setRestBaseURL(String restBaseURL) {
checkNotBuilt();
configurationBase.setRestBaseURL(restBaseURL);
return this;
}
public Configuration build() {
checkNotBuilt();
configurationBase.cacheInstance();
try {
return configurationBase;
} finally {
configurationBase = null;
}
}
private void checkNotBuilt() {
if (configurationBase == null) {
throw new IllegalStateException(
"Cannot use this builder any longer, build() has already been called");
}
}
}
package com.cedarstudios.cedarmapssdk.listeners;
import android.support.annotation.NonNull;
/**
* The listener for obtaining the Access Token needed in using CedarMaps API.
*/
public interface AccessTokenListener {
/**
* This method is called on UiThread when the Access Token is obtained successfully.
* @param accessToken The Access Token needed in CedarMaps APIs.
*/
void onSuccess(@NonNull String accessToken);
/**
* This method is called on UiThread when obtaining the Access Token is failed.
* @param errorMessage The error message for the reason of failure.
*/
void onFailure(@NonNull String errorMessage);
}
package com.cedarstudios.cedarmapssdk.listeners;
import android.support.annotation.NonNull;
import com.cedarstudios.cedarmapssdk.model.geocoder.forward.ForwardGeocode;
import java.util.List;
/**
* The listener for obtaining the results of a Forward Geocode request.
*/
public interface ForwardGeocodeResultsListener {
/**
* This method is called on UiThread when the results are obtained successfully.
* @param results The list of ForwardGeocode result items.
*/
void onSuccess(@NonNull List<ForwardGeocode> results);
/**
* This method is called on UiThread when obtaining the Forward Geocode result is failed.
* @param errorMessage The error message for the reason of failure.
*/
void onFailure(@NonNull String errorMessage);
}
package com.cedarstudios.cedarmapssdk.listeners;
import android.support.annotation.NonNull;
import com.cedarstudios.cedarmapssdk.model.routing.GeoRouting;
/**
* The listener for obtaining the results of a GeoRouting request (Direction and Distance).
*/
public interface GeoRoutingResultListener {
/**
* This method is called on UiThread when the results are obtained successfully.
* @param result The result of a GeoRouting request.
*/
void onSuccess(@NonNull GeoRouting result);
/**
* This method is called on UiThread when obtaining the GeoRouting result is failed.
* @param errorMessage The error message for the reason of failure.
*/
void onFailure(@NonNull String errorMessage);
}
package com.cedarstudios.cedarmapssdk.listeners;
import android.support.annotation.NonNull;
/**
* The listener for notifying the result of configuring the CedarMap tiles for using in a MapView.
*/
public interface OnTilesConfigured {
/**
* This method is called on UiThread when the tiles are configured successfully.
*/
void onSuccess();
/**
* This method is called on UiThread when configuring the tiles is failed.
* @param errorMessage The error message for the reason of failure.
*/
void onFailure(@NonNull String errorMessage);
}
package com.cedarstudios.cedarmapssdk.listeners;
import android.support.annotation.NonNull;
import com.cedarstudios.cedarmapssdk.model.geocoder.reverse.ReverseGeocode;
/**
* The listener for obtaining the results of a Reverse Geocode request.
*/
public interface ReverseGeocodeResultListener {
/**
* This method is called on UiThread when the results are obtained successfully.
* @param result The result of a Reverse Geocode request.
*/
void onSuccess(@NonNull ReverseGeocode result);
/**
* This method is called on UiThread when obtaining the Reverse Geocode result is failed.
* @param errorMessage The error message for the reason of failure.
*/
void onFailure(@NonNull String errorMessage);
}
package com.cedarstudios.cedarmapssdk.listeners;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
/**
* The listener for obtaining the results of a Static Map Image request.
*/
public interface StaticMapImageResultListener {
/**
* This method is called on UiThread when the result is obtained successfully.
* @param bitmap The bitmap for the requested static map image.
*/
void onSuccess(@NonNull Bitmap bitmap);
/**
* This method is called on UiThread when obtaining the Static Map Image result is failed.
* @param errorMessage The error message for the reason of failure.
*/
void onFailure(@NonNull String errorMessage);
}
package com.cedarstudios.cedarmapssdk.model.geocoder.forward;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.io.Serializable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.mapbox.mapboxsdk.geometry.LatLng;
/**
* The bounding box for a result of Forward Geocode request.
*/
public class BoundingBox implements Serializable
{
@SerializedName("ne")
@Expose
private String ne;
@SerializedName("sw")
@Expose
private String sw;
/**
* @return The north east coordinate of the bounding box.
*/
@Nullable
public LatLng getNorthEast() {
if (!TextUtils.isEmpty(ne)) {
if (ne.split(",").length == 2) {
return new LatLng(Double.parseDouble(ne.split(",")[0]), Double.parseDouble(ne.split(",")[1]));
}
}
return null;
}
/**
* @return The south west coordinate of the bounding box.
*/
@Nullable
public LatLng getSouthWest() {
if (!TextUtils.isEmpty(sw)) {
if (sw.split(",").length == 2) {
return new LatLng(Double.parseDouble(sw.split(",")[0]), Double.parseDouble(sw.split(",")[1]));
}
}
return null;
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.forward;
import android.support.annotation.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Detailed components of a Forward Geocode request
*/
public class Component implements Serializable
{
@SerializedName("country")
@Expose
private String country;
@SerializedName("province")
@Expose
private String province;
@SerializedName("city")
@Expose
private String city;
@SerializedName("districts")
@Expose
private List<String> districts = null;
@SerializedName("localities")
@Expose
private List<String> localities = null;
/**
*
* @return Country name.
*/
@Nullable
public String getCountry() {
return country;
}
/**
*
* @return Province name.
*/
@Nullable
public String getProvince() {
return province;
}
/**
*
* @return City name.
*/
@Nullable
public String getCity() {
return city;
}
/**
*
* @return List of municipality districts of the result.
* e.g District 1, District 2, etc.
*/
@Nullable
public List<String> getDistricts() {
return districts;
}
/**
*
* @return List of municipality locality names of the result.
* May be empty or null.
*/
@Nullable
public List<String> getLocalities() {
return localities;
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.forward;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* The result of Forward Geocode request
*/
public class ForwardGeocode implements Serializable
{
private static final Map<String,String> streetTypes = new HashMap<String,String>() {{
put("freeway", "آزادراه");
put("expressway", "بزرگراه");
put("road", "جاده");
put("boulevard", "بلوار");
put("roundabout", "میدان");
put("intersection", "تقاطع");
put("street", "خیابان");
put("city", "شهر");
put("locality", "محله");
put("poi", "مکان");
put("residential", "کوچه");
put("footway", "پیاده‌رو");
put("path", "پیاده‌رو");
put("primary", "خیابان اصلی");
put("secondary", "خیابان فرعی");
put("trunk", "بزرگراه");
put("trunk_link", "رمپ");
put("service", "کنارگذر");
}};
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("name")
@Expose
private String name;
@SerializedName("alternate_name")
@Expose
private String alternateName;
@SerializedName("full_name")
@Expose
private String fullName;
@SerializedName("name_en")
@Expose
private String nameEn;
@SerializedName("type")
@Expose
private String type;
/**
*
* @return Persian equivalent of field Type.
*/
@Nullable
public String getPersianType() {
if (type == null || type.isEmpty()) {
return null;
}
return streetTypes.get(type);
}
@SerializedName("location")
@Expose
private Location location;
@SerializedName("address")
@Expose
private String address;
@SerializedName("components")
@Expose
private Component components;
/**
*
* @return Identifier for the result.
*/
@NonNull
public Integer getId() {
return id;
}
/**
*
* @return Name of the result.
*/
@NonNull
public String getName() {
return name;
}
/**
*
* @return Alternate name of the result. e.g. Niayesh, Hashemi Rafsanjani
*/
@Nullable
public String getAlternateName() {
return alternateName;
}
/**
*
* @return Full name of the result. e.g. Hakim, Ayatollah Hakim
*/
@Nullable
public String getFullName() {
return fullName;
}
/**
*
* @return English name of the result
*/
@Nullable
public String getEnglishName() {
return nameEn;
}
/**
*
* @return Type of the result. e.g. street, locality, place, etc.
*/
@NonNull
public String getType() {
return type;
}
/**
*
* @return Geometric location of the result.
*/
@NonNull
public Location getLocation() {
return location;
}
/**
*
* @return A simple generated address from components field.
* @see #getComponents()
*/
@Nullable
public String getAddress() {
return address;
}
/**
*
* @return Detailed address components for the result.
*/
@NonNull
public Component getComponents() {
return components;
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.forward;
import java.io.Reader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* This class is used for serializing the Forward Geocode response using Gson.
*/
public class ForwardGeocodeResponse implements Serializable
{
@SerializedName("results")
@Expose
public List<ForwardGeocode> results = null;
@SerializedName("status")
@Expose
public String status = null;
public static ForwardGeocodeResponse parseJSON(Reader response) {
Gson gson = new GsonBuilder().create();
return gson.fromJson(response, ForwardGeocodeResponse.class);
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.forward;
import android.support.annotation.Nullable;
import java.io.Serializable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.mapbox.mapboxsdk.geometry.LatLng;
/**
*
* Geometric location of a Forward Geocode result.
*/
public class Location implements Serializable
{
@SerializedName("bb")
@Expose
private BoundingBox boundingBox;
@SerializedName("center")
@Expose
private String center;
/**
*
* @return The center coordinate of a Forward Geocode result.
*/
@Nullable
public LatLng getCenter() {
if (center == null) {
return null;
}
String[] latlng = center.split(",");
if (latlng.length == 2) {
double latitude = Double.parseDouble(latlng[0]);
double longitude = Double.parseDouble(latlng[1]);
return new LatLng(latitude, longitude);
} else {
return null;
}
}
/**
*
* @return The bounding box of a Forward Geocode result.
*/
@Nullable
public BoundingBox getBoundingBox() {
return boundingBox;
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.reverse;
import android.support.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
/**
* Detailed components of a Reverse Geocode request
*/
public class Component implements Serializable
{
@SerializedName("long_name")
@Expose
private String longName;
@SerializedName("short_name")
@Expose
private String shortName;
@SerializedName("type")
@Expose
private String type;
/**
*
* @return Long name of a component
*/
@Nullable
public String getLongName() {
return longName;
}
/**
*
* @return Short name of a component
*/
@Nullable
public String getShortName() {
return shortName;
}
/**
*
* @return Type of a component
*/
@Nullable
public String getType() {
return type;
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.reverse;
import android.support.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
/**
* The result of Reverse Geocode request
*/
public class ReverseGeocode implements Serializable {
@SerializedName("address")
@Expose
private String address;
@SerializedName("city")
@Expose
private String city;
@SerializedName("components")
@Expose
private List<Component> components = null;
@SerializedName("locality")
@Expose
private String locality;
@SerializedName("district")
@Expose
private String district;
@SerializedName("place")
@Expose
private String place;
@SerializedName("province")
@Expose
private String province;
@SerializedName("traffic_zone")
@Expose
private TrafficZone trafficZone;
/**
*
* @return Address of result.
*/
@Nullable
public String getAddress() {
return address;
}
/**
*
* @return City name.
*/
@Nullable
public String getCity() {
return city;
}
/**
*
* @return Address components.
*/
@Nullable
public List<Component> getComponents() {
return components;
}
/**
*
* @return Locality name
*/
@Nullable
public String getLocality() {
return locality;
}
/**
*
* @return District name
*/
@Nullable
public String getDistrict() {
return district;
}
/**
* Place name
* @return
*/
@Nullable
public String getPlace() {
return place;
}
/**
*
* @return Province name
*/
@Nullable
public String getProvince() {
return province;
}
/**
*
* @return Traffic zone info.
*/
@Nullable
public TrafficZone getTrafficZone() {
return trafficZone;
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.reverse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Reader;
import java.io.Serializable;
/**
* This class is used for serializing the Reverse Geocode response using Gson.
*/
public final class ReverseGeocodeResponse implements Serializable {
@SerializedName("result")
@Expose
public ReverseGeocode result = null;
@SerializedName("status")
@Expose
public String status = null;
public static ReverseGeocodeResponse parseJSON(Reader response) {
Gson gson = new GsonBuilder().create();
return gson.fromJson(response, ReverseGeocodeResponse.class);
}
}
package com.cedarstudios.cedarmapssdk.model.geocoder.reverse;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
/**
* Traffic zone info for a Reverse Geocode response
*/
public class TrafficZone implements Serializable {
@SerializedName("in_central")
@Expose
private Boolean isInCentral;
@SerializedName("in_evenodd")
@Expose
private Boolean isInEvenOdd;
@SerializedName("name")
@Expose
private String name;
/**
*
* @return Shows if the location is in Central Traffic Zone.
*/
public Boolean getInCentral() {
return isInCentral;
}
/**
*
* @return Shows if the location is in Even/Odd Traffic Zone.
*/
public Boolean getInEvenOdd() {
return isInEvenOdd;
}
/**
*
* @return Name of Traffic Zone.
*/
public String getName() {
return name;
}
}
package com.cedarstudios.cedarmapssdk.model.routing;
import android.support.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
/**
* The result of Routing (Direction/Distance) request
*/
public class GeoRouting implements Serializable {
@SerializedName("routes")
@Expose
private List<Route> routes = null;
/**
*
* @return Routes in a result.
*/
@Nullable
public List<Route> getRoutes() {
return routes;
}
}
package com.cedarstudios.cedarmapssdk.model.routing;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.Reader;
import java.io.Serializable;
/**
* This class is used for serializing the Routing response using Gson.
*/
public final class GeoRoutingResponse implements Serializable {
@SerializedName("result")
@Expose
public GeoRouting result = null;
@SerializedName("status")
@Expose
public String status = null;
public static GeoRoutingResponse parseJSON(Reader response) {
Gson gson = new GsonBuilder().create();
return gson.fromJson(response, GeoRoutingResponse.class);
}
}
package com.cedarstudios.cedarmapssdk.model.routing;
import android.support.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.mapbox.mapboxsdk.geometry.LatLng;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* The geometry info of obtained route.
*/
public class Geometry implements Serializable {
@SerializedName("coordinates")
@Expose
private List<List<Double>> coordinates = null;
@SerializedName("type")
@Expose
private String type;
/**
*
* @return Coordinates of turn by turn direction
*/
@Nullable
public List<LatLng> getCoordinates() {
ArrayList<LatLng> result = new ArrayList<>();
for (int i = 0; i < coordinates.size(); i++) {
List<Double> item = coordinates.get(i);
result.add(new LatLng(item.get(1), item.get(0)));
}
return result;
}
private String getType() {
return type;
}
}
package com.cedarstudios.cedarmapssdk.model.routing;
import android.support.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* A Route shows direction and distance info
*/
public class Route implements Serializable
{
@SerializedName("bbox")
@Expose
private List<Double> bbox = null;
@SerializedName("distance")
@Expose
private Double distance;
@SerializedName("geometry")
@Expose
private Geometry geometry;
@SerializedName("time")
@Expose
private Integer time;
/**
*
* @return Boundary for a route.
*/
@Nullable
public LatLngBounds getBoundingBox() {
if (bbox != null && bbox.size() == 4) {
ArrayList<LatLng> list = new ArrayList<LatLng>();
list.add(new LatLng(bbox.get(1), bbox.get(0)));
list.add(new LatLng(bbox.get(3), bbox.get(2)));
return new LatLngBounds.Builder().includes(list).build();
}
return null;
}
/**
*
* @return Total distance in a route in meters
*/
@Nullable
public Double getDistance() {
return distance;
}
/**
*
* @return The geometry info for a route. (GeoJSON coordinates)
*/
@Nullable
public Geometry getGeometry() {
return geometry;
}
/**
*
* @return ETA for a route in seconds
*/
@Nullable
public Integer getTime() {
return time;
}
}
package com.cedarstudios.cedarmapssdk.tileprovider;
import android.content.Context;
import com.cedarstudios.cedarmapssdk.tileprovider.modules.CedarMapTileAssetsProvider;
import com.cedarstudios.cedarmapssdk.tileprovider.modules.CedarMapTileDownloader;
import com.cedarstudios.cedarmapssdk.tileprovider.modules.CedarMapTileFileArchiveProvider;
import com.cedarstudios.cedarmapssdk.tileprovider.modules.CedarMapTileFilesystemProvider;
import com.cedarstudios.cedarmapssdk.tileprovider.modules.CedarTileWriter;
import org.osmdroid.tileprovider.IRegisterReceiver;
import org.osmdroid.tileprovider.MapTileProviderBasic;
import org.osmdroid.tileprovider.modules.INetworkAvailablityCheck;
import org.osmdroid.tileprovider.modules.NetworkAvailabliltyCheck;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
public class CedarMapTileProvider extends MapTileProviderBasic {
public CedarMapTileProvider(Context pContext, ITileSource pTileSource) {
this(new SimpleRegisterReceiver(pContext), new NetworkAvailabliltyCheck(pContext), pTileSource, pContext);
}
public CedarMapTileProvider(IRegisterReceiver pRegisterReceiver, INetworkAvailablityCheck aNetworkAvailablityCheck, ITileSource pTileSource, Context pContext) {
super(pRegisterReceiver, aNetworkAvailablityCheck, pTileSource, pContext);
overrideTitleProviderList(pRegisterReceiver, aNetworkAvailablityCheck, pTileSource, pContext);
}
private void overrideTitleProviderList(IRegisterReceiver pRegisterReceiver, INetworkAvailablityCheck aNetworkAvailablityCheck, ITileSource pTileSource, Context pContext) {
mTileProviderList.clear();
final CedarTileWriter tileWriter = new CedarTileWriter();
final CedarMapTileAssetsProvider assetsProvider = new CedarMapTileAssetsProvider(pRegisterReceiver, pContext.getAssets(), pTileSource);
mTileProviderList.add(assetsProvider);
final CedarMapTileFilesystemProvider fileSystemProvider = new CedarMapTileFilesystemProvider(pRegisterReceiver, pTileSource);
mTileProviderList.add(fileSystemProvider);
final CedarMapTileFileArchiveProvider archiveProvider = new CedarMapTileFileArchiveProvider(pRegisterReceiver, pTileSource);
mTileProviderList.add(archiveProvider);
final CedarMapTileDownloader downloaderProvider = new CedarMapTileDownloader(pTileSource, tileWriter, aNetworkAvailablityCheck);
mTileProviderList.add(downloaderProvider);
}
}
package com.cedarstudios.cedarmapssdk.tileprovider.constants;
import android.os.Environment;
import android.util.Log;
import org.osmdroid.api.IMapView;
import org.osmdroid.tileprovider.LRUMapTileCache;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class CedarMapTileProviderConstants {
/**
* Base path for osmdroid files. Zip/sqlite/mbtiles/etc files are in this folder.
* Note: also used for offline tile sources
*/
private static File OSMDROID_PATH = new File(Environment.getExternalStorageDirectory(), ".cedarmap");
public static File getBasePath() {
return OSMDROID_PATH;
}
/**
* Base path for tiles.
* /sdcard/osmdroid/tiles
*/
public static File TILE_PATH_BASE = new File(OSMDROID_PATH, "tiles");
static {
try {
TILE_PATH_BASE.mkdirs();
new File(TILE_PATH_BASE + "/.nomedia").createNewFile();
} catch (Exception ex) {
Log.e(IMapView.LOGTAG, "unable to create a nomedia file. downloaded tiles may be visible to the gallery. " + ex.getMessage());
}
}
public static boolean DEBUGMODE = false;
public static boolean DEBUG_TILE_PROVIDERS = false;
public static String USER_AGENT = "User-Agent";
private static String USER_AGENT_VALUE = "CedarMap";
/**
* Enables you to get the value for HTTP user agents. Used when downloading tiles
*
* @return
* @since 5.0
*/
public static String getUserAgentValue() {
return USER_AGENT_VALUE;
}
/**
* Enables you to override the default "osmdroid" value for HTTP user agents. Used when downloading tiles
*
* @param val
* @since 5.0
*/
public static void setUserAgentValue(String val) {
USER_AGENT_VALUE = val;
}
/**
* Minimum Zoom Level
*/
public static final int MINIMUM_ZOOMLEVEL = 0;
/**
* add an extension to files on sdcard so that gallery doesn't index them
*/
public static final String TILE_PATH_EXTENSION = ".tile";
/**
* Initial tile cache size (in memory). The size will be increased as required by calling
* {@link LRUMapTileCache#ensureCapacity(int)} The tile cache will always be at least 3x3.
*/
public static int CACHE_MAPTILECOUNT_DEFAULT = 9;
/**
* number of tile download threads, conforming to OSM policy:
* http://wiki.openstreetmap.org/wiki/Tile_usage_policy
*/
private static int NUMBER_OF_TILE_DOWNLOAD_THREADS = 2;
public static int getNumberOfTileDownloadThreads() {
return NUMBER_OF_TILE_DOWNLOAD_THREADS;
}
/**
* Overrides the number of tile download threads. The default value is '2' conforming to OSM policy:
* http://wiki.openstreetmap.org/wiki/Tile_usage_policy
* <p/>
* Only use the value of '2' when connecting to OSM tile sources.
*
* @param threads
* @since 5.1
*/
public static void setNumberOfTileDownloadThreads(int threads) {
if (threads > 12)
NUMBER_OF_TILE_DOWNLOAD_THREADS = 12;
else if (threads < 1)
NUMBER_OF_TILE_DOWNLOAD_THREADS = 1;
else
NUMBER_OF_TILE_DOWNLOAD_THREADS = threads;
}
public static final short NUMBER_OF_TILE_FILESYSTEM_THREADS = 8;
public static final long ONE_SECOND = 1000;
public static final long ONE_MINUTE = ONE_SECOND * 60;
public static final long ONE_HOUR = ONE_MINUTE * 60;
public static final long ONE_DAY = ONE_HOUR * 24;
public static final long ONE_WEEK = ONE_DAY * 7;
public static final long ONE_YEAR = ONE_DAY * 365;
public static final long DEFAULT_MAXIMUM_CACHED_FILE_AGE = ONE_WEEK;
public static final short TILE_DOWNLOAD_MAXIMUM_QUEUE_SIZE = 40;
public static final short TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE = 40;
/**
* 30 days
*/
public static final long TILE_EXPIRY_TIME_MILLISECONDS = 1000L * 60 * 60 * 24 * 30;
/**
* default is 600 Mb
*/
public static long TILE_MAX_CACHE_SIZE_BYTES = 600L * 1024 * 1024;
/**
* default is 500 Mb
*/
public static long TILE_TRIM_CACHE_SIZE_BYTES = 500L * 1024 * 1024;
/**
* Change the root path of the osmdroid cache.
* By default, it is defined in SD card, osmdroid directory.
*
* @param newFullPath
*/
public static void setCachePath(String newFullPath) {
File f = new File(newFullPath);
if (f.exists()) {
TILE_PATH_BASE = f.getAbsoluteFile();
try {
new File(TILE_PATH_BASE + "/.nomedia").createNewFile();
} catch (Exception ex) {
Log.e(IMapView.LOGTAG, "unable to create a nomedia file. downloaded tiles may be visible to the gallery.", ex);
}
}
}
/**
* Change the osmdroid tiles cache sizes. (note this represents size of the cache on disk, not in memory)
*
* @param maxCacheSize in Mb. Default is 600 Mb.
* @param trimCacheSize When the cache size exceeds maxCacheSize, tiles will be automatically removed to reach this target. In Mb. Default is 500 Mb.
* @author MKer
* @since 4.4
*/
public static void setCacheSizes(long maxCacheSize, long trimCacheSize) {
TILE_MAX_CACHE_SIZE_BYTES = maxCacheSize * 1024 * 1024;
TILE_TRIM_CACHE_SIZE_BYTES = trimCacheSize * 1024 * 1024;
}
/**
* allows for altering the osmdroid_path variable, which controls the location
* of where to search for offline tile sources
*
* @param path
*/
public static void setOfflineMapsPath(String path) {
OSMDROID_PATH = new File(path);
}
/**
* @since 5.1
*/
public static final String HTTP_EXPIRES_HEADER = "Expires";
/**
* @since 5.1
*/
public static final String HTTP_EXPIRES_HEADER_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
/**
* used for HTTP expires headers
*
* @since 5.1
*/
public static final SimpleDateFormat HTTP_HEADER_SDF = new SimpleDateFormat(HTTP_EXPIRES_HEADER_FORMAT, Locale.US);
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.tileprovider.modules;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import com.cedarstudios.cedarmapssdk.tileprovider.constants.CedarMapTileProviderConstants;
import org.osmdroid.tileprovider.IRegisterReceiver;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.MapTileRequestState;
import org.osmdroid.tileprovider.modules.MapTileFileStorageProviderBase;
import org.osmdroid.tileprovider.modules.MapTileModuleProviderBase;
import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase.LowMemoryException;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicReference;
public class CedarMapTileAssetsProvider extends MapTileFileStorageProviderBase {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final AssetManager mAssets;
private final AtomicReference<ITileSource> mTileSource = new AtomicReference<ITileSource>();
// ===========================================================
// Constructors
// ===========================================================
public CedarMapTileAssetsProvider(final IRegisterReceiver pRegisterReceiver, final AssetManager pAssets) {
this(pRegisterReceiver, pAssets, TileSourceFactory.DEFAULT_TILE_SOURCE);
}
public CedarMapTileAssetsProvider(final IRegisterReceiver pRegisterReceiver,
final AssetManager pAssets,
final ITileSource pTileSource) {
this(pRegisterReceiver, pAssets, pTileSource,
CedarMapTileProviderConstants.getNumberOfTileDownloadThreads(),
CedarMapTileProviderConstants.TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
}
public CedarMapTileAssetsProvider(final IRegisterReceiver pRegisterReceiver,
final AssetManager pAssets,
final ITileSource pTileSource, int pThreadPoolSize,
int pPendingQueueSize) {
super(pRegisterReceiver, pThreadPoolSize, pPendingQueueSize);
setTileSource(pTileSource);
mAssets = pAssets;
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
public boolean getUsesDataConnection() {
return false;
}
@Override
protected String getName() {
return "Assets Cache Provider";
}
@Override
protected String getThreadGroupName() {
return "assets";
}
@Override
protected Runnable getTileLoader() {
return new TileLoader(mAssets);
}
@Override
public int getMinimumZoomLevel() {
ITileSource tileSource = mTileSource.get();
return tileSource != null ? tileSource.getMinimumZoomLevel() : CedarMapTileProviderConstants.MINIMUM_ZOOMLEVEL;
}
@Override
public int getMaximumZoomLevel() {
ITileSource tileSource = mTileSource.get();
return tileSource != null ? tileSource.getMaximumZoomLevel()
: microsoft.mappoint.TileSystem.getMaximumZoomLevel();
}
@Override
public void setTileSource(final ITileSource pTileSource) {
mTileSource.set(pTileSource);
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
protected class TileLoader extends MapTileModuleProviderBase.TileLoader {
private AssetManager mAssets = null;
public TileLoader(AssetManager pAssets) {
mAssets = pAssets;
}
@Override
public Drawable loadTile(final MapTileRequestState pState) throws CantContinueException {
ITileSource tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}
final MapTile tile = pState.getMapTile();
try {
InputStream is = mAssets.open(tileSource.getTileRelativeFilenameString(tile));
final Drawable drawable = tileSource.getDrawable(is);
if (drawable != null) {
//https://github.com/osmdroid/osmdroid/issues/272 why was this set to expired?
//ExpirableBitmapDrawable.setDrawableExpired(drawable);
}
return drawable;
} catch (IOException e) {
} catch (final LowMemoryException e) {
throw new CantContinueException(e);
}
// If we get here then there is no file in the file cache
return null;
}
}
}
package com.cedarstudios.cedarmapssdk.tileprovider.modules;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Log;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.CedarMapsFactory;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Token;
import com.cedarstudios.cedarmapssdk.tileprovider.constants.CedarMapTileProviderConstants;
import com.cedarstudios.cedarmapssdk.tileprovider.tilesource.CedarMapsTileSource;
import com.cedarstudios.cedarmapssdk.utils.CedarMapsUtils;
import org.osmdroid.api.IMapView;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.MapTileRequestState;
import org.osmdroid.tileprovider.modules.IFilesystemCache;
import org.osmdroid.tileprovider.modules.INetworkAvailablityCheck;
import org.osmdroid.tileprovider.modules.MapTileDownloader;
import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
import org.osmdroid.tileprovider.util.StreamUtils;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.concurrent.atomic.AtomicReference;
public class CedarMapTileDownloader extends MapTileDownloader {
private final IFilesystemCache mFilesystemCache;
private final AtomicReference<OnlineTileSourceBase> mTileSource = new AtomicReference<>();
private final INetworkAvailablityCheck mNetworkAvailablityCheck;
public CedarMapTileDownloader(ITileSource pTileSource, IFilesystemCache pFilesystemCache, INetworkAvailablityCheck pNetworkAvailablityCheck) {
super(pTileSource, pFilesystemCache, pNetworkAvailablityCheck);
mFilesystemCache = pFilesystemCache;
mNetworkAvailablityCheck = pNetworkAvailablityCheck;
setCedarTileSource(pTileSource);
}
@Override
public ITileSource getTileSource() {
return mTileSource.get();
}
public void setCedarTileSource(final ITileSource tileSource) {
super.setTileSource(tileSource);
// We are only interested in OnlineTileSourceBase tile sources
if (tileSource instanceof OnlineTileSourceBase) {
mTileSource.set((OnlineTileSourceBase) tileSource);
} else {
// Otherwise shut down the tile downloader
mTileSource.set(null);
}
}
@Override
protected Runnable getTileLoader() {
return new CedarTileLoader();
}
protected class CedarTileLoader extends TileLoader {
@Override
public Drawable loadTile(MapTileRequestState aState) throws CantContinueException {
OnlineTileSourceBase tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}
InputStream in = null;
OutputStream out = null;
HttpURLConnection c = null;
final MapTile tile = aState.getMapTile();
try {
if (mNetworkAvailablityCheck != null
&& !mNetworkAvailablityCheck.getNetworkAvailable()) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Skipping " + getName() + " due to NetworkAvailabliltyCheck.");
}
return null;
}
final String tileURLString = tileSource.getTileURLString(tile);
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Downloading Maptile from url: " + tileURLString);
}
if (TextUtils.isEmpty(tileURLString)) {
return null;
}
c = (HttpURLConnection) new URL(tileURLString).openConnection();
c.setUseCaches(true);
c.setRequestProperty(CedarMapTileProviderConstants.USER_AGENT, CedarMapTileProviderConstants.getUserAgentValue());
c.connect();
// Check to see if we got success
if (c.getResponseCode() != 200) {
Log.w(IMapView.LOGTAG, "Problem downloading MapTile: " + tile + " HTTP response: " + c.getResponseMessage());
if (c.getResponseCode() == 401) {
CedarMapsFactory factory = new CedarMapsFactory(((CedarMapsTileSource) mTileSource.get()).getConfiguration());
CedarMaps cedarMaps = factory.getInstance();
try {
OAuth2Token oAuth2Token = cedarMaps.getOAuth2Token();
CedarMapsUtils.setAccessToken(oAuth2Token.getAccessToken());
((CedarMapsTileSource) mTileSource.get()).setAccessToken(oAuth2Token.getAccessToken());
loadTile(aState);
} catch (CedarMapsException e) {
e.printStackTrace();
}
}
return null;
}
in = c.getInputStream();
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, StreamUtils.IO_BUFFER_SIZE);
Date dateExpires = new Date(System.currentTimeMillis() + MAX_CACHED_TILE_AGE);
final String expires = c.getHeaderField(CedarMapTileProviderConstants.HTTP_EXPIRES_HEADER);
if (expires != null && expires.length() > 0) {
try {
dateExpires = CedarMapTileProviderConstants.HTTP_HEADER_SDF.parse(expires);
} catch (Exception ex) {
if (DEBUG)
Log.d(IMapView.LOGTAG, "Unable to parse expiration tag for tile, using default, server returned " + expires, ex);
}
}
tile.setExpires(dateExpires);
StreamUtils.copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
final ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
// Save the data to the filesystem cache
if (mFilesystemCache != null) {
mFilesystemCache.saveFile(tileSource, tile, byteStream);
byteStream.reset();
}
final Drawable result = tileSource.getDrawable(byteStream);
return result;
} catch (final UnknownHostException e) {
// no network connection so empty the queue
Log.w(IMapView.LOGTAG, "UnknownHostException downloading MapTile: " + tile + " : " + e);
throw new CantContinueException(e);
} catch (final BitmapTileSourceBase.LowMemoryException e) {
// low memory so empty the queue
Log.w(IMapView.LOGTAG, "LowMemoryException downloading MapTile: " + tile + " : " + e);
throw new CantContinueException(e);
} catch (final FileNotFoundException e) {
Log.w(IMapView.LOGTAG, "Tile not found: " + tile + " : " + e);
} catch (final IOException e) {
Log.w(IMapView.LOGTAG, "IOException downloading MapTile: " + tile + " : " + e);
} catch (final Throwable e) {
Log.e(IMapView.LOGTAG, "Error downloading MapTile: " + tile, e);
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
try {
c.disconnect();
} catch (Exception ex) {
}
}
return null;
}
}
}
package com.cedarstudios.cedarmapssdk.tileprovider.modules;
import android.graphics.drawable.Drawable;
import android.util.Log;
import com.cedarstudios.cedarmapssdk.tileprovider.constants.CedarMapTileProviderConstants;
import org.osmdroid.api.IMapView;
import org.osmdroid.tileprovider.IRegisterReceiver;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.MapTileProviderBase;
import org.osmdroid.tileprovider.MapTileRequestState;
import org.osmdroid.tileprovider.modules.ArchiveFileFactory;
import org.osmdroid.tileprovider.modules.IArchiveFile;
import org.osmdroid.tileprovider.modules.MapTileFileStorageProviderBase;
import org.osmdroid.tileprovider.modules.MapTileModuleProviderBase;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.util.StreamUtils;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
public class CedarMapTileFileArchiveProvider extends MapTileFileStorageProviderBase {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final ArrayList<IArchiveFile> mArchiveFiles = new ArrayList<IArchiveFile>();
private final AtomicReference<ITileSource> mTileSource = new AtomicReference<ITileSource>();
/**
* Disable the search of archives if specified in constructor
*/
private final boolean mSpecificArchivesProvided;
// ===========================================================
// Constructors
// ===========================================================
/**
* The tiles may be found on several media. This one works with tiles stored on the file system.
* It and its friends are typically created and controlled by {@link MapTileProviderBase}.
*/
public CedarMapTileFileArchiveProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource pTileSource, final IArchiveFile[] pArchives) {
super(pRegisterReceiver, CedarMapTileProviderConstants.NUMBER_OF_TILE_FILESYSTEM_THREADS,
CedarMapTileProviderConstants.TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
setTileSource(pTileSource);
if (pArchives == null) {
mSpecificArchivesProvided = false;
findArchiveFiles();
} else {
mSpecificArchivesProvided = true;
for (int i = pArchives.length - 1; i >= 0; i--) {
mArchiveFiles.add(pArchives[i]);
}
}
}
public CedarMapTileFileArchiveProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource pTileSource) {
this(pRegisterReceiver, pTileSource, null);
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
public boolean getUsesDataConnection() {
return false;
}
@Override
protected String getName() {
return "File Archive Provider";
}
@Override
protected String getThreadGroupName() {
return "filearchive";
}
@Override
protected Runnable getTileLoader() {
return new TileLoader();
}
@Override
public int getMinimumZoomLevel() {
ITileSource tileSource = mTileSource.get();
return tileSource != null ? tileSource.getMinimumZoomLevel() : CedarMapTileProviderConstants.MINIMUM_ZOOMLEVEL;
}
@Override
public int getMaximumZoomLevel() {
ITileSource tileSource = mTileSource.get();
return tileSource != null ? tileSource.getMaximumZoomLevel()
: microsoft.mappoint.TileSystem.getMaximumZoomLevel();
}
@Override
protected void onMediaMounted() {
if (!mSpecificArchivesProvided) {
findArchiveFiles();
}
}
@Override
protected void onMediaUnmounted() {
if (!mSpecificArchivesProvided) {
findArchiveFiles();
}
}
@Override
public void setTileSource(final ITileSource pTileSource) {
mTileSource.set(pTileSource);
}
@Override
public void detach() {
while (!mArchiveFiles.isEmpty()) {
IArchiveFile t = mArchiveFiles.get(0);
if (t != null)
mArchiveFiles.get(0).close();
mArchiveFiles.remove(0);
}
super.detach();
}
// ===========================================================
// Methods
// ===========================================================
private void findArchiveFiles() {
mArchiveFiles.clear();
if (!getSdCardAvailable()) {
return;
}
// path should be optionally configurable
File cachePaths = CedarMapTileProviderConstants.getBasePath();
final File[] files = cachePaths.listFiles();
if (files != null) {
for (final File file : files) {
final IArchiveFile archiveFile = ArchiveFileFactory.getArchiveFile(file);
if (archiveFile != null) {
mArchiveFiles.add(archiveFile);
}
}
}
}
private synchronized InputStream getInputStream(final MapTile pTile,
final ITileSource tileSource) {
for (final IArchiveFile archiveFile : mArchiveFiles) {
if (archiveFile != null) {
final InputStream in = archiveFile.getInputStream(tileSource, pTile);
if (in != null) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Found tile " + pTile + " in " + archiveFile);
}
return in;
}
}
}
return null;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
protected class TileLoader extends MapTileModuleProviderBase.TileLoader {
@Override
public Drawable loadTile(final MapTileRequestState pState) {
ITileSource tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}
final MapTile pTile = pState.getMapTile();
// if there's no sdcard then don't do anything
if (!getSdCardAvailable()) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "No sdcard - do nothing for tile: " + pTile);
}
return null;
}
InputStream inputStream = null;
try {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Tile doesn't exist: " + pTile);
}
inputStream = getInputStream(pTile, tileSource);
if (inputStream != null) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Use tile from archive: " + pTile);
}
final Drawable drawable = tileSource.getDrawable(inputStream);
return drawable;
}
} catch (final Throwable e) {
Log.e(IMapView.LOGTAG, "Error loading tile", e);
} finally {
if (inputStream != null) {
StreamUtils.closeStream(inputStream);
}
}
return null;
}
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.tileprovider.modules;
import android.graphics.drawable.Drawable;
import android.util.Log;
import com.cedarstudios.cedarmapssdk.tileprovider.constants.CedarMapTileProviderConstants;
import org.osmdroid.api.IMapView;
import org.osmdroid.tileprovider.ExpirableBitmapDrawable;
import org.osmdroid.tileprovider.IRegisterReceiver;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.MapTileRequestState;
import org.osmdroid.tileprovider.modules.DatabaseFileArchive;
import org.osmdroid.tileprovider.modules.MapTileFileStorageProviderBase;
import org.osmdroid.tileprovider.modules.MapTileModuleProviderBase;
import org.osmdroid.tileprovider.tilesource.BitmapTileSourceBase.LowMemoryException;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
public class CedarMapTileFilesystemProvider extends MapTileFileStorageProviderBase {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final long mMaximumCachedFileAge;
private DatabaseFileArchive databaseFileArchive;
private final AtomicReference<ITileSource> mTileSource = new AtomicReference<ITileSource>();
// ===========================================================
// Constructors
// ===========================================================
public CedarMapTileFilesystemProvider(final IRegisterReceiver pRegisterReceiver) {
this(pRegisterReceiver, TileSourceFactory.DEFAULT_TILE_SOURCE);
}
public CedarMapTileFilesystemProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource aTileSource) {
this(pRegisterReceiver, aTileSource, CedarMapTileProviderConstants.DEFAULT_MAXIMUM_CACHED_FILE_AGE);
}
public CedarMapTileFilesystemProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource pTileSource, final long pMaximumCachedFileAge) {
this(pRegisterReceiver, pTileSource, pMaximumCachedFileAge,
CedarMapTileProviderConstants.NUMBER_OF_TILE_FILESYSTEM_THREADS,
CedarMapTileProviderConstants.TILE_FILESYSTEM_MAXIMUM_QUEUE_SIZE);
}
/**
* Provides a file system based cache tile provider. Other providers can register and store data
* in the cache.
*
* @param pRegisterReceiver
*/
public CedarMapTileFilesystemProvider(final IRegisterReceiver pRegisterReceiver,
final ITileSource pTileSource, final long pMaximumCachedFileAge, int pThreadPoolSize,
int pPendingQueueSize) {
super(pRegisterReceiver, pThreadPoolSize, pPendingQueueSize);
setTileSource(pTileSource);
mMaximumCachedFileAge = pMaximumCachedFileAge;
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
public boolean getUsesDataConnection() {
return false;
}
@Override
protected String getName() {
return "File System Cache Provider";
}
@Override
protected String getThreadGroupName() {
return "filesystem";
}
@Override
protected Runnable getTileLoader() {
return new TileLoader();
}
@Override
public int getMinimumZoomLevel() {
ITileSource tileSource = mTileSource.get();
return tileSource != null ? tileSource.getMinimumZoomLevel() : CedarMapTileProviderConstants.MINIMUM_ZOOMLEVEL;
}
@Override
public int getMaximumZoomLevel() {
ITileSource tileSource = mTileSource.get();
return tileSource != null ? tileSource.getMaximumZoomLevel()
: microsoft.mappoint.TileSystem.getMaximumZoomLevel();
}
@Override
public void setTileSource(final ITileSource pTileSource) {
mTileSource.set(pTileSource);
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
protected class TileLoader extends MapTileModuleProviderBase.TileLoader {
@Override
public Drawable loadTile(final MapTileRequestState pState) throws CantContinueException {
ITileSource tileSource = mTileSource.get();
if (tileSource == null) {
return null;
}
final MapTile tile = pState.getMapTile();
// if there's no sdcard then don't do anything
if (!getSdCardAvailable()) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "No sdcard - do nothing for tile: " + tile);
}
return null;
}
// Check the tile source to see if its file is available and if so, then render the
// drawable and return the tile
final File file = new File(CedarMapTileProviderConstants.TILE_PATH_BASE,
tileSource.getTileRelativeFilenameString(tile) + CedarMapTileProviderConstants.TILE_PATH_EXTENSION);
if (file.exists()) {
try {
final Drawable drawable = tileSource.getDrawable(file.getPath());
// Check to see if file has expired
final long now = System.currentTimeMillis();
final long lastModified = file.lastModified();
final boolean fileExpired = lastModified < now - mMaximumCachedFileAge;
if (fileExpired && drawable != null) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Tile expired: " + tile);
}
ExpirableBitmapDrawable.setDrawableExpired(drawable);
}
return drawable;
} catch (final LowMemoryException e) {
// low memory so empty the queue
Log.w(IMapView.LOGTAG, "LowMemoryException downloading MapTile: " + tile + " : " + e);
throw new CantContinueException(e);
}
}
// If we get here then there is no file in the file cache
return null;
}
}
}
package com.cedarstudios.cedarmapssdk.tileprovider.modules;
import android.util.Log;
import com.cedarstudios.cedarmapssdk.tileprovider.constants.CedarMapTileProviderConstants;
import org.osmdroid.api.IMapView;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.modules.IFilesystemCache;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.util.StreamUtils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
public class CedarTileWriter implements IFilesystemCache {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
/** amount of disk space used by tile cache **/
private static long mUsedCacheSpace;
static boolean hasInited=false;
// ===========================================================
// Constructors
// ===========================================================
public CedarTileWriter() {
if (!hasInited) {
hasInited = true;
// do this in the background because it takes a long time
final Thread t = new Thread() {
@Override
public void run() {
mUsedCacheSpace = 0; // because it's static
calculateDirectorySize(CedarMapTileProviderConstants.TILE_PATH_BASE);
if (mUsedCacheSpace > CedarMapTileProviderConstants.TILE_MAX_CACHE_SIZE_BYTES) {
cutCurrentCache();
}
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG, "Finished init thread");
}
}
};
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
}
// ===========================================================
// Getter & Setter
// ===========================================================
/**
* Get the amount of disk space used by the tile cache. This will initially be zero since the
* used space is calculated in the background.
*
* @return size in bytes
*/
public static long getUsedCacheSpace() {
return mUsedCacheSpace;
}
// ===========================================================
// Methods from SuperClass/Interfaces
// ===========================================================
@Override
public boolean saveFile(final ITileSource pTileSource, final MapTile pTile,
final InputStream pStream) {
final File file = new File(CedarMapTileProviderConstants.TILE_PATH_BASE, pTileSource.getTileRelativeFilenameString(pTile)
+ CedarMapTileProviderConstants.TILE_PATH_EXTENSION);
if (CedarMapTileProviderConstants.DEBUG_TILE_PROVIDERS){
Log.d(IMapView.LOGTAG, "TileWrite " + file.getAbsolutePath());
}
final File parent = file.getParentFile();
if (!parent.exists() && !createFolderAndCheckIfExists(parent)) {
return false;
}
BufferedOutputStream outputStream = null;
try {
outputStream = new BufferedOutputStream(new FileOutputStream(file.getPath()),
StreamUtils.IO_BUFFER_SIZE);
final long length = StreamUtils.copy(pStream, outputStream);
mUsedCacheSpace += length;
if (mUsedCacheSpace > CedarMapTileProviderConstants.TILE_MAX_CACHE_SIZE_BYTES) {
cutCurrentCache(); // TODO perhaps we should do this in the background
}
} catch (final IOException e) {
return false;
} finally {
if (outputStream != null) {
StreamUtils.closeStream(outputStream);
}
}
return true;
}
// ===========================================================
// Methods
// ===========================================================
private boolean createFolderAndCheckIfExists(final File pFile) {
if (pFile.mkdirs()) {
return true;
}
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG,"Failed to create " + pFile + " - wait and check again");
}
// if create failed, wait a bit in case another thread created it
try {
Thread.sleep(500);
} catch (final InterruptedException ignore) {
}
// and then check again
if (pFile.exists()) {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG,"Seems like another thread created " + pFile);
}
return true;
} else {
if (CedarMapTileProviderConstants.DEBUGMODE) {
Log.d(IMapView.LOGTAG,"File still doesn't exist: " + pFile);
}
return false;
}
}
private void calculateDirectorySize(final File pDirectory) {
final File[] z = pDirectory.listFiles();
if (z != null) {
for (final File file : z) {
if (file.isFile()) {
mUsedCacheSpace += file.length();
}
if (file.isDirectory() && !isSymbolicDirectoryLink(pDirectory, file)) {
calculateDirectorySize(file); // *** recurse ***
}
}
}
}
/**
* Checks to see if it appears that a directory is a symbolic link. It does this by comparing
* the canonical path of the parent directory and the parent directory of the directory's
* canonical path. If they are equal, then they come from the same true parent. If not, then
* pDirectory is a symbolic link. If we get an exception, we err on the side of caution and
* return "true" expecting the calculateDirectorySize to now skip further processing since
* something went goofy.
*/
private boolean isSymbolicDirectoryLink(final File pParentDirectory, final File pDirectory) {
try {
final String canonicalParentPath1 = pParentDirectory.getCanonicalPath();
final String canonicalParentPath2 = pDirectory.getCanonicalFile().getParent();
return !canonicalParentPath1.equals(canonicalParentPath2);
} catch (final IOException e) {
return true;
} catch (final NoSuchElementException e) {
// See: http://code.google.com/p/android/issues/detail?id=4961
// See: http://code.google.com/p/android/issues/detail?id=5807
return true;
}
}
private List<File> getDirectoryFileList(final File aDirectory) {
final List<File> files = new ArrayList<File>();
final File[] z = aDirectory.listFiles();
if (z != null) {
for (final File file : z) {
if (file.isFile()) {
files.add(file);
}
if (file.isDirectory()) {
files.addAll(getDirectoryFileList(file));
}
}
}
return files;
}
/**
* If the cache size is greater than the max then trim it down to the trim level. This method is
* synchronized so that only one thread can run it at a time.
*/
private void cutCurrentCache() {
final File lock=CedarMapTileProviderConstants.TILE_PATH_BASE;
synchronized (lock) {
if (mUsedCacheSpace > CedarMapTileProviderConstants.TILE_TRIM_CACHE_SIZE_BYTES) {
Log.d(IMapView.LOGTAG,"Trimming tile cache from " + mUsedCacheSpace + " to "
+ CedarMapTileProviderConstants.TILE_TRIM_CACHE_SIZE_BYTES);
final List<File> z = getDirectoryFileList(CedarMapTileProviderConstants.TILE_PATH_BASE);
// order list by files day created from old to new
final File[] files = z.toArray(new File[0]);
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(final File f1, final File f2) {
return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
}
});
for (final File file : files) {
if (mUsedCacheSpace <= CedarMapTileProviderConstants.TILE_TRIM_CACHE_SIZE_BYTES) {
break;
}
final long length = file.length();
if (file.delete()) {
if (CedarMapTileProviderConstants.DEBUG_TILE_PROVIDERS){
Log.d(IMapView.LOGTAG,"Cache trim deleting " + file.getAbsolutePath());
}
mUsedCacheSpace -= length;
}
}
Log.d(IMapView.LOGTAG,"Finished trimming tile cache");
}
}
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.tileprovider.tilesource;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
import org.osmdroid.util.BoundingBoxE6;
public class CedarMapsTileSource extends OnlineTileSourceBase {
private String mMapId = "";
private String mAccessToken;
private CedarMapsTileSourceInfo mTileSourceInfo;
public CedarMapsTileSource() { // only for early initialization. should use CedarMapsTileSource with params
super("", 11, 18, 256, ".png", new String[]{});
}
public CedarMapsTileSource(CedarMapsTileSourceInfo tileLayer) {
super(tileLayer.getName(), tileLayer.getMinimumZoomLevel(), tileLayer.getMaximumZoomLevel(),
tileLayer.getTitleSize(), tileLayer.getImageExtension(), new String[]{tileLayer.getBaseUrl()});
mMapId = tileLayer.getMapId();
mAccessToken = tileLayer.getAccessToken();
mTileSourceInfo = tileLayer;
}
@Override
public String getTileURLString(final MapTile aMapTile) {
String url = getBaseUrl() +
mMapId +
"/" +
aMapTile.getZoomLevel() +
"/" +
aMapTile.getX() +
"/" +
aMapTile.getY() +
mTileSourceInfo.getImageExtension() +
"?access_token=" + mAccessToken;
return url;
}
public BoundingBoxE6 getBoundingBox() {
return mTileSourceInfo.getBoundingBox();
}
public Configuration getConfiguration() {
return mTileSourceInfo.getConfiguration();
}
public void setAccessToken(String accessToken) {
this.mAccessToken = accessToken;
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.tileprovider.tilesource;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.CedarMapsFactory;
import com.cedarstudios.cedarmapssdk.CedarMapsTileLayerListener;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Token;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import com.cedarstudios.cedarmapssdk.utils.CedarMapsUtils;
import com.cedarstudios.cedarmapssdk.utils.NetworkUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.util.BoundingBoxE6;
import org.osmdroid.util.GeoPoint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Locale;
public class CedarMapsTileSourceInfo {
private JSONObject tileJSON;
private final static String baseUrl = "http://api.cedarmaps.com/v1/tiles/";
private int mTileSize;
private String mTileExtension;
private CedarMapsTileLayerListener mTileLayerListener;
private int mMinimumZoomLevel;
private int mMaximumZoomLevel;
private String mName;
private String mDescription;
private String mAttribution;
private String mLegend;
private IGeoPoint mCenter;
private BoundingBoxE6 mBoundingBox;
public CedarMapsTileSourceInfo(Context context, Configuration configuration) {
mConfiguration = configuration;
if (TextUtils.isEmpty(mConfiguration.getMapId())) {
throw new NullPointerException("You should init configuration with a valid mapId");
}
if (TextUtils.isEmpty(mConfiguration.getOAuthClientId()) || TextUtils.isEmpty(mConfiguration.getOAuthClientSecret())) {
throw new NullPointerException("You should init configuration with a valid client id and secret");
}
int density = context.getResources().getDisplayMetrics().densityDpi;
mTileExtension = density >= DisplayMetrics.DENSITY_HIGH ? "@2x.png" : ".png";
mTileSize = density >= DisplayMetrics.DENSITY_HIGH ? 512 : 256;
init();
}
public int getMinimumZoomLevel() {
return mMinimumZoomLevel;
}
public int getMaximumZoomLevel() {
return mMaximumZoomLevel;
}
public String getName() {
return mName;
}
public String getDescription() {
return mDescription;
}
public String getAttribution() {
return mAttribution;
}
public String getLegend() {
return mLegend;
}
public String getBaseUrl() {
return baseUrl;
}
public IGeoPoint getCenter() {
return mCenter;
}
public BoundingBoxE6 getBoundingBox() {
return mBoundingBox;
}
private void init() {
if (CedarMapsUtils.getAccessToken() == null) {
new CedarMapsAuthenticateTask() {
@Override
protected void onPostExecute(Void aVoid) {
fetchBrandedJSONAndInit(getBrandedJSONURL());
}
}.execute();
} else {
fetchBrandedJSONAndInit(getBrandedJSONURL());
}
}
private void initWithTileJSON(JSONObject aTileJSON) {
this.setTileJSON((aTileJSON != null) ? aTileJSON : new JSONObject());
if (aTileJSON != null) {
mMinimumZoomLevel = getJSONFloat(this.tileJSON, "minzoom");
mMaximumZoomLevel = getJSONFloat(this.tileJSON, "maxzoom");
mName = this.tileJSON.optString("name");
mDescription = this.tileJSON.optString("description");
mAttribution = this.tileJSON.optString("attribution");
mLegend = this.tileJSON.optString("legend");
double[] center = getJSONDoubleArray(this.tileJSON, "center", 3);
if (center != null) {
mCenter = new GeoPoint(center[0], center[1], center[2]);
}
double[] bounds = getJSONDoubleArray(this.tileJSON, "bounds", 4);
if (bounds != null) {
mBoundingBox = new BoundingBoxE6(bounds[3], bounds[2], bounds[1], bounds[0]);
}
}
}
public Configuration getConfiguration() {
return mConfiguration;
}
public JSONObject getTileJSON() {
return tileJSON;
}
public void setTileJSON(JSONObject aTileJSON) {
this.tileJSON = aTileJSON;
}
private int getJSONFloat(JSONObject JSON, String key) {
int defaultValue = 0;
if (JSON.has(key)) {
try {
return JSON.getInt(key);
} catch (JSONException e) {
return defaultValue;
}
}
return defaultValue;
}
private double[] getJSONDoubleArray(JSONObject JSON, String key, int length) {
double[] defaultValue = null;
if (JSON.has(key)) {
try {
boolean valid = false;
double[] result = new double[length];
Object value = JSON.get(key);
if (value instanceof JSONArray) {
JSONArray array = ((JSONArray) value);
if (array.length() == length) {
for (int i = 0; i < array.length(); i++) {
result[i] = array.getDouble(i);
}
valid = true;
}
} else {
String[] array = JSON.getString(key).split(",");
if (array.length == length) {
for (int i = 0; i < array.length; i++) {
result[i] = Double.parseDouble(array[i]);
}
valid = true;
}
}
if (valid) {
return result;
}
} catch (JSONException e) {
return defaultValue;
}
}
return defaultValue;
}
byte[] readFully(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
for (int count; (count = in.read(buffer)) != -1; ) {
out.write(buffer, 0, count);
}
return out.toByteArray();
}
private void fetchBrandedJSONAndInit(String url) {
new RetrieveJSONTask() {
@Override
protected void onPostExecute(JSONObject jsonObject) {
initWithTileJSON(jsonObject);
if (mTileLayerListener != null) {
mTileLayerListener.onPrepared(CedarMapsTileSourceInfo.this);
}
}
}.execute(url);
}
private String getBrandedJSONURL() {
String url = String.format(Locale.ENGLISH, mConfiguration.getAPIBaseURL()
+ "tiles/%s.json?access_token=%s", mConfiguration.getMapId(), CedarMapsUtils.getAccessToken());
return url;
}
public String getMapId() {
return mConfiguration.getMapId();
}
public String getAccessToken() {
return CedarMapsUtils.getAccessToken();
}
public int getTitleSize() {
return mTileSize;
}
public String getImageExtension() {
return mTileExtension;
}
class RetrieveJSONTask extends AsyncTask<String, Void, JSONObject> {
protected JSONObject doInBackground(String... urls) {
InputStream in = null;
try {
URL url = new URL(urls[0]);
HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url);
connection.connect();
if (connection.getResponseCode() == 401) {
CedarMapsUtils.setAccessToken(null);
return null;
}
in = connection.getInputStream();
byte[] response = readFully(in);
String result = new String(response, "UTF-8");
return new JSONObject(result);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
Log.e(TAG, "Error closing InputStream: " + e.toString());
}
}
}
}
private static final String TAG = "TileJsonTileLayer";
private String mId;
private Configuration mConfiguration;
public String getCacheKey() {
return mId;
}
public void setTileLayerListener(CedarMapsTileLayerListener listener) {
mTileLayerListener = listener;
}
class CedarMapsAuthenticateTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
CedarMapsFactory factory = new CedarMapsFactory(mConfiguration);
CedarMaps cedarMaps = factory.getInstance();
try {
OAuth2Token oAuth2Token = cedarMaps.getOAuth2Token();
CedarMapsUtils.setAccessToken(oAuth2Token.getAccessToken());
Log.e(getClass().getSimpleName(), "token:" + oAuth2Token.getAccessToken());
} catch (CedarMapsException e) {
e.printStackTrace();
}
return null;
}
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.utils;
import android.text.TextUtils;
public class CedarMapsUtils {
private static String accessToken = null;
public static String getAccessToken() {
if (TextUtils.isEmpty(accessToken)) {
return null;
}
return accessToken;
}
public static void setAccessToken(String accessToken) {
CedarMapsUtils.accessToken = accessToken;
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.utils;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import com.cedarstudios.cedarmapssdk.BuildConfig;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.SSLSocketFactory;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.OkUrlFactory;
public class NetworkUtils {
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public static HttpURLConnection getHttpURLConnection(final URL url) {
return getHttpURLConnection(url, null, null);
}
public static HttpURLConnection getHttpURLConnection(final URL url, final Cache cache) {
return getHttpURLConnection(url, cache, null);
}
public static HttpURLConnection getHttpURLConnection(final URL url, final Cache cache, final SSLSocketFactory sslSocketFactory) {
OkHttpClient client = new OkHttpClient();
HttpURLConnection connection = new OkUrlFactory(client).open(url);
connection.setRequestProperty("User-Agent", getUserAgent());
return connection;
}
public static Cache getCache(final File cacheDir, final int maxSize) throws IOException {
return new Cache(cacheDir, maxSize);
}
public static String getUserAgent() {
StringBuilder sb = new StringBuilder("CedarMaps Android SDK");
sb.append("/");
sb.append(BuildConfig.VERSION_NAME);
return sb.toString();
}
}
\ No newline at end of file
package com.cedarstudios.cedarmapssdk.view;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import com.cedarstudios.cedarmapssdk.tileprovider.CedarMapTileProvider;
import com.cedarstudios.cedarmapssdk.tileprovider.tilesource.CedarMapsTileSource;
import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.MapTileProviderBase;
public class MapView extends org.osmdroid.views.MapView {
protected MapView(Context context, MapTileProviderBase tileProvider, Handler tileRequestCompleteHandler, AttributeSet attrs) {
super(context, tileProvider, tileRequestCompleteHandler, attrs);
}
public MapView(Context context, AttributeSet attrs) {
this(context, new FakeTileProvider(), null, attrs);
}
public MapView(Context context) {
super(context);
}
public MapView(Context context, MapTileProviderBase aTileProvider) {
super(context, aTileProvider);
}
public MapView(Context context, MapTileProviderBase aTileProvider, Handler tileRequestCompleteHandler) {
super(context, aTileProvider, tileRequestCompleteHandler);
}
@Override
public void setTileProvider(MapTileProviderBase base) {
super.setTileProvider(base);
if (base instanceof CedarMapTileProvider) {
CedarMapsTileSource cedarMapsTileSource = (CedarMapsTileSource) base.getTileSource();
setScrollableAreaLimit(cedarMapsTileSource.getBoundingBox());
invalidate();
setMinZoomLevel(cedarMapsTileSource.getMinimumZoomLevel());
setMaxZoomLevel(cedarMapsTileSource.getMaximumZoomLevel());
setMultiTouchControls(true);
}
}
static class FakeTileProvider extends MapTileProviderBase {
public FakeTileProvider() {
super(new CedarMapsTileSource());
}
@Override
public Drawable getMapTile(MapTile pTile) {
return null;
}
@Override
public void detach() {
}
@Override
public int getMinimumZoomLevel() {
return 0;
}
@Override
public int getMaximumZoomLevel() {
return 0;
}
}
}
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 23 compileSdkVersion 26
buildToolsVersion "23.0.3" buildToolsVersion "26.0.2"
defaultConfig { defaultConfig {
applicationId "com.cedarstudios.cedarmaps.sample" applicationId "com.cedarmaps.sdksampleapp"
minSdkVersion 9 minSdkVersion 15
targetSdkVersion 22 targetSdkVersion 26
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
vectorDrawables.useSupportLibrary = true
} }
buildTypes { buildTypes {
release { release {
...@@ -22,6 +24,8 @@ android { ...@@ -22,6 +24,8 @@ android {
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
compile(project(':CedarMapsSDK')) compile(project(':CedarMapsSDK'))
compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:appcompat-v7:26.1.0'
compile 'com.android.support:design:23.4.0' compile 'com.android.support:design:26.1.0'
compile 'com.android.support:support-vector-drawable:26.1.0'
compile 'com.android.support:support-v4:26.1.0'
} }
# Add project specific ProGuard rules here. # Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified # By default, the flags in this file are appended to flags specified
# in I:\Reza\Programming\Android\android-sdk/tools/proguard/proguard-android.txt # in /Users/saeed/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles # You can edit the include path and order by changing the proguardFiles
# directive in build.gradle. # directive in build.gradle.
# #
...@@ -15,3 +15,11 @@ ...@@ -15,3 +15,11 @@
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *; # public *;
#} #}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest package="com.cedarstudios.cedarmaps.sample" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:tools="http://schemas.android.com/tools"
package="com.cedarmaps.sdksampleapp">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application <application
android:allowClearUserData="true"
android:appCategory="maps"
android:fullBackupContent="true"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme"> android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:targetApi="o">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|screenSize|uiMode"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"> android:screenOrientation="portrait">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<meta-data android:name="android.max_aspect" android:value="2.1" />
</application> </application>
</manifest> </manifest>
\ No newline at end of file
package com.cedarmaps.sdksampleapp;
import com.mapbox.mapboxsdk.geometry.LatLng;
public class Constants {
public static final int PERMISSION_LOCATION_REQUEST_CODE = 100;
static final String CLIENT_ID = "";
static final String CLIENT_SECRET = "";
public static final LatLng VANAK_SQUARE = new LatLng(35.7572, 51.4099);
}
package com.cedarmaps.sdksampleapp;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Toast;
import com.cedarmaps.sdksampleapp.fragments.DirectionFragment;
import com.cedarmaps.sdksampleapp.fragments.ForwardGeocodeFragment;
import com.cedarmaps.sdksampleapp.fragments.MapFragment;
import com.cedarmaps.sdksampleapp.fragments.ReverseGeocodeFragment;
import com.cedarmaps.sdksampleapp.fragments.StaticMapFragment;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.listeners.OnTilesConfigured;
import static android.support.v4.content.PermissionChecker.PERMISSION_GRANTED;
public class MainActivity extends AppCompatActivity {
private Integer currentlySelectedMenuID = null;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment fragment = null;
switch (item.getItemId()) {
case R.id.navigation_map:
setTitle(R.string.title_map);
fragment = new MapFragment();
break;
case R.id.navigation_reverse:
setTitle(R.string.title_reverse);
fragment = new ReverseGeocodeFragment();
break;
case R.id.navigation_forward:
setTitle("");
fragment = new ForwardGeocodeFragment();
break;
case R.id.navigation_direction:
setTitle(R.string.title_direction);
fragment = new DirectionFragment();
break;
case R.id.navigation_static:
setTitle(R.string.title_static);
fragment = new StaticMapFragment();
break;
}
if (fragment != null && (currentlySelectedMenuID == null || currentlySelectedMenuID != item.getItemId())) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.content, fragment).commit();
currentlySelectedMenuID = item.getItemId();
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CedarMaps.getInstance().setClientID(Constants.CLIENT_ID);
CedarMaps.getInstance().setClientSecret(Constants.CLIENT_SECRET);
CedarMaps.getInstance().setContext(this);
CedarMaps.getInstance().prepareTiles(new OnTilesConfigured() {
@Override
public void onSuccess() {
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(R.id.navigation_map);
currentlySelectedMenuID = navigation.getSelectedItemId();
}
@Override
public void onFailure(@NonNull String error) {
Log.e("MainActivity", error);
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case Constants.PERMISSION_LOCATION_REQUEST_CODE:
if (!(grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED)) {
Toast.makeText(this, "App needs location to function", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
}
package com.cedarmaps.sdksampleapp;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.cedarmaps.sdksampleapp.fragments.ForwardGeocodeFragment;
import com.cedarstudios.cedarmapssdk.model.geocoder.forward.ForwardGeocode;
import java.util.List;
public class SearchViewAdapter extends RecyclerView.Adapter<SearchViewAdapter.SearchViewHolder> {
private List<ForwardGeocode> mItems;
static class SearchViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mNameTextView;
private TextView mTypeTextView;
private TextView mCityTextView;
private TextView mLocalityTextView;
private ForwardGeocode mItem;
SearchViewHolder(View v) {
super(v);
mNameTextView = (TextView) v.findViewById(R.id.search_view_list_item_name);
mTypeTextView = (TextView) v.findViewById(R.id.search_view_list_item_type);
mCityTextView = (TextView) v.findViewById(R.id.search_view_list_city);
mLocalityTextView = (TextView) v.findViewById(R.id.search_view_list_item_locality);
v.setOnClickListener(this);
}
void bindData(@NonNull ForwardGeocode item) {
mItem = item;
if (TextUtils.isEmpty(item.getName())) {
mNameTextView.setText("");
} else {
mNameTextView.setText(item.getName());
}
if (TextUtils.isEmpty(item.getPersianType())) {
mTypeTextView.setText("");
} else {
String result = "(" + item.getPersianType() + ") ";
mTypeTextView.setText(result);
}
String city = null;
if (item.getComponents() != null) {
city = item.getComponents().getCity();
if (TextUtils.isEmpty(city)) {
mCityTextView.setText("");
mCityTextView.setVisibility(View.GONE);
} else {
mCityTextView.setText(city);
mCityTextView.setVisibility(View.VISIBLE);
}
} else {
mCityTextView.setText("");
mCityTextView.setVisibility(View.GONE);
}
String locality = null;
if (item.getComponents() != null && item.getComponents().getLocalities() != null) {
for (int i = 0; i < Math.min(item.getComponents().getLocalities().size(), 3); i++) {
String l = item.getComponents().getLocalities().get(i);
if (locality == null) {
locality = l;
} else {
locality = locality + "، " + l;
}
}
}
if (TextUtils.isEmpty(locality)) {
mLocalityTextView.setText("");
mLocalityTextView.setVisibility(View.GONE);
} else {
mLocalityTextView.setText(locality);
mLocalityTextView.setVisibility(View.VISIBLE);
if (mCityTextView.getText().length() != 0) {
String result = city != null ? city + "،" : "";
mCityTextView.setText(result);
}
}
}
@Override
public void onClick(View v) {
MainActivity mainActivity = (MainActivity) v.getContext();
Fragment fragment = mainActivity.getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment instanceof ForwardGeocodeFragment) {
ForwardGeocodeFragment fgf = (ForwardGeocodeFragment)fragment;
fgf.showItemOnMap(mItem);
}
}
}
public SearchViewAdapter(List<ForwardGeocode> items) {
mItems = items;
}
@Override
public SearchViewAdapter.SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_search_autocomplete_item, parent, false);
return new SearchViewHolder(inflatedView);
}
@Override
public void onBindViewHolder(SearchViewAdapter.SearchViewHolder holder, int position) {
ForwardGeocode item = mItems.get(position);
holder.bindData(item);
}
@Override
public int getItemCount() {
return mItems.size();
}
}
package com.cedarmaps.sdksampleapp.fragments;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.cedarmaps.sdksampleapp.R;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.MapView;
import com.cedarstudios.cedarmapssdk.listeners.GeoRoutingResultListener;
import com.cedarstudios.cedarmapssdk.model.routing.GeoRouting;
import com.cedarstudios.cedarmapssdk.model.routing.Route;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import java.util.ArrayList;
public class DirectionFragment extends Fragment {
private MapView mMapView;
private MapboxMap mMapboxMap;
private Button resetButton;
private LinearLayout hintLayout;
private LinearLayout resultLayout;
private ProgressBar progressBar;
private TextView hintTextView;
private TextView distanceTextView;
private ArrayList<Marker> markers = new ArrayList<Marker>();
public DirectionFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_direction, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMapView = (MapView) view.findViewById(R.id.mapView);
resetButton = (Button) view.findViewById(R.id.direction_reset_button);
hintLayout = (LinearLayout) view.findViewById(R.id.direction_hint_layout);
resultLayout = (LinearLayout) view.findViewById(R.id.direction_result_layout);
progressBar = (ProgressBar) view.findViewById(R.id.direction_progress_bar);
hintTextView = (TextView) view.findViewById(R.id.direction_hint_text_view);
distanceTextView = (TextView) view.findViewById(R.id.direction_distance_text_view);
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mMapboxMap.clear();
markers.clear();
resultLayout.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
hintTextView.setVisibility(View.VISIBLE);
hintLayout.setVisibility(View.VISIBLE);
}
});
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
mMapboxMap.setMaxZoomPreference(17);
mMapboxMap.setMinZoomPreference(6);
mMapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
@Override
public void onMapClick(@NonNull LatLng latLng) {
if (markers.size() == 0) {
addMarkerToMapViewAtPosition(latLng, R.drawable.cedarmaps_marker_icon_start);
} else if (markers.size() == 1) {
addMarkerToMapViewAtPosition(latLng, R.drawable.cedarmaps_marker_icon_end);
computeDirection(markers.get(0).getPosition(), markers.get(1).getPosition());
}
}
});
}
});
}
private void computeDirection(LatLng departure, LatLng destination) {
progressBar.setVisibility(View.VISIBLE);
hintTextView.setVisibility(View.GONE);
progressBar.animate();
CedarMaps.getInstance().direction(departure, destination,
new GeoRoutingResultListener() {
@Override
public void onSuccess(@NonNull GeoRouting result) {
progressBar.clearAnimation();
Route route = result.getRoutes().get(0);
Double distance = route.getDistance();
if (distance > 1000) {
distance = distance / 1000.0;
distance = (double)Math.round(distance * 100d) / 100d;
distanceTextView.setText("" + distance + " Km");
} else {
distance = (double)Math.round(distance);
distanceTextView.setText("" + distance + "m");
}
ArrayList<LatLng> coordinates = new ArrayList<LatLng>();
for (int i = 0; i < route.getGeometry().getCoordinates().size(); i++) {
coordinates.add(route.getGeometry().getCoordinates().get(i));
}
drawCoordinatesInBound(coordinates, route.getBoundingBox());
hintLayout.setVisibility(View.GONE);
resultLayout.setVisibility(View.VISIBLE);
}
@Override
public void onFailure(@NonNull String error) {
progressBar.clearAnimation();
resetToInitialState();
Toast.makeText(getActivity(),
getString(R.string.direction_receiving_failed) + "\n" + error,
Toast.LENGTH_SHORT).show();
}
});
}
private void drawCoordinatesInBound(ArrayList<LatLng> coordinates, LatLngBounds bounds) {
if (mMapboxMap == null) {
return;
}
mMapboxMap.addPolyline(new PolylineOptions()
.addAll(coordinates)
.color(ContextCompat.getColor(getContext(), R.color.colorPrimary))
.width(6)
.alpha((float) 0.9));
mMapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(bounds, 150), 1000);
}
private void resetToInitialState() {
mMapboxMap.clear();
markers.clear();
resultLayout.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
hintTextView.setVisibility(View.VISIBLE);
hintLayout.setVisibility(View.VISIBLE);
}
private void addMarkerToMapViewAtPosition(LatLng coordinate, int markerImageID) {
if (mMapboxMap != null) {
Marker marker = mMapboxMap.addMarker(new MarkerViewOptions()
.position(coordinate)
.icon(IconFactory.getInstance(getContext()).fromResource(markerImageID))
);
markers.add(marker);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
public void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
mMapView = null;
}
}
package com.cedarmaps.sdksampleapp.fragments;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.cedarmaps.sdksampleapp.R;
import com.cedarmaps.sdksampleapp.SearchViewAdapter;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.MapView;
import com.cedarstudios.cedarmapssdk.listeners.ForwardGeocodeResultsListener;
import com.cedarstudios.cedarmapssdk.model.geocoder.forward.ForwardGeocode;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import java.util.List;
public class ForwardGeocodeFragment extends Fragment {
private MapView mMapView;
private MapboxMap mMapboxMap;
private SearchView mSearchView;
private SearchViewAdapter mRecyclerAdapter;
private RecyclerView mRecyclerView;
private ProgressBar mProgressBar;
private LinearLayout mLinearLayout;
private LinearLayoutManager mLinearLayoutManager;
private DividerItemDecoration mDividerItemDecoration;
private State state = State.MAP;
private enum State {
MAP,
MAP_PIN,
SEARCHING,
RESULTS
}
private void setState(State state) {
this.state = state;
switch (state) {
case MAP:
case MAP_PIN:
mLinearLayout.setVisibility(View.GONE);
break;
case SEARCHING:
mLinearLayout.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
break;
case RESULTS:
mLinearLayout.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
break;
}
}
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
return inflater.inflate(R.layout.fragment_forward_geocode, container, false);
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMapView = (MapView) view.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap.setMaxZoomPreference(17);
mMapboxMap.setMinZoomPreference(6);
mMapboxMap = mapboxMap;
}
});
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mLinearLayout = (LinearLayout) view.findViewById(R.id.search_results_linear_layout);
mProgressBar = (ProgressBar) view.findViewById(R.id.search_progress_bar);
mLinearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mDividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), mLinearLayoutManager.getOrientation());
mRecyclerView.addItemDecoration(mDividerItemDecoration);
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP && state == State.MAP_PIN) {
setState(State.RESULTS);
return true;
}
return false;
}
});
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.search_view_menu_item, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
final SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setIconifiedByDefault(false);
searchView.setQueryHint(getString(R.string.search_in_places));
searchView.setMaxWidth(Integer.MAX_VALUE);
mSearchView = searchView;
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus && state == State.MAP_PIN) {
mMapboxMap.clear();
if (!TextUtils.isEmpty(searchView.getQuery())) {
setState(State.RESULTS);
} else {
setState(State.MAP);
}
}
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
searchView.clearFocus();
return true;
}
@Override
public boolean onQueryTextChange(final String newText) {
if (TextUtils.isEmpty(newText)) {
mMapboxMap.clear();
setState(State.MAP);
} else {
setState(State.SEARCHING);
CedarMaps.getInstance().forwardGeocode(newText, new ForwardGeocodeResultsListener() {
@Override
public void onSuccess(@NonNull List<ForwardGeocode> results) {
setState(State.RESULTS);
if (results.size() > 0 && newText.equals(mSearchView.getQuery().toString())) {
mRecyclerAdapter = new SearchViewAdapter(results);
mRecyclerView.setAdapter(mRecyclerAdapter);
}
}
@Override
public void onFailure(@NonNull String errorMessage) {
setState(State.RESULTS);
Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
}
});
}
return false;
}
});
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search :
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void showItemOnMap(final ForwardGeocode item) {
setState(State.MAP_PIN);
mMapboxMap.clear();
mSearchView.clearFocus();
final Marker marker = mMapboxMap.addMarker(new MarkerViewOptions()
.position(item.getLocation().getCenter())
.title(item.getName())
.snippet(item.getAddress())
);
mMapboxMap.selectMarker(marker);
mMapboxMap.easeCamera(CameraUpdateFactory.newLatLng(item.getLocation().getCenter()), 1000);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
public void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
mMapView = null;
}
}
package com.cedarmaps.sdksampleapp.fragments;
import android.Manifest;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.cedarmaps.sdksampleapp.Constants;
import com.cedarmaps.sdksampleapp.R;
import com.cedarstudios.cedarmapssdk.MapView;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import static android.support.v4.content.PermissionChecker.PERMISSION_GRANTED;
public class MapFragment extends Fragment {
private MapView mMapView;
private MapboxMap mMapboxMap;
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_map, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMapView = (MapView) view.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
mMapboxMap.setMaxZoomPreference(17);
mMapboxMap.setMinZoomPreference(6);
//Move map to a certain position
animateToCoordinate(Constants.VANAK_SQUARE, 16);
//Add marker to map
addMarkerToMapViewAtPosition(Constants.VANAK_SQUARE);
//Set a touch event listener on the map
mMapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
@Override
public void onMapClick(@NonNull LatLng latLng) {
removeAllMarkersFromMapView();
addMarkerToMapViewAtPosition(latLng);
}
});
setupCurrentLocationButton();
}
});
}
//Add a marker to the map
private void addMarkerToMapViewAtPosition(LatLng coordinate) {
if (mMapboxMap != null) {
mMapboxMap.addMarker(new MarkerViewOptions()
.position(coordinate)
);
}
}
//Clear all markers on the map
private void removeAllMarkersFromMapView() {
mMapboxMap.clear();
}
private void animateToCoordinate(LatLng coordinate, int zoomLevel) {
CameraPosition position = new CameraPosition.Builder()
.target(coordinate)
.zoom(zoomLevel)
.build();
mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position));
}
private void setupCurrentLocationButton() {
FloatingActionButton fb = (FloatingActionButton) getView().findViewById(R.id.showCurrentLocationButton);
fb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hasLocationPermissions()) {
mMapboxMap.setMyLocationEnabled(true);
}
switch (mMapboxMap.getTrackingSettings().getMyBearingTrackingMode()) {
case MyBearingTracking.NONE:
Location location = mMapboxMap.getMyLocation();
if (location != null) {
animateToCoordinate(new LatLng(location.getLatitude(),location.getLongitude()), 17);
mMapboxMap.getTrackingSettings().setMyBearingTrackingMode(MyBearingTracking.GPS);
}
break;
case MyBearingTracking.GPS:
mMapboxMap.getTrackingSettings().setMyBearingTrackingMode(MyBearingTracking.COMPASS);
break;
case MyBearingTracking.COMPASS:
mMapboxMap.getTrackingSettings().setMyBearingTrackingMode(MyBearingTracking.NONE);
break;
}
}
});
}
private boolean hasLocationPermissions() {
//Request Location Permission
if (ContextCompat.checkSelfPermission(this.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this.getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, Constants.PERMISSION_LOCATION_REQUEST_CODE);
return false;
}
return true;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
public void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
mMapView = null;
}
}
package com.cedarmaps.sdksampleapp.fragments;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatTextView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.cedarmaps.sdksampleapp.R;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.MapView;
import com.cedarstudios.cedarmapssdk.listeners.ReverseGeocodeResultListener;
import com.cedarstudios.cedarmapssdk.model.geocoder.reverse.ReverseGeocode;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
public class ReverseGeocodeFragment extends Fragment {
private MapView mMapView;
private MapboxMap mMapboxMap;
private ProgressBar mProgressBar;
private AppCompatTextView mTextView;
public ReverseGeocodeFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_reverse_geocode, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mTextView = (AppCompatTextView) view.findViewById(R.id.reverse_geocode_textView);
mMapView = (MapView) view.findViewById(R.id.mapView);
mProgressBar = (ProgressBar) view.findViewById(R.id.reverse_geocode_progressBar);
mMapView = (MapView) view.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
mMapboxMap.setMaxZoomPreference(17);
mMapboxMap.setMinZoomPreference(6);
reverseGeocode(mapboxMap.getCameraPosition());
mMapboxMap.setOnCameraIdleListener(new MapboxMap.OnCameraIdleListener() {
@Override
public void onCameraIdle() {
reverseGeocode(mMapboxMap.getCameraPosition());
}
});
}
});
}
private void reverseGeocode(CameraPosition position) {
if (TextUtils.isEmpty(mTextView.getText())) {
mTextView.setVisibility(View.GONE);
} else {
mTextView.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.VISIBLE);
CedarMaps.getInstance().reverseGeocode(
position.target,
new ReverseGeocodeResultListener() {
@Override
public void onSuccess(@NonNull ReverseGeocode result) {
mProgressBar.setVisibility(View.GONE);
mTextView.setVisibility(View.VISIBLE);
mTextView.setText(fullAddressForItem(result));
}
@Override
public void onFailure(@NonNull String errorMessage) {
mProgressBar.setVisibility(View.GONE);
mTextView.setVisibility(View.VISIBLE);
mTextView.setText(getString(R.string.parse_error));
}
});
}
private String fullAddressForItem(ReverseGeocode item) {
String result = "";
if (!TextUtils.isEmpty(item.getProvince())) {
result += (getString(R.string.province) + " " + item.getProvince());
}
if (!TextUtils.isEmpty(item.getCity())) {
if (TextUtils.isEmpty(result)) {
result = item.getCity();
} else {
result = result + getString(R.string.comma) + " " + item.getCity();
}
}
if (!TextUtils.isEmpty(item.getLocality())) {
if (TextUtils.isEmpty(result)) {
result = item.getLocality();
} else {
result = result + getString(R.string.comma) + " " + item.getLocality();
}
}
if (!TextUtils.isEmpty(item.getAddress())) {
if (TextUtils.isEmpty(result)) {
result = item.getAddress();
} else {
result = result + getString(R.string.comma) + " " + item.getAddress();
}
}
if (!TextUtils.isEmpty(item.getPlace())) {
if (TextUtils.isEmpty(result)) {
result = item.getPlace();
} else {
result = result + getString(R.string.comma) + " " + item.getPlace();
}
}
return result;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
public void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onDetach() {
super.onDetach();
mMapView = null;
}
}
package com.cedarmaps.sdksampleapp.fragments;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.cedarmaps.sdksampleapp.R;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.Dimension;
import com.cedarstudios.cedarmapssdk.listeners.StaticMapImageResultListener;
import com.mapbox.mapboxsdk.geometry.LatLng;
import java.util.ArrayList;
public class StaticMapFragment extends Fragment {
private Button createMapButton;
private ImageView mapImageView;
private ProgressBar progressBar;
private TextView howToTextView;
private EditText latitude;
private EditText longitude;
private EditText zoomLevel;
public StaticMapFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_static_map, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
createMapButton = (Button)view.findViewById(R.id.static_map_create_button);
mapImageView = (ImageView)view.findViewById(R.id.static_map_image_view);
progressBar = (ProgressBar)view.findViewById(R.id.static_map_progress_bar);
howToTextView = (TextView)view.findViewById(R.id.static_map_hint);
latitude = (EditText)view.findViewById(R.id.edit_text_center_latitude);
longitude = (EditText)view.findViewById(R.id.edit_text_center_longitude);
zoomLevel = (EditText)view.findViewById(R.id.edit_text_zoom_level);
createMapButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
if (TextUtils.isEmpty(latitude.getText()) ||
TextUtils.isEmpty(longitude.getText()) ||
TextUtils.isEmpty(zoomLevel.getText())) {
Toast.makeText(getContext(), R.string.fill_all_fields, Toast.LENGTH_SHORT).show();
return;
}
v.setEnabled(false);
progressBar.animate();
progressBar.setVisibility(View.VISIBLE);
howToTextView.setVisibility(View.INVISIBLE);
LatLng coordinate = new LatLng(Double.parseDouble(latitude.getText().toString()), Double.parseDouble(longitude.getText().toString()));
ArrayList<CedarMaps.StaticMarker> markers = new ArrayList<CedarMaps.StaticMarker>();
markers.add(new CedarMaps.StaticMarker(coordinate, null));
CedarMaps.getInstance().staticMap(
new Dimension(mapImageView.getWidth(), mapImageView.getHeight()),
Integer.parseInt(zoomLevel.getText().toString()),
coordinate,
markers,
new StaticMapImageResultListener() {
@Override
public void onSuccess(@NonNull Bitmap result) {
progressBar.clearAnimation();
progressBar.setVisibility(View.INVISIBLE);
v.setEnabled(true);
mapImageView.setImageBitmap(result);
}
@Override
public void onFailure(@NonNull String errorMessage) {
progressBar.clearAnimation();
progressBar.setVisibility(View.INVISIBLE);
howToTextView.setVisibility(View.VISIBLE);
howToTextView.setText(R.string.map_download_failed);
v.setEnabled(true);
Log.e("StaticMapFragment", errorMessage);
}
});
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<!-- View background color -->
<solid
android:color="@android:color/white" >
</solid>
<!-- View border color and width -->
<stroke
android:width="1dp"
android:color="@android:color/darker_gray" >
</stroke>
<!-- The radius makes the corners rounded -->
<corners
android:radius="4dp" >
</corners>
</shape>
<!-- drawable/crosshairs-gps.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#FFF" android:pathData="M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8M3.05,13H1V11H3.05C3.5,6.83 6.83,3.5 11,3.05V1H13V3.05C17.17,3.5 20.5,6.83 20.95,11H23V13H20.95C20.5,17.17 17.17,20.5 13,20.95V23H11V20.95C6.83,20.5 3.5,17.17 3.05,13M12,5A7,7 0 0,0 5,12A7,7 0 0,0 12,19A7,7 0 0,0 19,12A7,7 0 0,0 12,5Z" />
</vector>
\ No newline at end of file
<vector android:height="24dp" android:viewportHeight="84.0"
android:viewportWidth="84.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#565D64" android:pathData="M70.31,39.71c-0.76,-2.11 -2.39,-3.59 -4.56,-3.9l-3.35,-12c-1.01,-3.63 -4.58,-6.77 -8.3,-7.32c-0.19,-0.03 -4.88,-0.71 -12.3,-0.71c-7.42,0 -12.15,0.68 -12.35,0.71c-3.72,0.54 -7.3,3.69 -8.31,7.32L17.79,35.85c-2.06,0.38 -3.55,1.83 -4.28,3.85c-1.8,5 -2.07,10.38 -0.77,15.53c0.58,2.33 2.24,4.08 4.61,4.46c0.18,0.03 0.4,0.05 0.58,0.08v5.96c0,2.2 1.76,4 3.96,4h4c2.2,0 4,-1.8 4,-4v-4.51c4.06,0.34 8.04,0.5 12,0.5s7.98,-0.16 12.04,-0.5v4.51c0,2.2 1.76,4 3.96,4h4c2.2,0 4,-1.8 4,-4v-5.96c0.18,-0.03 0.36,-0.05 0.54,-0.08c2.37,-0.38 4.06,-2.13 4.65,-4.46C72.34,50.24 72.05,44.55 70.31,39.71zM22.89,54.14c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-2.98 2.42,-5.4 5.4,-5.4c2.98,0 5.4,2.42 5.4,5.4C28.29,51.72 25.87,54.14 22.89,54.14zM26.12,35.78l2.73,-10.16c0.16,-0.59 1.15,-1.46 1.75,-1.55c0.04,-0.01 4.41,-0.63 11.19,-0.63s11.09,0.61 11.14,0.62c0.61,0.09 1.59,0.96 1.76,1.55l2.73,10.16H26.12zM60.89,54.14c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-2.98 2.42,-5.4 5.4,-5.4c2.98,0 5.4,2.42 5.4,5.4C66.29,51.72 63.87,54.14 60.89,54.14z"/>
</vector>
<vector android:height="24dp" android:viewportHeight="84.0"
android:viewportWidth="84.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#565D64" android:pathData="M42.1,10.42c-8.73,0 -15.81,7.08 -15.81,15.81c0,2.37 0.54,4.61 1.47,6.63l-6.92,9.31c-0.97,1.31 -1.02,3.16 0,4.54c1.25,1.68 3.64,2.04 5.32,0.78l9.3,-6.92c2.02,0.94 4.26,1.47 6.64,1.47c8.73,0 15.81,-7.08 15.81,-15.81C57.92,17.5 50.84,10.42 42.1,10.42zM42.1,37.2c-6.06,0 -10.97,-4.91 -10.97,-10.97s4.91,-10.97 10.97,-10.97c6.05,0 10.96,4.91 10.96,10.97S48.16,37.2 42.1,37.2z"/>
<path android:fillColor="#565D64" android:pathData="M69.43,26.93l-6.7,-2.89c0.08,0.72 0.15,1.46 0.15,2.2c0,11.48 -9.32,20.81 -20.8,20.81c-1.99,0 -3.93,-0.28 -5.82,-0.84l-7.12,5.3c-1.53,1.14 -3.34,1.74 -5.25,1.74c-2.77,0 -5.41,-1.33 -7.07,-3.55c-2.3,-3.09 -2.3,-7.41 -0,-10.5l5.3,-7.13c-0.56,-1.89 -0.84,-3.84 -0.84,-5.83c0,-1.66 0.22,-3.27 0.59,-4.82l-6.43,-2.72c-1.98,-0.86 -4.33,0.6 -4.33,2.75v41.67c0,1.2 0.85,2.28 1.95,2.75l19.35,8.33c0.85,0.36 1.84,0.32 2.65,-0.11l14.17,-7.64l17.83,7.67c1.97,0.84 4.05,-0.6 4.05,-2.76c0,-19.61 0,-21.59 0,-41.67C71.11,28.48 70.53,27.4 69.43,26.93z"/>
</vector>
<vector android:height="24dp" android:viewportHeight="84.0"
android:viewportWidth="84.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#565D64" android:pathData="M69.96,25.04l-19.28,-8.24c-0.87,-0.37 -1.91,-0.26 -2.61,0.12l-14.15,7.64l-17.95,-7.76c-1.98,-0.86 -4.19,0.6 -4.19,2.75v41.67c0,1.2 0.71,2.28 1.81,2.75l19.28,8.33c0.85,0.36 1.8,0.32 2.62,-0.11l14.16,-7.64L67.6,72.22c1.97,0.84 4.18,-0.6 4.18,-2.76c0,-19.61 0,-21.59 0,-41.67C71.78,26.59 71.06,25.51 69.96,25.04zM45.45,54.59c-0.97,0.8 -1.34,1.68 -2.22,3.41c-0.77,1.5 -1.15,2.22 -3.17,4.48c-1.85,2.07 -2.31,0.34 -2.71,-0.58c-0.4,-0.92 -0.74,-3.83 -0.74,-3.83s-0.37,-1.83 -2.25,-2.14c-4.69,-0.76 -2.61,-7.88 -2.61,-7.88c-1.21,-0.92 -3.88,-3.17 -7.49,-3.17c-2.16,0 -4.58,-0.49 -6.48,-1.11V24.12l13.02,5.63c1.13,2.12 2.46,2.76 2.96,4.49c1.08,3.69 -1.46,5.3 -1.99,4.09c-0.97,-2.23 -4.55,-1.72 -6.29,-1.15c-2.63,0.86 -3.7,2.5 -1.71,3.39c2,0.89 1.43,0.61 2,0c0.56,-0.61 1.22,-0.83 1.86,-0.27c0.64,0.55 2.16,0.91 2.34,2.27c0.19,1.37 0.26,2.01 1.8,2c1.87,-0.02 1.32,-0.5 2.6,-0.17c1.27,0.33 2.54,-0.33 3.54,-0.34c1.01,-0.01 2.92,1.19 2.92,1.19c2.92,0.31 3.89,0.48 4.8,1.07c0.91,0.59 2,2.66 2,4.3C47.64,52.08 47.19,53.15 45.45,54.59zM65.78,52.52c-1.14,1.28 -2.33,2.05 -2.83,1.99c-1.24,-0.07 -2.31,-1.4 -2.43,-1.69c-0.47,-1.13 -1.25,-5.24 -1.14,-6.48c0.42,-4.53 -0.72,-5.06 -4.34,-5.74c-1.51,-0.29 -3.67,-0.59 -4.79,-1.91c-3.86,-4.55 -3.58,-7.22 -0.1,-10.14c1.23,-1.03 3.88,-2.19 5.75,-3l9.87,4.22V52.52z"/>
</vector>
<vector android:height="24dp" android:viewportHeight="84.0"
android:viewportWidth="84.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#565D64" android:pathData="M36.03,51.91c1.59,1.54 2.58,1.67 4.26,0c0,0 11.93,-11.58 11.93,-22.84c0,-8.26 -6.3,-14.96 -14.06,-14.96c-7.77,0 -13.94,6.7 -13.94,14.96C24.22,40.33 36.03,51.91 36.03,51.91zM31.89,28.11c0,-3.5 2.83,-6.33 6.33,-6.33c3.5,0 6.33,2.84 6.33,6.33s-2.83,6.33 -6.33,6.33C34.72,34.44 31.89,31.61 31.89,28.11zM69.49,22.34L57.36,27.14c0.88,10.68 -7.32,22.65 -13.75,28.85c-3.37,3.33 -7.24,3.57 -10.9,0.01c-6.47,-6.3 -14.08,-17.69 -13.67,-27.89l-5.57,2.14c-0.76,0.31 -1.26,1.04 -1.26,1.86v40c0,1.43 1.45,2.38 2.74,1.86l19.17,-7.67L49.33,73.9c0.51,0.25 1.1,0.28 1.63,0.07l20,-7.91c0.76,-0.3 1.26,-1.04 1.26,-1.86v-40C72.22,22.79 70.79,21.82 69.49,22.34z"/>
</vector>
<vector android:height="24dp" android:viewportHeight="84.0"
android:viewportWidth="84.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#565D64" android:pathData="M68.13,18.49c-6.15,-0.97 -12.38,-1.57 -18.63,-1.81v9.77h-12v-9.77c-6.25,0.24 -12.48,0.84 -18.63,1.81c-1.95,0.31 -3.38,1.98 -3.38,3.95v40c0,1.97 1.43,3.64 3.38,3.95c15.93,2.52 32.56,2.64 49.25,0c1.94,-0.31 3.38,-1.98 3.38,-3.95v-40C71.5,20.48 70.07,18.8 68.13,18.49zM57.95,47.22c-4.88,7.32 -12.98,13.22 -13.3,13.47c-0.67,0.54 -1.61,0.54 -2.28,0c-0.32,-0.25 -8.43,-6.15 -13.31,-13.47c-0.81,-1.21 0.07,-2.83 1.52,-2.83h7.05c0.69,-3.73 1.79,-8.55 2.22,-9.15c0.68,-0.96 1.82,-1.62 3.65,-1.62c1.83,0 2.97,0.65 3.65,1.62c0.42,0.6 1.52,5.42 2.22,9.15h7.06C57.9,44.39 58.76,46.02 57.95,47.22z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.cedarmaps.sdksampleapp.MainActivity">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:menu="@menu/navigation" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layoutDirection="rtl"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/search_view_list_item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="textStart"
android:gravity="start"
android:textSize="15sp"
android:textColor="@android:color/black"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp" />
<TextView
android:id="@+id/search_view_list_item_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:maxLines="1"
android:textColor="@android:color/darker_gray"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/search_view_list_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:maxLines="1"
android:textColor="@android:color/black"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp" />
<TextView
android:id="@+id/search_view_list_item_locality"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="textStart"
android:gravity="start"
android:textSize="15sp"
android:textColor="@android:color/black"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context="com.cedarmaps.sdksampleapp.fragments.DirectionFragment">
<com.cedarstudios.cedarmapssdk.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
mapbox:mapbox_cameraZoom="14"
mapbox:mapbox_cameraTargetLat="35.7572"
mapbox:mapbox_cameraTargetLng="51.4099"
/>
<LinearLayout
android:id="@+id/direction_hint_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/direction_hint_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minLines="0"
android:textSize="16sp"
android:textColor="@android:color/black"
android:textAlignment="center"
android:text="@string/direction_hint"/>
<ProgressBar
android:id="@+id/direction_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"/>
</LinearLayout>
<LinearLayout
android:id="@+id/direction_result_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="vertical"
android:padding="12dp"
android:visibility="gone">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/distance"
android:textSize="16sp"
android:textColor="@android:color/black"
/>
<TextView
android:id="@+id/direction_distance_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="4dp"
android:paddingStart="4dp"
android:paddingRight="4dp"
android:paddingEnd="4dp"
android:textSize="18sp"
/>
</LinearLayout>
<Button
android:id="@+id/direction_reset_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="@string/reset_points"/>
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:mapbox="http://schemas.android.com/apk/res-auto">
<com.cedarstudios.cedarmapssdk.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraZoom="14"
mapbox:mapbox_cameraTargetLat="35.7572"
mapbox:mapbox_cameraTargetLng="51.4099"
/>
<LinearLayout
android:id="@+id/search_results_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/white"
android:visibility="gone"
>
<ProgressBar
android:id="@+id/search_progress_bar"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_gravity="center"
android:padding="8dp"
android:visibility="gone"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:id="@+id/recyclerView"
android:visibility="gone"/>
</LinearLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<com.cedarstudios.cedarmapssdk.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
mapbox:mapbox_cameraZoom="14"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/showCurrentLocationButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
app:backgroundTint="@color/colorPrimary"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
app:fabSize="normal"
app:srcCompat="@drawable/crosshairs_gps"
android:layout_margin="20dp"/>
</FrameLayout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cedarmaps.sdksampleapp.fragments.ReverseGeocodeFragment"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
>
<com.cedarstudios.cedarmapssdk.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
mapbox:mapbox_cameraZoom="14"
mapbox:mapbox_cameraTargetLat="35.7572"
mapbox:mapbox_cameraTargetLng="51.4099"
/>
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
mapbox:srcCompat="@drawable/cedarmaps_marker_icon_default"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_border"
android:orientation="horizontal"
android:gravity="center"
android:layout_gravity="bottom|center"
android:layout_marginBottom="32dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:padding="8dp"
>
<ProgressBar
android:id="@+id/reverse_geocode_progressBar"
android:layout_width="48dp"
android:layout_height="48dp"
android:visibility="visible"
/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/reverse_geocode_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="@android:color/black"
android:textSize="26sp"
android:visibility="gone"
/>
</LinearLayout>
</FrameLayout>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cedarmaps.sdksampleapp.fragments.StaticMapFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
>
<ImageView
android:id="@+id/static_map_image_view"
android:layout_width="match_parent"
android:layout_height="180dp"
android:adjustViewBounds="true"
android:background="#EEEEEE"
android:cropToPadding="true"
android:scaleType="fitCenter" />
<ProgressBar
android:id="@+id/static_map_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="invisible"/>
<TextView
android:id="@+id/static_map_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textSize="18sp"
android:visibility="visible"
android:text="@string/static_maps_hint"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@android:color/black"
android:text="@string/center_point"
android:layout_marginBottom="12dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout
android:id="@+id/linear_layout_sw_latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="@string/latitude"/>
<EditText
android:id="@+id/edit_text_center_latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/latitude_example"
android:inputType="numberDecimal" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="@string/longitude"/>
<EditText
android:id="@+id/edit_text_center_longitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/longitude_example"
android:inputType="numberDecimal"
/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@android:color/black"
android:text="@string/zoom"/>
<EditText
android:id="@+id/edit_text_zoom_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/zoom_level_hint"
android:text="@string/zoom_example"
android:inputType="numberDecimal"
/>
</LinearLayout>
<Button
android:id="@+id/static_map_create_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="@string/create_static_map"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_map"
android:icon="@drawable/ic_map_marker"
android:title="@string/title_map" />
<item
android:id="@+id/navigation_reverse"
android:icon="@drawable/ic_reverse_geocode"
android:title="@string/title_reverse" />
<item
android:id="@+id/navigation_forward"
android:icon="@drawable/ic_forward_geocode"
android:title="@string/title_forward" />
<item
android:id="@+id/navigation_direction"
android:icon="@drawable/ic_direction"
android:title="@string/title_direction" />
<item
android:id="@+id/navigation_static"
android:icon="@drawable/ic_static_map"
android:title="@string/title_static" />
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"
android:title="@string/search_in_places"
android:icon="@android:drawable/ic_menu_search"/>
</menu>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
\ No newline at end of file
<resources>
<string name="app_name">سیدارمپ - دمو</string>
<string name="title_map">نقشه</string>
<string name="title_reverse">نقطه‌یابی</string>
<string name="title_forward">جستجو</string>
<string name="title_direction">مسیریابی</string>
<string name="title_static">استاتیک</string>
<string name="no_results">متأسفانه نتیجه‌ای یافت نشد</string>
<string name="unknown_error">خطایی پیش آمد</string>
<string name="parse_error">خطای پردازش نتیجه</string>
<string name="searching">در حال جستجو …</string>
<string name="search_for">جستجو …</string>
<string name="latitude">عرض جغرافیایی: </string>
<string name="longitude">طول جغرافیایی: </string>
<string name="zoom">زوم: </string>
<string name="zoom_level_hint">۶ تا ۱۷</string>
<string name="create_static_map">ساخت نقشه استاتیک</string>
<string name="static_maps_hint">دکمه را لمس کنید تا تصویر نقشه مربوط به محدوده‌ی تعیین شده تولید شود</string>
<string name="center_point">نقطه مرکزی</string>
<string name="map_download_failed">خطا در دانلود نقشه</string>
<string name="fill_all_fields">لطفاً تمام موارد را پر کنید</string>
<string name="distance">فاصله:</string>
<string name="reset_points">انتخاب دوباره</string>
<string name="direction_hint">نقشه را برای انتخاب نقاط ابتدایی و نهایی لمس کنید</string>
<string name="direction_receiving_failed">خطا در دریافت اطلاعات مسیریابی</string>
<string name="search_in_places">در بین معابر جستجو کنید</string>
<string name="province">استان</string>
<string name="comma">،</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>
...@@ -2,12 +2,4 @@ ...@@ -2,12 +2,4 @@
<!-- Default screen margins, per the Android Design guidelines. --> <!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="nav_header_vertical_spacing">16dp</dimen>
<dimen name="nav_header_height">160dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<!-- Per the design guidelines, navigation drawers should be between 240dp and 320dp:
https://developer.android.com/design/patterns/navigation-drawer.html -->
<dimen name="navigation_drawer_width">240dp</dimen>
</resources> </resources>
<resources>
<string name="app_name">CedarMaps - Dev</string>
<string name="title_map">Map</string>
<string name="title_reverse">Reverse</string>
<string name="title_forward">Search</string>
<string name="title_direction">Direction</string>
<string name="title_static">Static</string>
<string name="no_results">Nothing found</string>
<string name="unknown_error">Unknown Error</string>
<string name="parse_error">Parsing Error</string>
<string name="searching">Searching …</string>
<string name="search_for">Search</string>
<string name="latitude">Latitude: </string>
<string name="longitude">Longitude: </string>
<string name="zoom">Zoom: </string>
<string name="zoom_level_hint">6 to 17</string>
<string name="create_static_map">Create Static Map</string>
<string name="static_maps_hint">Tap on Create button to fetch an image for the entered coordinate</string>
<string name="center_point">Center Point</string>
<string name="map_download_failed">Error in downloading map</string>
<string name="fill_all_fields">Please fill all fields.</string>
<string name="distance">Distance:</string>
<string name="reset_points">Reset</string>
<string name="direction_hint">Tap on the map to choose starting and ending points</string>
<string name="direction_receiving_failed">Error in receiving direction data</string>
<string name="search_in_places">Search in places</string>
<string name="province">استان</string>
<string name="comma">،</string>
<string name="latitude_example" translatable="false">35.7454</string>
<string name="longitude_example" translatable="false">51.3572</string>
<string name="zoom_example" translatable="false">13</string>
</resources>
...@@ -3,15 +3,9 @@ ...@@ -3,15 +3,9 @@
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style> </style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
</resources> </resources>
package com.cedarstudios.cedarmaps;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
\ No newline at end of file
package com.cedarstudios.cedarmaps.sample;
public class Constants {
public static final String MAPID_CEDARMAPS_STREETS = "cedarmaps.streets";
public static final String MAPID_CEDARMAPS_DRIVING = "cedarmaps.driving";
public static final String CLIENT_ID = "";
public static final String CLIENT_SECRET = "";
}
package com.cedarstudios.cedarmaps.sample;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import com.cedarstudios.cedarmaps.sample.fragment.APIAdvancedGeocodeTestFragment;
import com.cedarstudios.cedarmaps.sample.fragment.APIGeocodeTestFragment;
import com.cedarstudios.cedarmaps.sample.fragment.APIReverseGeocodeTestFragment;
import com.cedarstudios.cedarmaps.sample.fragment.ItemizedIconOverlayTestFragment;
import com.cedarstudios.cedarmaps.sample.fragment.MainTestFragment;
import com.cedarstudios.cedarmaps.sample.fragment.MarkersTestFragment;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.CedarMapsFactory;
import com.cedarstudios.cedarmapssdk.auth.OAuth2Token;
import com.cedarstudios.cedarmapssdk.config.ConfigurationBuilder;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public static final String PREF_NAME = "pref";
public static final String PREF_ID_ACCESS_TOKEN = "access_token";
public static final String PREF_ID_TOKEN_TYPE = "token_type";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
new CedarMapsAuthenticateTask().execute();
onNavigationItemSelected(navigationView.getMenu().getItem(0));
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
Fragment fragment;
switch (item.getItemId()) {
case R.id.mainTestMap:
fragment = new MainTestFragment();
break;
case R.id.markersTestMap:
fragment = new MarkersTestFragment();
break;
case R.id.itemizedOverlayTestMap:
fragment = new ItemizedIconOverlayTestFragment();
break;
case R.id.searchAPI:
fragment = new APIGeocodeTestFragment();
break;
case R.id.streetSearchAPIAdvanced:
fragment = new APIAdvancedGeocodeTestFragment();
break;
case R.id.reverseGeocode:
fragment = new APIReverseGeocodeTestFragment();
break;
default:
fragment = new MainTestFragment();
break;
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
setTitle(item.getTitle());
return true;
}
class CedarMapsAuthenticateTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
com.cedarstudios.cedarmapssdk.config.Configuration
configuration = new ConfigurationBuilder()
.setClientId(Constants.CLIENT_ID)
.setClientSecret(Constants.CLIENT_SECRET)
.build();
CedarMapsFactory factory = new CedarMapsFactory(configuration);
CedarMaps cedarMaps = factory.getInstance();
try {
OAuth2Token oAuth2Token = cedarMaps.getOAuth2Token();
SharedPreferences pref = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(PREF_ID_ACCESS_TOKEN, oAuth2Token.getAccessToken());
editor.putString(PREF_ID_TOKEN_TYPE, oAuth2Token.getTokenType());
editor.commit();
} catch (CedarMapsException e) {
e.printStackTrace();
}
return null;
}
}
}
package com.cedarstudios.cedarmaps.sample.fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.cedarstudios.cedarmaps.sample.Constants;
import com.cedarstudios.cedarmaps.sample.MainActivity;
import com.cedarstudios.cedarmaps.sample.R;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.CedarMapsFactory;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import com.cedarstudios.cedarmapssdk.config.ConfigurationBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.Marker;
import java.util.ArrayList;
public class APIAdvancedGeocodeTestFragment extends MainTestFragment implements View.OnClickListener {
private EditText mSearchEditText;
private ArrayList<Marker> mMarkers = new ArrayList<>();
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_search, container, false);
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.search).setOnClickListener(this);
mSearchEditText = (EditText) view.findViewById(R.id.term);
mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
view.findViewById(R.id.search).performClick();
return true;
}
return false;
}
});
}
@Override
public void onClick(View v) {
if (!TextUtils.isEmpty(mSearchEditText.getText().toString())) {
InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
clearMarkers();
new SearchAsyncTask().execute(mSearchEditText.getText().toString().trim());
}
}
private void clearMarkers() {
mMapView.getOverlays().clear();
mMapView.invalidate();
mMapView.getController().setZoom(12);
mMapView.getController().animateTo(new GeoPoint(35.6961, 51.4231)); // center of tehran
mMarkers.clear();
}
class SearchAsyncTask extends AsyncTask<String, Void, JSONObject> {
private ProgressDialog mProgress;
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgress = new ProgressDialog(getActivity());
mProgress.setMessage(getString(R.string.searching));
mProgress.show();
}
@Override
protected JSONObject doInBackground(String... params) {
JSONObject searchResult = null;
try {
SharedPreferences pref = getActivity().getSharedPreferences(MainActivity.PREF_NAME,
Context.MODE_PRIVATE);
Configuration configuration = new ConfigurationBuilder()
.setOAuth2AccessToken(pref.getString(MainActivity.PREF_ID_ACCESS_TOKEN, ""))
.setOAuth2TokenType(pref.getString(MainActivity.PREF_ID_TOKEN_TYPE, ""))
.setMapId(Constants.MAPID_CEDARMAPS_STREETS)
.build();
CedarMaps cedarMaps = new CedarMapsFactory(configuration).getInstance();
GeoPoint location = new GeoPoint(35.6961, 51.4231);
searchResult = cedarMaps.geocode(params[0], location, 50, null, 5);
} catch (CedarMapsException e) {
e.printStackTrace();
}
return searchResult;
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
mProgress.dismiss();
try {
String status = jsonObject.getString("status");
if (status.equals("OK")) {
JSONArray array = jsonObject.getJSONArray("results");
for (int i = 0; i < array.length(); i++) {
JSONObject item = array.getJSONObject(i);
String[] location = item.getJSONObject("location").getString("center").split(",");
GeoPoint latLng = new GeoPoint(Double.parseDouble(location[0]), Double.parseDouble(location[1]));
Marker marker = new Marker(mMapView);
marker.setPosition(latLng);
marker.setTitle(item.getString("name"));
mMapView.getOverlays().add(marker);
}
} else if (status.equals("ZERO_RESULTS")) {
Toast.makeText(getActivity(), getString(R.string.no_results), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), getString(R.string.unkonown_error), Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(getActivity(), getString(R.string.parse_error), Toast.LENGTH_LONG).show();
}
}
}
}
package com.cedarstudios.cedarmaps.sample.fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.cedarstudios.cedarmaps.sample.Constants;
import com.cedarstudios.cedarmaps.sample.MainActivity;
import com.cedarstudios.cedarmaps.sample.R;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.CedarMapsFactory;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import com.cedarstudios.cedarmapssdk.config.ConfigurationBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.Marker;
import java.util.ArrayList;
public class APIGeocodeTestFragment extends MainTestFragment implements View.OnClickListener {
private EditText mSearchEditText;
private ArrayList<Marker> mMarkers = new ArrayList<>();
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_search, container, false);
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.search).setOnClickListener(this);
mSearchEditText = (EditText) view.findViewById(R.id.term);
mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
view.findViewById(R.id.search).performClick();
return true;
}
return false;
}
});
}
@Override
public void onClick(View v) {
if (!TextUtils.isEmpty(mSearchEditText.getText().toString())) {
InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
clearMarkers();
new SearchAsyncTask().execute(mSearchEditText.getText().toString().trim());
}
}
private void clearMarkers() {
mMapView.getOverlays().clear();
mMapView.invalidate();
mMapView.getController().setZoom(12);
mMapView.getController().animateTo(new GeoPoint(35.6961, 51.4231)); // center of tehran
mMarkers.clear();
}
class SearchAsyncTask extends AsyncTask<String, Void, JSONObject> {
private ProgressDialog mProgress;
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgress = new ProgressDialog(getActivity());
mProgress.setMessage(getString(R.string.searching));
mProgress.show();
}
@Override
protected JSONObject doInBackground(String... params) {
JSONObject searchResult = null;
try {
SharedPreferences pref = getActivity().getSharedPreferences(MainActivity.PREF_NAME, Context.MODE_PRIVATE);
Configuration configuration = new ConfigurationBuilder()
.setOAuth2AccessToken(pref.getString(MainActivity.PREF_ID_ACCESS_TOKEN, ""))
.setOAuth2TokenType(pref.getString(MainActivity.PREF_ID_TOKEN_TYPE, ""))
.setMapId(Constants.MAPID_CEDARMAPS_STREETS)
.build();
CedarMaps cedarMaps = new CedarMapsFactory(configuration).getInstance();
searchResult = cedarMaps.geocode(params[0]);
} catch (CedarMapsException e) {
e.printStackTrace();
}
return searchResult;
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
mProgress.dismiss();
try {
String status = jsonObject.getString("status");
if (status.equals("OK")) {
JSONArray array = jsonObject.getJSONArray("results");
for (int i = 0; i < array.length(); i++) {
JSONObject item = array.getJSONObject(i);
String[] location = item.getJSONObject("location").getString("center").split(",");
GeoPoint latLng = new GeoPoint(Double.parseDouble(location[0]), Double.parseDouble(location[1]));
Marker marker = new Marker(mMapView);
marker.setPosition(latLng);
marker.setTitle(item.getString("name"));
mMapView.getOverlays().add(marker);
}
} else if (status.equals("ZERO_RESULTS")) {
Toast.makeText(getActivity(), getString(R.string.no_results), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), getString(R.string.unkonown_error), Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(getActivity(), getString(R.string.parse_error), Toast.LENGTH_LONG).show();
}
}
}
}
package com.cedarstudios.cedarmaps.sample.fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.cedarstudios.cedarmaps.sample.Constants;
import com.cedarstudios.cedarmaps.sample.MainActivity;
import com.cedarstudios.cedarmaps.sample.R;
import com.cedarstudios.cedarmapssdk.CedarMaps;
import com.cedarstudios.cedarmapssdk.CedarMapsException;
import com.cedarstudios.cedarmapssdk.CedarMapsFactory;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import com.cedarstudios.cedarmapssdk.config.ConfigurationBuilder;
import org.json.JSONObject;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.Marker;
import java.util.ArrayList;
public class APIReverseGeocodeTestFragment extends MainTestFragment implements View.OnClickListener {
private EditText mSearchEditText;
private ArrayList<Marker> mMarkers = new ArrayList<>();
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_search, container, false);
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.search).setOnClickListener(this);
mSearchEditText = (EditText) view.findViewById(R.id.term);
mSearchEditText.setText("35.759926, 51.432512");
mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
view.findViewById(R.id.search).performClick();
return true;
}
return false;
}
});
}
@Override
public void onClick(View v) {
if (!TextUtils.isEmpty(mSearchEditText.getText().toString())) {
InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
clearMarkers();
new ReverseGeocodeAsyncTask().execute(mSearchEditText.getText().toString().trim());
}
}
private void clearMarkers() {
mMapView.getOverlays().clear();
mMapView.invalidate();
mMapView.getController().setZoom(12);
mMapView.getController().animateTo(new GeoPoint(35.6961, 51.4231)); // center of tehran
mMarkers.clear();
}
class ReverseGeocodeAsyncTask extends AsyncTask<String, Void, JSONObject> {
private ProgressDialog mProgress;
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgress = new ProgressDialog(getActivity());
mProgress.setMessage(getString(R.string.searching));
mProgress.show();
}
@Override
protected JSONObject doInBackground(String... params) {
JSONObject searchResult = null;
try {
SharedPreferences pref = getActivity().getSharedPreferences(MainActivity.PREF_NAME,
Context.MODE_PRIVATE);
Configuration configuration = new ConfigurationBuilder()
.setOAuth2AccessToken(pref.getString(MainActivity.PREF_ID_ACCESS_TOKEN, ""))
.setOAuth2TokenType(pref.getString(MainActivity.PREF_ID_TOKEN_TYPE, ""))
.setMapId(Constants.MAPID_CEDARMAPS_STREETS)
.build();
CedarMaps cedarMaps = new CedarMapsFactory(configuration).getInstance();
String[] latlng = params[0].split(",");
searchResult = cedarMaps.geocode(Double.parseDouble(latlng[0]), Double.parseDouble(latlng[1]));
} catch (CedarMapsException e) {
e.printStackTrace();
}
return searchResult;
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
mProgress.dismiss();
try {
String status = jsonObject.getString("status");
if (status.equals("OK")) {
String address = jsonObject.getJSONObject("result").getString("address");
String[] location = mSearchEditText.getText().toString().trim().split(",");
GeoPoint latLng = new GeoPoint(Double.parseDouble(location[0]), Double.parseDouble(location[1]));
Marker marker = new Marker(mMapView);
marker.setPosition(latLng);
marker.setTitle(address);
mMapView.getOverlays().add(marker);
Toast.makeText(getActivity(), address, Toast.LENGTH_LONG).show();
} else if (status.equals("ZERO_RESULTS")) {
Toast.makeText(getActivity(), getString(R.string.no_results), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), getString(R.string.unkonown_error), Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(getActivity(), getString(R.string.parse_error), Toast.LENGTH_LONG).show();
}
}
}
}
package com.cedarstudios.cedarmaps.sample.fragment;
import android.widget.Toast;
import com.cedarstudios.cedarmaps.sample.R;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.ItemizedOverlay;
import org.osmdroid.views.overlay.OverlayItem;
import java.util.ArrayList;
public class ItemizedIconOverlayTestFragment extends MainTestFragment {
@Override
protected void onMapLoaded() {
mMapView.getController().setZoom(15);
mMapView.getController().setCenter(new GeoPoint(35.762734, 51.432126));
final ArrayList<OverlayItem> items = new ArrayList<>();
items.add(new OverlayItem(getString(R.string.haghani_metro), "", new GeoPoint(35.759926, 51.432512)));
items.add(new OverlayItem(getString(R.string.third_street), "", new GeoPoint(35.762329, 51.429722)));
items.add(new OverlayItem(getString(R.string.haghani_way), "", new GeoPoint(35.759055, 51.427362)));
items.add(new OverlayItem(getString(R.string.tabrizian), "", new GeoPoint(35.762538, 51.435173)));
/* OnTapListener for the Markers, shows a simple Toast. */
ItemizedOverlay<OverlayItem> mMyLocationOverlay = new ItemizedIconOverlay<>(items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
@Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
Toast.makeText(getActivity(), "Item '" + item.getTitle() + "' (index=" + index
+ ") got single tapped up", Toast.LENGTH_LONG).show();
return true; // We 'handled' this event.
}
@Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
Toast.makeText(getActivity(), "Item '" + item.getTitle() + "' (index=" + index
+ ") got long pressed", Toast.LENGTH_LONG).show();
return false;
}
}, getContext());
mMapView.getOverlays().add(mMyLocationOverlay);
}
}
package com.cedarstudios.cedarmaps.sample.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.cedarstudios.cedarmaps.sample.Constants;
import com.cedarstudios.cedarmaps.sample.R;
import com.cedarstudios.cedarmapssdk.CedarMapsTileLayerListener;
import com.cedarstudios.cedarmapssdk.config.Configuration;
import com.cedarstudios.cedarmapssdk.config.ConfigurationBuilder;
import com.cedarstudios.cedarmapssdk.tileprovider.CedarMapTileProvider;
import com.cedarstudios.cedarmapssdk.tileprovider.tilesource.CedarMapsTileSource;
import com.cedarstudios.cedarmapssdk.tileprovider.tilesource.CedarMapsTileSourceInfo;
import com.cedarstudios.cedarmapssdk.view.MapView;
import org.osmdroid.util.GeoPoint;
public class MainTestFragment extends Fragment {
protected MapView mMapView;
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_map, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMapView = (MapView) view.findViewById(R.id.mapView);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Configuration
configuration = new ConfigurationBuilder()
.setClientId(Constants.CLIENT_ID)
.setClientSecret(Constants.CLIENT_SECRET)
.setMapId(Constants.MAPID_CEDARMAPS_STREETS)
.build();
final CedarMapsTileSourceInfo cedarMapsTileSourceInfo = new CedarMapsTileSourceInfo(getContext(), configuration);
cedarMapsTileSourceInfo.setTileLayerListener(new CedarMapsTileLayerListener() {
@Override
public void onPrepared(CedarMapsTileSourceInfo tileLayer) {
CedarMapsTileSource cedarMapsTileSource = new CedarMapsTileSource(tileLayer);
CedarMapTileProvider provider = new CedarMapTileProvider(getActivity().getApplicationContext(), cedarMapsTileSource);
mMapView.setTileProvider(provider);
mMapView.getController().setZoom(12);
mMapView.getController().setCenter(new GeoPoint(35.6961, 51.4231));
onMapLoaded();
}
});
}
@Override
public void onDetach() {
super.onDetach();
mMapView.onDetach();
mMapView = null;
}
protected void onMapLoaded() {
}
}
package com.cedarstudios.cedarmaps.sample.fragment;
import android.support.v4.content.ContextCompat;
import com.cedarstudios.cedarmaps.sample.R;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.Marker;
public class MarkersTestFragment extends MainTestFragment {
@Override
protected void onMapLoaded() {
mMapView.getController().setZoom(14);
mMapView.getController().setCenter(new GeoPoint(35.703859, 51.408037));
GeoPoint position = new GeoPoint(35.709086, 51.401471);
addMarker(position);
position = new GeoPoint(35.699781, 51.397565);
addMarker(position);
position = new GeoPoint(35.705636, 51.414174);
addMarker(position);
position = new GeoPoint(35.698631, 51.407693);
addMarker(position);
}
private void addMarker(GeoPoint position) {
Marker marker = new Marker(mMapView);
marker.setIcon(ContextCompat.getDrawable(getContext(), R.drawable.marker_default));
marker.setPosition(position);
mMapView.getOverlays().add(marker);
}
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path
android:fillColor="#FF000000"
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z"/>
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z"/>
</vector>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="135"
android:centerColor="#4CAF50"
android:endColor="#2E7D32"
android:startColor="#81C784"
android:type="linear"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer"/>
</android.support.v4.widget.DrawerLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.cedarstudios.cedarmaps.sample.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main"/>
</android.support.design.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/content_frame"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.cedarstudios.cedarmaps.sample.MainActivity"
tools:showIn="@layout/app_bar_main">
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<com.cedarstudios.cedarmapssdk.view.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:padding="3dp"
android:src="@drawable/cedarmaps_attribution"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="3dp">
<ImageButton
android:id="@+id/search"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/ic_search" />
<EditText
android:id="@+id/term"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:imeOptions="actionSearch"
android:layout_margin="5dp"
android:hint="جستجو برای..." />
</LinearLayout>
<ListView
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<com.cedarstudios.cedarmapssdk.view.MapView
android:id="@+id/mapView"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/mainTestMap"
android:title="@string/mainTestMap"/>
<item
android:id="@+id/markersTestMap"
android:title="@string/markersTestMap"/>
<item
android:id="@+id/itemizedOverlayTestMap"
android:title="@string/itemizedOverlayTestMap"/>
<item
android:id="@+id/searchAPI"
android:title="@string/searchAPI"/>
<item
android:id="@+id/streetSearchAPIAdvanced"
android:title="@string/streetSearchAPIAdvanced"/>
<item
android:id="@+id/reverseGeocode"
android:title="@string/reverseGeocode"/>
</group>
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"/>
</menu>
<resources>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item>
<item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item>
<item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item>
<item name="ic_menu_manage" type="drawable">@android:drawable/ic_menu_manage</item>
<item name="ic_menu_share" type="drawable">@android:drawable/ic_menu_share</item>
<item name="ic_menu_send" type="drawable">@android:drawable/ic_menu_send</item>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CedarMaps Sample</string>
<string name="action_settings">Settings</string>
<string name="mainTestMap">Main Test Map</string>
<string name="markersTestMap">Markers Test</string>
<string name="itemizedOverlayTestMap">ItemizedIconOverlay</string>
<string name="searchAPI">Geocode API</string>
<string name="streetSearchAPIAdvanced">Advanced Geocode API</string>
<string name="reverseGeocode">Reverse geocode API</string>
<string name="drawerOpen">Open Nav Drawer</string>
<string name="drawerClose">Close Nav Drawer</string>
<string name="haghani_metro">مترو شهید حقانی</string>
<string name="third_street">خیابان سوم</string>
<string name="haghani_way">بزرگراه حقانی</string>
<string name="tabrizian">خیابان تبریزیان</string>
<string name="searching">در حال جستجو...</string>
<string name="unkonown_error">خطایی پیش آمد</string>
<string name="no_results">نتیجه‌ای یافت نشد</string>
<string name="parse_error">خطای پردازش نتیجه</string>
<string name="title_activity_main">MainActivity</string>
<string name="title_section1">Section 1</string>
<string name="title_section2">Section 2</string>
<string name="title_section3">Section 3</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
</resources>
...@@ -16,7 +16,7 @@ repositories { ...@@ -16,7 +16,7 @@ repositories {
} }
dependencies { dependencies {
compile('com.cedarmaps:CedarMapsSDK:1.0.0@aar') { compile('com.cedarmaps:CedarMapsSDK:1.0.1@aar') {
transitive = true transitive = true
} }
} }
......
...@@ -5,8 +5,8 @@ buildscript { ...@@ -5,8 +5,8 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
...@@ -16,5 +16,11 @@ buildscript { ...@@ -16,5 +16,11 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
jcenter() jcenter()
maven {
url "https://maven.google.com"
}
maven {
url "http://repo.cedarmaps.com/android/"
}
} }
} }
GROUP=com.cedarmaps
VERSION_NAME=2.0.0
# Project-wide Gradle settings. # Project-wide Gradle settings.
# IDE (e.g. Android Studio) users: # IDE (e.g. Android Studio) users:
......
#Tue Aug 23 18:48:06 IRDT 2016 #Tue Sep 12 11:03:14 IRDT 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
File mode changed from 100644 to 100755
include ':CedarMapsTestApp', ':CedarMapsSDK' include ':CedarMapsSDK', ':CedarMapsSampleApp'
rootProject.name = 'artifact' rootProject.name = 'artifact'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment