I need to loads some KMZ/KML (I tryed both) in my Google Map MapView instance.
But they load really slow, they are 8 KMZ of around 300KB each and for each one it takes more than 3/4 seconds to get loaded.
How can I solve this?
Surfing in search of a solution I found they suggest to use the V3 version because it fix a polyline creation cycle really time consuming in V2.
This is the library:
implementation 'com.google.maps.android:android-maps-utils-v3:1.3.1'
The problem is that when I use this library the constructors of KmlLayer stop working because inside the class KmlLayer it doesn't found the following package of the GoogleMap class, so because all the constructors require a GoogleMap instance they stop working:
import com.google.android.libraries.maps.GoogleMap;
How can I solve this? Is using the V3 version a solution to my problem? If no how can I solve this?
I found other people having the same problem but when they load KML of 10MB or more and not of just 300KB...
This is the class where there is the MapView instance:
public class MappaNuovoGuastoFragment extends Fragment
implements OnMapReadyCallback,
GetLocationManager.OnLocationUpdateCallback,
GoogleMap.OnMapClickListener,
GoogleMap.OnMapLongClickListener,
BaseRetrofitHelper.INetworkResponseCallback {
private static final String TAG = MappaNuovoGuastoFragment.class.getSimpleName();
// Requests Codes - Permission
private static final int REQ_PERMISSION_LOCATION = 0xB01;
// Requests Codes - Networking
private static final int REQ_CODE_PLACES_AUTOCOMPLETE = 0x1;
private static final int REQ_CODE_GET_PLACE_DETAIL = 0x2;
#BindView(R.id.ll_search)
protected LinearLayout mllSearch;
#BindView(R.id.actv_search_field)
protected AutoCompleteTextView mactvSearchField;
#BindView(R.id.map_view)
protected MapView mMapView;
private GoogleMap mGoogleMap;
private GetLocationManager mGetLocationManager;
private LatLng mMyLocation;
private LatLng mClickedLocation;
private Marker mMarker;
private List<GoogleMapPlace> mPlaces;
public static MappaNuovoGuastoFragment newInstance(){
return new MappaNuovoGuastoFragment();
}
//region [#] Override Lifecycle Methods
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_mappa_nuovo_guasto, container, false);
ButterKnife.bind(this, view);
initOnCreateView(savedInstanceState);
return view;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQ_PERMISSION_LOCATION) {
if (grantResults.length > 0x0) {
for (int res : grantResults) {
if (res == PackageManager.PERMISSION_GRANTED) {
mMapView.getMapAsync(this);
break;
}
}
}
}
}
#Override
public void onResume() {
super.onResume();
mMapView.onResume();
mGetLocationManager.startLocationUpdates();
}
#Override
public void onPause() {
mGetLocationManager.stopLocationUpdates();
mMapView.onPause();
super.onPause();
}
#Override
public void onDestroy() {
if(mMapView != null){
mMapView.onDestroy();
}
super.onDestroy();
}
#Override
public void onLowMemory() {
mMapView.onLowMemory();
super.onLowMemory();
}
//endregion
//region [#] Actions Methods
#OnClick(R.id.ib_search)
void onClickSearch(View view){
GoogleMapPlace place = null;
if(mPlaces != null && !mPlaces.isEmpty()){
for(GoogleMapPlace p : mPlaces){
if(p.getDescription().equals(mactvSearchField.getText().toString())){
place = p;
break;
}
}
}
if(place != null){
requestPlaceDetails(place.getPlaceId());
} else {
showSnackbarLocationNotFound();
}
}
#OnClick(R.id.b_make)
void onClickMake(View view){
if(mClickedLocation != null || mMyLocation != null){
startActivityGeneraGuasto();
}
}
#OnClick(R.id.b_map_type)
void onClickMapType(View view){
if(mGoogleMap != null){
switch (mGoogleMap.getMapType()){
case GoogleMap.MAP_TYPE_NONE:
case GoogleMap.MAP_TYPE_HYBRID:
case GoogleMap.MAP_TYPE_SATELLITE:
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
break;
case GoogleMap.MAP_TYPE_NORMAL:
case GoogleMap.MAP_TYPE_TERRAIN:
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
break;
}
}
}
//endregion
//region [#] Override OnMapReadyCallback Methods
#Override
public void onMapReady(#NonNull GoogleMap googleMap) {
mGoogleMap = googleMap;
initGoogleMap();
loadKmz();
}
//endregion
//region [#] Override GetLocationManager.OnLocationUpdateCallback Methods
#Override
public void onLocationUpdated(#Nullable Location location) {
if(mMyLocation == null){
mMyLocation = location != null ? new LatLng(location.getLatitude(), location.getLongitude()) : null;
if(mMyLocation != null){
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mMyLocation, 16.0f));
}
} else {
mMyLocation = location != null ? new LatLng(location.getLatitude(), location.getLongitude()) : null;
}
}
//endregion
//region [#] Override GoogleMap.OnMapClickListener Methods
#Override
public void onMapClick(#NonNull LatLng latLng) {
mClickedLocation = latLng;
initMark();
}
//endregion
//region [#] Override GoogleMap.OnMapLongClickListener Methods
#Override
public void onMapLongClick(#NonNull LatLng latLng) {
if(mClickedLocation != null && PositionUtils.distanceBetween(mClickedLocation.latitude, mClickedLocation.longitude, latLng.latitude, latLng.longitude) <= 100){
mClickedLocation = null;
mMarker.remove();
mMarker = null;
}
}
//endregion
//region [#] Override BaseRetrofitHelper.INetworkResponseCallback Methods
#Override
public void onNetworkResponseSuccess(int requestCode, Object answer) {
switch (requestCode){
case REQ_CODE_PLACES_AUTOCOMPLETE:
if(answer != null){
mPlaces = ((GoogleApiPlaceAutocompleteResponse)answer).getPlaces();
List<String> strings = new ArrayList<>();
for(GoogleMapPlace place : mPlaces){
strings.add(place.getDescription());
}
((ArrayAdapter<String>)mactvSearchField.getAdapter()).clear();
((ArrayAdapter<String>)mactvSearchField.getAdapter()).addAll(strings);
}
break;
case REQ_CODE_GET_PLACE_DETAIL:
if(answer != null){
LatLng latlng = ((GoogleApiPlaceDetailsResponse)answer).getResult().getLatLng();
onMapClick(latlng);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latlng, 15));
} else {
showSnackbarLocationNotFound();
}
break;
}
}
#Override
public void onNetworkResponseError(int requestCode, Throwable t) {
switch (requestCode){
case REQ_CODE_GET_PLACE_DETAIL:
showSnackbarLocationNotFound();
break;
}
}
//endregion
//region [#] Private Methods
private void initOnCreateView(Bundle savedInstanceState){
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try {
MapsInitializer.initialize(requireActivity().getApplicationContext());
} catch (Exception e){
EMaxLogger.onException(TAG, e);
e.printStackTrace();
}
mMapView.getMapAsync(this);
mGetLocationManager = GetLocationManager.initInstance(requireActivity()).setCallback(this);
initAutocompleteTextView();
mllSearch.bringToFront();
}
private void initGoogleMap(){
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(requireActivity(), new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, REQ_PERMISSION_LOCATION);
} else {
mGoogleMap.setMyLocationEnabled(true);
}
mGoogleMap.setOnMapClickListener(this);
mGoogleMap.setOnMapLongClickListener(this);
}
private void initMark(){
if(mMarker != null){
mMarker.remove();
}
LatLng pos = new LatLng(mClickedLocation.latitude, mClickedLocation.longitude);
MarkerOptions opt = new MarkerOptions().position(pos).title(getString(R.string.label_nuovo_guasto));
opt.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_mark_work));
mMarker = mGoogleMap.addMarker(opt);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(pos, 16.0f));
if (mMarker != null) {
mMarker.showInfoWindow();
}
}
private void initAutocompleteTextView(){
ArrayAdapter<String> adapter = new ArrayAdapter<String>(requireContext(), android.R.layout.select_dialog_item, new ArrayList<>());
mactvSearchField.setThreshold(0x4);
mactvSearchField.setAdapter(adapter);
mactvSearchField.addTextChangedListener(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) {
}
#Override
public void afterTextChanged(Editable s) {
if(s.toString().length() >= 0x4){
requestPlaceAutocomplete(s.toString());
}
}
});
}
private void startActivityGeneraGuasto(){
startActivity(GeneraGuastoActivity.getIntent(requireContext(), mClickedLocation != null ? mClickedLocation.latitude : mMyLocation.latitude, mClickedLocation != null ? mClickedLocation.longitude : mMyLocation.longitude));
}
private void showSnackbarLocationNotFound(){
DesignUtils.showSnackbar(mactvSearchField, getString(R.string.error_location_not_found), Snackbar.LENGTH_SHORT);
}
//region [#] Requests Methods
private void requestPlaceAutocomplete(String input){
String key = getString(R.string.google_maps_key);
String components = String.format("country:%1$s", ((TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE)).getNetworkCountryIso());
TicketRetrofitHelper.getInstance().requestAsyncGetPlaceAutocomplete(TicketConstants.URL_GOOGLE_API_PLACE_AUTOCOMPLETE, key, input, components, REQ_CODE_PLACES_AUTOCOMPLETE, this);
}
private void requestPlaceDetails(String idPlace){
String key = getString(R.string.google_maps_key);
TicketRetrofitHelper.getInstance().requestAsyncGetPlaceDetails(TicketConstants.URL_GOOGLE_API_PLACE_DETAILS, key, idPlace, REQ_CODE_GET_PLACE_DETAIL, this);
}
//endregion
private void loadKmz(){
try {
KmlLayer kmz1 = new KmlLayer(mGoogleMap, R.raw.centri_abitati_1, requireContext());
KmlLayer kmz2 = new KmlLayer(mGoogleMap, R.raw.centri_abitati_2, requireContext());
KmlLayer kmz3 = new KmlLayer(mGoogleMap, R.raw.confini_comuni_1, requireContext());
KmlLayer kmz4 = new KmlLayer(mGoogleMap, R.raw.confini_comuni_2, requireContext());
KmlLayer kmz5 = new KmlLayer(mGoogleMap, R.raw.viabilita_1, requireContext());
KmlLayer kmz6 = new KmlLayer(mGoogleMap, R.raw.viabilita_2, requireContext());
KmlLayer kmz7 = new KmlLayer(mGoogleMap, R.raw.viabilita_3, requireContext());
KmlLayer kmz8 = new KmlLayer(mGoogleMap, R.raw.viabilita_4, requireContext());
kmz1.addLayerToMap();
kmz2.addLayerToMap();
kmz3.addLayerToMap();
kmz4.addLayerToMap();
kmz5.addLayerToMap();
kmz6.addLayerToMap();
kmz7.addLayerToMap();
kmz8.addLayerToMap();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//endregion
}
Related
I am trying to launch the NavigationLauncher.startNavigation, from another activity but am unable to do so. I have a button in the second activity which I want to use to start the navigation.
Any suggestions are welcome. Thanks
Here is my code:
/*
fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean simulateRoute = false;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(route)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(MainActivity.this, options);
}
});
*/
fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, Before_Go.class);
startActivity(intent);
// Here is where I want to go to a new activity, inside this activity have a button to
// launch the "NavigationLauncher.startNavigation"
}
});
NavigationLauncher.startnavigation() opens a new activity that handles the navigation. Therefore it does not matter from where it is called. However, wherever it is called from, the NavigationLauncher must be defined, and the options object that is passed as the second parameter has to contain the directionsRoute object.
Can you please share code of the activity from which you call it, as well as how you initialize and define the options object?
thanks for your response to my question. I am new to stakoverflow, so i hope i get this additional posting of code right.
MainActivity
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, PermissionsListener,
MapboxMap.OnMapLongClickListener, OnRouteSelectionChangeListener {
private static final int REQUEST_CODE_AUTOCOMPLETE = 1;
private static final int ONE_HUNDRED_MILLISECONDS = 100;
//private static final String DROPPED_MARKER_LAYER_ID = "DROPPED_MARKER_LAYER_ID";
//Mapbox
private MapView mapView;
private MapboxMap mapboxMap;
private LocationComponent locationComponent;
private PermissionsManager permissionsManager;
private LocationEngine locationEngine;
private long DEFAULT_INTERVAL_IN_MILLISECONDS = 1000L;
private long DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS * 5;
private final MainActivityLocationCallback callback = new MainActivityLocationCallback(this);
private NavigationMapRoute mapRoute;
private DirectionsRoute route;
private String symbolIconId = "symbolIconId";
private String geojsonSourceLayerId = "geojsonSourceLayerId";
private StyleCycle styleCycle = new StyleCycle();
CarmenFeature selectedCarmenFeature;
CarmenFeature feature;
Layer layer;
private static final String TAG = "DirectionsActivity";
// variables
private FloatingActionButton fablocation;
private FloatingActionButton fabstart;
private FloatingActionButton fabRemoveRoute;
private FloatingActionButton fabStyles;
private TextView search;
private TextView kmDisplay;
private TextView timeDisplay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
search=findViewById(R.id.search);
kmDisplay = findViewById(R.id.kmDisplay);
timeDisplay = findViewById(R.id.timeDisplay);
fablocation=findViewById(R.id.fabLocation);
fabstart=findViewById(R.id.fabStart);
fabRemoveRoute=findViewById(R.id.fabRemoveRoute);
fabStyles=findViewById(R.id.fabStyles);
fablocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Location lastKnownLocation = mapboxMap.getLocationComponent().getLastKnownLocation();
// Move map camera back to current device location
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()))
.zoom(15)
.build()), 3000);
}
});
}
#Override
public boolean onMapLongClick(#NonNull LatLng point) {
vibrate();
Point destinationPoint = Point.fromLngLat(point.getLongitude(), point.getLatitude());
Point originPoint = Point.fromLngLat(locationComponent.getLastKnownLocation().getLongitude(),
locationComponent.getLastKnownLocation().getLatitude());
GeoJsonSource source = mapboxMap.getStyle().getSourceAs("destination-source-id");
if (source != null) {
source.setGeoJson(Feature.fromGeometry(destinationPoint));
} else {
// Use the map camera target's coordinates to make a reverse geocoding search
reverseGeocode(Point.fromLngLat(point.getLongitude(), point.getLatitude()));
}
getRoute(originPoint, destinationPoint);
if(destinationPoint !=originPoint) {
fabRemoveRoute.setOnClickListener(new View.OnClickListener() {
#SuppressLint("RestrictedApi")
#Override
public void onClick(View view) {
removeRouteAndMarkers();
fabstart.setVisibility(View.INVISIBLE);
fabRemoveRoute.setVisibility(View.INVISIBLE);
//fablocation.setVisibility(View.INVISIBLE);
kmDisplay.setText("");
timeDisplay.setText("");
search.setText(String.format(getString(R.string.hint_where_to)));
Location lastKnownLocation = mapboxMap.getLocationComponent().getLastKnownLocation();
// Move map camera back to current device location
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()))
.zoom(15)
.build()), 3000);
}
});
}
//imageView.setEnabled(true);
//imageView.setBackgroundResource(R.color.mapboxBlue);
return true;
}
private void getRoute(Point origin, Point destination) {
NavigationRoute.builder(this)
.accessToken(Mapbox.getAccessToken())
.origin(origin)
.destination(destination)
.voiceUnits(DirectionsCriteria.METRIC)
.alternatives(true)
.build()
.getRoute(new Callback<DirectionsResponse>() {
#SuppressLint("RestrictedApi")
#Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
if (response.isSuccessful()
&& response.body() != null
&& !response.body().routes().isEmpty()) {
List<DirectionsRoute> routes = response.body().routes();
mapRoute.addRoutes(routes);
//routeLoading.setVisibility(View.INVISIBLE);
fabRemoveRoute.setVisibility(View.VISIBLE);
fablocation.setVisibility(View.VISIBLE);
fabstart.setVisibility(View.VISIBLE);
route = response.body().routes().get(0);
routeCalcs();
}
// Once you have the route zoom the camera out to show the route within the bounds of the device
mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(
new LatLngBounds.Builder()
.include(new LatLng(origin.latitude(), origin.longitude()))
.include(new LatLng(destination.latitude(), destination.longitude()))
.build(), 150), 4000);
}
#Override
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
Log.e(TAG, "Error: " + throwable.getMessage());
}
});
}
private void removeRouteAndMarkers() {
mapRoute.removeRoute();
toggleLayer();
}
#Override
public void onNewPrimaryRouteSelected(DirectionsRoute directionsRoute) {
route = directionsRoute;
routeCalcs();
}
private void routeCalcs(){
// rounds the kilometer to zero decimals
kmDisplay.setText((int) Math.ceil(route.distance()/1000) + " km");
//Log.d(TAG1,(int) Math.ceil(currentRoute.distance()/1000) + " km");
// This converts to output of duration() in seconds to minutes and hours format
int minutes = (int) (route.duration() / 60);
long hour = TimeUnit.MINUTES.toHours(minutes);
long remainMinute = minutes - TimeUnit.HOURS.toMinutes(hour);
if (hour >= 1) {
timeDisplay.setText(String.format(getString(R.string.hours_textview),hour)
+ String.format(getString(R.string.minutes_textview),remainMinute));
} else {
timeDisplay.setText(String.format(getString(R.string.minutes_textview), remainMinute));
}
}
private void reverseGeocode(Point point) {
if (selectedCarmenFeature == null) {
try {
MapboxGeocoding client = MapboxGeocoding.builder()
.accessToken(getString(R.string.access_token))
.query(Point.fromLngLat(point.longitude(), point.latitude()))
.geocodingTypes(GeocodingCriteria.TYPE_ADDRESS)
.build();
client.enqueueCall(new Callback<GeocodingResponse>() {
#Override
public void onResponse(Call<GeocodingResponse> call, Response<GeocodingResponse> response) {
if (response.body() != null) {
List<CarmenFeature> results = response.body().features();
if (results.size() > 0) {
feature = results.get(0);
// If the geocoder returns a result, we take the first in the list and show a Toast with the place name.
mapboxMap.getStyle(new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
if (style.getLayer("SYMBOL_LAYER_ID") != null) {
search.setText(feature.placeName());
}
}
});
} else {
Toast.makeText(MainActivity.this,
getString(R.string.location_picker_dropped_marker_snippet_no_results), Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<GeocodingResponse> call, Throwable throwable) {
Timber.e("Geocoding Failure: %s", throwable.getMessage());
}
});
} catch (ServicesException servicesException) {
Timber.e("Error geocoding: %s", servicesException.toString());
servicesException.printStackTrace();
}
}
}
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style){
mapRoute = new NavigationMapRoute(null, mapView, mapboxMap);
mapRoute.setOnRouteSelectionChangeListener(MainActivity.this::onNewPrimaryRouteSelected);
mapboxMap.addOnMapLongClickListener(MainActivity.this);
initializeLocationComponent(style);
// Add the symbol layer icon to map for future use
style.addImage(symbolIconId, BitmapFactory.decodeResource(
MainActivity.this.getResources(), R.drawable.mapbox_marker_icon_default));
// Create an empty GeoJSON source using the empty feature collection
setUpSource(style);
// Set up a new symbol layer for displaying the searched location's feature coordinates
setupLayer(style);
fabStyles.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mapboxMap != null) {
mapboxMap.setStyle(styleCycle.getNextStyle());
}
}
});
initSearchFab();
}
});
// This is the code in the docs, but this launches the turn by turn navigation inside this activity
// and this is not what I need
/* fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean simulateRoute = false;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(route)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(MainActivity.this, options);
}
});*/
fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, Before_Go.class);
startActivity(intent);
// Here is where I want to go to a new activity, inside this activity have a button to
// launch the "NavigationLauncher.startNavigation"
}
});
}
private static class StyleCycle {
private static final String[] STYLES = new String[] {
Style.MAPBOX_STREETS,
Style.OUTDOORS,
Style.LIGHT,
Style.DARK,
//Style.SATELLITE_STREETS,
Style.TRAFFIC_DAY,
Style.TRAFFIC_NIGHT
};
private int index;
private String getNextStyle() {
index++;
if (index == STYLES.length) {
index = 0;
}
return getStyle();
}
private String getStyle() {
return STYLES[index];
}
}
private void initSearchFab() {
findViewById(R.id.search).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new PlaceAutocomplete.IntentBuilder()
.accessToken(Mapbox.getAccessToken())
.placeOptions(PlaceOptions.builder()
.backgroundColor(Color.parseColor("#EEEEEE"))
.limit(10)
//.addInjectedFeature(home)
//.addInjectedFeature(work)
.build(PlaceOptions.MODE_CARDS))
.build(MainActivity.this);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
}
});
}
#SuppressWarnings( {"MissingPermission"})
private void initializeLocationComponent(#NonNull Style loadedMapStyle) {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
locationComponent = mapboxMap.getLocationComponent();
// Set the LocationComponent activation options
LocationComponentActivationOptions locationComponentActivationOptions =
LocationComponentActivationOptions.builder(this, loadedMapStyle)
.useDefaultLocationEngine(false)
.build();
// Activate with the LocationComponentActivationOptions object
locationComponent.activateLocationComponent(locationComponentActivationOptions);
locationComponent.setLocationComponentEnabled(true);
locationComponent.setRenderMode(RenderMode.NORMAL);
locationComponent.setCameraMode(CameraMode.TRACKING);
//locationComponent.zoomWhileTracking(10d);
initLocationEngine();
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_AUTOCOMPLETE) {
// Retrieve selected location's CarmenFeature
selectedCarmenFeature = PlaceAutocomplete.getPlace(data);
search.setText(selectedCarmenFeature.placeName());
// Create a new FeatureCollection and add a new Feature to it using selectedCarmenFeature above.
// Then retrieve and update the source designated for showing a selected location's symbol layer icon
if (mapboxMap != null) {
Style style = mapboxMap.getStyle();
if (style != null) {
GeoJsonSource source = style.getSourceAs(geojsonSourceLayerId);
if (source != null) {
source.setGeoJson(FeatureCollection.fromFeatures(
new Feature[] {Feature.fromJson(selectedCarmenFeature.toJson())}));
}
// Move map camera to the selected location
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(((Point) selectedCarmenFeature.geometry()).latitude(),
((Point) selectedCarmenFeature.geometry()).longitude()))
.zoom(14)
.build()), 4000);
}
}
}
}
#SuppressLint("MissingPermission")
private void vibrate() {
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(ONE_HUNDRED_MILLISECONDS, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
vibrator.vibrate(ONE_HUNDRED_MILLISECONDS);
}
}
/**
* Set up the LocationEngine and the parameters for querying the device's location
*/
#SuppressLint("MissingPermission")
private void initLocationEngine() {
locationEngine = LocationEngineProvider.getBestLocationEngine(this);
LocationEngineRequest request = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(DEFAULT_MAX_WAIT_TIME).build();
locationEngine.requestLocationUpdates(request, callback, getMainLooper());
locationEngine.getLastLocation(callback);
}
#Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show();
}
#Override
public void onPermissionResult(boolean granted) {
if (granted) {
if (mapboxMap.getStyle() != null) {
initializeLocationComponent(mapboxMap.getStyle());
}
} else {
Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show();
finish();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private static class MainActivityLocationCallback
implements LocationEngineCallback<LocationEngineResult> {
private final WeakReference<MainActivity> activityWeakReference;
MainActivityLocationCallback(MainActivity activity) {
this.activityWeakReference = new WeakReference<>(activity);
}
#Override
public void onSuccess(LocationEngineResult result) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
Location location = result.getLastLocation();
if (location == null) {
return;
}
if (activity.mapboxMap != null && result.getLastLocation() != null) {
activity.mapboxMap.getLocationComponent().forceLocationUpdate(result.getLastLocation());
}
}
}
#Override
public void onFailure(#NonNull Exception exception) {
Timber.d(exception.getLocalizedMessage());
MainActivity activity = activityWeakReference.get();
if (activity != null) {
Toast.makeText(activity, exception.getLocalizedMessage(),
Toast.LENGTH_SHORT).show();
}
}
}
/**
* Adds the GeoJSON source to the map
*/
private void setUpSource(#NonNull Style loadedMapStyle) {
loadedMapStyle.addSource(new GeoJsonSource(geojsonSourceLayerId));
}
/**
* Setup a layer with maki icons, eg. west coast city.
*/
private void setupLayer(#NonNull Style loadedMapStyle) {
loadedMapStyle.addLayer(new SymbolLayer("SYMBOL_LAYER_ID", geojsonSourceLayerId).withProperties(
iconImage(symbolIconId),
iconOffset(new Float[] {0f, -8f})
));
}
// This method will remove the destination icon
private void toggleLayer() {
mapboxMap.getStyle(new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
layer = style.getLayer("SYMBOL_LAYER_ID");
if (layer != null) {
if (VISIBLE.equals(layer.getVisibility().getValue())) {
layer.setProperties(visibility(NONE));
} else {
layer.setProperties(visibility(VISIBLE));
}
}
}
});
}
// Add the mapView lifecycle to the activity's lifecycle methods
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
protected void onStart() {
super.onStart();
mapView.onStart();
if (mapRoute != null) {
mapRoute.onStart();
}
}
#Override
protected void onStop() {
super.onStop();
mapView.onStop();
if (mapRoute != null) {
mapRoute.onStop();
}
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
Before_Go - this is the activity where i want to click the button and launch the navigationlauncher
public class Before_Go extends AppCompatActivity {
Button btnGo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_before__go);
btnGo=findViewById(R.id.btnGo);
btnGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent btnGo = new Intent(Before_Go.this, Go.class);
startActivity(btnGo);
}
});
}
}
GoActivity, this is where the navigation launcher needs to launch after the button click in the Before_Go activity
public class Go extends AppCompatActivity implements OnNavigationReadyCallback,
NavigationListener {
private NavigationView navigationView;
private DirectionsRoute route;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
setTheme(R.style.Theme_AppCompat_NoActionBar);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_go);
navigationView = findViewById(R.id.navigationViewB);
navigationView.onCreate(savedInstanceState);
}
/*fabstart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean simulateRoute = false;
NavigationLauncherOptions options = NavigationLauncherOptions.builder()
.directionsRoute(route)
.shouldSimulateRoute(simulateRoute)
.build();
// Call this method with Context from within an Activity
NavigationLauncher.startNavigation(MainActivity.this, options);
}
});*/
#Override
public void onNavigationReady(boolean isRunning) {
MapboxNavigationOptions.Builder navigationOptions = MapboxNavigationOptions.builder();
NavigationViewOptions.Builder options = NavigationViewOptions.builder();
options.navigationListener(this);
extractRoute(options);
extractConfiguration(options);
options.navigationOptions(navigationOptions.build());
//options.navigationOptions(new MapboxNavigationOptions.Builder().build());
launchNavigationWithRoute();
//navigationView.startNavigation(options.build());
navigationView.initialize(this);
/*MapboxNavigationOptions.Builder navigationOptions = MapboxNavigationOptions.builder();
NavigationViewOptions.Builder options = NavigationViewOptions.builder();
options.navigationListener(this);
extractRoute(options);
options.navigationOptions(navigationOptions.build());
//navigationView = NavigationLauncher.startNavigation(options.build());
navigationView.startNavigation(options.build());
initialize();*/
}
#Override
public void onCancelNavigation() {
// Navigation canceled, finish the activity
showCustomCancel();
finishNavigation();
}
#Override
public void onNavigationFinished() {
}
#Override
public void onNavigationRunning() {
}
private void launchNavigationWithRoute() {
if (route != null) {
NavigationLauncher.startNavigation(this, route);
}
}
private void extractRoute(NavigationViewOptions.Builder options) {
route = NavigationLauncher.extractRoute(this);
options.directionsRoute(route);
}
private void extractConfiguration(NavigationViewOptions.Builder options) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
options.shouldSimulateRoute(preferences.getBoolean(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE, false));
}
private void finishNavigation() {
NavigationLauncher.cleanUpPreferences(this);
finish();
}
private void showCustomCancel(){
ViewGroup viewGroup = findViewById(android.R.id.content);
View dialogView2 = LayoutInflater.from(this).inflate(R.layout.my_dialog_logout, viewGroup, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialogView2);
AlertDialog alertDialog2 = builder.create();
Button buttonNo = dialogView2.findViewById(R.id.buttonNo);
Button buttonYes = dialogView2.findViewById(R.id.buttonYes);
buttonYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (alertDialog2 != null && alertDialog2.isShowing()) {
alertDialog2.dismiss();
}
Intent intentCancelTrip_Yes = new Intent(getApplicationContext(),MainActivity.class);
startActivity(intentCancelTrip_Yes);
finish();
navigationView.stopNavigation();
}
});
buttonNo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (alertDialog2 != null && alertDialog2.isShowing()) {
alertDialog2.dismiss();
}
navigationView.onResume();
}
});
alertDialog2.show();
}
/* private void initialize() {
Parcelable position = getIntent().getParcelableExtra(NavigationConstants.NAVIGATION_VIEW_INITIAL_MAP_POSITION);
if (position != null) {
navigationView.initialize(this, (CameraPosition) position);
} else {
navigationView.initialize(this);
}
}*/
#Override
public void onStart() {
super.onStart();
navigationView.onStart();
}
#Override
public void onResume() {
super.onResume();
navigationView.onResume();
}
#Override
public void onLowMemory() {
super.onLowMemory();
navigationView.onLowMemory();
}
#Override
public void onBackPressed() {
// If the navigation view didn't need to do anything, call super
if (!navigationView.onBackPressed()) {
super.onBackPressed();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
navigationView.onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
navigationView.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onPause() {
super.onPause();
navigationView.onPause();
}
#Override
public void onStop() {
super.onStop();
navigationView.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
navigationView.onDestroy();
}
}
NavigationLauncher class i am using to try initiate the navigation inside the Go activity
public class NavigationLauncher {
public static void startNavigation(Activity activity, DirectionsRoute route) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY, new Gson().toJson(route));
//editor.putString(NavigationConstants.NAVIGATION_VIEW_AWS_POOL_ID, awsPoolId);
//editor.putBoolean(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE, simulateRoute);
editor.apply();
Intent navigationActivity = new Intent(activity, Go.class);
activity.startActivity(navigationActivity);
}
/* public static void startNavigation(Activity activity, NavigationLauncherOptions options){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor editor = preferences.edit();
storeDirectionsRouteValue(options, editor);
storeConfiguration(options, editor);
editor.apply();
Intent navigationActivity = new Intent(activity, Go.class);
storeInitialMapPosition(options, navigationActivity);
activity.startActivity(navigationActivity);
}*/
private static void storeConfiguration(NavigationLauncherOptions options, SharedPreferences.Editor editor) {
editor.putBoolean(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE, options.shouldSimulateRoute());
}
private static void storeDirectionsRouteValue(NavigationLauncherOptions options, SharedPreferences.Editor editor) {
editor.putString(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY, options.directionsRoute().toJson());
/*if (options.directionsRoute() != null) {
storeDirectionsRouteValue(options, editor);
}
else {
throw new RuntimeException("A valid DirectionsRoute or origin and "
+ "destination must be provided in NavigationViewOptions");
}*/
}
static DirectionsRoute extractRoute(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String directionsRouteJson = preferences.getString(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY, "");
return DirectionsRoute.fromJson(directionsRouteJson);
}
static void cleanUpPreferences(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor
.remove(NavigationConstants.NAVIGATION_VIEW_ROUTE_KEY)
.remove(NavigationConstants.NAVIGATION_VIEW_SIMULATE_ROUTE)
.apply();
}
private static void storeInitialMapPosition(NavigationLauncherOptions options, Intent navigationActivity) {
if (options.initialMapCameraPosition() != null) {
navigationActivity.putExtra(
NavigationConstants.NAVIGATION_VIEW_INITIAL_MAP_POSITION, options.initialMapCameraPosition()
);
}
}
}
I assume that the application crashes once the activity "Go.java" is launched.
The problem appears to be that you are not instantiating the Mapbox object in this activity. You are doing it correclty in your "mainactivity.java" however you are missing it in "go.java". Make sure to have the line Mapbox.getInstance(this, getString(R.string.access_token)); also in your "go.java" activity before calling setContentView()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_main);
I want to get current (or last known) device location and move the camera to it on map when the app starts. I have tried so many ways, but nothing works on Fragment.
Here is my current code with whom the app turns off immediately.
MapFragment.java
public class MapFragment extends Fragment implements OnMapReadyCallback
{
private GoogleMap mGoogleMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private boolean mLocationPermissionGranted;
private Location mLastKnownLocation;
private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
private static final int DEFAULT_ZOOM = 15;
public MapFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this.getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.fragment_map, container, false);
return mView;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(getContext());
mGoogleMap = googleMap;
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// Turn on the My Location layer and the related control on the map.
updateLocationUI();
// Get the current location of the device and set the position of the map.
getDeviceLocation();
}
private void getLocationPermission() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
if (ContextCompat.checkSelfPermission(this.getActivity(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this.getActivity(),
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
}
}
updateLocationUI();
}
private void updateLocationUI() {
if (mGoogleMap == null) {
return;
}
try {
if (mLocationPermissionGranted) {
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
} else {
mGoogleMap.setMyLocationEnabled(false);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
mLastKnownLocation = null;
getLocationPermission();
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (mLocationPermissionGranted) {
Task locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener((Executor) this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
mLastKnownLocation = (Location) task.getResult();
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
});
}
} catch(SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
This way works on FragmentActivity, but not on Fragment.
I've also given ACCESS_FINE_LOCATION permission in AndroindManifest.xml.
I am developing an taxi application in android. I need to store retrieve and update location of my cabs and show it on maps using geofire. I have used firebase for authentication.
Need a complete tutorial for android geofire but can't find any
I have also seen SFVehicle example but didn't understand much
Any help would be appreciated!!!
first of all currently there are no complete tutorials on geofire so all you have in your disposal is the official documentation of Geofire go for java and js.And here is a small but maybe helpful stuff--
https://firebase.googleblog.com/2013/09/geofire-location-queries-for-fun-and.html,
https://medium.com/google-cloud/firebase-is-cool-geofire-is-just-awesome-b7f2be5e0f0f#.x78gjws28,
I hope that these could be of some help to you.
I have created a library for Android, which provides geo-based firestore data to find the list of data within a given radius in KM / MILES.
It also gives the faster response in a single query read with the classification of the ADDED and REMOVED data in and from the query with real-time updates.
You can refer Geo-Firestore
It has well-documentation so you can easily develop the same.
here are a few more links
https://firebase.googleblog.com/2014/08/geofire-goes-mobile.html
https://firebase.googleblog.com/2014/06/geofire-20.html
How to save GeoFire coordinates along with other items in Firebase database?
Here is an example code for having a current location of driver
public class MainActivity extends AppCompatActivity implements
OnMapReadyCallback, PermissionsListener {
// Variables needed to initialize a map
private MapboxMap mapboxMap;
private MapView mapView;
// Variables needed to handle location permissions
private PermissionsManager permissionsManager;
// Variables needed to add the location engine
private LocationEngine locationEngine;
private long DEFAULT_INTERVAL_IN_MILLISECONDS = 1000L;
private long DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS *1;
// Variables needed to listen to location updates
private MainActivityLocationCallback callback = new MainActivityLocationCallback(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, "");
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_main);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
#Override
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.TRAFFIC_NIGHT,
new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
enableLocationComponent(style);
}
});
}
/**
* Initialize the Maps SDK's LocationComponent
*/
#SuppressWarnings( {"MissingPermission"})
private void enableLocationComponent(#NonNull Style loadedMapStyle) {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
// Get an instance of the component
LocationComponent locationComponent = mapboxMap.getLocationComponent();
// Set the LocationComponent activation options
LocationComponentActivationOptions locationComponentActivationOptions =
LocationComponentActivationOptions.builder(this, loadedMapStyle)
.useDefaultLocationEngine(false)
.build();
// Activate with the LocationComponentActivationOptions object
locationComponent.activateLocationComponent(locationComponentActivationOptions);
// Enable to make component visible
locationComponent.setLocationComponentEnabled(true);
// Set the component's camera mode
locationComponent.setCameraMode(CameraMode.TRACKING);
// Set the component's render mode
locationComponent.setRenderMode(RenderMode.COMPASS);
initLocationEngine();
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
/**
* Set up the LocationEngine and the parameters for querying the device's location
*/
#SuppressLint("MissingPermission")
private void initLocationEngine() {
locationEngine = LocationEngineProvider.getBestLocationEngine(this);
LocationEngineRequest request = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(DEFAULT_MAX_WAIT_TIME).build();
locationEngine.requestLocationUpdates(request, callback, getMainLooper());
locationEngine.getLastLocation(callback);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
Toast.makeText(this, "Enable Location", Toast.LENGTH_LONG).show();
}
#Override
public void onPermissionResult(boolean granted) {
if (granted) {
if (mapboxMap.getStyle() != null) {
enableLocationComponent(mapboxMap.getStyle());
}
} else {
Toast.makeText(this, "Permission Not Granted", Toast.LENGTH_LONG).show();
finish();
}
}
private static class MainActivityLocationCallback
implements LocationEngineCallback<LocationEngineResult> {
private final WeakReference<MainActivity> activityWeakReference;
MainActivityLocationCallback(MainActivity activity) {
this.activityWeakReference = new WeakReference<>(activity);
}
/**
* The LocationEngineCallback interface's method which fires when the device's location has changed.
*
* #param result the LocationEngineResult object which has the last known location within it.
*/
#Override
public void onSuccess(LocationEngineResult result) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
Location location = result.getLastLocation();
if (location == null) {
return;
}
FirebaseDatabase database = FirebaseDatabase.getInstance();
String somi_id2 = "emp_samad";
DatabaseReference myRef3 = database.getReference("current");
GeoFire geoFire = new GeoFire(myRef3);
geoFire.setLocation(somi_id2,new GeoLocation(location.getLatitude(),location.getLongitude()));
Toast.makeText(activity,String.valueOf(location.getLatitude()+"\n"+String.valueOf(location.getLongitude())),Toast.LENGTH_SHORT).show();
// Pass the new location to the Maps SDK's LocationComponent
if (activity.mapboxMap != null && result.getLastLocation() != null) {
activity.mapboxMap.getLocationComponent().forceLocationUpdate(result.getLastLocation());
}
}
}
/**
* The LocationEngineCallback interface's method which fires when the device's location can not be captured
*
* #param exception the exception message
*/
#Override
public void onFailure(#NonNull Exception exception) {
Log.d("LocationChangeActivity", exception.getLocalizedMessage());
MainActivity activity = activityWeakReference.get();
if (activity != null) {
Toast.makeText(activity, exception.getLocalizedMessage(),
Toast.LENGTH_SHORT).show();
}
}
}
#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(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
#Override
protected void onDestroy() {
super.onDestroy();
// Prevent leaks
if (locationEngine != null) {
locationEngine.removeLocationUpdates(callback);
}
mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
Now here is the code for showing him on map for realtime
public class MainActivity extends AppCompatActivity
implements
OnMapReadyCallback, PermissionsListener{
private MapView mapView;
private PermissionsManager permissionsManager;
private MapboxMap mapboxMap;
private GeoJsonSource geoJsonSource;
private ValueAnimator animator;
public static double pre_lat,pre_long;
public static Marker marker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, "*YOUR_KEY*");
setContentView(R.layout.activity_main);
Mapbox.getInstance(this, "");
mapView = findViewById(R.id.mapView);
//fetchData process = new fetchData();
// process.execute();
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
MainActivity.this.mapboxMap = mapboxMap;
mapboxMap.setCameraPosition(new CameraPosition.Builder()
.zoom(19)
.target(new
LatLng(24.987029999999997,67.056585))
.build());
mapboxMap.setStyle(Style.DARK,
new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// enableLocationComponent(style);
// Create an Icon object for the marker to use
FirebaseDatabase database = FirebaseDatabase.getInstance();
String somi_id2 = "emp_samad";
DatabaseReference myRef3 = database.getReference("current");
GeoFire geoFire = new GeoFire(myRef3);
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(24.987043333333336, 67.05663333333334), 10);
geoFire.getLocation("emp_samad", new LocationCallback() {
#Override
public void onLocationResult(String key, GeoLocation location) {
if (location != null) {
pre_lat = location.latitude;
pre_long = location.longitude;
// Location prevLoc = new Location(location.latitude,location.longitude);
// Location newLoc = ;
// float bearing = prevLoc.bearingTo(newLoc) ;
marker = mapboxMap.addMarker(new MarkerOptions()
.position(new LatLng(pre_lat,pre_long))
.icon(IconFactory.getInstance(MainActivity.this).fromResource(R.drawable.marker)));
System.out.println(String.format("The location for key %s is [%f,%f]", key, location.latitude, location.longitude));
} else {
System.out.println(String.format("There is no location for key %s in GeoFire", key));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
geoQuery.addGeoQueryDataEventListener(new GeoQueryDataEventListener() {
#Override
public void onDataEntered(DataSnapshot dataSnapshot, GeoLocation location) {
System.out.println(String.format("The location is [%f,%f]", location.latitude, location.longitude));
}
#Override
public void onDataExited(DataSnapshot dataSnapshot) {
}
#Override
public void onDataMoved(DataSnapshot dataSnapshot, GeoLocation location) {
}
#Override
public void onDataChanged(DataSnapshot dataSnapshot, GeoLocation location) {
double lat = pre_lat;
double lon = pre_long;
LatLng pre_latlng = new LatLng(lat,lon);
LatLng washington = new LatLng(location.latitude,location.longitude);
ValueAnimator markerAnimator = ValueAnimator.ofObject(new TypeEvaluator<LatLng>() {
#Override
public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
return new LatLng(startValue.getLatitude() + (endValue.getLatitude() - startValue.getLatitude()) * fraction, startValue.getLongitude() + (endValue.getLongitude() - startValue.getLongitude()) * fraction);
}
}, new LatLng[]{pre_latlng, washington});
markerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
if (marker != null) {
marker.setPosition((LatLng) animation.getAnimatedValue());
}
}
});
markerAnimator.setDuration(7500);
//markerAnimator.setRepeatCount(ValueAnimator.INFINITE);
//markerAnimator.setRepeatMode(ValueAnimator.REVERSE);
markerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
markerAnimator.start();
/* if(marker!=null)
{
//marker.remove();
//marker.setPosition(new LatLng(location.latitude,location.longitude));
}
System.out.println(String.format("The location is [%f,%f]", location.latitude, location.longitude));
*/
}
#Override
public void onGeoQueryReady() {
}
#Override
public void onGeoQueryError(DatabaseError error) {
}
});
}
});
}
});
}
#SuppressWarnings( {"MissingPermission"})
private void enableLocationComponent(#NonNull Style loadedMapStyle) {
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
// Get an instance of the component
LocationComponent locationComponent = mapboxMap.getLocationComponent();
// Activate with options
locationComponent.activateLocationComponent(
LocationComponentActivationOptions.builder(this, loadedMapStyle).build());
// Enable to make component visible
locationComponent.setLocationComponentEnabled(true);
// Set the component's camera mode
locationComponent.setCameraMode(CameraMode.TRACKING);
// Set the component's render mode
locationComponent.setRenderMode(RenderMode.COMPASS);
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
Toast.makeText(this, "Enable Location", Toast.LENGTH_LONG).show();
}
#Override
public void onPermissionResult(boolean granted) {
if (granted) {
mapboxMap.getStyle(new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
// enableLocationComponent(style);
}
});
} else {
Toast.makeText(this, "Permission Not Granted", Toast.LENGTH_LONG).show();
// finish();
}
}
#Override
#SuppressWarnings( {"MissingPermission"})
public void onStart() {
super.onStart();
mapView.onStart();
}
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onStop() {
super.onStop();
mapView.onStop();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
public void onMapReady(#NonNull MapboxMap mapboxMap)
{
}
}
what you have to use for this is to implement a geofire library
Geofire implementation
implementation 'com.firebase:geofire-android:3.0.0'
I hope that this will help you alot
In my app I've a MapFragment with the classic "MyLocationButton".
On older APIs I don't have any kind of issue, but since Google asked developers to use Runtime Permissions, I'm facing this problem: when the user clicks ALLOW, the already said button is not appearing, at least not until the user refreshes this fragment. Is there a way to catch the user's press to make the fragment refresh as soon as he's given permissions?
EDIT:
I'm using nested fragments, and I've found out my problem is the same you can see at this page of the AOSP Issue Tracker. I've solved it using the last version of Android APIs (v24).
I'll post my MapFragment:
public class MapFragment extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, PetrolStationsArray.PetrolStationsListener {
private GoogleMap mGoogleMap;
private int mMapType;
private static LatLng mPosition;
private static float mZoom;
private CoordinatorLayout mCoordinatorLayout;
private View mLocationButton;
private AppCompatImageButton mTurnGPSOn;
private FragmentManager mFragmentManager;
private FragmentTransaction mFragmentTransaction;
private SupportMapFragment mSupportMapFragment;
private SupportPlaceAutocompleteFragment mSupportPlaceAutocompleteFragment;
private LocalBroadcastManager mLocalBroadcastManager;
private PetrolStationsArray mPetrolStationsArray;
protected LocationRequest mLocationRequest;
protected GoogleApiClient mGoogleApiClient;
Marker mCurrLocationMarker;
private CountDownTimer mDragTimer;
private boolean mTimerIsRunning = false;
// Design pattern to instantiate a new fragment.
public static MapFragment newInstance() {
MapFragment fragment = new MapFragment();
return fragment;
}
/********************************************************/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Since API 23, Android requests you check for Location Permissions.
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
mMapType = Integer.parseInt(loadPreferences(SETTINGS_PREFERENCES, MAP_KEY));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_map, container, false);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(getContext());
mPetrolStationsArray = PetrolStationsArray.get();
mDragTimer = new CountDownTimer(DRAG_TIMER_INTERVAL, DRAG_TIMER_INTERVAL + 1) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
mTimerIsRunning = false;
mPetrolStationsArray.setPosition(mPosition);
}
};
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Initialise a new fragment inside of this one.
mFragmentManager = getChildFragmentManager();
mSupportMapFragment = (SupportMapFragment) mFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG);
mSupportPlaceAutocompleteFragment = (SupportPlaceAutocompleteFragment) mFragmentManager.findFragmentByTag(AUTOCOMPLETE_FRAGMENT_TAG);
mCoordinatorLayout = (CoordinatorLayout) view.findViewById(R.id.coordinator_layout);
/*
** Never inflate fragments inside other fragments in a layout.xml!
** Do it programmatically.
** See here for reference: http://stackoverflow.com/a/19815266/4938112.
*/
if (mSupportMapFragment == null) {
mSupportMapFragment = new SupportMapFragment();
fragmentTransaction(mFragmentManager, mSupportMapFragment, R.id.map_fragment_container, MAP_FRAGMENT_TAG);
}
// Asynchronous thread to load map.
mSupportMapFragment.getMapAsync(this);
if (mSupportPlaceAutocompleteFragment == null) {
mSupportPlaceAutocompleteFragment = new SupportPlaceAutocompleteFragment();
fragmentTransaction(mFragmentManager, mSupportPlaceAutocompleteFragment, R.id.card_view, AUTOCOMPLETE_FRAGMENT_TAG);
}
// Filter for a specific place type.
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setTypeFilter(AutocompleteFilter.TYPE_FILTER_CITIES | AutocompleteFilter.TYPE_FILTER_ADDRESS)
.build();
mSupportPlaceAutocompleteFragment.setFilter(typeFilter);
mSupportPlaceAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
LatLng position = place.getLatLng();
CameraUpdate centre = CameraUpdateFactory.newLatLng(position);
CameraUpdate zoom = CameraUpdateFactory.zoomTo(ZOOM_LEVEL);
mGoogleMap.moveCamera(centre);
mGoogleMap.animateCamera(zoom);
}
#Override
public void onError(Status status) {
Log.d("PLACE_ERROR", "An error occurred: " + status);
}
});
mTurnGPSOn = ((AppCompatImageButton) view.findViewById(R.id.turn_gps_on));
mTurnGPSOn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Ask if the user wants to open the GPS - settings.
displayPromptToEnableGPS(getActivity());
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.mGoogleMap = googleMap;
mGoogleMap.setMapType(mMapType);
if (mPosition != null) {
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(mPosition, mZoom);
mGoogleMap.moveCamera(cameraUpdate);
}
mGoogleMap.setTrafficEnabled(true);
mGoogleMap.getUiSettings().setMapToolbarEnabled(false);
mGoogleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
mPosition = cameraPosition.target;
mZoom = cameraPosition.zoom;
if (mTimerIsRunning) {
mDragTimer.cancel();
}
mDragTimer.start();
mTimerIsRunning = true;
}
});
// Get the "My Position" button.
mLocationButton = ((View) mSupportMapFragment.getView().findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) mLocationButton.getLayoutParams();
Resources r = getActivity().getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
10,
r.getDisplayMetrics()
);
// Position on right bottom.
rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
rlp.setMargins(0, 0, px, px);
turnOnMyLocation();
}
#Override
public void onPause() {
super.onPause();
// Stop location updates when Activity is no longer active.
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
mPetrolStationsArray.removePetrolStationListener(this);
}
#Override
public void onResume() {
super.onResume();
mPetrolStationsArray.setPetrolStationsListener(this);
}
#Override
public void onListUpdated() {
// Cleaning all the markers.
if (mGoogleMap != null) {
mGoogleMap.clear();
}
List<PetrolStation> petrolStationList = mPetrolStationsArray.getList();
for (PetrolStation petrolStation : petrolStationList) {
double lat = petrolStation.getLat();
double lon = petrolStation.getLon();
String name = petrolStation.getName();
if (mGoogleMap != null) {
mGoogleMap.addMarker(new MarkerOptions()
.position(new LatLng(lat, lon))
.title(name));
}
}
}
#Override
public void onServerRequest() {
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
// TODO
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// TODO
}
#Override
public void onLocationChanged(Location location) {
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
// Just a check to overtake the
// 'java.lang.IllegalStateException: Fragment MapFragment{42f519d0} not attached to Activity'
// exception I've encountered.
if (!isAdded()) {
return;
}
// Stop location updates.
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
// Start the transaction between different fragments.
private void fragmentTransaction(FragmentManager mFragmentManager, Fragment fragment, int id, String tag) {
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.add(id, fragment, tag);
mFragmentTransaction.commit();
mFragmentManager.executePendingTransactions();
}
/*********************************************
************ LOCATION PERMISSIONS ************
*********************************************/
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, 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) {
turnOnMyLocation();
} else {
// Permission denied, boo! Disable the functionality that depends on this permission.
String message = getResources().getString(R.string.permission_denied);
Snackbar snackbar = Snackbar
.make(mCoordinatorLayout, message, Snackbar.LENGTH_LONG)
.setAction(R.string.close_snack_bar, new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
snackbar.show();
}
}
}
}
// Ask for permission (START DIALOG) in Android APIs >= 23.
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
// Prompt the user once explanation has been shown.
requestPermissions(new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
requestPermissions(new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
public void turnOnMyLocation() {
// Initialise Google Play Services.
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mGoogleMap.setMyLocationEnabled(true);
}
} else {
mGoogleMap.setMyLocationEnabled(true);
}
}
// Let's build our Location Services API Client.
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient
.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
public static void displayPromptToEnableGPS(final Activity activity) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final String action = Settings.ACTION_LOCATION_SOURCE_SETTINGS;
final String message = MyFuelApp.getAppContext().getResources().getString(R.string.open_gps_settings);
builder.setMessage(message)
.setPositiveButton(MyFuelApp.getAppContext().getResources().getString(R.string.confirm_ok),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int id) {
activity.startActivity(new Intent(action));
d.dismiss();
}
})
.setNegativeButton(MyFuelApp.getAppContext().getResources().getString(R.string.deny_no),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int id) {
d.cancel();
}
});
builder.create().show();
}
}
One way to solve is to ask before open your MapFragment. This way you only have to check if you have the permission or not at your fragment to load one view or another.
The other way, is to add the button at your method turnOnMyLocation().
You can use
onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
within this callback you should check the equality of the request code that you passed while requesting permission with the one in the parameter. If it matches, you can get the user result.
If user allow the permission, then you can simply detach and attach your fragment as follow:
Fragment currentFragment = getFragmentManager().findFragmentByTag("FRAGMENT");
FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
fragTransaction.detach(currentFragment);
fragTransaction.attach(currentFragment);
fragTransaction.commit();
This is how your fragment will be reloaded and also your views gets refreshed. I hope by this you can address your problem.
I'm getting problems using MapFragment + ListFragment in an Activity,
when I use show() and hide() method, everything works ok, but when I have my application in background and I return, I get the GoogleMap stunned or blocked, and I don't know what to do to solve that. The only solution I got to work fine, is using replace transactions, but I don't like this way, because in every transaction we should initiate all map place balloons, and it doesn't keep your last camera location, so... I don't know what to do.
PS: I use SherlockActionBar
Thanks in advance:
Here is my code:
Activity:
...
#Override
public void onCreate(Bundle savedInstanceState) {
BugSenseHandler.initAndStartSession(this, "f8013578");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_route_place);
setViews();
setData();
doStuff();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.route_place_list:
analyticTracker.sendView("/RoutePlaceActivity/List");
isMap = true;
changeFragments();
break;
case R.id.route_place_map:
analyticTracker.sendView("/RoutePlaceActivity/Home");
isMap = false;
changeFragments();
break;
default:
break;
}
}
#Override
public void onRouteMapPlaceClick(Place place) {
goToDetails(place);
}
#Override
public void onRouteListPlaceClick(Place place) {
goToDetails(place);
}
#Override
public void onShowMessage(String message, Message type) {
showMessage(message, type);
}
...
private void setData() {
route = getIntent().getExtras().getParcelable("route");
analyticTracker = GoogleAnalytics.getInstance(this).getTracker(Config.GOOGLE_ANALYTICS_ID);
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
/*
* If the activity is killed while in BG, it's possible that the
* fragment still remains in the FragmentManager, so, we don't need to
* add it again.
*/
if (mapFragment == null) {
Log.v("RoutePlaceActivity", "mapFragment = null");
mapFragment = new RoutePlaceMapFragment();
ft.add(R.id.route_place_container, mapFragment);
}
ft.hide(mapFragment);
if (listFragment == null) {
Log.v("RoutePlaceActivity", "listFragment = null");
listFragment = RoutePlaceListFragment.newInstance();
ft.add(R.id.route_place_container, listFragment);
}
ft.hide(listFragment);
ft.commit();
}
private void doStuff() {
changeFragments();
sendItineraryPlacesRequest();
}
private void changeFragments() {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
if (isMap) {
ft.hide(listFragment);
ft.show(mapFragment);
switcherView.setDisplayedChild(VIEW_LIST);
} else {
ft.hide(mapFragment);
ft.show(listFragment);
switcherView.setDisplayedChild(VIEW_MAP);
}
ft.commit();
}
private void sendItineraryPlacesRequest() {
... {
...
#Override
public void onSuccess(JSONObject response) {
super.onSuccess(response);
Places places = JSONObjectAdapter.getPlaces(response);
mapFragment.addPlaces(places);
listFragment.addPlaces(places);
}
...
});
}
MapFragment:
/********************* Constructors **********************/
...
/********************* Class Methods *********************/
...
#Override
public void onCreate(Bundle savedInstanceState) {
Log.v(CLASS_TAG, "onCreate");
super.onCreate(savedInstanceState);
setData(savedInstanceState);
setUpMapIfNeeded();
}
#Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
}
...
#Override
public void onDestroyView() {
((ViewGroup)getView()).removeAllViews();
super.onDestroyView();
}
/******************** Public Methods ********************/
public void addPlaces(Places places) {
mMap.clear();
placeMap.clear();
Builder builder = new LatLngBounds.Builder();
for (Place place : places) {
LatLng placePos = new LatLng(place.getLatitude(), place.getLongitude());
builder.include(placePos);
Marker m = mMap.addMarker(new MarkerOptions().position(placePos).title(place.getName()).draggable(false));
placeMap.put(m, place);
}
if (places.size() > 1) {
final LatLngBounds bounds = builder.build();
try {
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
} catch (Exception e) {
// layout not yet initialized
final View mapView = getView();
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
// We check which build version we are using.
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
// mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
}
});
}
}
} else if (places.size() != 0) {
final CameraPosition cameraPosition = new CameraPosition.Builder().zoom(17).target(new LatLng(places.get(0).getLatitude(), places.get(0).getLongitude())).tilt(25).build();
try {
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 4000, null);
} catch (Exception e) {
// layout not yet initialized
final View mapView = getView();
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
// We check which build version we are using.
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 4000, null);
}
});
}
}
} else {
myListener.onShowMessage("No se han encontrado sitios cercanos", Message.INFO);
}
}
/******************** Private Methods ********************/
private void setData(Bundle savedInstanceState) {
placeMap = new HashMap<Marker, Place>();
mMap = null;
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
mMap = getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.setMyLocationEnabled(true);
mMap.setOnInfoWindowClickListener(this);
// mMap.setOnMarkerClickListener(this);
UiSettings uiSettings = mMap.getUiSettings();
uiSettings.setCompassEnabled(false);
Places places = getArguments().getParcelable("places");
if (places != null) {
addPlaces(places);
}
}
I was also facing the same problem in the new maps api(Maps V2 android).
But i solved it by overriding onSaveInstance and onRestoreInstance method in the container activity..
and not calling super.onSaveInstance(). and super.onRestoreInstance().
This is just a temporary hack.. but i think u will be up and running with your beautiful app..