I have followed some online tutorials for adding markers to the google maps api in android. There code is structured differently from mine but in general I saw them do it in the onCreate method. Below I have a really basic code to try and get a marker in the middle of the map, however, I get a null pointer exception. Does anyone know of a simple fix to this?
Here is the error in detail and below is my method. I have map declared as a global variable.
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.Marker com.google.android.gms.maps.GoogleMap.addMarker(com.google.android.gms.maps.model.MarkerOptions)' on a null object reference
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serviceManager = ServiceManager.getInstance(getActivity());
userID = getString(R.string.mobile_health_client_user_id);
client = MobileIOClient.getInstance(getContext(), userID);
//client = MobileIOClient.getInstance(userID);
map.addMarker(new MarkerOptions()
.position(new LatLng(0, 0))
.title("Hello world"));
}
I have also ran through the google tutorial which overrides onMapReady() but that method did not work for me either. I am not sure how to get it working in my code and can't find adequate resource online to assist me. Any help would be appreciated.
Thanks
You should not be interacting with the map object in your activity or fragment's onCreate() method. The simple reasoning being that the map probably isn't ready yet. The proper way to handle this is to implement the OnMapReadyCallback interface and add you marker in your implementation of the onMapReady(GoogleMap googleMap) function.
Your solution will need to be slightly different if you are using a MapFragment vs a MapView, but the general idea remains the same.
Example:
public class MyActivity extends Activity implements OnMapReadyCallback {
.
.
#Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap; // Set your local instance of GoogleMap for future use
map.addMarker(new MarkerOptions()
.position(new LatLng(0, 0))
.title("Hello world"));
}
.
.
}
If you are using a MapView, you will need to get a handle to your view in your layout and explicitly call map.getMapAsync(this) in order to attach the onMapReady() listener.
I hope this helps!
Here is the code I use:
public class Map extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleMap mMap;
public GoogleApiClient mGoogleApiClient;
public static final String TAG = Map.class.getSimpleName();
public LocationRequest mLocationRequest;
double latitude;
double longitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng here = new LatLng(latitude,longitude);
mMap.addMarker(new MarkerOptions().position(here).title("Here!"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(here));
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "Location services connected.");
Location location = null;
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
else {
handleNewLocation(location);
};
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
protected void onResume(){
super.onResume();
//setUpMapIfNeeded();
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
latitude = location.getLatitude();
longitude = location.getLongitude();
LatLng latLng = new LatLng(latitude,longitude);
MarkerOptions options = new MarkerOptions()
.position(latLng)
.title("I am here!");
mMap.addMarker(options);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
#Override
public void onLocationChanged(Location location) {
handleNewLocation(location);
}
}
Write simply in onMapReadygoogleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0));
Related
I want to access my location using google maps and I don't know why it doesn't work.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
that is what appears when I rule the emulator:
Now I try to learn sth about maps, but in final I want to press on a button and to apear in google maps the location of a restaurant or sth else. How can I do this?
This is the Complete Code for accessing device location (not including the maps key part which i think you have already done)
public class MapsActivity extends FragmentActivity implements
OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
{
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
public Location mLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
#Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
public void onConnected( Bundle bundle) {
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLocation != null && mMap != null) {
LatLng tun = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(tun).title("Marker in Sydney"));
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
you have to write this code in the manifest.xml as well
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
this will allow app to be able to use device's location
The only thing that remains is that you MUST do GRANT the access of the Location by going to the settings of the app in the permissions menu Allow App for GPS location in other case it will not show the location
'com.google.android.gms:play-services:11.0.2'
you have to compile play services in order to access LocationListener
Did you add the acces location permissions in the manifest
I have been trying to implement markers in my google maps activity while the application runs. There are some pre-defined "Location" objects, and there is a marker at the "current location" of the user.
Using a SeekBar, I'm trying to change the range of the current location in which the markers of the location objects should be displayed, but on changing the SeekBar, nothing happens (no markers get added, there's just one at the current location). Apologies for the unwanted extra code, I believe the most important parts to look at are onConnected(), onSeekBarChangedListener() and onMapReady()
This is my MapsActivity.java:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.
OnConnectionFailedListener, OnSeekBarChangeListener {
private GoogleApiClient googleApiClient;
private SeekBar rangeSeekBar;
private GoogleMap mMap;
private Intent intent;
private Location currentLocation;
private Location[] locations;
private double range;
Location locationOne;
Location locationTwo;
Location locationThree;
Location locationFour;
Location locationFive;
Location locationSix;
Location locationSeven;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
locationOne = new Location("");
locationTwo = new Location("");
locationThree = new Location("");
locationFour = new Location("");
locationFive = new Location("");
locationSix = new Location("");
locationSeven = new Location("");
locationOne.setLatitude(10.1399);
locationOne.setLongitude(76.1784);
locationTwo.setLatitude(10.2244);
locationTwo.setLongitude(76.1978);
locationThree.setLatitude(9.6175);
locationThree.setLongitude(76.4301);
locationFour.setLatitude(9.5987);
locationFour.setLongitude(76.3116);
locationFive.setLatitude(9.6175);
locationFive.setLongitude(76.4301);
locationSix.setLatitude(9.6737);
locationSix.setLongitude(76.5610);
locationSeven.setLatitude(15.5152);
locationSeven.setLongitude(73.8565);
locations = new Location[]{
locationOne,
locationTwo,
locationThree,
locationFour,
locationFive,
locationSix,
locationSeven
};
rangeSeekBar = (SeekBar)findViewById(R.id.rangeSeekBar);
rangeSeekBar.setProgress(0);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
protected void onStop() {
super.onStop();
googleApiClient.disconnect();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng india = new LatLng(20.5937, 78.9629);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(india, 5));
if(googleApiClient==null){
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
googleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if(ContextCompat.checkSelfPermission(MapsActivity.this, android.Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION},1);
} else {
currentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
LatLng currentLoc = new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(currentLoc).title("Your current location"));
}
addingMarkersInRange(0);
}
public void addingMarkersInRange(double range){
for(int i=0;i<locations.length;i++){
if(currentLocation.distanceTo(locations[i])<range) {
LatLng tempLatLng = new LatLng(locations[i].getLatitude(), locations[i].getLongitude());
mMap.addMarker(new MarkerOptions().position(tempLatLng));
mMap.moveCamera(CameraUpdateFactory.newLatLng(tempLatLng));
}
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
addingMarkersInRange(rangeSeekBar.getProgress()*700000);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
Your addinMarkersInRange() method is only adding markers for LatLngs in locations array. So, you need to add to locations array before invoking addingMarkersInRange. But, since you cannot add to an array, please change locations to a List and you should be good to go.
You are not setting listener on SeekBar object. Please set OnSeekBarChangeListener like so in your onCreate():
// code you already have
rangeSeekBar = (SeekBar)findViewById(R.id.rangeSeekBar);
rangeSeekBar.setProgress(0);
// register event listener here
rangeSeekBar.setOnSeekBarChangeListener(this);
I think you have issue in addingMarkersInRange().
But let proceed in a way,
First set listener to seekbar. Then set max value of seekbar.
Now initially call addingMarkersInRange(1) instead of passing zero.
Now while seek bar change make use of isfromUser flag in onProgress change.
And remove that onCameraChange() & place it outside of for loop. And use latlongbound to animate camera zoom level.
Now run and check any change made on UI ...!
I new in coding google map,
my question is how i control the user gestur drag , zoom in and zoom out.
because my code always back to the current location of user when i zoomin/out, nad when i drag/ scroll up, down, left, right. always back to the current possition .
its my code for current loc user
private GoogleMap.OnMyLocationChangeListener myLocationChangeListener = new GoogleMap.OnMyLocationChangeListener() {
#Override
public void onMyLocationChange(Location location) {
LatLng loc = new LatLng(location.getLatitude(), location.getLongitude());
mMarker = mMap.addMarker(new MarkerOptions().position(loc));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 16));
}
};
You can use a boolean to move the camera only the first time:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMyLocationChangeListener {
private GoogleMap mMap;
private Marker mMarker;
private boolean firstTime = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMyLocationEnabled(true);
mMap.setOnMyLocationChangeListener(this);
}
#Override
public void onMyLocationChange(Location location) {
LatLng loc = new LatLng(location.getLatitude(), location.getLongitude());
mMarker = mMap.addMarker(new MarkerOptions().position(loc));
if (firstTime) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 16));
firstTime = false;
}
}
}
NOTE: Take into account that this example uses GoogleMap.OnMyLocationChangeListener only because that is the method that you are using in your question, but it's deprecated and you must use the FusedLocationProviderApi according to the documentation:
public final void setOnMyLocationChangeListener
(GoogleMap.OnMyLocationChangeListener listener)
This method was deprecated. use
com.google.android.gms.location.FusedLocationProviderApi instead.
FusedLocationProviderApi provides improved location finding and power
usage and is used by the "My Location" blue dot. See the
MyLocationDemoActivity in the sample applications folder for example
example code, or the Location Developer Guide.
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.
public class MainActivity extends FragmentActivity{
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
//mMap.setMyLocationEnabled(true);
}
}
This is my Activity.
I want to start my app with my current location. I looked for some codes but none have the answer that I want. Can someone tell me what I should add?
Did you try:
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 10);
map.animateCamera(cameraUpdate);
Please use Android's LocationManager to get Lat/Lng with respect to your current services. Please refer to this answer that explains the usage of LocationManager.
After getting a Location object from the LocationManager, use the lat/lng to position the map like this.