I am working on an app that has a method called PostCar that when called should create a databasereference and add a child to My Firebase Consoles Lender table a child that contains the user's id and location. The problem is the location keeps getting marked as null. The code in my PostCar method that reads "geoFire.setLocation(userId,new GeoLocation(mlastlocation.getLatitude(),mlastlocation.getLongitude()));" keeps throwing the error "attempt to invoke virtual method 'double android.location.location.getlatitude()' on a null object reference". The devices location is on and I check for location permissions. Here is the code below.
package com.example.movir;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.firebase.geofire.GeoFire;
import com.firebase.geofire.GeoLocation;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
public class LendersMenuPageActivity extends AppCompatActivity {
private String userId;
private FirebaseAuth mAuth;
private LocationManager lm;
Location mlastlocation;
LocationRequest locationRequest;
LocationCallback locationCallback;
private Button lendcarButton;
final LendCarForm cardlend = new LendCarForm(userId,"brand new Toyota","Toyota","Camry S9");
private FusedLocationProviderClient fusedLocationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lenders_menu_page);
mAuth = FirebaseAuth.getInstance();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, 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
}
}
});
FirebaseUser currentUser = mAuth.getCurrentUser();
userId = currentUser.getUid();
DatabaseReference lendersReference = FirebaseDatabase.getInstance().getReference("Users").child("Lenders").child(userId);
lendcarButton = findViewById(R.id.lenders_car_button);
lendcarButton.setOnClickListener(onClick);
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
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;
}
LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
if(getApplicationContext()!=null) {
mlastlocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
}
}
}
};
mlastlocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
#Override
protected void onStart() {
super.onStart();
checkLocationPermission();
}
private void startLocationUpdates() {
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback,
Looper.getMainLooper());
}
public View.OnClickListener onClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(LendersMenuPageActivity.this,"hello",Toast.LENGTH_LONG);
postCar();
}
};
private void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
new AlertDialog.Builder(this)
.setTitle("give permission")
.setMessage("give permission messaage")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(LendersMenuPageActivity.this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION
}, 1);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(LendersMenuPageActivity.this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION
}, 1);
}
}
}
public void postCar(){
DatabaseReference carsForRent = FirebaseDatabase.getInstance().getReference("Users").child("Lenders").child(userId);
GeoFire geoFire = new GeoFire(carsForRent);
geoFire.setLocation(userId,new GeoLocation(mlastlocation.getLatitude(),mlastlocation.getLongitude()));
carsForRent.setValue(cardlend);
}
}
Are you testing this with the Xcode IOS simulator? The simulator can't actually access your real location so when queried it will return null unless specified manually (Features tab, Location, Custom Location.)
The reason fusedapi was not working for me is because i was not using a google maps project. So I overode onlocatiochanged instead. This worked for me, but you have to extend onlcationchanged and googleapi
Related
Is there a way to get latitude longitude constantly updated without running Google MAPS app in emulators background. I would like to receive updated latitude and longitude from the users device. The code gets the latitude and longitude only after I change between apps or setup a driving route and press the button. I would like to update every X amount of time.
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
public class MainActivity extends AppCompatActivity {
Button bt_Location;
TextView tv_nearStopName, tv_nextBusIDtoNearStop;
EditText txtinput_busID;
FusedLocationProviderClient fusedLocationProviderClient;
LocationHelper locationHelper;
User user;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//assign variables
bt_Location = findViewById(R.id.bt_checkIN);
tv_nearStopName = findViewById(R.id.tv_stopName);
tv_nextBusIDtoNearStop = findViewById(R.id.tv_nextBusID);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
txtinput_busID = findViewById(R.id.txtinput_busID);
//if not get location permissions...
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
user = new User(0.0,0.0);
getCurrentLocation();
}else {
ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1000);
}
bt_Location.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getCurrentLocation()
}
});
}//end onCreate
#Override
protected void onStart() {
super.onStart();
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
getCurrentLocation();
}else {
ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1000);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 100 && grantResults.length > 0 && (grantResults[0] + grantResults[1] == PackageManager.PERMISSION_GRANTED)) {
getCurrentLocation();
} else {
Toast.makeText(getApplicationContext(), "Permission denied.", Toast.LENGTH_SHORT).show();
}
}
#SuppressLint("MissingPermission")
private void getCurrentLocation() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
fusedLocationProviderClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
Location location = task.getResult();
//check condition
if (location != null){
//initialize user object
user.setLongitude(location.getLongitude());
user.setLatitude(location.getLatitude());
tv_nextBusIDtoNearStop.setText(String.valueOf(user.getLongitude()));
}else {
LocationRequest locationRequest = new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(1000).setFastestInterval(100).setNumUpdates(1);
LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Log.d("DEBUGGING: ", "onLocationResult executing....");
Location location1 = locationResult.getLastLocation();
user.setLatitude(location1.getLatitude());
user.setLongitude(location1.getLongitude());
// tvLatitude.setText(String.valueOf(user.getLatitude()));
tv_nextBusIDtoNearStop.setText(String.valueOf(user.getLongitude()));
}
};
locationReqeuest, locaitoncallback, Looper.MyLooper()
fusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
}
});
}else {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}//end getCurrentLocation
}
I made this page a while back but I've come back to it and a lot of the tags have depreciated. Could anyone give me some help on what to replace them with? I'm hoping it isn't the case but I'm expecting the rest of the code to be useless now that the tags need changing.
Here is a list of the tags that are not used (have a line through them in android studio)
GoogleApiClient
ConnectionCallBacks
OnConnectionFailedListener
Builder
FusedLocationApi
Thanks,
Max
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentActivity;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class DriverMapActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
private GoogleMap mMap;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
LocationRequest mLocationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_driver_map);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
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 onLocationChanged(Location location) {
mLastLocation = location;
LatLng latLng = new LatLng(location.getLatitude (), location.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
#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) {
mLocationRequest =new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}```
GoogleApiClient: GoogleApi based APIs.
ConnectionCallBacks: Same as above. API implementors should use the stand-alone ConnectionCallbacks instead.
OnConnectionFailedListener: Same as above. Api implementors should use the stand-alone OnConnectionFailedListener instead.
Builder: Same as above.
See Moving Past GoogleApiClient.
As for FusedLocationProviderApi, use the GoogleApi-based API FusedLocationProviderClient instead.
Hope this helps!
im writing android navigation app using geolocation but i have problem with frequency updating location.
picture
i get response in log.d() after approx 20 seconds. Im afraid its too slow for example when i use it while driving. The assumption is that the Marker should move smoothly.
NavigationActivity class:
package com.nowinski.kamil.drivertool;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlaceAutocompleteFragment;
import com.google.android.gms.location.places.ui.PlaceSelectionListener;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import utils.LatLngInterpolator;
import utils.MarkerAnimation;
public class NavigationActivity extends FragmentActivity implements
OnMapReadyCallback, LocationListener {
private GoogleMap mMap;
private LocationManager locationManager;
private Location location;
private double latitude;
private double longitude;
private PlaceAutocompleteFragment placeAutocompleteFragment;
private Marker marker;
private Marker markerCurrentLocation = null;
private final float ZOOM = 12.2f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
// 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);
//initialize placeAutocompleteFragment and set on listener
placeAutocompleteFragment = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);
placeAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
final LatLng latLngLoc = place.getLatLng();
if(marker!=null){
marker.remove();
}
marker = mMap.addMarker(new MarkerOptions().position(latLngLoc).title(place.getName().toString()));
mMap.animateCamera(CameraUpdateFactory.zoomTo(12), 2000, null);
}
#Override
public void onError(Status status) {
Toast.makeText(NavigationActivity.this, ""+status.toString(), Toast.LENGTH_SHORT).show();
}
});
//check permissions
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;
}
//initialize locationManager to get the location system service
locationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location != null){
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
private void updateMarkerPosition(Location newLocation){
//test
Log.d("locationChanged", Double.toString(newLocation.getLatitude())+" "+Double.toString(newLocation.getLongitude()));
LatLng newLatLng = new LatLng(newLocation.getLatitude(), newLocation.getLongitude());
//if marker used first time addMarker to map and move camera
if(markerCurrentLocation == null){
markerCurrentLocation = mMap.addMarker(new MarkerOptions().position(newLatLng));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(newLatLng, ZOOM));
} else {
MarkerAnimation.animateMarkerToICS(markerCurrentLocation, newLatLng, new LatLngInterpolator.Spherical());
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newLatLng, ZOOM));
}
}
#Override
public void onLocationChanged(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
this.location = location;
updateMarkerPosition(location);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
//activity life cycle
#Override
protected void onDestroy(){
super.onDestroy();
//stop GPS
locationManager.removeUpdates(this);
}
}
There are detected activities when user is walking or driving or running. Google doc.
But i suggest you implement this by using these well tested and maintained libraries like
1.https://github.com/akexorcist/Android-GoogleDirectionLibrary
2.https://github.com/jd-alexander/Google-Directions-Android
Which provide you many in library functions to use. and you will need not to RnD on everything of location listening.
i tried for hours to get my location,but that does not work...
i did it with a video guide step by step, the emulator is shot down while i run the application.
I already try lot of things like this solution.
And the GPS is enable in the virtual device... It's not working on my phone too. So this is my code
package com.example.idanhay.safebox;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class settings extends AppCompatActivity {
private Button button;
private TextView textView;
private LocationManager locationManager;
private LocationListener locationListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting2);
button = (Button) findViewById(R.id.bloc);
textView = (TextView) findViewById(R.id.tvloc);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
textView.append("/n" + location.getAltitude() + "" + location.getLongitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(settings.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.INTERNET}, 10);
return;
}
} else
configurationButten();
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grandresult) {
switch (requestCode) {
case 10:
if (grandresult.length > 0 && grandresult[0] == PackageManager.PERMISSION_GRANTED)
configurationButten();
return;
}
}
private void configurationButten() {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(settings.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;
}
}
locationManager.requestLocationUpdates("gps", 4000, 0, locationListener);
}
});
/*
My current goal is to send the LatLng to Firebase. I did achieve this but the problem I have now is that after a couple of updates to Firebase, my location field starts to receive updates super fast which in turn lags my application and also increases my phones temperature.
How would I go about sending location updates to firebase twice every minute without having the application lag?
I send the location updates to Firebase under the onLocationChanged(Location) method.
Here is my Mapfragment class.
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.mycompany.neighbors.MainActivity;
import com.mycompany.neighbors.R;
import com.mycompany.neighbors.User;
/**
* Created by joshua on 5/25/2016.
*/
public class MapFragment extends Fragment implements OnMapReadyCallback,LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
private GoogleApiClient mGoogleApiClient;
private final String FIREBASE_URL = "MY_URL";
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 101;
SupportMapFragment mSupportMapFragment;
private GoogleMap maps;
private boolean permissionIsGranted = false;
private LatLng mLatLng;
private User mApplicationUser;
private static String mApplicationUserUID;
public static MapFragment newInstance(int index){
MapFragment mapFragment = new MapFragment();
Bundle args = new Bundle();
args.putInt("index",index);
mapFragment.setArguments(args);
return mapFragment;
}
private void createMap(){
mSupportMapFragment = SupportMapFragment.newInstance();
FragmentManager fm = getFragmentManager();
mSupportMapFragment.getMapAsync(this);
if(!mSupportMapFragment.isAdded())
fm.beginTransaction().add(R.id.map_frag,mSupportMapFragment).commit();
else if(mSupportMapFragment.isAdded())
fm.beginTransaction().hide(mSupportMapFragment).commit();
else
fm.beginTransaction().show(mSupportMapFragment).commit();
}
private void requestLocationUpdates() {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(60000);
if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
/////////////////////////////////////////OVERRIDE METHODS////////////////////////////////////////////////////////////
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_map,container,false);
mApplicationUserUID = MainActivity.getUID();
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
createMap();
return v;
}
////////////////////////////////////////LIFECYCLE METHODS///////////////////////////////////////////////////////////
#Override
public void onStart(){
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onResume(){
super.onResume();
if(permissionIsGranted){
if(mGoogleApiClient.isConnected()){
requestLocationUpdates();
}
}
}
#Override
public void onStop(){
if(permissionIsGranted){
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
mGoogleApiClient.disconnect();
}
super.onStop();
}
///////////////////////LIFECYCLE METHODS//////////////////////////////////////////////
#Override
public void onMapReady(GoogleMap googleMap) {
maps = googleMap;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d("TAG_JOSH", "onConnected");
requestLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
Log.d("TAG_JOSH", "Connection suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d("TAG_JOSH", "Connection failed");
}
#Override
public void onLocationChanged(final Location location) {
Log.d("TAG_JOSH","Latitude: " +Double.toString(location.getLatitude()));
final LatLng coordinates = new LatLng(location.getLatitude(),location.getLongitude());
final Firebase userRef = new Firebase("MY_URL");
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userRef.setValue(coordinates);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults){
super.onRequestPermissionsResult(requestCode,permissions,grantResults);
switch(requestCode){
case MY_PERMISSIONS_REQUEST_FINE_LOCATION:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Permission granted
permissionIsGranted = true;
} else{
//Permission denied
permissionIsGranted = false;
Toast.makeText(getContext(),"This app requires location permissions", Toast.LENGTH_SHORT).show();
}
break;
}
}
/////////////////////////////////////////OVERRIDE METHODS////////////////////////////////////////////////////////////
}
If you're trying to send your location twice a minute, you need to remove the part of sending location updates in Firebase inside onLocationChanged.
Add a CountDownTimer and trigger to send a location update after each 30 seconds have passed.
So you need to do something like this.
Take two global variables
private Location currentLocation;
private Location previousLocation;
Now inside your onCreateView declare a timer like this.
new CountDownTimer(30000, 1000) { // 30 seconds timer
public void onTick(long millisUntilFinished) {
// Do nothing
}
public void onFinish() {
// Send location update to firebase here if the previous location sent to server and the current location is not the same.
final LatLng coordinates = new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude());
if(currentLocation == previousLocation) return; // Pseudo code
final Firebase userRef = new Firebase("MY_URL");
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userRef.setValue(coordinates);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
// Now start the timer from here again.
this.start(); // Pseudo code.
}
}.start();
Inside your onLocationChanged function, just update the currentLocation like this
#Override
public void onLocationChanged(final Location location) {
currentLocation = location; // Update the current location here
}