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
}