Android google maps crashes after fragment navigation - android

I have an app with a navigation drawer and uses fragment to display new screens after user selects a nav item
The part of my MainActivity class that handles that looks like this:
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_new) {
addFragment(new NewFragment(), id);
} else if (id == R.id.nav_start) {
addFragment(new StartFragment(), id);
} else if (id == R.id.nav_delete) {
addFragment(new DeleteFragment(), id);
} else if (id == R.id.nav_gps) {
addFragment(new GPSFragment(), id);
}
...
And the addFragment method looks like this:
public void addFragment(Fragment fragment, int id) {
if (fragment != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (fragmentManager.getFragments() == null) {
fragmentTransaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName())
.commit();
} else {
fragmentTransaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(Integer.toString(id))
.commit();
}
}
}
One of the fragments is a GPS one where I have implemented google maps. It works, but there are 2 major problems with it and I'm not sure what's going on:
When I navigate to GPS, then to another fragment, then to GPS (repeated multiple times) using the nav drawer, eventually the screen will turn black and completely reload the MainActivity
When I navigate around using the back button (from GPS to another fragment, back to GPS, repeated many times), or use the home button to pause the app and bring it back to resume (repeated multiple times) the app gets extremely slow and takes about a minute to respond to any user input
This must be due to the way I've implemented google maps, or more specifically the way I handle the transition between different states (maybe). I thought that with the way I've implemented my code, whenever I use the nav drawer, or press the back button, or press home to leave the GPS fragment, gmaps will disconnect and the fragment be suspended.
I'm not sure why that would lead to such slowdowns, or a restarting of the app back to the MainActivity. Maybe a memory issue? I'm not sure what would be causing that if I'm always disconnecting from gmaps and removing the fragment when I navigate away. I don't think this was a problem before I added the code to get mMapView.getMapAsync(this) working, so maybe its related to the mapready event and how it interacts with navigation?
The GPSfragment simply listens for changes in lat,lon positions and moves the camera and marker to center the users location. Here is the GPSFragment class:
public class GPSFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener, OnMapReadyCallback {
private GoogleMap googleMap;
private GoogleApiClient mGoogleApiClient;
double lat, lon;
LocationRequest mLocationRequest;
CoordinatorLayout coordinatorLayout;
UiSettings mapSettings;
CameraPosition cameraPosition;
MarkerOptions markerOptions;
Marker marker;
Location mLastLocation;
MapView mMapView;
public GPSFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
coordinatorLayout = (CoordinatorLayout) getActivity().findViewById(R.id.coordinator_layout);
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_gps, container, false);
//Set the nav drawer item highlight
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.navigationView.setCheckedItem(R.id.nav_gps);
//Set actionbar title
mainActivity.setTitle("GPS");
//Create api connector and map
buildGoogleApiClient();
mMapView = (MapView) view.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
//mMapView.onResume();
//When map is ready, set it up with a onMapReady callback
mMapView.getMapAsync(this);
return view;
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
mMapView.onResume();
} else {
mGoogleApiClient.connect();
mMapView.onResume();
}
}
#Override
public void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
mMapView.onPause();
mGoogleApiClient.disconnect();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (mGoogleApiClient.isConnected()) {
mMapView.onDestroy();
mGoogleApiClient.disconnect();
}
}
#Override
public void onLowMemory() {
super.onLowMemory();
if (mGoogleApiClient.isConnected()) {
mMapView.onLowMemory();
mGoogleApiClient.disconnect();
}
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(100); // Update location every second
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
lat = mLastLocation.getLatitude();
lon = mLastLocation.getLongitude();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
lat = location.getLatitude();
lon = location.getLongitude();
marker.setPosition(new LatLng(lat, lon));
googleMap.animateCamera(CameraUpdateFactory
.newLatLng(new LatLng(lat, lon)));
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
buildGoogleApiClient();
}
synchronized void buildGoogleApiClient() {
//Request permission for location data
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//If permission has not been granted
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)) {
//If they have previously declined permission, show explanation
Snackbar.make(coordinatorLayout, R.string.permission_explain_gps,
Snackbar.LENGTH_INDEFINITE).setAction(R.string.request_permission, new View.OnClickListener() {
#Override
public void onClick(View view) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
0);
}
}).show();
} else {
//If no previous declines
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
0);
}
} else {
//If permission has been granted
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
}
#Override
public void onMapReady(GoogleMap mMapView) {
googleMap = mMapView;
setupMap();
}
public void setupMap() {
mapSettings = googleMap.getUiSettings();
mapSettings.setZoomGesturesEnabled(true);
mapSettings.setZoomControlsEnabled(true);
mapSettings.setScrollGesturesEnabled(true);
mapSettings.setTiltGesturesEnabled(true);
mapSettings.setRotateGesturesEnabled(true);
markerOptions = new MarkerOptions().position(new LatLng(lat, lon));
marker = googleMap.addMarker(markerOptions);
cameraPosition = new CameraPosition.Builder()
.target(new LatLng(lat, lon)).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
}
EDIT: also just noticed that after closing and uninstalling the app from my phone, the map marker icon is still in my status bar at the top, which I think only comes on when the phone is currently requesting location information...

Related

get last known location in android [duplicate]

This question already has answers here:
Location is empty at the start
(5 answers)
Closed 3 years ago.
This topic is populated in SO, but due to my limited knowledge in java, I am unable to get my location.
If I manually put latitude and longitude, my code is working as expected. I use this to put the latitude and longitude hardcoded:
class latlang {
public static double Lat=28.28;
public static double Lang=84.0;
}
which is used in other fragments, as, but not only in map:
MapFragment.java
public class MapFragment extends Fragment {
private MapView mMapView;
private GoogleMap googleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_map, container, false);
mMapView = rootView.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();
}
mMapView.getMapAsync(mMap -> {
googleMap = mMap;
LatLng sydney = new LatLng(latlang.Lat, latlang.Lang);
googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker Title").snippet("Marker Description"));
// For zooming automatically to the location of the marker
CameraPosition cameraPosition = new CameraPosition.Builder().target(sydney).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
});
return rootView;
}
#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();
}
}
Kindly help. I am totally confused with FusedLocationProviderClient
main_activity.java
public class MainActivity extends AppCompatActivity {
private FusedLocationProviderClient mFusedLocationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
//new SecondFragment();
//TabLayout tabs = findViewById(R.id.tabs);
//tabs.setupWithViewPager(viewPager);
FloatingActionButton fab = findViewById(R.id.fab);
FontDrawable drawable = new FontDrawable(this, R.string.fa_plus_solid, true, false);
drawable.setTextColor(ContextCompat.getColor(this, android.R.color.white));
fab.setImageDrawable(drawable);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
//Check permission
if (ContextCompat.checkSelfPermission(getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getApplicationContext(),
android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
}
}
}
First you need to initialize the fusedLocationClient like this :
In Fragment:
fusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext());
In Activity:
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
then to retrieve last known location :
fusedLocationClient.getLastLocation()
.addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations, this can be null.
if (location != null) {
// Logic to handle location object
double latitude= location.getLatitude();
double longitude= location.getLongitude();
} else {
//handle null location
}
}
});
Hope this helps!

In Google Maps, why is OnLocationChanged() not called again, when the app is maximized from its minimized state?

I am developing an Android Application. In that I integrated Google Maps in a Fragment .
My Problem
In the Map , in normal running state , OnLocationChanged function called by LocationListener and my Map Marker is moving correctly.
But , if I minimizes the app and after I maximize it , the marker is not moving . I checked and found , the OnLocationChanged not get called after Maximizing the App.
So I put some Log.D commends in the onLocationChanged and reran it.
Until minimizing the App , The Log commends exectuted on each and every location changed. But After I minimized and maximized the App , The Log printing stoped and marker stopped moving.
My Efforts to Resolve
I tried implementing OnResume method in Fragment but it not called.
So I searched the internet. Based on the suggestions I recreated the Fragment on the onResume method of the parent Activity of the Fragment.
After that , the the tracking worked even after resuming. But I fell in to an another problem.
When the Fragment get Recreated in the onResume() of the parent Activity , the Map loading the from the beginning. That is the Map showing Whole world map..... then slowly it goes to current location and the old markers cleared and new markers draw again. After that marker start moving.
So that process takes long time.
Now I can't move further. Since I am new to Google Maps I can't fix it..
My Code:
Map_Fragment.java
/**
* A simple {#link Fragment} subclass.
*/
public class Map_Fragment extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, LocationSource,
GoogleApiClient.OnConnectionFailedListener, GeoQueryEventListener, ValueEventListener,LocationListener {
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
private GoogleMap mMap;
LocationManager locationManager;
RelativeLayout toolbarLayout;
String driverId = "5acgh565733";
RelativeLayout progressLayout1, progresslayout, onlinelay;
String tripState, onlinecheck;
FrameLayout fragmentcontainer;
TextView onlineTxt;
SharedPreferences.Editor editor;
String onlinestatus;
View mapView;
Bitmap mapBitmap;
Marker mCurrLocationMarker;
CameraUpdate cameraUpdate = null;
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private OnLocationChangedListener mMapLocationListener = null;
LocationRequest mLocationRequest;
Dialog d, dialogTripSummary, dialog;
ProgressWheel pwOne;
ImageView requestMapView;
ArrayList<LatLng> MarkerPoints;
Location mCurrentLocation, lStart, lEnd;
RelativeLayout FAB;
GeoFire geoFire;
BottomBar bottomBar;
boolean clicked = false;
public Map_Fragment() {
// Required empty public constructor
}
#SuppressLint("CommitPrefEdits")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_map, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
toolbarLayout = view.findViewById(R.id.toolbar);
onlinelay = view.findViewById(R.id.onlinelay);
onlineTxt = view.findViewById(R.id.onlineTxt);
FAB = view.findViewById(R.id.myLocationButton);
toolbarLayout.setVisibility(View.VISIBLE);
bottomBar=(BottomBar)getActivity().findViewById(R.id.bottomBar);
editor = this.getActivity().getSharedPreferences(Constants.MY_PREFS_NAME, getActivity().MODE_PRIVATE).edit();
if(mCurrentLocation!=null){
LatLng latLng = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
System.out.println("INSIDE LOCAION CHANGE" + mCurrentLocation.getLatitude() + mCurrentLocation.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng) // Sets the center of the map to current location
.zoom(15)
.tilt(0) // Sets the tilt of the camera to 0 degrees
.build();
mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.car))
.position(latLng));
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
checkOnlineStatus();
}
fabmethod();
onlinelay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Toast.makeText(getActivity(), "Online Clicked", Toast.LENGTH_SHORT).show();
setOnlineStatus();
}
});
return view;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if(mCurrentLocation!=null){
LatLng latLng = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
System.out.println("INSIDE LOCAION CHANGE" + mCurrentLocation.getLatitude() + mCurrentLocation.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng) // Sets the center of the map to current location
.zoom(15)
.tilt(0) // Sets the tilt of the camera to 0 degrees
.build();
mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.car))
.position(latLng));
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
Log.D(TAG,"You moved.. The current lat is "+location.getLatitude());
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.car));
mCurrLocationMarker = mMap.addMarker(markerOptions);
updateLocationToFirebase(location);
}
#Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mMapLocationListener = onLocationChangedListener;
}
#Override
public void deactivate() {}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getMinZoomLevel();
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
FAB.setVisibility(View.INVISIBLE);
toolbarLayout.setVisibility(View.INVISIBLE);
bottomBar.setVisibility(View.GONE);
}
});
mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
#Override
public void onCameraIdle() {
FAB.setVisibility(View.VISIBLE);
bottomBar.setVisibility(View.VISIBLE);
toolbarLayout.setVisibility(View.VISIBLE);
}
});
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Location Permission already granted
buildGoogleApiClient();
// mMap.setMyLocationEnabled(true);
} else {
//Request Location Permission
checkLocationPermission();
}
} else {
buildGoogleApiClient();
//mMap.setMyLocationEnabled(true);
}
// System.out.println("INSIDE LOCAION CHANGE" + mCurrentLocation);
if(mCurrentLocation!=null){
LatLng latLng = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
System.out.println("INSIDE LOCAION CHANGE" + mCurrentLocation.getLatitude() + mCurrentLocation.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng) // Sets the center of the map to current location
.zoom(15)
.tilt(0) // Sets the tilt of the camera to 0 degrees
.build();
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, Map_Fragment.this);
}
}
}
Toast.makeText(getActivity(),"Retriving current location. Please Wait...",Toast.LENGTH_LONG).show();
}
#Override
public void onDataChange(DataSnapshot dataSnapshot) {}
#Override
public void onCancelled(DatabaseError databaseError) {}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
private void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)) {
new AlertDialog.Builder(getActivity())
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION );
}
})
.create()
.show();
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION );
}
}
}
public void fabmethod() {
FAB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mCurrentLocation != null) {
LatLng latLng = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
System.out.println("INSIDE LOCAION CHANGE" + mCurrentLocation.getLatitude() + mCurrentLocation.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng) // Sets the center of the map to current location
.zoom(15)
.tilt(0) // Sets the tilt of the camera to 0 degrees
.build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
else{
Toast.makeText(getApplicationContext(),"mmap not Added", Toast.LENGTH_SHORT).show();
}
}
});
}
public void onPause() {
super.onPause();
//stop location updates when Activity is no longer active
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}
In the above Program , the onLocationChanged not called after resuming.
MainActivity.java
public class MainActivity extends FragmentActivity {
BottomBar bottomBar;
Fragment fragment =null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
bottomBar = (BottomBar) findViewById(R.id.bottomBar);
bottomBar.setVisibility(View.VISIBLE);
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
if (tabId == R.id.tab_profile) {
fragment = new Viewprofile_Fragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
if (tabId == R.id.tab_rating) {
fragment = new Ratings_Fragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
if (tabId == R.id.tab_earning) {
fragment = new Earnings_Fragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
if (tabId == R.id.tab_home) {
fragment = new Map_Fragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
}
});
}
#Override
public void onResume(){
super.onResume();
fragment = new Map_Fragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
}
In the above program, the onResume() ,method recreates the Map since
the Fragment recreated. So the Map takes time to load.
Final Words
Please Help me to enable Tracking location continuously even after maximizing the App
if ( mGoogleApiClient!=null && mLocationRequest!=null )
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
add this code in onResume() method of MapActivity.

Have tabs preload their Fragments when app starts and have tabs save state

I have 3 tabs:
Home
Google Map
Settings
I have a main activity which has a TabLayout to show the 3 tabs:
public class MainActivity extends AppCompatActivity implements MyMapFragment.OnFragmentInteractionListener, SettingsFragment.OnFragmentInteractionListener {
private static final int INDEX_HOME_FRAGMENT = 0;
private static final int INDEX_MAP_FRAGMENT = 1;
private static final int INDEX_SETTINGS_FRAGMENT = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Home"));
tabLayout.addTab(tabLayout.newTab().setText("Map"));
tabLayout.addTab(tabLayout.newTab().setText("Settings"));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch(tab.getPosition()) {
case INDEX_HOME_FRAGMENT:
HomeFragment homeFragment = new HomeFragment();
transaction.replace(R.id.frame_layout, homeFragment);
// Commit the transaction
transaction.commit();
break;
case INDEX_MAP_FRAGMENT:
MyMapFragment myMapFragment = new MyMapFragment();
transaction.replace(R.id.frame_layout, myMapFragment);
// Commit the transaction
transaction.commit();
break;
case INDEX_SETTINGS_FRAGMENT:
SettingsFragment settingsFragment = new SettingsFragment();
transaction.replace(R.id.frame_layout, settingsFragment);
// Commit the transaction
transaction.commit();
break;
default:
//error occured here
Log.e("Error occured = ", " TAB_ERROR");
break;
}
}
});
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.frame_layout) != null) {
if (savedInstanceState != null) {
return;
}
HomeFragment homeFragment = new HomeFragment();
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.frame_layout, homeFragment ).commit();
}
}
#Override
public void onFragmentInteraction(Uri uri) {
//do nothing
}
}
This Activity also handles when a tab gets clicked. When a tab gets clicked it should show the Fragment in the FrameLayout.
This all works fine. The only problem is when I click the Maps tab, Google maps always refreshes.
I want the map to preload when the app starts so when the user clicks the map tab the map shoudl already be loaded. As well when the user goes away from the map tab and comes back it should save the map as it was previously. Currently when the user goes back to the map tab the map is reloaded and it takes again some time for it to load.
This is my map Fragment:
public class MyMapFragment extends SupportMapFragment
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
GoogleMap mGoogleMap;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Marker lastOpenned = null;
#Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mGoogleMap == null) {
getMapAsync(this);
}
}
#Override
public void onPause() {
super.onPause();
//stop location updates when Activity is no longer active
if (mGoogleApiClient != null) {
//LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
LatLngBounds.Builder builder = new LatLngBounds.Builder();
mGoogleMap.addMarker(new MarkerOptions()
.position(new LatLng(40.76793169992044, -73.98180484771729))
.title("San Francisco"));
mGoogleMap.addMarker(new MarkerOptions()
.position(new LatLng(41.76793169992044, -72.98180484771729))
.title("Las Vegas"));
builder.include(new LatLng(40.76793169992044, -73.98180484771729));
builder.include(new LatLng(41.76793169992044, -72.98180484771729));
LatLngBounds bounds = builder.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 200));
mGoogleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
public boolean onMarkerClick(Marker marker) {
return true;
}
});
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Location Permission already granted
buildGoogleApiClient();
mGoogleMap.setMyLocationEnabled(true);
} else {
//Request Location Permission
checkLocationPermission();
}
} else {
buildGoogleApiClient();
mGoogleMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
}
private void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(getActivity())
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mGoogleMap.setMyLocationEnabled(true);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(getActivity(), "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
I would suggest not making new MyMapFragment() every time you click the tab if you don't want the map to reload.
A simple way to do that is a simple wrapper Fragment holder class.
public class MainActivity extends AppCompatActivity
implements MyMapFragment.OnFragmentInteractionListener, SettingsFragment.OnFragmentInteractionListener {
static class FragmentTab {
String name;
Fragment frag;
public FragmentTab(String name, Fragment f) {
this.name = name;
this.frag = f;
}
}
// These are only created once, not per-click
private List<FragmentTab> tabs = Arrays.asList(
new FragmentTab("Home", new HomeFragment()),
new FragmentTab("Map", new MyMapFragment()),
new FragmentTab("Settings", new SettingsFragment()),
);
Then, you can iterate and index that list to clean up the rest of your code
for (FragmentTab tab : tabs) {
tabLayout.addTab(tabLayout.newTab().setText(tab.name));
}
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, tabs.get(tab.getPosition()).frag)
.commit();
}
};
A LinkedHashMap<String, Fragment> would also work, but replacing tab.getPosition() for tab.getTitle() (I think)

getLastLocation() always null in GoogleApiClient

Am trying to build an application that requests the current location using the GoogleClientApi and LocationServices, but the Location is always null even that I enabled the WiFi,Mobile Data and GPS , tested it on several devices all the same
the permissions from the manifest.xml :
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Activity:
public class FindStation extends Fragment implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,com.google.android.gms.location.LocationListener
{
public static FragmentManager fragmentManager;
Button goButton;
Spinner spinner;
SupportMapFragment mapFragment;
GoogleMap map;
List<Stations> stationsList;
ArrayList<String> stationsAddresses;
private static View view;
ArrayList<MarkerOptions> markers;
GoogleApiClient mGoogleApiClient;
LocationServices locationServices;
Location location;
private static String TAG="FIND_STATION";
Context context;
LocationRequest mLocationRequest;
LocationListener locationListener;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
context= getActivity();
locationListener=this;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(10);
/*mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();*/
buildGoogleApiClient();
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
try {
view = inflater.inflate(R.layout.activity_find_station, container, false);
} catch (InflateException e) {
}
inflater.inflate(R.layout.activity_find_station,container,false);
stationsAddresses = new ArrayList<>();
goButton= (Button) view.findViewById(R.id.button);
//goButton.setVisibility(View.INVISIBLE);
spinner= (Spinner) view.findViewById(R.id.spinner);
stationsList = Stations.listAll(Stations.class);
markers = new ArrayList<>();
for (int i = 0; i <stationsList.size() ; i++) {
stationsAddresses.add(stationsList.get(i).getStationLocation());
markers.add(new MarkerOptions().position(new LatLng(stationsList.get(i).getStationLat(), stationsList.get(i).getStationLong())).title(stationsList.get(i).getStationName()));
}
goButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//location= LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
});
try {
initialize();
} catch (Exception e) {
e.printStackTrace();
}
try {
// map.setMyLocationEnabled(true);
} catch (Exception e) {
e.printStackTrace();
}
/*thread = new Thread(new MyThread());
thread.start();*/
return view;
}
private void initialize() {
if (map==null) {
Fragment fragment= getChildFragmentManager().findFragmentById(R.id.map);
mapFragment= (SupportMapFragment) fragment;
map=mapFragment.getMap();
for (int i = 0; i <markers.size() ; i++) {
map.addMarker(markers.get(i));
}
// check if map is created successfully or not
if (map==null) {
Toast.makeText(super.getActivity(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
}
public void onDestroyView() {
super.onDestroyView();
android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
SupportMapFragment fragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
if (fragment!=null) {
android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
ft.remove(fragment);
ft.commit();
}
}
#Override
public void onConnected(Bundle bundle) {
location= LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location!=null){
Log.d(TAG,location.toString());
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),3f);
map.animateCamera(update);
}
Log.d(TAG,"connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG,"connection suspended "+String.valueOf(i));
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG,"connection failed");
}
#Override
public void onLocationChanged(Location location) {`enter code here`
Log.d(TAG,location.toString());
this.location=location;
if (location!=null) {
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 3f);
map.animateCamera(update);
Log.d(TAG, "camera updated to new position");
goButton.setVisibility(View.VISIBLE);
}
}
#Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
Log.d(TAG,"connect() was called");
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
the strange thing is that the onConnect() method is called but after that the Location is always null and onLocationChanged() is never called
using the maps, i tried the enabling my location and it works when you have the button on the right top corner it returns the location and animates the camera.
UPDATE 1
updated the onConnected() method and made it request locations updates,
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationListener);
if (location!=null){
Log.d(TAG,location.toString());
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),3f);
map.animateCamera(update);
}
Log.d(TAG,"connected");}
then with a button i call lastKnownLocation() since the onLocationChanged() is not called still, and still the returned Location is null
UPDATE 2 :
The very same code worked on Android 5.0.1 and worked perfectly
all the other devices was on android 2.3.7,4.0.1 none of them worked,
Any idea about what difference in the Android APIs regarding the location?
You need to call requestLocationUpdates() in order to register the listener and have onLocationChanged() invoked.
Be sure to un-register the listener as soon as possible to avoid excessive battery drain.
Also note that the getLastLocation() method can and will return null. The main problem is that it doesn't prompt a request to the OS for a new location lock, instead it just checks if there was a last known location from some other app's location request. If no other app had recently made a location request, then you get a null location returned to you.
The only way to guarantee that you actually get a location is to request one, and this is done with a call to requestLocationUpdates().
Here is a working example for reference:
public class MainActivity extends FragmentActivity
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap map;
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private Marker marker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
buildGoogleApiClient();
mGoogleApiClient.connect();
if (map == null) {
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap retMap) {
map = retMap;
setUpMap();
}
public void setUpMap(){
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
map.setMyLocationEnabled(true);
}
#Override
protected void onPause(){
super.onPause();
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
protected synchronized void buildGoogleApiClient() {
Toast.makeText(this, "buildGoogleApiClient", Toast.LENGTH_SHORT).show();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onConnected(Bundle bundle) {
Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setSmallestDisplacement(0.1F);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
//remove previous current location Marker
if (marker != null){
marker.remove();
}
double dLatitude = mLastLocation.getLatitude();
double dLongitude = mLastLocation.getLongitude();
marker = map.addMarker(new MarkerOptions().position(new LatLng(dLatitude, dLongitude))
.title("My Location").icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(dLatitude, dLongitude), 8));
}
}
One more thing, if your map is in a Fragment, there is no need to have a nested SupportMapFragment. You can just have your Fragment extend SupportMapFragment. This removes the need of having a nested Fragment, and you don't even need to inflate any layout xml, here is a simple example:
public class MapTabFragment extends SupportMapFragment
implements OnMapReadyCallback {
private GoogleMap mMap;
private Marker marker;
public MapTabFragment() {
}
#Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
setUpMap();
}
private void setUpMap() {
mMap.setMyLocationEnabled(true);
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
mMap.getUiSettings().setMapToolbarEnabled(false);
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
//remove previously placed Marker
if (marker != null) {
marker.remove();
}
//place marker where user just clicked
marker = mMap.addMarker(new MarkerOptions().position(point).title("Marker")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
}
});
}
}

Change zoom level Google Maps Api v2 on app start

Is it possible to change the zoom level as soon as the map is ready? When I open the app it shows the map and the blue dot for my location. However, the zoom level is the default 3. How can I change this? I know how to do it when the 'MyLocationButton'is clicked but not when the app starts.
This is my class
public class MainPhoneActivity extends FragmentActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationSource, LocationListener, OnMyLocationButtonClickListener, OnMapReadyCallback{
private GoogleApiClient mGoogleApiClient;
private OnLocationChangedListener mMapLocationListener = null;
// location accuracy settings
private static final LocationRequest REQUEST = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_phone);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.mapView);
mapFragment.getMapAsync(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
protected void onResume() {
super.onResume();
mGoogleApiClient.connect();
}
#Override
public void onPause() {
super.onPause();
mGoogleApiClient.disconnect();
}
#Override
public void onMapReady(GoogleMap map) {
map.setLocationSource(this);
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(this);
}
public void showMyLocation(View view) {
if (mGoogleApiClient.isConnected()) {
String msg = "Location = "
+ LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onLocationChanged(Location location) {
if (mMapLocationListener != null) {
mMapLocationListener.onLocationChanged(location);
}
}
#Override
public void onConnected(Bundle connectionHint) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, REQUEST,this);
}
#Override
public void onConnectionSuspended(int cause) {
// Do nothing
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Do nothing
}
#Override
public boolean onMyLocationButtonClick() {
return false;
}
#Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mMapLocationListener = onLocationChangedListener;
}
#Override
public void deactivate() {
mMapLocationListener = null;
}
}
You can set zoom level like following:
map.animateCamera(CameraUpdateFactory.newLatLngZoom(point,15));
Where point is your LatLng position. In this way you can center the map in that point with given zoom level.
Complete method:
#Override
public void onMapReady(GoogleMap map) {
map.setLocationSource(this);
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(this);
//newLatLngZoom(LatLng , ZoomLevel) -> choose your zoom level
// and change my 'point' with yours
map.animateCamera(CameraUpdateFactory.newLatLngZoom(point,15));
}
EDIT:
If you want to get the dot coords, you can try this:
Location loc = map.getMyLocation();
LatLng point = new LatLng(loc.getlatitude() , loc.getLongitude());
and use that point as center.
Complete method:
#Override
public void onMapReady(GoogleMap map) {
map.setLocationSource(this);
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(this);
Location loc = map.getMyLocation();
if(loc != null){
LatLng point = new LatLng(loc.getLatitude() , loc.getLongitude());
map.animateCamera(CameraUpdateFactory.newLatLngZoom(point,15));
}
}
This could cause a NullPointerException beacuse loc could be null.
OTHER SOLUTION
If you want to get only first time the coordinates, you should work in onLocationChanged, using a boolean variable to set first call.
Declare it CRDS_CALL = false;
#Override
public void onLocationChanged(Location location) {
if (mMapLocationListener != null) {
mMapLocationListener.onLocationChanged(location);
if(!CRDS_CALL){
LatLng point = new LatLng(location.getLatitude(), location.getLognitude());
map.animateCamera(CameraUpdateFactory.newLatLngZoom(point,15));
CRDS_CALL = true;
}
}
}
In this answer i use map, but you have to use your mapFragment, but if you want to use it in other methods over onCreate, you have to declare outside of it.
Add this just before the onCreate
SupportMapFragment mapFragment;
And inside it, use it like follwing:
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.mapView);
mapFragment.getMapAsync(this);
In that way, you can use mapFragment in other methods
Solution
The solution was to do everything #MikeKeepsOnShine said but remove the
Location loc = map.getMyLocation();
LatLng point = new LatLng(loc.getLatitude() , loc.getLongitude());
map.animateCamera(CameraUpdateFactory.newLatLngZoom(point,15));
part from onMapReady. Works absolutely perfectly now!
You should use this. And you should put this request in onMapReady() callback. Something like this:
#Override
public void onMapReady(GoogleMap map) {
map.setLocationSource(this);
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(this);
map.animateCamera(CameraUpdateFactory.zoomTo(14), 2000, null);
}
you have already done the new "MapAsync" way so you are one step forward to the result.
In order to zoom, you can use the animateCamera method for googleMap object to zoom to a specific location:
https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.html#animateCamera(com.google.android.gms.maps.CameraUpdate)
for example, a zoomin:
map.animateCamera(CameraUpdateFactory.zoomIn());
or if you already know "where":
map.animateCamera(CameraUpdateFactory.newLatLngZoom(knownlocation,17));
and you will be very close to the location.
If you need to do at the first "locationUpdate" you should keep a flag to false and set to true the first time you receive a location, at that time you perform the zoom to location.
EDIT: If you want to zoom only the first time, where you receive location updates (which is not really clear from your code), you can do, assuming you have a class variable like:
private boolean FIRST_TIME = true;
the following code:
if(FIRST_TIME){
myMap.animateCamera(CameraUpdateFactory.newLatLngZoom(location,17));
FIRST_TIME = false;
}
The best option is to remove the listener but it seems you use location updates as "blue dot" updates.
What worked for me was:
mMap.setMinZoomPreference(6.0f);
mMap.setMaxZoomPreference(20.0f);
You can modify the zoom preference values to your taste.

Categories

Resources