Use ActivityContext in service for Custom Listner - android

PrimaryDashBoard where i use LocatinListener and retrieve the location from the service
public class PrimaryDashboard extends AppCompatActivity implements LocationListener {
public LatLng myLatLng=new LatLng(0.0,0.0);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primary_dashboard);
try {
Intent i = new Intent(this, LocationManager.class);
startService(i);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onLocationChanged(Location location) {
myLatLng=new LatLng(location.getLatitude(),location.getLongitude());
}
#Override
public void GPSDisabled(String errorMessage) {
}
#Override
public void GPSEnabled() {
}
}
Here is LocationListner
public interface LocationListener {
public void onLocationChanged(Location location);
public void GPSDisabled(String errorMessage);
public void GPSEnabled();
}
Here is my Service where i want to initilized the LocationListner and want to update the location values from the listners
public class LocationManager extends IntentService {
private static final String TAG = LocationManager.class.getSimpleName();
// Registered callbacks
public LocationListener locationUpdate;
public static final int REQUEST_CHECK_SETTINGS = 0x1;
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private FusedLocationProviderClient mFusedLocationClient;
private SettingsClient mSettingsClient;
private LocationRequest mLocationRequest;
private LocationSettingsRequest mLocationSettingsRequest;
private LocationCallback mLocationCallback;
private Location mCurrentLocation;
private Boolean mRequestingLocationUpdates = false;
#SuppressLint("ServiceCast")
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
this.locationUpdate = (LocationListener) getApplicationContext();
mRequestingLocationUpdates = false;
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
mSettingsClient = LocationServices.getSettingsClient(getApplicationContext());
createLocationCallback();
createLocationRequest();
buildLocationSettingsRequest();
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
startLocationUpdates();
}
return START_STICKY;
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
}
#SuppressLint("ServiceCast")
#Override
public void onCreate() {
super.onCreate();
}
public LocationManager() {
super("locationManager");
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Creates a callback for receiving location events.
*/
private void createLocationCallback() {
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
mCurrentLocation = locationResult.getLastLocation();
PrefManager.getInstance(getApplicationContext()).setLastLatLng(Double.valueOf(locationResult.getLastLocation().getLatitude()), Double.valueOf(locationResult.getLastLocation().getLongitude()));
if (locationUpdate != null)
locationUpdate.onLocationChanged(locationResult.getLastLocation());
}
};
}
private void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
private void startLocationUpdates() {
// Begin by checking if the device has the necessary location settings.
mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
#SuppressLint("MissingPermission")
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
LogCat.show("All location settings are satisfied.");
if (locationUpdate != null)
locationUpdate.GPSEnabled();
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
if (locationUpdate != null)
locationUpdate.GPSDisabled("Location settings are not satisfied. Attempting to upgrade location settings ");
LogCat.show("Location settings are not satisfied. Attempting to upgrade location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult((Activity) getApplicationContext(), REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
LogCat.show(errorMessage);
if (locationUpdate != null)
locationUpdate.GPSDisabled(errorMessage);
Toast.makeText(getApplicationContext(), errorMessage, Toast.LENGTH_LONG).show();
mRequestingLocationUpdates = false;
}
}
});
}
}
This line of code create me a problem because it want Activity context, when it will not be a service and i pass activity Context it works perfect.
this.locationUpdate = (LocationListener) getApplicationContext();
Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to driver.com.driver.LocationComponents.LocationListener
java.lang.RuntimeException: Unable to create service driver.com.driver.LocationComponents.LocationManager: java.lang.ClassCastException: android.app.Application cannot be cast to driver.com.driver.LocationComponents.LocationListener

Firstly , Your application class does not implement the LocationListener interface so your are getting this error. You cannot get the Activity instance inside your intent service , because 1) It may no longer be active 2) Intent Service can be started from other services or broadcast receivers. In order to communicate the LocationListener methods with your activity , you need to use a LocalBroadcastManager.

Related

Get last location from FusedLocation in service

I' trying to getLastLocation() in my Service, witch is starting every minute. As I can see, fusedLocation requires Activity or Executor in .addOnSuccessListener(). How I can get it in Service?
LocationCheckService.class
public class LocationCheckService extends Service{
private FusedLocationProviderClient mFusedLocationClient;
#Override
public void onCreate() {
super.onCreate();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.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) {
}
}
});
}
#SuppressLint("MissingPermission")
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
You don't need GoogleApiClient -
first in gradle add -
implementation 'com.google.android.gms:play-services-location:15.0.0'
In Android Manifest -
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
than create a service to get location update as -
public class LocationUpdateService extends Service {
private FusedLocationProviderClient client;
private LocationRequest locationRequest;
#Override
public void onCreate() {
super.onCreate();
client = LocationServices.getFusedLocationProviderClient(this);
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(0);
locationRequest.setFastestInterval(0);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
client.requestLocationUpdates(locationRequest, locationCallback, null);
} catch (SecurityException ignore) {
Log.e("AppLocationService", "SecurityException - " + ignore.toString(), ignore);
}
return START_STICKY;
}
private final LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
List<Location> locationList = locationResult.getLocations();
if (locationList.size() != 0) {
Location location = locationList.get(0);
Log.e("AppLocationService", "Latitude - " +location.getLatitude()+", longitude - " +location.getLongitude() );
}
}
};
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
}
To get update in activity you can use LocalBroadCast OR same code you can use in Activity
NOTE : don't forget to take permission above 23
I provide one separate class for fetching location data using faused API. you can call this class into your service it gets latest location lat and long value.
public class GPSController implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
OnLocationUpdateListener onLocationUpdateListener;
public final String TAG = getClass().getSimpleName();
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
GoogleApiClient googleApiClient;
LocationRequest mLocationRequest;
Location mCurrentLocation;
private static long INTERVAL = 1000 * 10;
private static long FASTEST_INTERVAL = 1000 * 5;
FragmentActivity mActivity;
private boolean isLiveUpdate = false;
PendingResult<LocationSettingsResult> result;
/**
* Checking permission and connect with Google Location service
* #param activity
*/
public GPSController(FragmentActivity activity) {
this.mActivity = activity;
if(PermissionManager.checkPermission(mActivity,PermissionManager.ACCESS_LOCATION))
{
if (!isGooglePlayServicesAvailable()) {
CustomLogHandler.printInfolog("checking googleplayservice : ", "false");
((BaseActivity)mActivity).showAlertDialog(mActivity, mActivity.getString(R.string.app_name), mActivity.getString(R.string.play_service_not_found));
} else {
CustomLogHandler.printInfolog("checking googleplayservice : ", "true");
createLocationRequest();
initFuseAPI();
}
}
else
{
PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION,mActivity);
}
}
public void connectForLocation()
{
createLocationRequest();
initFuseAPI();
}
/**
* Turn on Live update of location on given interval
* #param value
* #param INTERVAL
* #param FASTEST_INTERVAL
*/
public void turnOnLiveUpdate(boolean value,long INTERVAL,long FASTEST_INTERVAL)
{
isLiveUpdate = value;
this.INTERVAL = INTERVAL;
this.FASTEST_INTERVAL = FASTEST_INTERVAL;
}
/**
* Turn off live update of location
*/
public void turnOffLiveUpdate()
{
isLiveUpdate = false;
}
/**
* Disconnect from Google location service
*/
public void disconnect()
{
try {
Log.d(TAG, "onStop fired ..............");
googleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " +googleApiClient.isConnected());
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Resume Location update service if stopped
*/
public void onResumeUpdate()
{
try {
if(googleApiClient != null) {
if (googleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener)
{
this.onLocationUpdateListener = onLocationUpdateListener;
}
/**
* Create location update request
*/
protected void createLocationRequest() {
try {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Initialize google location service
*/
void initFuseAPI()
{
try
{
googleApiClient = new GoogleApiClient.Builder(mActivity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.d(TAG, "initFuseAPI fired ..............");
googleApiClient.connect();
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Check Google location service is available or not
* #return
*/
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, mActivity, 0).show();
return false;
}
}
/**
* called when connected with google location service
* #param bundle
*/
#Override
public void onConnected( Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + googleApiClient.isConnected());
LocationManager manager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE );
boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(statusOfGPS) {
startLocationUpdates();
}else
{
enableGpsService();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed( ConnectionResult connectionResult) {
}
/**
* Location update received here
* #param location
*/
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
SetLocation();
}
void enableGpsService()
{
try
{
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult( LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
//already connected to GPS
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by
// showing the user a dialog.
try {
status.startResolutionForResult(mActivity, PermissionManager.REQUEST_LOCATION);
startLocationUpdates();
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
//redirect user to setting screen, manually user can enble GPS
mActivity.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
break;
}
}
});
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Request location update service
*/
public void startLocationUpdates()
{
try {
//check required even you checked it previously
if (PermissionManager.checkPermission(mActivity, PermissionManager.ACCESS_LOCATION))
{
fusedLocationProviderApi.requestLocationUpdates(googleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
} else {
PermissionManager.askForPermission(PermissionManager.ACCESS_LOCATION, mActivity);
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* Stop location update
*/
public void stopLocationUpdates() {
try {
if(googleApiClient != null) {
fusedLocationProviderApi.removeLocationUpdates(
googleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
/**
* set location values received
*/
private void SetLocation()
{
try {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
onLocationUpdateListener.onLocationUpdate(mCurrentLocation);
/**isLiveUpdate = true for Live update **/
if (!isLiveUpdate) {
fusedLocationProviderApi.removeLocationUpdates(googleApiClient,this);
}
googleApiClient.disconnect();
//mCurrentLocation.getAccuracy()
//mCurrentLocation.getProvider()
} else {
Log.d(TAG, "location is null ...............");
}
}catch (Throwable throwable)
{
throwable.printStackTrace();
}
}
public Location getLocation(){
return mCurrentLocation;
}
public static List<Address> getAddress(Double mLat, Double mLang, Context context)
{
List<Address> addresses = null;
try
{
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
addresses = geocoder.getFromLocation(mLat, mLang, 1);
}catch (Exception e)
{
e.printStackTrace();
}
return addresses;
}
/**
* For receive location update
*/
public interface OnLocationUpdateListener {
void onLocationUpdate(Location mCurrentLocation);
}
}
call into this service class like this ..
gpsController = new GPSController(getActivity());
gpsController.setLocatonUpdateListener(this);
if (gpsController != null)
gpsController.onResumeUpdate();
public void setLocatonUpdateListener(OnLocationUpdateListener onLocationUpdateListener) {
this.onLocationUpdateListener = onLocationUpdateListener;
}
and also implement this into class ..
implements GPSController.OnLocationUpdateListener
#Override
public void onLocationUpdate(Location mCurrentLocation) {
CURRENT_LET = String.valueOf(mCurrentLocation.getLatitude());// both string variable to store value
CURRENT_LANG = String.valueOf(mCurrentLocation.getLongitude());
}
This implementation in Java works in a service class, after the fusedLocationClient has been initialized:
fusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
Location last_known_loction = task.getResult();
latitude = last_known_loction.getLatitude();
longitude = last_known_loction.getLongitude();
}
});

Re- JobScheduler combined with FusedLocationProvider Api oftens gives null location value

I have a jobScheduler with fusedLocationApi provider. It works alright but once a while it gives null value for a no. of time (6-7 times in a sequence). I tried onLocationChanged() and LocationServices.FusedLocationApi.requestLocationUpdates(), both gives null values at same time. How can I improve it? I have set high accuracy or Gps,wifi and mobile networks as locating method in device setting. thanks in advance.
One more thing, 80% of the null value are received when there is no wifi. I think Fused Api should have worked well without wifi as well Since there is gps available, isn't it?
Main class
public class LiveTrack extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_track);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
JobInfo jobInfo =
new JobInfo.Builder(MYJOBID, jobService).setPeriodic(15 * 60 * 1000L)
.setExtras(bundle)
.build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
Log.e("status","running");
}else{
Log.e("status","failed");
}
}
}
JobService class with fused Api Provider
public class MyJobService extends JobService
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
, LocationListener {
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
private Location mLastLocation;
public static String latitude;
public static String latitudeIfNull;
public static String longitude;
public static String longitudeIfNull;
#Override
public boolean onStartJob(JobParameters jobParameters) {
setUpLocationClientIfNeeded();
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(30000);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"App has stopped working. Please open the app again. Thankyou",
Toast.LENGTH_LONG).show();
return false;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
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(this.mGoogleApiClient,mLocationRequest, this);
createLocationRequest();
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
private void setUpLocationClientIfNeeded()
{
if(mGoogleApiClient == null)
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
this.mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
latitudeIfNull = location.getLatitude() + "";
longitudeIfNull = location.getLongitude() + "";
Log.e("gps longitude",longitudeIfNull);
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(60000);
mLocationRequest.setFastestInterval(50000);
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, new LocationCallback() {
#Override
public void onLocationResult(final LocationResult locationResult) {
latitude = locationResult.getLastLocation().getLatitude() + "";
longitude = locationResult.getLastLocation().getLongitude() + "";
Log.i("latitude ", latitude + "");
Log.i("longitude ", longitude + "");
}
#Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
Log.i("onLocationAvailability", "onLocationAvailability: isLocationAvailable = " + locationAvailability.isLocationAvailable());
}
}, null);
}
}
.
Try this
Create a background service class like this
public class LocationBackGroundService extends Service implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationBackGroundService";
private static final long INTERVAL = 100;
private static final long FASTEST_INTERVAL = 100;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
Context mCOntext;
public void LocationBackGroundService(Context mContext) {
this.mCOntext = mContext;
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
mGoogleApiClient.connect();
}
#Override
public void onCreate() {
super.onCreate();
if (!isGooglePlayServicesAvailable()) {
// finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
return false;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "OnConnection Suspended", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this, "OnConnection Failed", Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location) {
if (null != mCurrentLocation) {
mCurrentLocation = location;
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
}
}
}
And call when activity starts like this
startService(new Intent(this, yourBackgroundServiceName.class));
and in menifest
<service android:name=".yourBackgroundServiceName"></service>
and don;t forget to add run time permissions before stating a service

Android Location update is happening twice

I want to run location update as a service. Now I can able to run the service correctly but the location updation is happening twice, Here is the code,
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<service
android:name=".services.LocationService"
android:icon="#drawable/ic_location"
android:label="Location Service">
<intent-filter>
<action android:name="android.service.notification.service" />
</intent-filter>
</service>
In the Activity Class we are using startLocationService() to start the service and stopLocationService() to stop the service, Also created a Broadcast Receiver to get the location updation on the Activity Calss.
private BroadcastReceiver broadcastReceiver;
private Intent mLocationServiceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigtaion_drawer);
AppController.getInstance().activityResumed();
broadcastReceiver = createBroadcastReceiver();
registerReceiver(broadcastReceiver, new IntentFilter(getPackageName()));
if (!Permissions.hasLocationPermission(this)) {
Permissions.requestLocationPermission(this, PermissionKeys.LOCATION_REQUEST_HOME_ON_RESUME);
} else
startLocationService();
}
private BroadcastReceiver createBroadcastReceiver() {
return new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra(LocationService.LOCATION_UPDATED)) {
Bundle b = intent.getExtras();
if (b != null) {
Location mCurrentLocation = (Location) b.get(LocationService.LOCATION_UPDATED);
}
}
}
};
}
//Function To Start the Service
public void startLocationService() {
if (mLocationServiceIntent == null)
mLocationServiceIntent = new Intent(this, LocationService.class);
startService(mLocationServiceIntent);
}
//Function To Stop the Service
public void stopLocationService() {
if (mLocationServiceIntent != null)
stopService(mLocationServiceIntent);
}
LocationService.java
public class LocationService extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public static final String LOCATION_UPDATED = "LocationUpdated";
public static final String LATITUDE = "Latitude";
public static final String LONGITUDE = "Longitude";
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
private static final String TAG = "###LocationService:: ";
private static final int LOCATION_INTERVAL = 15000;
private static final int FASTEST_INTERVAL = 10000;
private static final float LOCATION_DISTANCE = 7f;
#Override
public void onCreate() {
if (isGooglePlayServicesAvailable()) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(LOCATION_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
//mLocationRequest.setSmallestDisplacement(10.0f); /* min dist for location change, here it is 10 meter */
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
}
//Check Google play is available or not
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
return ConnectionResult.SUCCESS == status;
}
#Override
public void onConnected(Bundle bundle) {
Log.e(TAG, "Connected");
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
Log.e(TAG, "Connection suspended");
}
protected void startLocationUpdates() {
Log.e(TAG, "Start Location Updates");
try {
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
} catch (IllegalStateException e) {
}
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.e(TAG, "Location Changed : " + location.getLatitude() + "," + location.getLongitude());
Intent intent = new Intent(getPackageName());
intent.putExtra(LOCATION_UPDATED, location);
sendBroadcast(intent);
}
}
/* LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};*/
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed:: "+connectionResult.getErrorMessage());
}
}
I have fixed this issue by adding a condition checking before start the service,
My updated startLocationService() function is like,
//Function To Start the Service
public void startLocationService() {
if (mLocationServiceIntent == null)
mLocationServiceIntent = new Intent(this, LocationService.class);
if(!isServiceRunning(HomeScreenActivity.this, LocationService.class)) {
startService(mLocationServiceIntent);
}
}
Here is the function to check if the service is already running or not.
//This function is to check the service is already running or not
public boolean isServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.e("ServiceRunning", serviceClass.getSimpleName() + " is alredy running");
return true;
}
}
return false;
}

Location Updates using google play services and FusedLocationProviderClient

I want to get location updates on a "background service" using latest fused location provider client.I don't want to use the location listeners and Google API Client that all are using.
I also need to use location settings Api provided by google play services to check whether location setting are disable or enable on that "background service".Please help.
if we need to use fusion location api then we need to use Google API client, For the background service it is not an issue to use it, Following is the example which I used for getting location update in background, But one more thing as Google introduces 'DOZE' mode from 6.0 so I can not give surety give update when your device in 'DOZE' mode,
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
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;
/**
* Created By Dhaval Solanki
*/
public class ConnectionService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
String TAG = "ConnectionService";
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location previousLocation;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private Location mLastLocation;
private Context context;
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = getApplicationContext();
Log.i(TAG, "onStartCommand");
if (checkPermsion(context)) {
setupLocationService(context);
}
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
ApplicationCLass.isServiceRunning = true;
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
ApplicationCLass.isServiceRunning = false;
return super.onUnbind(intent);
}
#Override
public void onDestroy() {
ApplicationCLass.isServiceRunning = false;
super.onDestroy();
}
private void setupLocationService(Context context) {
if (checkPlayServices()) {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
createLocationRequest();
}
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest().create();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mGoogleApiClient.connect();
}
public boolean checkPermsion(Context context) {
int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
} else if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
} else {
return true;
}
} else {
return true;
}
}
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result = googleAPI.isGooglePlayServicesAvailable(this);
if (result != ConnectionResult.SUCCESS) {
return false;
}
return true;
}
private void startLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (Prefs.getUserLat(context).trim().length() > 0 && Prefs.getUserLong(context).trim().length() > 0) {
} else {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
Prefs.setUserLat(context, String.valueOf(mLastLocation.getLatitude()));
Prefs.setUserLong(context, String.valueOf(mLastLocation.getLongitude()));
}
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "Connected to onConnected");
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connected to onConnectionSuspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connected to onConnectionFailed");
}
#Override
public void onLocationChanged(Location location) {
try {
Logger.print("onLocationChanged", "latitued :" + location.getLatitude() + " ,, Longitude " + location.getLongitude());
} catch (Exception e) {
e.printStackTrace();
}
}
}
One another alaram service continues runnning or not
import android.app.ActivityManager;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AlarmService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
boolean isServiceRunning = false;
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (ConnectionService.class.getName().equals(service.service.getClassName())) {
isServiceRunning = true;
break;
}
}
Log.i("AlarmService", "Service is running " + isServiceRunning);
if(!isServiceRunning) {
startService(new Intent(getApplicationContext(),ConnectionService.class));
} else {
ConnectionService.checkConnectionAndConnect(getApplicationContext());
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public AlarmService() {
super("AlaramService");
}
}
And Finaly start service
private void checkAndStartService() {
final ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
new AsyncTask<Void, Void, Boolean>() {
boolean isServiceRunning = false;
#Override
protected Boolean doInBackground(Void... params) {
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (ConnectionService.class.getName().equals(service.service.getClassName())) {
isServiceRunning = true;
break;
}
}
return isServiceRunning;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
Log.i("onPostExecute", "Service running = " + aBoolean);
if (!aBoolean) {
startService(new Intent(ActivitySplash.this, ConnectionService.class));
Intent i = new Intent(ActivitySplash.this, AlarmService.class);
PendingIntent pi = PendingIntent.getService(ActivitySplash.this, 0, i, 0);
AlarmManager am = (AlarmManager) ActivitySplash.this.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pi);
}
}
}.execute();
}
You can write the code for the intentService as given below. It has been considered that since it is running in the background, we would not show the permission dialogs.
public class GetLocationService extends IntentService
implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static String TAG = GetLocationService.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;
public GetLocationService() {
super(TAG);
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* #param name Used to name the worker thread, important only for debugging.
*/
public GetLocationService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
Log.d(TAG, "disconnecting");
mGoogleApiClient.disconnect();
}
Log.d(TAG, "onHandleIntent");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationRequest locationRequestLow = LocationRequest.create();
locationRequestLow.setPriority(LocationRequest.PRIORITY_LOW_POWER);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_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.
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
} else {
Log.d(TAG, "permission denied");
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, location.toString());
}
}
You can extend the service class like
public class BackgroundLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener
You can check the full source code here BackgroundLocationService.java
For enable location settings
private void displayLocationSettingsRequest() {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(10000 / 2);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(context, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException ignored) {
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to
startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
//startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
displayLocationSettingsRequest();//keep asking
showToast("Location permission needed");
break;
}
break;
}
}
You can check location settings from Service and if location is off ,
LocationManager lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
boolean network_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {}
if(!gps_enabled && !network_enabled) {
// notify user
// Either you can display a Notification(Recommended way) or you can show dialog with
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//It needs SYSTEM_ALERT_WINDOW permission. Add this permission in Manifest.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
}
Hi I have good understanding about location services and how we can use in it perfect way. See i'll give you idea about fused apis.
Just make sure follow the below steps. It is pretty nice and simple.
Step 1. Make this class
GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
Step2. Make this interface
LocationUpdateListener.java
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* #param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* #param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
Step 3. Make this Location service class
LocationService.java
public class LocationService extends Service {
private GoogleLocationService googleLocationService;
#Override
public void onCreate() {
super.onCreate();
//start the handler for getting locations
//create component
updateLocation(getApplicationContext());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
//get current location os user
private void updateLocation(Context context) {
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
}
IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//stop location updates on stopping the service
#Override
public void onDestroy() {
super.onDestroy();
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
}
}
Edited Answer:
How to use service,
Start service in your main activity,like this
startService(new Intent(context, LocationService.class));
for stop,
stopService(new Intent(context, LocationService.class));
and declare in manifest like this,
<service
android:name=".service.location.LocationService"
android:enabled="true"></service>
Note: I have done this because i need location after killed the app.If you dont want service.Then,you can call directly below code in class where location need to be update and remove locationservice.
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
#Override
public void canReceiveLocationUpdates() {
}
#Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
#Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
#Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
Remember Locationservice should be declare in manifest as well.
According to me this is the best solution.
Thanks hope this will help you
The question does not appear to be very specific. It seems like you're having trouble starting up with using location services.
The best idea would probably be checking out the Google samples (https://github.com/googlesamples/android-play-location) to better understand the mechanics.
I would probably start by implementing the simplest example (LocationUpdates). It uses the FusedLocationProvider and also checks if the settings are enabled, so it should fit your needs, or at least get you started.
If you really need to use a service you can check out LocationUpdatesForegroundService or LocationUpdatesPendingIntent. But I would strongly recommend to read and understand the first example before you do this.

Android gps location not getting updated periodically

I am using fusedlocation api in a Service for updating gps location to server every few seconds.In the MainActivity I have written the code to open locationSettings.Then in onResume method I start the Service(GpsService.java).The Service class send Broadcast everytime location is updated and it is received in the onResume() method.But I only get the location coordinates once.sendAmblnceGps() method is where the location is send to the server.
GpsService.java:
public class GpsService extends Service implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
com.google.android.gms.location.LocationListener locationListener;
LocationRequest mLocationRequest;
private static final long INTERVAL = 100* 50;
private static final long FASTEST_INTERVAL = 100 * 20;
GoogleApiClient googleApiClient;
boolean connected;
public GpsService() {
super();
}
#Override
public void onCreate() {
super.onCreate();
GoogleApiClient.Builder googleApiClientbuilder=new GoogleApiClient.Builder(GpsService.this).addConnectionCallbacks(GpsService.this).addOnConnectionFailedListener(GpsService.this).addApi(LocationServices.API);
googleApiClient=googleApiClientbuilder.build();
googleApiClient.connect();
Toast.makeText(getApplicationContext(),"service created",Toast.LENGTH_SHORT).show();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(100);
}
protected 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) {
// 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;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest, locationListener);
Log.d("TAG", "Location update started ..............: ");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("Service Command", "Started");
locationListener = new com.google.android.gms.location.LocationListener()
{
#Override
public void onLocationChanged(Location location) {
Intent intent = new Intent("location_updates");
intent.putExtra("lat", location.getLatitude());
intent.putExtra("longt", location.getLongitude());
Log.e("location", "lat:" + " " + Double.toString(location.getLatitude()) + " " + "Longt:" + " " + Double.toString(location.getLongitude()));
sendBroadcast(intent);
} };
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient,locationListener);
if(googleApiClient.isConnected()){
googleApiClient.disconnect();
}
Log.e("Service","Stopped");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("Connection failed","Service stopped");
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient,locationListener);
if(googleApiClient.isConnected()){
googleApiClient.disconnect();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
createLocationRequest();
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
Log.e("Connection","suspended");
}
}
MainActivity.java:
#Override
protected void onResume() {
super.onResume();
if (locationManager == null) {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} else {
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isConnected()) {
if (gps_enabled) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Acquiring your current location");
progressDialog.setIndeterminate(true);
progressDialog.getWindow().setGravity(Gravity.CENTER);
progressDialog.show();
Log.e("starting", "service");
intent = new Intent(MainActivity.this, GpsService.class);
startService(intent);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("starting", "broadcastservice");
latitude = Double.toString(intent.getDoubleExtra("lat", 0.0));
longitude = Double.toString(intent.getDoubleExtra("longt", 0.0));
if (isConnected()) {
sendAmblnceGps();
} else {
progressDialog.cancel();
Toast.makeText(getApplicationContext(), "Please enable internet connection", Toast.LENGTH_SHORT).show();
}
}
};
Log.e("registering", "broadcastservice");
registerReceiver(broadcastReceiver, new IntentFilter("location_updates"));
}
}
else {
Toast.makeText(getApplicationContext(),"Enable Internet Connection",Toast.LENGTH_SHORT).show();
}
}
}
You have specified mLocationRequest.setSmallestDisplacement(100);, so you need to move at least 100 meters from the location of the initial location update to have a new location update.

Categories

Resources