I tried to develop a android app with maps. I'm a beginner in android app development, i doesn't know how to generate a path between my current position and to the destination. I can able to view by current location by the code shown below.
package com.example.myapp;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class Grandinmaps extends Activity implements OnMapReadyCallback{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grandinmaps);
MapFragment mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap map) {
// TODO Auto-generated method stub
map.setMyLocationEnabled(true);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(12.971907, 80.220462), 18));
}
}
And i doesn't know the code to generate the path to destination.
Any HELP...!!! Please:-)
For Drawing Route you can use this code:
Call for printing location route:
GmapV2Direction route;
Document document;
LatLng toPosition = new LatLng(routeData.get(i).latitude, routeData.get(i).longitude);
new GetRouteTask() {
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}.execute((LatLng) toPosition);
private class GetRouteTask extends AsyncTask<LatLng, Void, String> {
String response = "";
#Override
protected String doInBackground(LatLng... params) {
document = route.getDocument(fromPosition, params[0], GmapV2Direction.MODE_WALKING);//fromPosition is another LatLng object.can be your current location.
response = "Success";
return response;
}
#Override
protected void onPostExecute(String s) {
// directionMap.clear();
if (response.equalsIgnoreCase("Success")) {
Log.v("Map", "got here");
ArrayList<LatLng> directionPoint = route.getDirection(document);
PolylineOptions rectLine = new PolylineOptions().width(10).color(
Color.RED);
for (int i = 0; i < directionPoint.size(); i++) {
rectLine.add(directionPoint.get(i));
}
// Adding route on the map
map.addPolyline(rectLine);
}
}
}
Related
I am using MapBox to create a route between two points. I have LatLng of two points already and have successfully add Markers at source and destination point but the problem is, I am unable to create a route between them. Here is the code. I don't know where i am lacking but i have followed a tutorial but in that Tutor is creating a route between current location and the location clicked on map and he is doing stuff in onMapClicked method since i am not using that approach due to have customized point. Instead, i am doing stuff in the onMapReady method other than all the procedure is identical.
package com.devaj.googlemaps;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.devaj.googlemaps.models.TDD;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
public class NavigationActivity extends AppCompatActivity implements OnMapReadyCallback{
public static final String TAG = "NavigationActivity";
private MapView mapView;
private TDD tdd;
private Point originPosition, dstPosition;
private Double originLat, originLng, dstLat, dstLng;
private LatLng originLatLng, dstLatLng;
private MapboxMap map;
private NavigationMapRoute navigationMapRoute;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_navigation);
MapBox(savedInstanceState);
}
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
map = mapboxMap;
originPosition = Point.fromLngLat(originLat, originLng);
dstPosition = Point.fromLngLat(dstLat, dstLng);
MarkerOptions options = new MarkerOptions();
options.title("Source");
options.position(originLatLng);
MarkerOptions options1 = new MarkerOptions();
options1.title("Destination");
options1.position(dstLatLng);
mapboxMap.addMarker(options);
mapboxMap.addMarker(options1);
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);
getRoute(originPosition, dstPosition);
}
});
}
private void MapBox(Bundle savedInstanceState)
{
Intent i = getIntent();
tdd = (TDD) i.getSerializableExtra("tdd");
originLat = Double.parseDouble(tdd.getmSrcLat());
originLng = Double.parseDouble(tdd.getmSrcLng());
dstLat = Double.parseDouble(tdd.getmDstLat());
dstLng = Double.parseDouble(tdd.getmDstLng());
originLatLng = new LatLng(originLat, originLng);
dstLatLng = new LatLng(dstLat, dstLng);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
private void getRoute(Point origin, Point destination)
{
// CameraPosition position = new CameraPosition.Builder()
// .target(originLatLng) // Sets the new camera position
// .zoom(17) // Sets the zoom
// .bearing(180) // Rotate the camera
// .tilt(30) // Set the camera tilt
// .build(); // Creates a CameraPosition from the builder
//
// map.animateCamera(CameraUpdateFactory
// .newCameraPosition(position), 7000);
NavigationRoute.builder(NavigationActivity.this)
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.build()
.getRoute(new Callback<DirectionsResponse>() {
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
if (response.body() == null)
{
Usable.logMessage(TAG, "No routes found, Check User and Access Token..");
return;
} else if (response.body().routes().size() == 0)
{
Usable.logMessage(TAG, "No routes found..");
return;
}
DirectionsRoute currentRoute = response.body().routes().get(0);
navigationMapRoute.addRoute(currentRoute);
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable t) {
Log.e(TAG, "Error: "+ t.getMessage());
}
});
}
#Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
#Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
#Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
#Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
#Override
protected void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
}
You've got your lat/long order mixed up whenever you use Point.fromLngLat().
For example, dstPosition = Point.fromLngLat(dstLat, dstLng); is the wrong order.
Is there a log message in your logcat when you try the code you posted above? Search for Mbgl. Is response.body() null? Is the route size == 0? Basically, it'd be helpful if you could explain more when you say I am unable to create a route between them.
By the way, you don't have to use the Mapbox Navigation SDK for Android if you want to get a route between two points. The Mapbox Java SDK can do that.
https://docs.mapbox.com/android/java/overview/directions
https://docs.mapbox.com/android/java/examples/show-directions-on-a-map
https://docs.mapbox.com/android/java/examples/dashed-directions-line
Also, I'd move the onMapReady() stuff into the onStyleLoaded() callback.
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
map = mapboxMap;
originPosition = Point.fromLngLat(originLng, originLat);
dstPosition = Point.fromLngLat(dstLng, dstLat);
MarkerOptions options = new MarkerOptions();
options.title("Source");
options.position(originLatLng);
MarkerOptions options1 = new MarkerOptions();
options1.title("Destination");
options1.position(dstLatLng);
mapboxMap.addMarker(options);
mapboxMap.addMarker(options1);
navigationMapRoute = new NavigationMapRoute(null, mapView, map, R.style.NavigationMapRoute);
getRoute(originPosition, dstPosition);
}
});
}
This is my first time working with google maps in android.I was able to create a map showing my current user location.
However, I would like to display multiple markers whose data I'm fetching using volley. To do this I'm using a backgroundTask class with a singleton class. The backgroundTask class is the one returning the arrayList of the location data.
For this reason I need to populate my BackgroungTask class with the arrayList before my MapActivity become active and access the arraylist of objects in onCreate but it seems the MapActivity loads very fast and a reference to the arrayList of objects from the BackgroungTask class is always null.
This is the BackgroundTask class which is fetching the data
package com.example.carwashplaces;
import android.content.Context;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class BackgroundTask {
private Context context;
private ArrayList<ModelLocation> locationArrayList = new ArrayList<>();
String json_url = "http://histogenetic-exhaus.000webhostapp.com/location.php";
public BackgroundTask(Context context) {
this.context = context;
}
public ArrayList<ModelLocation> getLocationArrayList(){
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest (
Request.Method.POST,
json_url,
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
int count = 0;
while (count<response.length()){
try {
JSONObject jsonObject = response.getJSONObject(count);
ModelLocation modelLocation = new ModelLocation(
jsonObject.getString("id"),
jsonObject.getString("name"),
jsonObject.getString("latitude"),
jsonObject.getString("longitude"),
jsonObject.getString("staff"),
jsonObject.getString("comment"),
jsonObject.getString("phone"));
locationArrayList.add(modelLocation);
count++;
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "Error fetching car wash places... ", Toast.LENGTH_SHORT).show();
error.printStackTrace();
}
});
MySingleton.getInstance(context).addToRequestque(jsonArrayRequest);
return locationArrayList;
}
}
This is the MapActivity where I want to display the locations.
package com.example.carwashplaces;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.AutocompletePrediction;
import com.google.android.libraries.places.api.model.AutocompleteSessionToken;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.TypeFilter;
import com.google.android.libraries.places.api.net.FetchPlaceRequest;
import com.google.android.libraries.places.api.net.FetchPlaceResponse;
import com.google.android.libraries.places.api.net.FindAutocompletePredictionsRequest;
import com.google.android.libraries.places.api.net.FindAutocompletePredictionsResponse;
import com.google.android.libraries.places.api.net.PlacesClient;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.mancj.materialsearchbar.MaterialSearchBar;
import com.mancj.materialsearchbar.adapter.SuggestionsAdapter;
import com.skyfishjy.library.RippleBackground;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private PlacesClient placesClient;
private List<AutocompletePrediction> predictionList;
private ArrayList<ModelLocation> locations;
private BackgroundTask backgroundTask;
private Location mLastKnownLocation;
private LocationCallback locationCallback;
private MaterialSearchBar materialSearchBar;
private View mapView;
private Button btnFind;
private RippleBackground rippleBg;
private final float DEFAULT_ZOOM = 18;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
//init views
materialSearchBar = findViewById(R.id.searchBar);
btnFind = findViewById(R.id.btnFind);
rippleBg = findViewById(R.id.ripple_bg);
//an object of backgroung task
backgroundTask = new BackgroundTask(MapActivity.this);
locations = new ArrayList<>();
//getting location data from background task
locations = backgroundTask.getLocationArrayList();
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mapView = mapFragment.getView();
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MapActivity.this);
Places.initialize(MapActivity.this, "MY_KEY");
placesClient = Places.createClient(this);
final AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();
materialSearchBar.setOnSearchActionListener(new MaterialSearchBar.OnSearchActionListener() {
#Override
public void onSearchStateChanged(boolean enabled) {
}
#Override
public void onSearchConfirmed(CharSequence text) {
startSearch(text.toString(), true, null, true);
}
#Override
public void onButtonClicked(int buttonCode) {
if (buttonCode == MaterialSearchBar.BUTTON_NAVIGATION){
//opening or closing a navigation drawer
}else if (buttonCode == MaterialSearchBar.BUTTON_BACK){
materialSearchBar.disableSearch();
}
}
});
materialSearchBar.addTextChangeListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
FindAutocompletePredictionsRequest predictionsRequest = FindAutocompletePredictionsRequest.builder()
.setCountry("ke")
.setTypeFilter(TypeFilter.ADDRESS)
.setSessionToken(token)
.setQuery(s.toString())
.build();
placesClient.findAutocompletePredictions(predictionsRequest).addOnCompleteListener(new OnCompleteListener<FindAutocompletePredictionsResponse>() {
#Override
public void onComplete(#NonNull Task<FindAutocompletePredictionsResponse> task) {
if (task.isSuccessful()){
//predictions found, find out what suggestions we have from google
FindAutocompletePredictionsResponse predictionsResponse = task.getResult();
if (predictionsResponse != null){
predictionList = predictionsResponse.getAutocompletePredictions();
//converting predictionList into a list of string
List<String> suggestionsList = new ArrayList<>();
for (int i = 0; i < predictionList.size(); i++){
AutocompletePrediction prediction = predictionList.get(i);
suggestionsList.add(prediction.getFullText(null).toString());
}
//pass suggestion list to our MaterialSearchBar
materialSearchBar.updateLastSuggestions(suggestionsList);
if (!materialSearchBar.isSuggestionsVisible()){
materialSearchBar.showSuggestionsList();
}
}
}
else {
//some error
Log.i("mytag", "prediction fetching task failed");
}
}
});
}
#Override
public void afterTextChanged(Editable s) {
}
});
materialSearchBar.setSuggstionsClickListener(new SuggestionsAdapter.OnItemViewClickListener() {
#Override
public void OnItemClickListener(int position, View v) {
// seek the longitude and latitude of that suggestion
if (position >= predictionList.size()){
return;
}
AutocompletePrediction selectedPrediction = predictionList.get(position);
String suggestion = materialSearchBar.getLastSuggestions().get(position).toString();
materialSearchBar.setText(suggestion);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
materialSearchBar.clearSuggestions();
}
},1000);
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
if (imm != null){
imm.hideSoftInputFromWindow(materialSearchBar.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
}
String placeId = selectedPrediction.getPlaceId();
List<Place.Field> placeFields = Arrays.asList(Place.Field.LAT_LNG);// get latitude and longitude of a place
FetchPlaceRequest fetchPlaceRequest = FetchPlaceRequest.builder(placeId, placeFields).build();
placesClient.fetchPlace(fetchPlaceRequest).addOnSuccessListener(new OnSuccessListener<FetchPlaceResponse>() {
#Override
public void onSuccess(FetchPlaceResponse fetchPlaceResponse) {
// place found, update camera Factory
Place place = fetchPlaceResponse.getPlace();
Log.i("mytag", "place found: "+place.getName());
LatLng latLngOfPlace = place.getLatLng();
if (latLngOfPlace != null){
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLngOfPlace, DEFAULT_ZOOM));
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException){
ApiException apiException = (ApiException) e;
apiException.printStackTrace();
int statusCode = apiException.getStatusCode();
Log.i("mytag", "place not found: " +e.getMessage());
Log.i("mytag", "status code: "+statusCode);
}
}
});
}
#Override
public void OnItemDeleteListener(int position, View v) {
}
});
btnFind.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//get the current location of the marker
LatLng currentMarkerLocation = mMap.getCameraPosition().target;
rippleBg.startRippleAnimation();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
rippleBg.stopRippleAnimation();
Toast.makeText(MapActivity.this, "Nearest Car Wash", Toast.LENGTH_SHORT).show();
}
},3000);
}
});
}
//Called when the map is loaded
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
if (mapView != null && mapView.findViewById(Integer.parseInt("1")) != null){
View locationButton = ((View) mapView.findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) locationButton.getLayoutParams();
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
layoutParams.setMargins(0, 0, 40, 180);
}
//check if gps is enabled or not and then request user to enable it
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
SettingsClient settingsClient = LocationServices.getSettingsClient(MapActivity.this);
Task<LocationSettingsResponse> task = settingsClient.checkLocationSettings(builder.build());
task.addOnSuccessListener(MapActivity.this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
getDeviceLocation();
setMarkersToCarWashes();
}
});
task.addOnFailureListener(MapActivity.this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ResolvableApiException){
ResolvableApiException resolvable = (ResolvableApiException) e;
try {
resolvable.startResolutionForResult(MapActivity.this, 51);
} catch (IntentSender.SendIntentException ex) {
ex.printStackTrace();
}
}
}
});
mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
#Override
public boolean onMyLocationButtonClick() {
if (materialSearchBar.isSuggestionsVisible())
materialSearchBar.clearSuggestions();
if (materialSearchBar.isSearchEnabled())
materialSearchBar.disableSearch();
return false;
}
});
setMarkersToCarWashes();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 51) {
if (resultCode == RESULT_OK) {
getDeviceLocation();
setMarkersToCarWashes();
}
}
}
private void setMarkersToCarWashes() {
if (locations != null){
for(int i = 0; i < locations.size(); i++){
double lati = Double.parseDouble(locations.get(i).getLatitude());
double longLat = Double.parseDouble(locations.get(i).getLongitude());
//set markers to car wash places
mMap.addMarker(new MarkerOptions().position(
new LatLng(lati, longLat))
.title(locations.get(i).getName())
.snippet(locations.get(i).getComment()));
}
}
}
private void getDeviceLocation() {
mFusedLocationProviderClient.getLastLocation()
.addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful()){
mLastKnownLocation = task.getResult();
if (mLastKnownLocation != null){
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
}else {
final LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
if (locationResult == null){
return;
}
mLastKnownLocation = locationResult.getLastLocation();
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
mFusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
};
mFusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null);
}
}else {
Toast.makeText(MapActivity.this, "Unable to get last Location", Toast.LENGTH_SHORT).show();
}
}
});
}
}
And This is the part of the code in MapActivity where I'm trying to get the arraylist from the BackgroundTask class
//an object of backgroung task
backgroundTask = new BackgroundTask(MapActivity.this);
locations = new ArrayList<>();
//getting location data from background task
locations = backgroundTask.getLocationArrayList();
How do I display the markers in onMapReady method i.e populate the BackgroundTask before the onMapReady method executes?
This is my approach, based off of this solution from related thread. First let's create an interface to handle the volley's response.
public interface LocationsCallback {
void onSuccess(ArrayList<ModelLocation> fetchedLocations);
}
Then modify your getLocationArrayList method as follows:
public ArrayList<ModelLocation> getLocationArrayList(final LocationsCallback locationsCallback)
Inside the onResponse method of getLocationArrayList, right at the end, add the callback:
public ArrayList<ModelLocation> getLocationArrayList(final LocationsCallback locationsCallback) {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
Request.Method.POST,
json_url,
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// your code here...
// Add this at the end here
ArrayList<ModelLocation> locations = locationArrayList;
locationsCallback.onSuccess(locations);
}
//...
Now assign your MapActivity's locations to the fetched array:
locations = new ArrayList<>();
backgroundTask = new BackgroundTask(MapActivity.this);
backgroundTask.getLocationArrayList(new LocationsCallback() {
#Override
public void onSuccess(ArrayList<ModelLocation> fetchedLocations) {
locations = fetchedLocations;
// Your other code goes here...
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(MapActivity.this);
mapView = mapFragment.getView();
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MapActivity.this);
Places.initialize(MapActivity.this, "KEY");
placesClient = Places.createClient(MapActivity.this);
//...
}
});
And the markers will now be displayed on the map. See screenshot below. :)
I am trying to use Geofire to store and display the users that are logged in on a map i am new in android studio
i am getting this error
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.parthtiwari.trace/com.example.parthtiwari.trace.tracking}: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.Circle com.google.android.gms.maps.GoogleMap.addCircle(com.google.android.gms.maps.model.CircleOptions)' on a null object reference
import android.app.AlertDialog;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import com.firebase.geofire.GeoFire;
import com.firebase.geofire.GeoLocation;
import com.firebase.geofire.GeoQuery;
import com.firebase.geofire.GeoQueryEventListener;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.*;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import java.util.HashMap;
import java.util.Map;
public class tracking extends FragmentActivity implements
GeoQueryEventListener,OnMapReadyCallback,
GoogleMap.OnCameraChangeListener{
private static final GeoLocation INITIAL_CENTER = new GeoLocation(22.7789,
-78.4017);
private static final int INITIAL_ZOOM_LEVEL = 14;
private static final String GEO_FIRE_DB = "https://trace-
5fa8c.firebaseio.com";
private static final String GEO_FIRE_REF = GEO_FIRE_DB + "/_geofire";
private GoogleMap mMap;
private GoogleMap map;
private Circle searchCircle;
private GeoFire geoFire;
private GeoQuery geoQuery;
private Map<String,Marker> markers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tracking);
// Obtain the SupportMapFragment and get notified when the map is ready
to be used.
SupportMapFragment mapFragment = (SupportMapFragment)
getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync((OnMapReadyCallback) this);
LatLng latLngCenter = new LatLng(INITIAL_CENTER.latitude,
INITIAL_CENTER.longitude);
this.searchCircle = this.map.addCircle(new
CircleOptions().center(latLngCenter).radius(1000));
this.searchCircle.setFillColor(Color.argb(66, 255, 0, 255));
this.searchCircle.setStrokeColor(Color.argb(66, 0, 0, 0));
this.map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLngCenter,
INITIAL_ZOOM_LEVEL));
this.map.setOnCameraChangeListener(this);
FirebaseOptions options = new FirebaseOptions.Builder().setApplicationId("geofire").setDatabaseUrl(GEO_FIRE_DB).build();
FirebaseApp app = FirebaseApp.initializeApp(this, options);
// setup GeoFire
this.geoFire = new GeoFire(FirebaseDatabase.getInstance(app).getReferenceFromUrl(GEO_FIRE_REF));
// radius in km
this.geoQuery = this.geoFire.queryAtLocation(INITIAL_CENTER, 1);
// setup markers
this.markers = new HashMap<String, Marker>();
}
#Override
protected void onStop() {
super.onStop();
// remove all event listeners to stop updating in the background
this.geoQuery.removeAllListeners();
for (Marker marker: this.markers.values()) {
marker.remove();
}
this.markers.clear();
}
#Override
protected void onStart() {
super.onStart();
// add an event listener to start updating locations again
this.geoQuery.addGeoQueryEventListener(this);
}
#Override
public void onKeyEntered(String key, GeoLocation location) {
// Add a new marker to the map
Marker marker = this.map.addMarker(new MarkerOptions().position(new
LatLng(location.latitude, location.longitude)));
this.markers.put(key, marker);
}
#Override
public void onKeyExited(String key) {
// Remove any old marker
Marker marker = this.markers.get(key);
if (marker != null) {
marker.remove();
this.markers.remove(key);
}
}
#Override
public void onKeyMoved(String key, GeoLocation location) {
// Move the marker
Marker marker = this.markers.get(key);
if (marker != null) {
this.animateMarkerTo(marker, location.latitude, location.longitude);
}
}
#Override
public void onGeoQueryReady() {
}
#Override
public void onGeoQueryError(DatabaseError error) {
new AlertDialog.Builder(this)
.setTitle("Error")
.setMessage("There was an unexpected error querying GeoFire: " +
error.getMessage())
.setPositiveButton(android.R.string.ok, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
// Animation handler for old APIs without animation support
private void animateMarkerTo(final Marker marker, final double lat, final
double lng) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final long DURATION_MS = 3000;
final Interpolator interpolator = new
AccelerateDecelerateInterpolator();
final LatLng startPosition = marker.getPosition();
handler.post(new Runnable() {
#Override
public void run() {
float elapsed = SystemClock.uptimeMillis() - start;
float t = elapsed/DURATION_MS;
float v = interpolator.getInterpolation(t);
double currentLat = (lat - startPosition.latitude) * v +
startPosition.latitude;
double currentLng = (lng - startPosition.longitude) * v +
startPosition.longitude;
marker.setPosition(new LatLng(currentLat, currentLng));
// if animation is not finished yet, repeat
if (t < 1) {
handler.postDelayed(this, 16);
}
}
});
}
private double zoomLevelToRadius(double zoomLevel) {
// Approximation to fit circle into view
return 16384000/Math.pow(2, zoomLevel);
}
#Override
public void onCameraChange(CameraPosition cameraPosition) {
LatLng center = cameraPosition.target;
double radius = zoomLevelToRadius(cameraPosition.zoom);
this.searchCircle.setCenter(center);
this.searchCircle.setRadius(radius);
this.geoQuery.setCenter(new GeoLocation(center.latitude,
center.longitude));
// radius in km
this.geoQuery.setRadius(radius/1000);
}
#Override
public void onMapReady(GoogleMap googleMap) {
}
}
You are requesting the GoogleMap instance asynchronously with this statement:
mapFragment.getMapAsync((OnMapReadyCallback) this);
When the map is available for use, it will be reported to you in this callback:
#Override
public void onMapReady(GoogleMap googleMap) {
}
You need to take all initialization code that uses the map out of your activity's onCreate() method and move it into onMapReady() or methods that are called from onMapReady(). For example:
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
//mMap = googleMap; // not used?
// all the map init stuff
LatLng latLngCenter = new LatLng(INITIAL_CENTER.latitude,
INITIAL_CENTER.longitude);
this.searchCircle = this.map.addCircle(new
CircleOptions().center(latLngCenter).radius(1000));
this.searchCircle.setFillColor(Color.argb(66, 255, 0, 255));
this.searchCircle.setStrokeColor(Color.argb(66, 0, 0, 0));
this.map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLngCenter,
INITIAL_ZOOM_LEVEL));
this.map.setOnCameraChangeListener(this);
}
It's not clear why you are creating another app instance. I don't think Geofire needs it. Try using the default:
//FirebaseOptions options = new FirebaseOptions.Builder().setApplicationId("geofire").setDatabaseUrl(GEO_FIRE_DB).build();
//FirebaseApp app = FirebaseApp.initializeApp(this, options);
// setup GeoFire
this.geoFire = new GeoFire(FirebaseDatabase.getInstance().getReferenceFromUrl(GEO_FIRE_REF));
I am trying to write code on button click in a fragment,but the buttons are not working. The buttons are set to increase and decrease the value of textview (rangeText).
I have implemented OnClickListener to my fragment.
I want to know where is the mistake.
package com.neoresearch.bookmyspace;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
/**
* A fragment that launches other parts of the demo application.
*/
public class ParkingFinderMapFragment extends Fragment implements View.OnClickListener {
LinearLayout layoutOfPopup;
PopupWindow popupMessage;
Button popupButton, insidePopupButton, searchButton, rangeIncrement, rangeDecrement;
TextView rangeText;
TextView name, contact, address, availability;
AutoCompleteTextView searchText;
LatLng latLng;
MarkerOptions markerOptions;
MapView mMapView;
GoogleMap googleMap;
private EditText editText;
String string;
private View v;
int range;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflat and return the layout
v = inflater.inflate(R.layout.fragment_parking_finder_map, container,
false);
searchText = (AutoCompleteTextView) v.findViewById(R.id.search_on_map);
searchButton = (Button) v.findViewById(R.id.button_search);
rangeIncrement = (Button) v.findViewById(R.id.range_increment);
rangeDecrement = (Button) v.findViewById(R.id.range_decrament);
rangeText = (TextView) v.findViewById(R.id.range_select);
mMapView = (MapView) v.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();// needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
googleMap = mMapView.getMap();
// latitude and longitude
double latitude = 17.385044;
double longitude = 78.486671;
// create marker
MarkerOptions marker = new MarkerOptions().position(
new LatLng(latitude, longitude)).title("Hello Maps");
// Changing marker icon
marker.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
// adding marker
googleMap.addMarker(marker);
LatLng indore = new LatLng(22.7000, 75.9000);
final MarkerOptions marker2 = new MarkerOptions().position(indore).title("Indore");
googleMap.addMarker(marker2);
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(22.7000, 75.9000)).zoom(8).build();
googleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
// Perform any camera updates here
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
PopupOnMap pop = new PopupOnMap(getActivity());
pop.show();
pop.setName("prafull", marker.getTitle(), "8269564260");
return false;
}
});
searchButton.setOnClickListener(this);
rangeDecrement.setOnClickListener(this);//these are my buttons
rangeIncrement.setOnClickListener(this);
return v;
}
#Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
//here is onclick listeners
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_search:
break;
case R.id.range_increment:
range = Integer.parseInt(rangeText.getText().toString());
if (range > 0 && range < 20) {
range = range++;
}
rangeText.setText(range);
break;
case R.id.range_decrament:
range = Integer.parseInt(rangeText.getText().toString());
if (range > 0 && range < 20) {
range = range--;
}
rangeText.setText(range);
break;
}
}
}
Make the following changes to your onClick() method :
case R.id.range_increment:
range = Integer.parseInt(rangeText.getText().toString());
if (range > 0 && range < 20) {
range = range++;
}
rangeText.setText(String.valueOf(range));
break;
case R.id.range_decrament:
range = Integer.parseInt(rangeText.getText().toString());
if (range > 0 && range < 20) {
range = range--;
}
rangeText.setText(String.valueOf(range));
break;
I'm having some troubles with onMarkerClick
Basically for now I just want that when ANY marker previously created starts the same activity when clicked. I will implement the filtering of the marker later on.
What I get now is no error. Simply nothing happens when the marker is clicked.
Here is my source:
I'm looping through a database to populate the map and then the markers are displayed
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class NevianoMaps extends Activity implements OnMarkerClickListener{
private GoogleMap googleMap;
DatabaseHandler db = new DatabaseHandler(this);
double latitude;
double longitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.neviano_maps);
try {
// Loading map
initilizeMap();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* function to load map. If map is not created it will create it for you
* */
private void initilizeMap() {
if (googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(
R.id.map)).getMap();
CameraPosition cameraPosition = new CameraPosition.Builder().target(
new LatLng(double value, double value)).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
//Luoghi di interesse check
if (getIntent().getIntExtra("str1", 0) == 0){
for(int x = 1; x < 6; x = x+1) {
latitude = db.getCultura(x).getCoordLat();
longitude = db.getCultura(x).getCoordLong();
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude)).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
.title(db.getCultura(x).getName()));
}
}
if (getIntent().getIntExtra("str1", 1) == 1){
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(double value, double value)).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))
.title("Sport"));
}
// check if map is created successfully or not
if (googleMap == null) {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
}
#Override
public boolean onMarkerClick(Marker arg0) {
Intent i = new Intent(this, informazioni.class);
//i.putExtra("str1", db.getCulturaName(arg0.getTitle()).getDescription());
startActivity(i);
return false;
}
#Override
protected void onResume() {
super.onResume();
initilizeMap();
}
}
Hope somebody can help! Thank you
In your initilizeMap() method, please add this line after you've got your map:
googleMap.setOnMarkerClickListener(this);