This is the error I'm getting: java.lang. Attempt to call the virtual method 'double android.location.Location.getLatitude()' on a null object reference results in a NullPointerException.Can anyone guide me on how to achieve this?
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks ,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
private ActivityMapsBinding binding;
private static final int MY_PERMISSION_REQUEST_CODE =71922 ;
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 300193;
private LocationRequest locationRequest;
private GoogleApiClient googleApiClient;
private Location mLastLocation ;
private static int UPDATE_INTERVAL =5000;
private static int FARTEST_INTERVAL =5000;
private static int DISPLACEMENT =10;
Marker marker;
DatabaseReference ref ;
GeoFire geoFire;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 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);
ref = FirebaseDatabase.getInstance().getReference("Test");
setupLocation();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case MY_PERMISSION_REQUEST_CODE:
if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
if(checkPlayServices())
{
buildGoogleApiCLient();
createLocationRequest();
displayLocation();
}
}
break;
}
}
private void setupLocation() {
try {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED )
{
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
}, MY_PERMISSION_REQUEST_CODE);
}
else {
if(checkPlayServices())
{
buildGoogleApiCLient();
createLocationRequest();
displayLocation();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void displayLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED )
{
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if(mLastLocation != null)
{
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
Log.d("EDMDEV",String.format("your location was changed: %f %f ",latitude,longitude));
// upDate to firebase
geoFire.setLocation("You", new GeoLocation(latitude, longitude), new GeoFire.CompletionListener() {
#Override
public void onComplete(String key, DatabaseError error) {
if(marker != null){
marker.remove(); //remove old marker
marker = mMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude,longitude))
.title("Ele"));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude,longitude),12.0f));
}
}
});
}
else {
Log.d("EDMDEV","cannot get ur location");
}
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FARTEST_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void buildGoogleApiCLient() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS)
{
if(GooglePlayServicesUtil.isUserRecoverableError(resultCode))
GooglePlayServicesUtil.getErrorDialog(resultCode,this,PLAY_SERVICES_RESOLUTION_REQUEST).show();
else {
Toast.makeText(this, "this device is not support", Toast.LENGTH_SHORT).show();
finish();
}
return false ;
}
return true;
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// LatLng syd = new LatLng( -34,151);
// mMap.addMarker(new MarkerOptions().position(syd).title("mar in syd"));
// mMap.moveCamera(CameraUpdateFactory.newLatLng(syd));
//Create area
LatLng village = new LatLng(35.7533,-122.4056);
mMap.addCircle(new CircleOptions()
.center(village)
.radius(500) // in meter
.strokeColor(Color.BLUE)
.fillColor(0x220000FF)
.strokeWidth(5.0f)
);
// 0.5f = 0.5km = 500 m
GeoQuery geoQuery = geoFire .queryAtLocation(new GeoLocation(village.latitude,village.longitude),0.5f);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
#Override
public void onKeyEntered(String key, GeoLocation location) {
sendNotification("EDKDD",String.format("%s entered village area ",key ));
}
#Override
public void onKeyExited(String key) {
sendNotification("EDKDD",String.format("%s no longer village area ",key ));
}
#Override
public void onKeyMoved(String key, GeoLocation location) {
sendNotification("Move",String.format("%s moved within the village area [%f/%f]",key,location.latitude, location.longitude ));
}
#Override
public void onGeoQueryReady() {
}
#Override
public void onGeoQueryError(DatabaseError error) {
Log.e("Error","" + error);// 36.46
}
});
}
private void sendNotification(String title, String content) {
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title)
.setContentText(content);
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this,MapsActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_IMMUTABLE);
builder.setContentIntent(contentIntent);
Notification notification = builder.build();
notification.flags = Notification.DEFAULT_SOUND;
notificationManager.notify(new Random().nextInt(),notification);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
displayLocation();
startLocationUpdate();
}
private void startLocationUpdate() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED )
{
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient,locationRequest,this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
displayLocation();
}
}
java.lang.NullPointerException Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.newapp.elephantapplication, PID: 3267
java.lang.NullPointerException: Attempt to invoke virtual method 'com.firebase.geofire.GeoQuery com.firebase.geofire.GeoFire.queryAtLocation(com.firebase.geofire.GeoLocation, double)' on a null object reference
at com.newapp.elephantapplication.MapsActivity.onMapReady(MapsActivity.java:224)
at com.google.android.gms.maps.zzat.zzb(com.google.android.gms:play-services-maps##18.0.0:1)
at com.google.android.gms.maps.internal.zzaq.zza(com.google.android.gms:play-services-maps##18.0.0:5)
at com.google.android.gms.internal.maps.zzb.onTransact(com.google.android.gms:play-services-maps##18.0.0:3)
at android.os.Binder.transact(Binder.java:387)
at eg.aZ(:com.google.android.gms.dynamite_mapsdynamite#220920047#22.09.20 (040308-0):2)
at com.google.maps.api.android.lib6.impl.bk.run(:com.google.android.gms.dynamite_mapsdynamite#220920047#22.09.20 (040308-0):1)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Just getting used to Java and Android and I've got the above error.
Can anyone guide me on how to achieve this?
Related
I'm implementing Google Maps api in which I'm trying to get the initial location at the start at onMapReady().
mCurrentLocation should be the variable that stores the location so I tried to output that in log in onMapReady(), but at the start mCurrentLocation is null, so first I have to request a location. I'm not familiar with the api. I made a guess and put startLocationUpdates(this) in the front.
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.setMyLocationEnabled(true);
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 14.0f));
// Start the update??
startLocationUpdates(this);
// This is where I want to retrieve the location coordinates
Log.w("Location", "Current reading: " + mCurrentLocation.toString());
}
It didn't work. In stack trace it says java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.location.Location.toString()' on a null object reference. I also tried other methods like initLocation() and it didn't work either.
This is rest of the code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
initLocations();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case ACCESS_FINE_LOCATION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, null /* Looper */);
}
return;
}
}
}
private void initLocations() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
ACCESS_FINE_LOCATION);
}
return;
}
}
private void startLocationUpdates(Context context) {
Intent intent = new Intent(context, LocationService.class);
mLocationPendingIntent = PendingIntent.getService(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Task<Void> locationTask = mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationPendingIntent);
if (locationTask != null) {
locationTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
Log.w("Main2Activity", ((ApiException) e).getStatusMessage());
} else {
Log.w("Main2Activity", e.getMessage());
}
}
});
locationTask.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.d("Main2Activity", "restarting gps successful!");
}
});
}
}
}
private void stopLocationUpdates(){
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
#Override
protected void onResume() {
super.onResume();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
accelerometer.startAccelerometerRecording();
}
private Location mCurrentLocation;
private String mLastUpdateTime;
LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
mCurrentLocation = locationResult.getLastLocation();
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.i("MAP", "new location " + mCurrentLocation.toString());
if (mMap != null)
mMap.addMarker(new MarkerOptions().position(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()))
.title(mLastUpdateTime));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()), 14.0f));
}
};
What is the proper way to request a location?
I'm always use the LocationManager to get the current location also make sure that your current gps is turned on.
final LocationManager locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
locationManager.requestSingleUpdate(criteria, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// this is where you get the location location.getLatitude(), location.getLongitude()
}
#Override public void onStatusChanged(String provider, int status, Bundle extras) { }
#Override public void onProviderEnabled(String provider) { }
#Override public void onProviderDisabled(String provider) { }
}, null);
You can use this approach :
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tracking_order);
mService = Common.geoCodeService();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mapFrag = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
}
public void onMapReady(GoogleMap googleMap)
{
mMap=googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(120000); // two minute interval
mLocationRequest.setFastestInterval(120000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Location Permission already granted
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
mMap.setMyLocationEnabled(true);
} else {
//Request Location Permission
checkLocationPermission();
}
}
else {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
mMap.setMyLocationEnabled(true);
}
}
LocationCallback mLocationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
Log.i("MapsActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng yourLocation = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(yourLocation);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(yourLocation, 11));
//after add marker for your location add marker for this order
drawRoute(yourLocation,Common.currentRequest.getAddress());
}
}
};
I'm new creating apps and I want to show a drawn route in a Google Map starting from the current location. I've just found how to get the current location, but now I'm stuck in the second part, which is drawing the route from the current location to another marker point.
Here is my code:
`public class Trazo_Rutas extends FragmentActivity implements
OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
GoogleApiClient googleApiClient;
LocationRequest locationRequest;
Location lastLocation;
Marker userLocation;
private static final int Request_User_Location_Code = 99;
PlaceAutocompleteFragment placeAutoComplete;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trazo__rutas);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkUserLocationPermission();
}
//Check if Google Play Services Available or not
if (!CheckGooglePlayServices()) {
Log.d("onCreate", "Finishing test case since Google Play Services are not available");
finish();
}
else {
Log.d("onCreate","Google Play Services available.");
}
//AutoComplete search bar
placeAutoComplete = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete);
placeAutoComplete.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
Log.d("Maps", "Place selected: " + place.getName());
}
#Override
public void onError(Status status) {
Log.d("Maps", "An error occurred: " + status);
}
});
// 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);
}
private boolean CheckGooglePlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result = googleAPI.isGooglePlayServicesAvailable(this);
if(result != ConnectionResult.SUCCESS) {
if(googleAPI.isUserResolvableError(result)) {
googleAPI.getErrorDialog(this, result,
0).show();
}
return false;
}
return true;
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setZoomControlsEnabled(true);
//get latlong for corners for specified place
LatLng corner1 = new LatLng(25.64379, -103.60966);
LatLng corner2 = new LatLng(25.64317, -103.20935);
LatLng corner3 = new LatLng(25.43872, -103.61104);
LatLng corner4 = new LatLng(25.43748, -103.20866);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(corner1);
builder.include(corner2);
builder.include(corner3);
builder.include(corner4);
LatLngBounds bounds = builder.build();
//add them to builder
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
// 20% padding
int padding = (int) (width * 0.20);
//set latlng bounds
mMap.setLatLngBoundsForCameraTarget(bounds);
//move camera to fill the bound to screen
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding));
//set zoom to level to current so that you won't be able to zoom out viz. move outside bounds
mMap.setMinZoomPreference(mMap.getCameraPosition().zoom);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
} else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
public boolean checkUserLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)){
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, Request_User_Location_Code);
} else {
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, Request_User_Location_Code);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case Request_User_Location_Code:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (googleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
Toast.makeText(this, "Se requieren Permisos de Google", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
}
protected synchronized void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
lastLocation = location;
if (userLocation != null) {
userLocation.remove();
}
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.draggable(true);
markerOptions.title("Tu ubicación");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
userLocation = mMap.addMarker(markerOptions);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16));
if (googleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
locationRequest = new LocationRequest();
locationRequest.setInterval(1100);
locationRequest.setFastestInterval(1100);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}`
My concern is that I don't know how to implement the other marker and draw the route.
Thank you.
I'm quite new in Android and I need a help.
I'm developing an app like Runkeeper, Nike Running Club etc. So I want to know how to add line which shows route you passed on Google Map.Like that.
I have already tried many methods from here, here and here , but I can't understand them.
I know that I have to use onLocationChanged drawpolyline, but I don't know how and I can't find anywhere explanation of it.
Here is how I was trying to do it, but it always crashes
GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
TextView textAutoUpdateLocation;
private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private static final String COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private Boolean mLocationPermissionGranted = false;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1234;
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationProviderClient;
private static final float DEFAULT_ZOOM = 15f;
private PolylineOptions polylineOptions;
private ArrayList<LatLng> arrayPoints;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textAutoUpdateLocation = (TextView) findViewById(R.id.autoupdatelocation);
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
getLocationPermission();
}
private void initMap() {
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync((OnMapReadyCallback) this);
}
private void getDeviceLocation() {
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
try {
if (mLocationPermissionGranted) {
final Task location = mFusedLocationProviderClient.getLastLocation();
location.addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
Location currentLocation = (Location) task.getResult();
moveCamera(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()), DEFAULT_ZOOM);
} else {
}
}
});
}
} catch (SecurityException e) {
}
}
private void moveCamera(LatLng latLng, float zoom) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom));
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (mLocationPermissionGranted) {
getDeviceLocation();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mMap.setMyLocationEnabled(true);
}
this.init();
}
private void init() {
String coordinates[] = { "37.517180", "127.041268" };
double lat = Double.parseDouble(coordinates[0]);
double lng = Double.parseDouble(coordinates[1]);
LatLng position = new LatLng(lat, lng);
GooglePlayServicesUtil.isGooglePlayServicesAvailable(
MainActivity.this);
// 맵 위치이동.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position, 15));
}
private void getLocationPermission() {
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
if (ContextCompat.checkSelfPermission(this.getApplicationContext(), FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this.getApplicationContext(), COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
initMap();
} else {
ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE);
}
} else {
ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE);
}
}
public void RequestPermissionResult(int requestCode, #NonNull String[]permissions, #NonNull int[]grantResults) {
switch (requestCode){
case LOCATION_PERMISSION_REQUEST_CODE:{
if (grantResults.length > 0) {
for (int i = 0; i<grantResults.length;i++){
if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
mLocationPermissionGranted=false;
return;
}
}
mLocationPermissionGranted=true;
initMap();
}
}
}
}
#Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions marker = new MarkerOptions();
marker.position(latLng);
mMap.addMarker(marker);
polylineOptions = new PolylineOptions();
polylineOptions.color(Color.RED);
polylineOptions.width(5);
arrayPoints.add(latLng);
polylineOptions.addAll(arrayPoints);
mMap.addPolyline(polylineOptions);
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Toast.makeText(MainActivity.this,
"onConnectionFailed: \n" + connectionResult.toString(),
Toast.LENGTH_LONG).show();
}
}
Please help and explain it to me.
Thanks beforehand.
LOGCAT
08-03 13:51:02.605 20065-20065/? E/Zygote: isWhitelistProcess - Process is Whitelisted
08-03 13:51:03.125 20065-20065/com.mcarrow.myapplication E/zygote64: The String#value field is not present on Android versions >= 6.0
08-03 13:51:03.810 20065-20065/com.mcarrow.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mcarrow.myapplication, PID: 20065
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference
at com.mcarrow.myapplication.MainActivity.onLocationChanged(MainActivity.java:209)
at com.google.android.gms.internal.location.zzay.notifyListener(Unknown Source:4)
at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(Unknown Source:8)
at com.google.android.gms.common.api.internal.ListenerHolder$zza.handleMessage(Unknown Source:16)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
You have NOT initialized arrayPoints.
In your code, change arrayPoints declaration to this
private ArrayList<LatLng> arrayPoints; = new ArrayList<LatLng>();
This is my tracking class, I have imported the relevant dependencies.
public class TrackingOrder extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener{
private GoogleMap mMap;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private final static int LOCATION_PERMISSION_REQUEST = 1001;
private Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private static int UPDATE_INTERVAL = 1000;
private static int FATEST_INTERVAL = 5000;
private static int DISPLACEMENT = 10;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tracking_order);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
requestRuntimePermission();
}
else
{
if(checkPlayServices())
{
buildGoogleApiClient();
createLocationRequest();
}
displayLocation();
}
displayLocation();
// 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);
}
private void displayLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
requestRuntimePermission();
}
else
{
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLastLocation != null)
{
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
//Adding Marker to location
LatLng yourLocation = new LatLng(latitude,longitude);
mMap.addMarker(new MarkerOptions().position(yourLocation).title("Your Location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(yourLocation));
mMap.animateCamera(CameraUpdateFactory.zoomTo(17.0f));
}
else
{
Toast.makeText(this, "Couldn't Get Location", Toast.LENGTH_SHORT).show();
}
}
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
private void requestRuntimePermission() {
ActivityCompat.requestPermissions(this, new String[]
{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
}, LOCATION_PERMISSION_REQUEST);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
displayLocation();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (checkPlayServices())
{
buildGoogleApiClient();
createLocationRequest();
}
}
break;
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
mGoogleApiClient.connect();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resultCode != ConnectionResult.SUCCESS)
{
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))
{
GooglePlayServicesUtil.getErrorDialog(resultCode,this,PLAY_SERVICES_RESOLUTION_REQUEST).show();
}
else
{
Toast.makeText(this, "This Device is not Supported", Toast.LENGTH_SHORT).show();
finish();
}
return false;
}
return true;
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onConnected(#Nullable Bundle bundle) {
displayLocation();
startLocationUpdates();
}
private void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
#Override
protected void onStart() {
super.onStart();
if(mGoogleApiClient != null)
mGoogleApiClient.connect();
}
}
I have changed FusedLocationApi to FusedLocatinProviderClient however it still shows errors.
When I enter FusedLocationProviderClient, it comes up red and won't work either. I get an error.
Due to the issue I am unable to find the users location on my application.
I am trying to add a marker to a current location of my device. Whatever I try, onLocationChanged method triggers once when I starts the app.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
private static final String LOG_TAG = "MainActivity";
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
//Initialize Google Play Services
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
} else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(3000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
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) {
Log.d(LOG_TAG, "current location " + location.toString());
mLastLocation = location;
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(mLastLocation);
markerOptions.title("Test");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
mCurrLocationMarker = mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(17));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[], int... grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
}
}
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onStop() {
super.onStop();
}
}
You need to remove these statements
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
Once they are gone you should have OnLocatioChanged working continuously.
You may try with OnMyLocationChangeListener like below:
public class MapsActivity extends FragmentActivity implements
OnMyLocationChangeListener {
#Override
public void onMyLocationChange(Location location) {
}
}