I am making a map application where I am showing route between two points (dynamically). In this I am retrieving latitude and longitude from the database (which can change with time). This is a college project, so have not worked on the security part. This is the java file for the navigation:
public class NavigationActivity extends AppCompatActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
GoogleMap.OnMarkerDragListener,
GoogleMap.OnMapLongClickListener,
LocationListener {
private GoogleMap mMap;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
private double longitude;
private double latitude;
private double fromLongitude;
private double fromLatitude;
private double toLongitude;
private double toLatitude;
private static final String LOGIN_URL = "http://192.168.211.1/xyz/lat.php";
private static final String LOGIN_URLS = "http://192.168.211.1/xyz/lng.php";
public static final String KEY_MYNAME = "User";
public static final String LAT = "lat";
public static final String LANG = "lang";
public LocationManager locationManager;
public Criteria criteria;
public String bestProvider;
private static final String TAG = NavigationActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
getLocation();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
public static boolean isLocationEnabled(Context context)
{
return true;
}
protected void getLocation() {
if (isLocationEnabled(NavigationActivity.this)) {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
bestProvider = String.valueOf(locationManager.getBestProvider(criteria, true)).toString();
//You can still do this if you like, you might get lucky:
Location location = locationManager.getLastKnownLocation(bestProvider);
if (location != null) {
Log.e("TAG", "GPS is on");
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(NavigationActivity.this, "latitude:" + latitude + " longitude:" + longitude, Toast.LENGTH_SHORT).show();
//Trying to send the data to the database
final StringRequest stringrequest=new StringRequest(Request.Method.POST,LOGIN_URL,new Response.Listener<String>(){
#Override
public void onResponse(String s) {
if (!s.equalsIgnoreCase("updated")) {
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
getPoints();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), volleyError.toString(), Toast.LENGTH_LONG).show();
}
}){
protected Map<String,String> getParams(){
Map<String,String>params=new HashMap<String, String>();
SharedPreferences sharedPreferences = NavigationActivity.this.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
String KEY_MYUSERNAME = sharedPreferences.getString(Config.EMAIL_SHARED_PREF, "Not Found");
params.put(LAT, String.valueOf(latitude));
params.put(LANG, String.valueOf(longitude));
params.put(KEY_MYNAME, KEY_MYUSERNAME);
return params;
}
};
RequestQueue requestQueue= Volley.newRequestQueue(this);
requestQueue.add(stringrequest);
} else {
//This is what you need:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(bestProvider, 1000, 0, this);
}
}
else
{
//prompt user to enable location....
//.................
}
}
#Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
} else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// if (ContextCompat.checkSelfPermission(this,
// Manifest.permission.ACCESS_FINE_LOCATION)
// == PackageManager.PERMISSION_GRANTED) {
// LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
// }
}
private void getPoints() {
//Getting the URL
fromLatitude = latitude;
fromLongitude = longitude;
//To get to latitude
StringRequest stringRequests = new StringRequest(Request.Method.POST, LOGIN_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.equalsIgnoreCase("Connection Error")) {
Toast.makeText(NavigationActivity.this, response, Toast.LENGTH_SHORT).show();
}
else {
toLatitude = Double.parseDouble(response);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(NavigationActivity.this, error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
SharedPreferences sharedPreferences = NavigationActivity.this.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
String KEY_MYUSERNAME = sharedPreferences.getString(Config.EMAIL_SHARED_PREF,"Not Found");
Map<String,String> params = new HashMap<String, String>();
params.put(KEY_MYNAME,KEY_MYUSERNAME);
return params;
}
};
RequestQueue requestQueues = Volley.newRequestQueue(this);
requestQueues.add(stringRequests);
StringRequest stringRequestss = new StringRequest(Request.Method.POST, LOGIN_URLS,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.equalsIgnoreCase("Connection Error")) {
Toast.makeText(NavigationActivity.this, response, Toast.LENGTH_SHORT).show();
}
else {
toLongitude = Double.parseDouble(response);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(NavigationActivity.this, error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
SharedPreferences sharedPreferences = NavigationActivity.this.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
String KEY_MYUSERNAME = sharedPreferences.getString(Config.EMAIL_SHARED_PREF,"Not Found");
Map<String,String> params = new HashMap<String, String>();
params.put(KEY_MYNAME,KEY_MYUSERNAME);
return params;
}
};
RequestQueue requestQueuess = Volley.newRequestQueue(this);
requestQueuess.add(stringRequestss);
getDirections();
}
private void getDirections() {
double flat = fromLatitude;
double flong = fromLongitude;
double tlat = toLatitude;
double tlong = toLongitude;
LatLng origin = new LatLng(flat, flong);
LatLng dest = new LatLng(tlat, tlong);
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
}
private String getDirectionsUrl(LatLng origin,LatLng dest){
// Origin of route
String str_origin = "origin="+origin.latitude+","+origin.longitude;
// Destination of route
String str_dest = "destination="+dest.latitude+","+dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin+"&"+str_dest+"&"+sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
return url;
}
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String> {
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> >{
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try{
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
}catch(Exception e){
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(2);
lineOptions.color(Color.RED);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(final Location location) {
getLocation();
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
Toast.makeText(NavigationActivity.this, String.valueOf(location.getLatitude()), Toast.LENGTH_LONG).show();
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//stop location updates
if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, (com.google.android.gms.location.LocationListener) this);
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(NavigationActivity.this, "Connection Lost", Toast.LENGTH_LONG).show();
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
}
}
This is my logcat:
03-24 15:00:51.174 9970-9970/com.xyz.user.xyz E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xyz.user.xyz, PID: 9970
java.lang.NullPointerException: PolylineOptions cannot be null.
at com.google.maps.api.android.lib6.common.k.a(:com.google.android.gms.DynamiteModulesB:42)
at com.google.maps.api.android.lib6.impl.dp.<init>(:com.google.android.gms.DynamiteModulesB:146)
at com.google.maps.api.android.lib6.impl.az.a(:com.google.android.gms.DynamiteModulesB:931)
at com.google.android.gms.maps.internal.l.onTransact(:com.google.android.gms.DynamiteModulesB:137)
at android.os.Binder.transact(Binder.java:380)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.addPolyline(Unknown Source)
at com.google.android.gms.maps.GoogleMap.addPolyline(Unknown Source)
at com.xyz.user.xyz.NavigationActivity$ParserTask.onPostExecute(NavigationActivity.java:474)
at com.xyz.user.xyz.NavigationActivity$ParserTask.onPostExecute(NavigationActivity.java:420)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Can anyone suggest me some solution?
I tried to use the below code:
if(lineOptions!=null)
{
mMap.addPolyline(lineOptions);
}
The above code helps from the app from not crashing, but it still is not helping me to draw the route between those points.
The retrieved data are correct, I checked that with the toast.
I review your code and found some issue where causes of crash, first of all you had initialize null ArrayList<LatLng>points=null and PolylineOptions lineOptions=null so what if path is null then lineOptions too null, thus i fix that line review below code apply it run it, if success Enjoy!
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = new ArrayList<LatLng>();;
PolylineOptions lineOptions = new PolylineOptions();;
lineOptions.width(2);
lineOptions.color(Color.RED);
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
}
// Drawing polyline in the Google Map for the i-th route
if(points.size()!=0)mMap.addPolyline(lineOptions);//to avoid crash
}
Why you are you initializing ArrayList,PolylineOption under for loop it will create new instance as many time for loop runs so try to fix these and add two mMap.moveCamera(CameraUpdateFactory.newLatLng(position));
mMap.animateCamera(CameraUpdateFactory.zoomTo(10));
ArrayList<LatLng> points = new ArrayList<LatLng>();
PolylineOptions lineOptions = new PolylineOptions();;
MarkerOptions markerOptions = new MarkerOptions();
LatLng position = null;
// Traversing through all the routes
for(int i=0;i<result.size();i++){
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
mMap.moveCamera(CameraUpdateFactory.newLatLng(position));
mMap.animateCamera(CameraUpdateFactory.zoomTo(10));
lineOptions.addAll(points);
lineOptions.width(2);
lineOptions.color(Color.RED);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
you can avoid crash by simply adding this line in protected void onPostExecute(List>> result) method
enter code here
if(points)!=null {
mMap.addPolyline(lineOptions);
}
But because of error in your call to direction API it is returning null value to points. Check wether direction api is enabled correctly
TRY THIS!!!
1. In any case you should add a check to see if polyLineOptions is null before using it
if (polyLineOptions != null){
googleMap.addPolyline(polyLineOptions);
}
It will prevent from Crash
2. To make a route draw Add your API KEY at end of the getDirectionsUrl like,
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters +"&key=" +"YOUR KEY";
Please You must enable Billing on the Google Cloud Project at https://console.cloud.google.com/project/_/billing/enable
Related
I have one fragment as below
public class WantToTrack extends Fragment {
// Code are here to set the view.
//Layout name file is - want_to_track
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
MapShowFragment f1 = new MapShowFragment();
fragmentTransaction.replace(R.id.map, f1);
fragmentTransaction.commit();
}
My Layout file(want_to_track) is as below:
<?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:background="#color/back_ground_clr"
android:layout_marginTop="10dip"
>
<TextView
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/text_clr_for_back_ground"
android:gravity="center"
android:textSize="#dimen/header_text_size"
android:textStyle="bold"
android:text="WANT TO TRACK" />
<EditText
android:id="#+id/child_mail_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginTop="60dp"
android:textColorHint="#color/text_clr_for_back_ground"
android:inputType="textPersonName"
android:hint="Email ID Whom you want to track" />
<Button
android:id="#+id/sbmit_child_mail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignTop="#+id/editText4"
android:layout_marginEnd="18dp"
android:background="#color/btn_login_bg"
android:textColor="#color/btn_login"
android:text="Go" />
<ListView
android:id="#+id/listview"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="11dp"
android:layout_marginTop="126dp" />
<FrameLayout
android:id="#+id/map"
android:layout_below="#+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
As by above mentioned code, I am trying to call dynamic fragment which will show Map. But map is not showing.My class
MapShowFragment
is as below
public class MapShowFragment extends Fragment implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
ArrayList<LatLng> MarkerPoints;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
List<Double> listOfLatitude,listOfLongitude;
public View onCreateView(LayoutInflater inflater, ViewGroup vg, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.map_show, vg, false);
addItem();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// Initializing
MarkerPoints = new ArrayList<>();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
MapFragment mapFragment = (MapFragment) getChildFragmentManager()
.findFragmentById(R.id.mapgoogle);
mapFragment.getMapAsync(this);
return v;
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
for(int i = 0; i<listOfLongitude.size();i++){
mapDraw(i);
try {
Thread.sleep(200);
} catch (Exception e){
e.printStackTrace();
}
}
// Setting onclick event listener for the map
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
}
});
}
private String getUrl(LatLng origin, LatLng dest) {
// Origin of route
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
// Destination of route
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin + "&" + str_dest + "&" + sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;
return url;
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
Log.d("downloadUrl", data.toString());
br.close();
} catch (Exception e) {
Log.d("Exception", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class FetchUrl extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try {
// Fetching the data from web service
data = downloadUrl(url[0]);
Log.d("Background Task data", data.toString());
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
Log.d("ParserTask",jsonData[0].toString());
DataParser parser = new DataParser();
Log.d("ParserTask", parser.toString());
// Starts parsing data
routes = parser.parse(jObject);
Log.d("ParserTask","Executing routes");
Log.d("ParserTask",routes.toString());
} catch (Exception e) {
Log.d("ParserTask",e.toString());
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points;
PolylineOptions lineOptions = null;
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(10);
lineOptions.color(Color.RED);
Log.d("onPostExecute","onPostExecute lineoptions decoded");
}
// Drawing polyline in the Google Map for the i-th route
if(lineOptions != null) {
mMap.addPolyline(lineOptions);
}
else {
Log.d("onPostExecute","without Polylines drawn");
}
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(getActivity(), "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other permissions this app might request.
// You can add here other case statements according to your requirement.
}
}
void addItem(){
listOfLatitude = new ArrayList<>();
listOfLongitude = new ArrayList<>();
listOfLatitude.add(12.9177); // Silk Board
listOfLatitude.add(12.9255); // Banshankri
listOfLatitude.add(13.0350); // Nagwara
listOfLongitude.add(77.6233); // Silk Board
listOfLongitude.add(77.5468); // Banshankri
listOfLongitude.add(77.6235); // Nagwara
}
void mapDraw(int i){
// Already two locations
LatLng point = new LatLng(listOfLatitude.get(i), listOfLongitude.get(i));
/* if (MarkerPoints.size() > 1) {
MarkerPoints.clear();
mMap.clear();
}*/
// Adding new item to the ArrayList
MarkerPoints.add(point);
// Creating MarkerOptions
MarkerOptions options = new MarkerOptions();
// Setting the position of the marker
options.position(point);
/**
* For the start location, the color of marker is GREEN and
* for the end location, the color of marker is RED.
*/
if (MarkerPoints.size() == 1) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
} else if (MarkerPoints.size() == 2) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}else if (MarkerPoints.size() == 3) {
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
// Add new marker to the Google Map Android API V2
mMap.addMarker(options);
// Checks, whether start and end locations are captured
if (MarkerPoints.size() >= 2) {
if(MarkerPoints.size()<=i+1) {
LatLng origin = MarkerPoints.get(i-1);
LatLng dest = MarkerPoints.get(i);
// Getting URL to the Google Directions API
String url = getUrl(origin, dest);
Log.d("onMapClick", url.toString());
FetchUrl FetchUrl = new FetchUrl();
// Start downloading json data from Google Directions API
FetchUrl.execute(url);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(origin));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
}
}
}
Even i have used correct API key which is generated from Google console. In below image map should come on red rectangle but its not populating.
I tried to track my issue through Log-cat but i am not able to find any trace which could help me.
I'm trying to implement an simple navigation app using Google maps. Initially I developed a code for marking two Geo points on map and showing route between them. Now I am trying to move the first marker towards second marker (destination) based on users location.
My first marker is the device's location and the second is fetched from db through api.
For this I used LocationListener and implemented code in onLocationChanged. The problem is onLocationChanged is not getting fired and marker is not moving based on user location.Marker moves only on loading the app every single time.
Here is my code.
public class MainActivity extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleMap mMap;
ArrayList<LatLng> MarkerPoints = new ArrayList<>();
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker1,mCurrLocationMarker2;
LocationRequest mLocationRequest;
FrameLayout mainFrameLayout;
Snackbar snackbar;
private static final int PERMISSIONS_REQUEST_READ_PHONE_STATE = 1;
String stringIMEI = "",stringLatitudeOrigin = "",stringLongitudeOrigin = "",
stringLatitudeDest = "",stringLongitudeDest = "",stringCurrentDate = "";
SharedPreferences sharedPreferences;
#TargetApi(Build.VERSION_CODES.N)
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
sharedPreferences = getSharedPreferences("sharedPreferences", Context.MODE_PRIVATE);
Calendar c = Calendar.getInstance();
System.out.println("Current time => "+c.getTime());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
stringCurrentDate = df.format(c.getTime());
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(map);
mapFragment.getMapAsync(this);
mainFrameLayout = (FrameLayout)findViewById(R.id.mainFrameLayout);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
if (ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.READ_PHONE_STATE},
PERMISSIONS_REQUEST_READ_PHONE_STATE);
}else {
TelephonyManager mngr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
stringIMEI = mngr.getDeviceId().toString();
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
if (checkLocationPermission()) {
mMap.setMyLocationEnabled(true);
mMap.setTrafficEnabled(false);
mMap.setIndoorEnabled(false);
mMap.setBuildingsEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(mMap.getCameraPosition().target).zoom(17).bearing(30).tilt(45).build()));
}
}
private String getUrl(LatLng origin, LatLng dest) {
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
String key = "key=AIzaSyDkuXKvLCxtKs1jkXRXyt5Kk1Qv3fUe7mU";
String parameters = str_origin + "&" + str_dest + "&" + key;//+ waypoints + "&"
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;
return url;
}
private class FetchUrl extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
// TODO Auto-generated method stub
String data = "";
try {
HttpConnection http = new HttpConnection();
data = http.downloadUrl(url[0]);
} catch (Exception e) {
// TODO: handle exception
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
new ParserTask().execute(result);
}
}
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(
String... jsonData) {
// TODO Auto-generated method stub
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
if (!jObject.equals("")){
//save route api call
SaveRouteVolleyRequest(jObject.toString());
}
DirectionsJSONParser parser = new DirectionsJSONParser();
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = new ArrayList<LatLng>();
PolylineOptions lineOptions = new PolylineOptions();
lineOptions.width(8);
lineOptions.color(Color.RED);
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
}
// Drawing polyline in the Google Map for the i-th route
if(points.size()!=0)mMap.addPolyline(lineOptions);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setExpirationDuration(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setSmallestDisplacement(0.1f);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) { }
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
mMap.clear();
if (mCurrLocationMarker1 != null) {
mCurrLocationMarker1.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
stringLatitudeOrigin = String.valueOf(location.getLatitude());
stringLongitudeOrigin = String.valueOf(location.getLongitude());
mCurrLocationMarker1 = mMap.addMarker(new MarkerOptions().position(latLng).title("Your device").draggable(true)
.visible(true).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker)).anchor(0.5f, 0.5f));
if (isConnectingToInternet(MainActivity.this) == true) {
GetLocationVolleyRequest();
}else{snackbar = Snackbar.make(mainFrameLayout, "No Internet Connection,Please Verify", Snackbar.LENGTH_LONG);
snackbar.show();
}
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,13.0f));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) { }
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
mMap.setTrafficEnabled(false);
mMap.setIndoorEnabled(false);
mMap.setBuildingsEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(mMap.getCameraPosition().target).zoom(17).bearing(30).tilt(45).build()));
}
}else {
snackbar = Snackbar.make(mainFrameLayout, "permission denied", Snackbar.LENGTH_LONG);
snackbar.show();
}
return;
}
case PERMISSIONS_REQUEST_READ_PHONE_STATE : {
if (requestCode == PERMISSIONS_REQUEST_READ_PHONE_STATE
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
TelephonyManager mngr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
stringIMEI = mngr.getDeviceId().toString();
}else {
snackbar = Snackbar.make(mainFrameLayout, "permission denied", Snackbar.LENGTH_LONG);
snackbar.show();
}
}
}
}
public void GetLocationVolleyRequest(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.LOCATIONAPI_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject json = new JSONObject(response);
if (json.getString("success").equals("1")) {
if (json.has("id")) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("device_id", json.getString("id"));
editor.commit();
}else {
snackbar = Snackbar.make(mainFrameLayout, json.getString("msg"), Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
}
if (json.has("latitude")) {
stringLatitudeDest = json.getString("latitude");
stringLongitudeDest = json.getString("longitude");
snackbar = Snackbar.make(mainFrameLayout, "Other Device -> Lat : " + stringLatitudeDest + " Lng : " +
stringLongitudeDest, Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
mCurrLocationMarker2 = mMap.addMarker(new MarkerOptions().position(new LatLng(Double.parseDouble(stringLatitudeDest),
Double.parseDouble(stringLongitudeDest))).title("Other device").icon(BitmapDescriptorFactory.fromResource(R.drawable.marker)));
MarkerPoints.add(new LatLng(Double.parseDouble(stringLatitudeOrigin), Double.parseDouble(stringLongitudeOrigin)));
MarkerPoints.add(new LatLng(Double.parseDouble(stringLatitudeDest), Double.parseDouble(stringLongitudeDest)));
if (MarkerPoints.size() >= 2) {
LatLng origin = MarkerPoints.get(0);
LatLng dest = MarkerPoints.get(1);
// Getting URL to the Google Directions API
String url = getUrl(origin, dest);
Log.d("onMapClick", url.toString());
FetchUrl fetchUrl = new FetchUrl();
// Start downloading json data from Google Directions API
fetchUrl.execute(url);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(origin, 14.0f));
}
}
}else {
snackbar = Snackbar.make(mainFrameLayout, "No Co-ordinates due to"+json.getString("msg"), Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
}
}catch (JSONException je){
je.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
snackbar = Snackbar.make(mainFrameLayout, error.toString(), Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
}
}){
#Override
protected Map<String,String> getParams(){
String stringDeviceModel = Build.MODEL;
String stringDeviceSeries = Build.SERIAL;
String stringDeviceOS = Build.VERSION.RELEASE;
Map<String,String> params = new HashMap<String, String>();
params.put("imei",stringIMEI);
params.put("model",stringDeviceModel);
params.put("series",stringDeviceSeries);
params.put("os",stringDeviceOS);
params.put("latitude",stringLatitudeOrigin);
params.put("longitude",stringLongitudeOrigin);
params.put("datetime",stringCurrentDate);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
public void SaveRouteVolleyRequest(String route){
final String paramRoute = route;
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.SAVEROUTEAPI_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject json = new JSONObject(response);
if (json.getString("success").equals("1")) {
snackbar = Snackbar.make(mainFrameLayout, json.getString("msg"), Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
}else {
snackbar = Snackbar.make(mainFrameLayout,"No Co-ordinates due to"+json.getString("msg"), Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
}
}catch (JSONException je){
je.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
snackbar = Snackbar.make(mainFrameLayout, error.toString(), Snackbar.LENGTH_LONG);
snackbar.getView().setBackgroundColor(R.color.colorPrimaryDark);
TextView mainTextView = (TextView) (snackbar.getView()).findViewById(android.support.design.R.id.snackbar_text);
mainTextView.setTextColor(Color.WHITE);
snackbar.show();
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
params.put("device_id",sharedPreferences.getString("device_id",""));
params.put("route",paramRoute);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
public boolean isConnectingToInternet(Context context){
ConnectivityManager connectivity=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo info[]=connectivity.getAllNetworkInfo();
if(info!=null)
{
for(int i=0;i<info.length;i++)
if(info[i].getState()== NetworkInfo.State.CONNECTED)
return true;
}
}
return false;
}
}
The problem is
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
in your onLocationChanged method.
You are removing location updates the moment you get your first location update as mGoogleApiClient != null is true.
Move the removeLocationUpdates to your onDestroy block and everything should work.
I've been following this tutorial on displaying nearby places, in my case I need nearby hospitals. I'm able to show my current location and display nearby hospitals. But what I want to do is add the telephone number of those hospitals being displayed. I've tried adding formatted_phone_number in my code but it doesn't display the correct phone number but instead displays "-NA-" which is the default in the event that there's no number available.
Any help would be greatly appreciated thanks!
Code Snippet of GetNearbyPlacesData class:
private void ShowNearbyPlaces(List<HashMap<String, String>> nearbyPlacesList) {
for (int i = 0; i < nearbyPlacesList.size(); i++) {
Log.d("onPostExecute","Entered into showing locations");
MarkerOptions markerOptions = new MarkerOptions();
HashMap<String, String> googlePlace = nearbyPlacesList.get(i);
double lat = Double.parseDouble(googlePlace.get("lat"));
double lng = Double.parseDouble(googlePlace.get("lng"));
String placeName = googlePlace.get("place_name");
String vicinity = googlePlace.get("vicinity");
String formatted_phone_number = googlePlace.get("formatted_phone_number");
LatLng latLng = new LatLng(lat, lng);
markerOptions.position(latLng);
markerOptions.title(placeName + " : " + vicinity);
markerOptions.snippet(vicinity + formatted_phone_number);
mMap.addMarker(markerOptions);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
}
DataParser class:
public class DataParser {
public List<HashMap<String, String>> parse(String jsonData) {
JSONArray jsonArray = null;
JSONObject jsonObject;
try {
Log.d("Places", "parse");
jsonObject = new JSONObject((String) jsonData);
jsonArray = jsonObject.getJSONArray("results");
} catch (JSONException e) {
Log.d("Places", "parse error");
e.printStackTrace();
}
return getPlaces(jsonArray);
}
private List<HashMap<String, String>> getPlaces(JSONArray jsonArray) {
int placesCount = jsonArray.length();
List<HashMap<String, String>> placesList = new ArrayList<>();
HashMap<String, String> placeMap = null;
Log.d("Places", "getPlaces");
for (int i = 0; i < placesCount; i++) {
try {
placeMap = getPlace((JSONObject) jsonArray.get(i));
placesList.add(placeMap);
Log.d("Places", "Adding places");
} catch (JSONException e) {
Log.d("Places", "Error in Adding places");
e.printStackTrace();
}
}
return placesList;
}
private HashMap<String, String> getPlace(JSONObject googlePlaceJson) {
HashMap<String, String> googlePlaceMap = new HashMap<String, String>();
String placeName = "-NA-";
String vicinity = "-NA-";
String formatted_phone_number = "-NA-";
String latitude = "";
String longitude = "";
String reference = "";
Log.d("getPlace", "Entered");
try {
if (!googlePlaceJson.isNull("name")) {
placeName = googlePlaceJson.getString("name");
}
if (!googlePlaceJson.isNull("vicinity")) {
vicinity = googlePlaceJson.getString("vicinity");
}
if (!googlePlaceJson.isNull("formatted_phone_number")) {
formatted_phone_number = googlePlaceJson.getString("formatted_phone_number");
}
latitude = googlePlaceJson.getJSONObject("geometry").getJSONObject("location").getString("lat");
longitude = googlePlaceJson.getJSONObject("geometry").getJSONObject("location").getString("lng");
reference = googlePlaceJson.getString("reference");
googlePlaceMap.put("place_name", placeName);
googlePlaceMap.put("vicinity", vicinity);
googlePlaceMap.put("formatted_phone_number", formatted_phone_number);
googlePlaceMap.put("lat", latitude);
googlePlaceMap.put("lng", longitude);
googlePlaceMap.put("reference", reference);
Log.d("getPlace", "Putting Places");
} catch (JSONException e) {
Log.d("getPlace", "Error");
e.printStackTrace();
}
return googlePlaceMap;
}
}
MapsActivity class:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
double latitude;
double longitude;
private int PROXIMITY_RADIUS = 20000;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
//Check if Google Play Services Available or not
if (!CheckGooglePlayServices()) {
Log.d("onCreate", "Finishing test case since Google Play Services are not available");
finish();
}
else {
Log.d("onCreate","Google Play Services available.");
}
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
private boolean CheckGooglePlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result = googleAPI.isGooglePlayServicesAvailable(this);
if(result != ConnectionResult.SUCCESS) {
if(googleAPI.isUserResolvableError(result)) {
googleAPI.getErrorDialog(this, result,
0).show();
}
return false;
}
return true;
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
Button btnHospital = (Button) findViewById(R.id.btnHospital);
btnHospital.setOnClickListener(new View.OnClickListener() {
String Hospital = "hospital";
#Override
public void onClick(View v) {
Log.d("onClick", "Button is Clicked");
mMap.clear();
String url = getUrl(latitude, longitude, Hospital);
Object[] DataTransfer = new Object[2];
DataTransfer[0] = mMap;
DataTransfer[1] = url;
Log.d("onClick", url);
GetNearbyPlacesData getNearbyPlacesData = new GetNearbyPlacesData();
getNearbyPlacesData.execute(DataTransfer);
Toast.makeText(MapsActivity.this,"Nearby Hospitals", Toast.LENGTH_LONG).show();
}
});
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
private String getUrl(double latitude, double longitude, String nearbyPlace) {
StringBuilder googlePlacesUrl = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
googlePlacesUrl.append("location=" + latitude + "," + longitude);
googlePlacesUrl.append("&radius=" + PROXIMITY_RADIUS);
googlePlacesUrl.append("&type=" + nearbyPlace);
googlePlacesUrl.append("&sensor=true");
googlePlacesUrl.append("&key=" + "AIzaSyATuUiZUkEc_UgHuqsBJa1oqaODI-3mLs0"); //dito yung api key nasa sticky note
Log.d("getUrl", googlePlacesUrl.toString());
return (googlePlacesUrl.toString());
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
Log.d("onLocationChanged", "entered");
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
latitude = location.getLatitude();
longitude = location.getLongitude();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
Toast.makeText(MapsActivity.this,"Your Current Location", Toast.LENGTH_LONG).show();
Log.d("onLocationChanged", String.format("latitude:%.3f longitude:%.3f",latitude,longitude));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
Log.d("onLocationChanged", "Removing Location Updates");
}
Log.d("onLocationChanged", "Exit");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other permissions this app might request.
// You can add here other case statements according to your requirement.
}
}
}
In MapsActivity.class, function getUrl() is taking "Hospital" as one of the arguments which is not in the list of supported types. So, the result type is default, since it doesn't match any supported types.
The response will give you all the places nearby search request for places of type 'default'. To make a request to Nearby Places API to get nearby hospitals, pass hospital instead of Hospital.
In the code, you make a request to Nearby Places API, formatted_phone_number is not returned in response. For more information, refer to the documentation.
To get the phone number(formatted_phone_number or international_phone_number) make a request to Place Details API with the PlaceId.
To get more clarity, enter the url in the browser and look at the response.
Hope this helps you. Good luck :)
I got the correct souce and destination latitude and longitude in map but I am able to drwa line between Source and destination but this line is strait line display in map between source and destination marker. Destination Latitide and Destination Longitude are fetch successfully from Server.
But I want to Draw line between source and destination Like this below.
This is Example.
Google Map is also Display CurrectPosition of Source and Destination.
How can it Possible?
Please Guide me.
Please Help me.
Thank you.
My Code is,
public class Map extends FragmentActivity {
GoogleMap googleMap;
SupportMapFragment fm;
double myLat = 23.0137759;
double destLat = 0.0;
double myLng = 72.5158836;
double destLng = 0.0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigate_to_me_map);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Intent intent = getIntent();
destLat = intent.getDoubleExtra("latitude", 0.0);
destLng = intent.getDoubleExtra("longitude", 0.0);
int status = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getBaseContext());
// Showing status
if (status != ConnectionResult.SUCCESS) { // Google Play Services
int requestCode = 10;
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status,
this, requestCode);
dialog.show();
} else {
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.fullmap);
googleMap = supportMapFragment.getMap();
googleMap.setMyLocationEnabled(true);
}
googleMap
.setOnMyLocationChangeListener(new OnMyLocationChangeListener() {
public void onMyLocationChange(Location location) {
// TODO Auto-generated method stub
myLat = location.getLatitude();
myLng = location.getLongitude();
}
});
drawRoutePath(strAddressOne);
}
}
private void drawRoutePath(String searchText) {
try {
// find current address latlong and true than draw route
// between to points or current loction and search
// address
googleMap.clear();
if (myLat != 0 && myLng != 0) {
LatLng origin = new LatLng(myLat, myLng);
drawMarker(origin);
LatLng dest = new LatLng(destLat, destLng);
drawMarker(dest);
Polyline line = googleMap.addPolyline(new PolylineOptions()
.add(origin, dest).width(5).color(Color.RED));
} else {
Toast.makeText(getApplicationContext(),
"Current Location does not found",
Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
// TODO: handle exception
Log.e("Second ", "drawRoutePath errro " + e.toString());
}
}
private void drawMarker(LatLng point) {
// Creating an instance of MarkerOptions
MarkerOptions markerOptions = new MarkerOptions();
// Setting latitude and longitude for the marker
markerOptions.position(point);
// Adding marker on the Google Map
googleMap.addMarker(new MarkerOptions().position(point).visible(true))
.showInfoWindow();
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(
point.latitude, point.longitude), 6f));
}
}
Here's the source code to draw a route between the source and destination :
public class MapActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private SupportMapFragment mapFragment;
private GoogleMap map;
private GoogleApiClient mGoogleApiClient;
ArrayList markerPoints;
private LocationRequest mLocationRequest;
private long UPDATE_INTERVAL = 15000; /* 15 secs */
private long FASTEST_INTERVAL = 5000; /* 5 secs */
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
// Marker marker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isGooglePlayServicesAvailable()) {
finish();
}
setContentView(R.layout.activity_map);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setDisplayShowCustomEnabled(true);
getSupportActionBar().setCustomView(R.layout.custom_actionbar_maps);
markerPoints = new ArrayList();
mapFragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
if (mapFragment != null) {
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap map) {
loadMap(map);
}
});
} else {
Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show();
}
}
protected void loadMap(GoogleMap googleMap) {
map = googleMap;
if (map != null) {
// Map is ready
Toast.makeText(this, "Map Fragment was loaded properly!", Toast.LENGTH_SHORT).show();
map.setMyLocationEnabled(true);
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
// Already two locations
if(markerPoints.size()>1){
markerPoints.clear();
map.clear();
}
// Adding new item to the ArrayList
markerPoints.add(point);
// Creating MarkerOptions
MarkerOptions options = new MarkerOptions();
// Setting the position of the marker
options.position(point);
/**
* For the start location, the color of marker is GREEN and
* for the end location, the color of marker is RED.
*/
if(markerPoints.size()==1){
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}else if(markerPoints.size()==2){
options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
// Add new marker to the Google Map Android API V2
map.addMarker(options);
// Checks, whether start and end locations are captured
if(markerPoints.size() >= 2){
LatLng origin = (LatLng) markerPoints.get(0);
LatLng dest = (LatLng) markerPoints.get(1);
// Getting URL to the Google Directions API
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
}
}
});
// Now that map has loaded, let's get our location!
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
connectClient();
} else {
Toast.makeText(this, "Error - Map was null!!", Toast.LENGTH_SHORT).show();
}
}
protected void connectClient() {
// Connect the client.
if (isGooglePlayServicesAvailable() && mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
/*
* Called when the Activity becomes visible.
*/
#Override
protected void onStart() {
super.onStart();
connectClient();
}
/*
* Called when the Activity is no longer visible.
*/
#Override
protected void onStop() {
// Disconnecting the client invalidates it.
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onStop();
}
/*
* Handle results returned to the FragmentActivity by Google Play services
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Decide what to do based on the original request code
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST:
/*
* If the result code is Activity.RESULT_OK, try to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK:
mGoogleApiClient.connect();
break;
}
}
}
// Fetches data from url passed
private boolean isGooglePlayServicesAvailable() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d("Location Updates", "Google Play services is available.");
return true;
} else {
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment for the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(errorDialog);
errorFragment.show(getSupportFragmentManager(), "Location Updates");
}
return false;
}
}
/*
* Called by Location Services when the request to connect the client
* finishes successfully. At this point, you can request the current
* location or start periodic updates
*/
#Override
public void onConnected(Bundle dataBundle) {
// Display the connection status
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location != null) {
Toast.makeText(this, "GPS location was found!", Toast.LENGTH_SHORT).show();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
map.animateCamera(cameraUpdate);
//marker = map.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.vehicle_marker)).flat(true).anchor(0.5f,0.5f));
startLocationUpdates();
} else {
Toast.makeText(this, "Current location was null, enable GPS on emulator!", Toast.LENGTH_SHORT).show();
}
}
protected void startLocationUpdates() {
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
}
public void onLocationChanged(Location location) {
// Report to the UI that the location was updated
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
/* if(marker == null){
*//* marker.remove();*//*
marker = map.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.vehicle_marker)));
}
marker.setPosition(latLng);
*/
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16);
map.animateCamera(cameraUpdate);
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the connection to the location client
* drops because of an error.
*/
#Override
public void onConnectionSuspended(int i) {
if (i == CAUSE_SERVICE_DISCONNECTED) {
Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
} else if (i == CAUSE_NETWORK_LOST) {
Toast.makeText(this, "Network lost. Please re-connect.", Toast.LENGTH_SHORT).show();
}
}
/*
* Called by Location Services if the attempt to Location Services fails.
*/
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects. If the error
* has a resolution, try sending an Intent to start a Google Play
* services activity that can resolve error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(),
"Sorry. Location services not available to you", Toast.LENGTH_LONG).show();
}
}
// Define a DialogFragment that displays the error dialog
public static class ErrorDialogFragment extends DialogFragment {
// Global field to contain the error dialog
private Dialog mDialog;
// Default constructor. Sets the dialog field to null
public ErrorDialogFragment() {
super();
mDialog = null;
}
// Set the dialog to display
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
// Return a Dialog to the DialogFragment.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String>{
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> >{
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try{
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
}catch(Exception e){
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
points = new ArrayList();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j <path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(12);
lineOptions.color(Color.RED);
lineOptions.geodesic(true);
}
// Drawing polyline in the Google Map for the i-th route
map.addPolyline(lineOptions);
}
}
private String getDirectionsUrl(LatLng origin,LatLng dest){
// Origin of route
String str_origin = "origin="+origin.latitude+","+origin.longitude;
// Destination of route
String str_dest = "destination="+dest.latitude+","+dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin+"&"+str_dest+"&"+sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
return url;
}
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
}
DirectionsJSONParser.java is given below :
import com.google.android.gms.maps.model.LatLng;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DirectionsJSONParser {
/** Receives a JSONObject and returns a list of lists containing latitude and longitude */
public List<List<HashMap<String,String>>> parse(JSONObject jObject){
List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>() ;
JSONArray jRoutes = null;
JSONArray jLegs = null;
JSONArray jSteps = null;
try {
jRoutes = jObject.getJSONArray("routes");
/** Traversing all routes */
for(int i=0;i<jRoutes.length();i++){
jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
List path = new ArrayList<HashMap<String, String>>();
/** Traversing all legs */
for(int j=0;j<jLegs.length();j++){
jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");
/** Traversing all steps */
for(int k=0;k<jSteps.length();k++){
String polyline = "";
polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
List list = decodePoly(polyline);
/** Traversing all points */
for(int l=0;l <list.size();l++){
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) );
hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) );
path.add(hm);
}
}
routes.add(path);
}
}
} catch (JSONException e) {
e.printStackTrace();
}catch (Exception e){
}
return routes;
}
/**
* Method to decode polyline points
* Courtesy : http://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
* */
private List decodePoly(String encoded) {
List poly = new ArrayList();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
}
You can use below library:
Google-Directions-Android
According to the sample app that finds the user location it is a good idea to listen for location changes in the activity:
class MyActivity extends Activity implements LocationListener {
#Inject
private LocationManager locationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
#Override
public void onLocationChanged(Location location) {
// do something with location
}
// ...
}
However, I'm not sure about that. When there is a configuration change, my activity gets destroyed and recreated, registering itself as listener next time. The reference to the old Activity is held in the LocationManager, isn't it?
If I extract the LocationListener to separate object, still I have the problem of how to notify the current activity about new location (not necessarily the same as the requesting activity).
Is there any common pattern to solve this?
In this example you have also another problem: your GPS listener will work always and will drain battery.
The better practice is:
1) register LocationListener into Activity's onStart()
2) remove LocationListener into Activity's onStop()
This will fix both problems.
If you need that your app track user position in background (for example, GPS tracker) use Service (http://developer.android.com/reference/android/app/Service.html)
I had memory leaks using all these suggestions. I got them to stop by applying this method at the point I didn't need the Listener anymore, to onDestroy, and onStop. I also added it to onPause, but you'll have to decide if this is best for your application.
private void stopLocationListener() {
if (locationManager !=null) locationManager.removeUpdates(locationListener);
if (locationManager !=null) locationManager =null;
if (locationListener !=null) locationListener =null;
}
You can make a separate class to do the same and then implement the LocationListenerFinder.onLocationChanged interface to your activity
Now you won't face the leak problem.
public class LocationListenerFinder implements LocationListener {
onLocationChanged onLocationChanged;
public LocationListenerFinder(Context context) {
onLocationChanged = (LocationListenerFinder.onLocationChanged) context;
}
#Override
public void onLocationChanged(Location location) {
onLocationChanged.onLocationChanged(location);
onLocationChanged = null;
}
public interface onLocationChanged {
void onLocationChanged(Location location);
}
}
In my case activity was this... you can refer the same and can convert as per your need.
public class ActivityMapNearByPlace extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListenerFinder.onLocationChanged {
private GoogleMap mMap;
ArrayList<LatLng> listMarkerPoints;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
private boolean locationPermission;
private ArrayList<NearByPlaces> listNearByFacility;
private int facilityPosition, locationPosition;
private ImageView ivBack, ivMyLocation;
private TextView tvPlaceOriginName, tvPlaceDestinationName, tvPlaceKmDistance, tvPlaceTime;
private TableRow trPlaceTimeKm;
private Marker currentSelectedMarker;
private Map<Integer, Map<String, Object>> mapDistancePathData;
private Polyline polyline;
private boolean flagCalculatingPath = false;
private FetchUrl fetchUrl;
private SupportMapFragment mapFragment;
private LocationListenerFinder locationListenerFinder;
//private WeakLocationListener locationListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_near_by_place);
initView();
initListener();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
} else {
locationPermission = true;
}
// Initializing
listMarkerPoints = new ArrayList<>();
getBundleData();
listNearByFacility.get(0).getNearBy();
LatLng origin = new LatLng(Double.valueOf(listNearByFacility.get(0).getGeoLocLat()), Double.valueOf(listNearByFacility.get(0).getGeoLocLong()));
listMarkerPoints.add(origin);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
protected void onRestart() {
super.onRestart();
//if (mGoogleApiClient != null) mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
//if (mGoogleApiClient != null) mGoogleApiClient.disconnect();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListenerFinder);
mGoogleApiClient.disconnect();
mGoogleApiClient.unregisterConnectionCallbacks(this);
mGoogleApiClient.unregisterConnectionFailedListener(this);
// locationListener.clearData();
locationListenerFinder = null;
}
mGoogleApiClient = null;
fetchUrl.cancel(true);
if (mMap != null) mMap.setMyLocationEnabled(false);
//if (mapFragment != null) mapFragment.onDestroy();
}
#Override
public void onBackPressed() {
finish();
}
private void initListener() {
ivBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ivMyLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mCurrLocationMarker.getTag() != null && !flagCalculatingPath) {
locationPosition = (int) mCurrLocationMarker.getTag();
if (mapDistancePathData.get(locationPosition) != null) {
if (polyline != null) {
polyline.remove();
}
Map<String, Object> hashMapDistancePathInfo = mapDistancePathData.get(locationPosition);
setPathInfo((String) hashMapDistancePathInfo.get("duration"), (String) hashMapDistancePathInfo.get("distance"), (PolylineOptions) hashMapDistancePathInfo.get("polyLineOptions"), "Current Location");
trPlaceTimeKm.setVisibility(View.VISIBLE);
} else {
Locations locations = new Locations();
locations.setName("Current Location");
locations.setLatitude(String.valueOf(mLastLocation.getLatitude()));
locations.setLongitude(String.valueOf(mLastLocation.getLongitude()));
findDistanceAndMarkDirection(locations);
}
}
//mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
//mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
});
}
private void initView() {
ivBack = (ImageView) findViewById(R.id.iv_back_btn);
ivMyLocation = (ImageView) findViewById(R.id.iv_my_location);
tvPlaceOriginName = (TextView) findViewById(R.id.tv_near_by_place_origin);
tvPlaceDestinationName = (TextView) findViewById(R.id.tv_near_by_place_destination);
tvPlaceKmDistance = (TextView) findViewById(R.id.tv_near_by_place_km);
tvPlaceTime = (TextView) findViewById(R.id.tv_near_by_place_time);
trPlaceTimeKm = (TableRow) findViewById(R.id.tr_near_by_place_km_time);
}
private void getBundleData() {
listNearByFacility = (ArrayList<NearByPlaces>) getIntent().getBundleExtra("nearByLocationBundle").getSerializable("nearByLocationData");
facilityPosition = getIntent().getIntExtra("facilityPosition", 0);
locationPosition = getIntent().getIntExtra("locationPosition", 0);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
//Initialize Google Play Services
if (locationPermission) {
buildGoogleApiClient();
checkLocationStatus();
//mMap.setMyLocationEnabled(true);
loadMap();
}
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
if (marker.getTag() != null && !flagCalculatingPath) {
locationPosition = (int) marker.getTag();
if (mapDistancePathData.get(locationPosition) != null) {
if (polyline != null) {
polyline.remove();
}
Map<String, Object> hashMapDistancePathInfo = mapDistancePathData.get(locationPosition);
setPathInfo((String) hashMapDistancePathInfo.get("duration"), (String) hashMapDistancePathInfo.get("distance"), (PolylineOptions) hashMapDistancePathInfo.get("polyLineOptions"), listNearByFacility.get(0).getNearBy().get(facilityPosition).getLocations().get(locationPosition).getName());
trPlaceTimeKm.setVisibility(View.VISIBLE);
} else {
findDistanceAndMarkDirection(listNearByFacility.get(0).getNearBy().get(facilityPosition).getLocations().get(locationPosition));
}
}
return false;
}
});
mMap.getUiSettings().setMyLocationButtonEnabled(false);
mMap.getUiSettings().setRotateGesturesEnabled(false);
}
private void loadMap() {
NearByPlaces originLocation = listNearByFacility.get(0);
if (listMarkerPoints.size() > 1) {
mMap.clear();
listMarkerPoints.remove(1);
}
// Adding new item to the ArrayList
NearBy nearBy = listNearByFacility.get(0).getNearBy().get(facilityPosition);
tvPlaceOriginName.setText(originLocation.getProjectName());
//tvPlaceDestinationName.setText(nearBy.getLocations().get(locationPosition).getName());
if (mapDistancePathData == null) {
mapDistancePathData = new HashMap<>();
}
// .get(locationPosition);
// LatLng destination = new LatLng(Double.valueOf(location.getLatitude()), Double.valueOf(location.getLongitude()));
//listMarkerPoints.add(destination);
MarkerOptions options = new MarkerOptions();
options.position(listMarkerPoints.get(0));
options.icon(BitmapDescriptorFactory.fromBitmap(getBitmapMarker(originLocation.getProjectName(), R.drawable.ic_marker_red)));
//options.title(originLocation.getProjectName());
mMap.addMarker(options).showInfoWindow();
for (int position = 0; position < nearBy.getLocations().size(); position++) {
Locations locations = nearBy.getLocations().get(position);
// Creating MarkerOptions
options = new MarkerOptions();
LatLng markerPosition = new LatLng(Double.valueOf(locations.getLatitude()), Double.valueOf(locations.getLongitude()));
// Setting the videoPlayPosition of the marker
options.position(markerPosition);
/**
* For the start location, the color of marker is GREEN and
* for the end location, the color of marker is RED.
*/
options.icon(BitmapDescriptorFactory.fromBitmap(getBitmapMarker(locations.getName(), 0)));
//options.title(locationRanges.getName());
// Add new marker to the Google Map Android API V2
Marker marker = mMap.addMarker(options);
// marker.showInfoWindow();
marker.setTag(position);
}
findDistanceAndMarkDirection(nearBy.getLocations().get(locationPosition));
}
public Bitmap getBitmapMarker(String title, int id) {
View customMarkerView = this.getLayoutInflater().inflate(R.layout.layout_marker_with_title, null);
customMarkerView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
TextView tvMarkerProjectName = (TextView) customMarkerView.findViewById(R.id.tv_marker_project_name);
if (id != 0) {
ImageView ivMarkerImage = (ImageView) customMarkerView.findViewById(R.id.iv_marker_image);
ivMarkerImage.setImageResource(id);
}
tvMarkerProjectName.setText(title);
customMarkerView.setDrawingCacheEnabled(true);
customMarkerView.buildDrawingCache();
Bitmap bm = customMarkerView.getDrawingCache();
return bm;
}
private void findDistanceAndMarkDirection(Locations destinationLocation) {
flagCalculatingPath = true;
if (polyline != null) {
polyline.remove();
}
trPlaceTimeKm.setVisibility(View.INVISIBLE);
tvPlaceDestinationName.setText(destinationLocation.getName());
// Checks, whether start and end locationRanges are captured
LatLng latLngDest = new LatLng(Double.valueOf(destinationLocation.getLatitude()), Double.valueOf(destinationLocation.getLongitude()));
LatLng origin = listMarkerPoints.get(0);
// Getting URL to the Google Directions API
String url = getUrl(origin, latLngDest);
//Log.d("onMapClick", url.toString());
fetchUrl = new FetchUrl();
// Start downloading json data from Google Directions API
fetchUrl.execute(url);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(origin));
mMap.animateCamera(CameraUpdateFactory.zoomTo(12));
}
private void setPathInfo(String duration, String distance, PolylineOptions polylineOptions, String destName) {
tvPlaceTime.setText(duration);
tvPlaceKmDistance.setText(distance);
polyline = mMap.addPolyline(polylineOptions);
tvPlaceDestinationName.setText(destName);
}
private String getUrl(LatLng origin, LatLng dest) {
// Origin of route
String str_origin = "origin=" + origin.latitude + "," + origin.longitude;
// Destination of route
String str_dest = "destination=" + dest.latitude + "," + dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin + "&" + str_dest + "&" + sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;
return url;
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(15000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setDoInput(true);
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
//Log.d("downloadUrl", data.toString());
br.close();
} catch (Exception e) {
// Log.d("Exception", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class FetchUrl extends AsyncTask<String, Void, String> {
#Override
protected void onCancelled() {
//super.onCancelled();
}
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try {
// Fetching the data from web service
data = downloadUrl(url[0]);
//Log.d("Background Task data", data.toString());
} catch (Exception e) {
// Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (!TextUtils.isEmpty(result)) {
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
} else {
flagCalculatingPath = false;
}
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
//Log.d("ParserTask", jsonData[0].toString());
DataParser parser = new DataParser();
//Log.d("ParserTask", parser.toString());
// Starts parsing data
routes = parser.parse(jObject);
//Log.d("ParserTask", "Executing routes");
//Log.d("ParserTask", routes.toString());
} catch (Exception e) {
//Log.d("ParserTask", e.toString());
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points;
PolylineOptions lineOptions = null;
HashMap<String, Object> hashMapDistancePathInfo = null;
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 1; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(5);
lineOptions.color(Color.RED);
tvPlaceTime.setText(path.get(0).get("duration"));
tvPlaceKmDistance.setText(path.get(0).get("distance"));
trPlaceTimeKm.setVisibility(View.VISIBLE);
hashMapDistancePathInfo = new HashMap<>();
hashMapDistancePathInfo.put("duration", path.get(0).get("duration"));
hashMapDistancePathInfo.put("distance", path.get(0).get("distance"));
hashMapDistancePathInfo.put("polyLineOptions", lineOptions);
//Log.d("onPostExecute", "onPostExecute lineoptions decoded");
}
// Drawing polyline in the Google Map for the i-th route
if (lineOptions != null) {
mapDistancePathData.put(locationPosition, hashMapDistancePathInfo);
polyline = mMap.addPolyline(lineOptions);
} else {
//Log.d("onPostExecute", "without Polylines drawn");
}
flagCalculatingPath = false;
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationListenerFinder = new LocationListenerFinder(this);
if (locationPermission) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationListenerFinder);
}
}
#Override
public void onConnectionSuspended(int i) {
mLocationRequest = null;
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
int size = listNearByFacility.get(0).getNearBy().get(facilityPosition).getLocations().size();
ivMyLocation.setVisibility(View.VISIBLE);
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(getBitmapMarker("Current Location", R.drawable.ic_marker_blue)));
//MarkerOptions markerOptions = new MarkerOptions();
//markerOptions.videoPlayPosition(latLng);
//markerOptions.title("Current Location");
//markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
mCurrLocationMarker.setTag(size + 1);
//move map camera
// mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
//mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListenerFinder);
mGoogleApiClient.disconnect();
mGoogleApiClient.unregisterConnectionCallbacks(this);
mGoogleApiClient.unregisterConnectionFailedListener(this);
//locationListener.clearData();
mLocationRequest = null;
locationListenerFinder = null;
}
mGoogleApiClient = null;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public void checkLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Utility.isPermissionAllowed(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
Utility.showPermissionDialog(this, Manifest.permission.ACCESS_FINE_LOCATION, BookingKARConstants.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
locationPermission = false;
return;
} else {
locationPermission = true;
return;
}
}
locationPermission = true;
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
//Checking the request code of our request
if (requestCode == BookingKARConstants.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
locationPermission = true;
if (mGoogleApiClient == null) {
buildGoogleApiClient();
checkLocationStatus();
}
loadMap();
//mMap.setMyLocationEnabled(true);
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
finish();
}
return;
}
// other 'case' lines to check for other permissions this app might request.
// You can add here other case statements according to your requirement.
}
private void checkLocationStatus() {
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
if (!gps_enabled && !network_enabled) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setMessage(getResources().getString(R.string.gps_network_not_enabled));
dialog.setPositiveButton(getResources().getString(R.string.open_location_settings), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// TODO Auto-generated method stub
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
//get gps
}
});
dialog.setNegativeButton(getString(R.string.Cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// TODO Auto-generated method stub
}
});
dialog.show();
}
}
/*class WeakLocationListener implements LocationListener {
private final WeakReference<LocationListener> locationListenerRef;
public WeakLocationListener(#NonNull LocationListener locationListener) {
locationListenerRef = new WeakReference<>(WeakLocationListener.this);
}
#Override
public void onLocationChanged(android.location.Location location) {
if (locationListenerRef.get() == null) {
return;
}
locationListenerRef.get().onLocationChanged(location);
}
public interface onLocationChanged {
void onLocationChanged(Location location);
}
public void clearData() {
if (locationListenerRef.get() != null) {
locationListenerRef.clear();
}
}*/
//}
}
#Override
public void onDestroy() {
super.onDestroy();
mLocationManager.removeUpdates(locationListener);
}