Using LocationServices.FusedLocationApi.requestLocationUpdates in an Android background service...onLocationChanged never called - android

I've searched for days and days and somehow the answer to why onLocationChanged isn't being called has eluded me. I've read the documentation extensively and I MUST be missing something crucial. I simply want a service that runs in the background, when location has changed, I want to log the location.
Here's my service...
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
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;
public class BackgroundLocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private final String TAG = ((Object) this).getClass().getSimpleName();
IBinder mBinder = new LocalBinder();
GoogleApiAvailability googleAPI;
PowerManager.WakeLock mWakeLock;
private boolean mInProgress;
private Boolean servicesAvailable = false;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
private Intent mIntentService;
private PendingIntent mPendingIntent;
public class LocalBinder extends Binder {
public BackgroundLocationService getServerInstance() {
return BackgroundLocationService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
googleAPI = GoogleApiAvailability.getInstance();
mInProgress = false;
mIntentService = new Intent(this,BackgroundLocationService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT);
servicesAvailable = servicesConnected();
/*
* Create a new google api client, using the enclosing class to handle callbacks.
*/
buildGoogleApiClient();
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = googleAPI.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
protected void startLocationUpdates() {
Log.i(TAG, "Started Location Updates");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
}
protected void stopLocationUpdates() {
Log.i(TAG,"Stopped Location Updates");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent);
}
protected void createLocationRequest() {
Log.i(TAG, "createLocationRequest()");
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(1000);
//mLocationRequest.setMaxWaitTime(10000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE); //*** added this
if (this.mWakeLock == null) {
mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "aWakeLock"); //*** added this
}
if (!this.mWakeLock.isHeld()) {
mWakeLock.acquire(); //*** added this
}
if (!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress)
return START_STICKY;
if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) {
Log.e(TAG, "Location Client not connected, connecting...");
mInProgress = true;
mGoogleApiClient.connect();
}
Log.e(TAG, "Location Client: onStartCommand");
return START_STICKY;
}
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
if (mGoogleApiClient == null) {
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
createLocationRequest();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onDestroy() {
// Turn off the request flag
this.mInProgress = false;
if (this.mWakeLock != null) {
this.mWakeLock.release();
this.mWakeLock = null;
}
Log.e(TAG, "Location Client: ON DESTROY");
super.onDestroy();
stopLocationUpdates();
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onLocationChanged(Location location) {
Log.e(TAG, "Location Receiver [Location Changed]: " + location.getLatitude() + ", " + location.getLongitude());
}
#Override
public void onConnectionSuspended(int i) {
Log.e(TAG, "Location Client: ON CONNECTED");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
Log.e(TAG, "Location Client: ON CONNECTION FAILED");
if (connectionResult.hasResolution()) {
// If no resolution is available, display an error dialog
} else {
}
}
}
I'm starting the service like this...
Intent BackgroundLocationService = new Intent(this, BackgroundLocationService.class);
startService(BackgroundLocationService);
I have the following permission in the manifest as well...
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

The requestLocationUpdates uses a pendingintent currently which is fired to start the service again. This is not calling the OnLocationchanged callback. Try using the requestLocationUpdates with location listener (3rd parameter). It should call OnLocationchanged.

Related

How to run geofencing app in background?

I am creating a attendance monitoring app for my campus using geofencing api.Everything else is working smoothly, but I want my app to work in the background.(Similar to a music player). Currently, it works only when the app is open. Here is the Service class code I have used:
package com.app.androidkt.geofencing;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class BackgroundService extends Service{
MainActivity main;
public int onStartCommand(Intent intent, int flags, int startId) {
main.isMonitoring = true;
main.startGeofencing();
main.startLocationMonitor();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
//use this method to communicate with your activity
return null;
}
}
And here is the MainActivity.java:
package com.app.androidkt.geofencing;
import android.Manifest;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
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.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingRequest;
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.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.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends AppCompatActivity implements
OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener{
private static final String TAG = "MainActivity";
private static final int REQUEST_LOCATION_PERMISSION_CODE = 101;
private GoogleMap googleMap;
private GeofencingRequest geofencingRequest;
public GoogleApiClient googleApiClient;
public boolean isMonitoring = false;
private MarkerOptions markerOptions;
private Marker currentLocationMarker;
private PendingIntent pendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERMISSION_CODE);
}
}
public void startLocationMonitor() {
Log.d(TAG, "start location monitor");
LocationRequest locationRequest = LocationRequest.create()
.setInterval(2000)
.setFastestInterval(1000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
try {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (currentLocationMarker != null) {
currentLocationMarker.remove();
}
markerOptions = new MarkerOptions();
markerOptions.position(new LatLng(location.getLatitude(), location.getLongitude()));
markerOptions.title("Current Location");
currentLocationMarker = googleMap.addMarker(markerOptions);
Log.d(TAG, "Location Change Lat Lng " + location.getLatitude() + " " + location.getLongitude());
}
});
} catch (SecurityException e) {
Log.d(TAG, e.getMessage());
}
}
public void startGeofencing() {
Log.d(TAG, "Start geofencing monitoring call");
pendingIntent = getGeofencePendingIntent();
geofencingRequest = new GeofencingRequest.Builder()
.setInitialTrigger(Geofence.GEOFENCE_TRANSITION_ENTER)
.addGeofence(getGeofence())
.build();
if (!googleApiClient.isConnected()) {
Log.d(TAG, "Google API client not connected");
} else {
try {
LocationServices.GeofencingApi.addGeofences(googleApiClient, geofencingRequest, pendingIntent).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
Log.d(TAG, "Successfully Geofencing Connected");
} else {
Log.d(TAG, "Failed to add Geofencing " + status.getStatus());
}
}
});
} catch (SecurityException e) {
Log.d(TAG, e.getMessage());
}
}
isMonitoring = true;
invalidateOptionsMenu();
}
#NonNull
public Geofence getGeofence() {
LatLng latLng = Constants.AREA_LANDMARKS.get(Constants.GEOFENCE_ID_STAN_UNI);
return new Geofence.Builder()
.setRequestId(Constants.GEOFENCE_ID_STAN_UNI)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setCircularRegion(latLng.latitude, latLng.longitude, Constants.GEOFENCE_RADIUS_IN_METERS)
.setNotificationResponsiveness(1000)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
}
public PendingIntent getGeofencePendingIntent() {
if (pendingIntent != null) {
return pendingIntent;
}
Intent intent = new Intent(this, GeofenceRegistrationService.class);
return PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
}
private void stopGeoFencing() {
pendingIntent = getGeofencePendingIntent();
LocationServices.GeofencingApi.removeGeofences(googleApiClient, pendingIntent)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess())
Log.d(TAG, "Stop geofencing");
else
Log.d(TAG, "Not stop geofencing");
}
});
isMonitoring = false;
invalidateOptionsMenu();
}
#Override
protected void onResume() {
super.onResume();
int response = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(MainActivity.this);
if (response != ConnectionResult.SUCCESS) {
Log.d(TAG, "Google Play Service Not Available");
GoogleApiAvailability.getInstance().getErrorDialog(MainActivity.this, response, 1).show();
} else {
Log.d(TAG, "Google play service available");
}
}
#Override
protected void onStart() {
super.onStart();
googleApiClient.reconnect();
}
#Override
protected void onStop() {
super.onStop();
googleApiClient.disconnect();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.manu_map_activity, menu);
if (isMonitoring) {
menu.findItem(R.id.action_start_monitor).setVisible(false);
menu.findItem(R.id.action_stop_monitor).setVisible(true);
menu.findItem(R.id.startservice).setVisible(true);
} else {
menu.findItem(R.id.action_start_monitor).setVisible(true);
menu.findItem(R.id.action_stop_monitor).setVisible(false);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_start_monitor:
startGeofencing();
break;
case R.id.action_stop_monitor:
stopGeoFencing();
break;
case R.id.startservice:
startService(new Intent(this, BackgroundService.class));
break;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void onMapReady(GoogleMap googleMap) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
this.googleMap = googleMap;
LatLng latLng = Constants.AREA_LANDMARKS.get(Constants.GEOFENCE_ID_STAN_UNI);
googleMap.addMarker(new MarkerOptions().position(latLng).title("Stanford University"));
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 17f));
googleMap.setMyLocationEnabled(true);
Circle circle = googleMap.addCircle(new CircleOptions()
.center(new LatLng(latLng.latitude, latLng.longitude))
.radius(Constants.GEOFENCE_RADIUS_IN_METERS)
.strokeColor(Color.RED)
.strokeWidth(4f));
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d(TAG, "Google Api Client Connected");
isMonitoring = true;
startGeofencing();
startLocationMonitor();
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "Google Connection Suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
isMonitoring = false;
Log.e(TAG, "Connection Failed:" + connectionResult.getErrorMessage());
}
}
When I try to run the app in background by clicking the background option i have provided in the app, the app crashes and i get a runtime error saying:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.androidkt.geofencing, PID: 24176
java.lang.RuntimeException: Unable to start service com.app.androidkt.geofencing.BackgroundService#52135c5 with Intent { cmp=com.app.androidkt.geofencing/.BackgroundService }: java.lang.NullPointerException: Attempt to write to field 'boolean com.app.androidkt.geofencing.MainActivity.isMonitoring' on a null object reference
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3335)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1578)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.NullPointerException: Attempt to write to field 'boolean com.app.androidkt.geofencing.MainActivity.isMonitoring' on a null object reference
at com.app.androidkt.geofencing.BackgroundService.onStartCommand(BackgroundService.java:13)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3318)
at android.app.ActivityThread.-wrap21(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1578) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6123) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757) 
Please suggest me changes in my code.
MainActivity main;
is not initialized in your BackgroundService.
Try to implement the interface instead accessing the Activity's method like this.
Check this answer to implement the interface.

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: Intent Service

I am trying to obtain location by using Fused location provider api by implementing it in the intentservice class and at the same time i am starting a newtimertask in the same service.
so when intentservice gets called, the timertask starts and the googleapiclent gets connected to get the location.
i want that if the location is not availaible ,my timertask disconnects the googleapiclient in next 60 seconds.
But this doesnot work...if it doesnot get the location...the intent service keeps on running or the fusedlocatinprovider keeps for looking location.so i have to stop these?
package com.example.rj.intentlocationapi;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
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;
public class BackgrndService extends IntentService implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
LocationManager mlocationmanger;
int bool = 0;
CountDownTimer cnt;
public BackgrndService() {
super("BackgrndService");
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
return false;
}
}
#Override
protected void onHandleIntent(Intent intent) {
if (!isGooglePlayServicesAvailable()) {
stopLocationService();
}
mlocationmanger = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
cnt = new CountDownTimer(60000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Log.w("haha", "going to finish it");
stopLocationService();
}
}.start();
mGoogleApiClient.registerConnectionCallbacks(this);
mGoogleApiClient.connect();
Log.w("haha", "blocked to finish it");
}
public void onConnected(Bundle bundle) {
Log.w("hello", "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
Log.w("hhaahaa", "Connection suspended stop here ");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.w("hhaahaa", "Connection failed stop here ");
}
#Override
public void onLocationChanged(Location location) {
Log.w("hello", "Firing onLocationChanged..............................................");
mCurrentLocation = location;
if (mCurrentLocation != null) {
Log.w("hi", mCurrentLocation.getLatitude() + " " + mCurrentLocation.getLongitude());
}
stopLocationService();
}
public void stopLocationService() {
Log.w("haha", "killing begins");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
cnt.cancel();
Intent alarm = new Intent(this, BackgrndService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarm, 0);
if (bool == 0) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()
+ 1000 * 100, pendingIntent);
bool = 1;
}
}
}
Either you will shift or change Intent-Service to Service and use stopSelf() method to stop the service.This method stop the service.
IntentService automatically stops itself when onHandleIntent() ends, if no more commands had been sent to it while onHandleIntent() was running. Hence, you do not manually stop an IntentService yourself.

Service not receiving location updates

I have implemented a background service to receive location updates:
public class TestActivity extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static String TAG = TestActivity_backup.class.getName();
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient=null;
#Override
public void onCreate() {
super.onCreate();
if (!isGooglePlayServicesAvailable()) {
stopSelf();
}
setContentView(R.layout.activity_test);
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10000).setFastestInterval(5000).setSmallestDisplacement(20);
this.buildGoogleApiClient();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.destination = intent.getStringExtra("DESTINATION");
LatLng latLng = intent.getParcelableExtra("LOCATION");
this.location = new Location("");
this.location.setLatitude(latLng.latitude);
this.location.setLongitude(latLng.longitude);
return START_NOT_STICKY;
}
#Override
public void onLocationChanged(Location location){
Toast.makeText(TestActivity.this, "User location changed", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnected(Bundle bundle) {
Toast.makeText(TestActivity.this, "Location service connected", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
//TODO
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
//GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
}
I have implemented all relevant methods.onCreate and onStartCommand are called but onConnec
ted and onLocationChanged are never ever called.If I implement an activity for location updates then its working fine.
What am I missing here?
Don't forget to add permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION depending upon Accuracy
And use this Code
public class LocationService extends Service {
private LocationListener locationListener;
#Override
public IBinder onBind(final Intent intent) {
return null;
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
super.onStartCommand(intent, flags, startId);
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
this.locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, this.locationListener);
}
private static class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(final Location location) {
}
#Override
public void onProviderDisabled(final String provider) {
}
#Override
public void onProviderEnabled(final String provider) {
}
#Override
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
}
}
}
Here is my code that worked for me!
Don't forget to add mgoogleApiClient.connect() in onCreate()
and then take a look at the onConnected Method of googleapiClient - here I've created the the LocationRequest with
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest, this);
and then for testing I used
LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
for the initial Request.
If you are using emulator don't forget to telnet localhost 5543 (to your emulator) and then use the command geo fix to set the initial location.
You can test it with geofixing to another location then the onLocationChanged Methode should be called ...
package com.pekam.androidservice;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.pekam.myandroidtheme.*;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.location.*;
import com.google.android.gms.location.LocationListener;
public class MyService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,LocationListener {
private NotificationManager nm;
private Timer timer = new Timer();
private int counter = 0;
private int incrementby = 1;
private static boolean isRunning = false;
private GoogleApiClient googleApiClient;
private LocationRequest mLocationRequest = new LocationRequest();
private String strLOG="LOG";
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
int mValue = 0; // Holds last value set by a client.
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_INT_VALUE = 3;
static final int MSG_SET_STRING_VALUE = 4;
static final int MSG_SET_STRING_LOG =5;
final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.
// LocationRequest
#Override
public void onLocationChanged(Location location) {
Location mCurrentLocation = location;
sendLogMessageToUI("Last Known Loc" + mCurrentLocation.getLongitude() + mCurrentLocation.getLatitude());
}
//GoogleApiClient
#Override
public void onConnectionFailed(ConnectionResult bundle) {
}
#Override
public void onConnected(Bundle bundle) {
Log.i("onConnected", "GoogleApiClient" );
try {
Toast.makeText(this, "Location service connected", Toast.LENGTH_SHORT).show();
createLocationRequest();
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest, this);
LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
} catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
Log.e("Google APi Connected", "Google APi Connected Failed.", t);
}
}
#Override
public void onConnectionSuspended(int i) {
}
//Service
#Override
public void onCreate() {
super.onCreate();
Log.i("MyService", "Service Started.");
showNotification();
timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 1900L);
isRunning = true;
try {
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY; // run until explicitly stopped.
}
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
public static boolean isRunning()
{
return isRunning;
}
private void onTimerTick() {
Log.i("TimerTick", "Timer doing work." + counter);
try {
counter += incrementby;
sendMessageToUI(counter);
// LocationServices.FusedLocationApi.setMockMode(googleApiClient, true);
// double latitude = LocationServices.FusedLocationApi.getLastLocation(googleApiClient).getLatitude();
} catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
Log.e("TimerTick", "Timer Tick Failed.", t);
}
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
//GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TabBarActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
nm.notify(R.string.service_started, notification);
}
protected void createLocationRequest() {
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void sendMessageToUI(int intvaluetosend) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0));
//Send data as a String
Bundle b = new Bundle();
b.putString("str1", "ab" + intvaluetosend + "cd");
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
private void sendLogMessageToUI(String strLOG) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain());
//Send data as a String
Bundle b = new Bundle();
b.putString("strLOG", strLOG);
Message msg = Message.obtain(null, MSG_SET_STRING_LOG);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
class IncomingHandler extends Handler { // Handler of incoming messages from clients.
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_INT_VALUE:
incrementby = msg.arg1;
break;
default:
super.handleMessage(msg);
}
}
}
}

onConnected() not being called to get location updates (GooglePlayApi for location)

So i have this code:
package com.entu.bocterapp;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class LocationManager implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private Context mContext;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private LocationRequest mLocationRequest;
public LocationManager(Context context) {
mContext = context;
//
if (checkIfGooglePlayServicesAreAvailable()) {
//Get Access to the google service api
buildGoogleApiClient();
mGoogleApiClient.connect();
} else {
//Use Android Location Services
//TODO:
}
}
public Location getCoarseLocation() {
if (mLastLocation != null) {
return mLastLocation;
} else return null;
}
private synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private boolean checkIfGooglePlayServicesAreAvailable() {
int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);
if (errorCode != ConnectionResult.SUCCESS) {
GooglePlayServicesUtil.getErrorDialog(errorCode, (RecentSightings) mContext, 0).show();
return false;
}
return true;
}
#Override
public void onConnected(Bundle bundle) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location != null) {
mLastLocation = location;
Toast.makeText(mContext, location.getLongitude() + " , " + location.getLatitude() + " : " + location.getAccuracy(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(mContext, "suspended", Toast.LENGTH_LONG).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
I am trying to get location in this class, but onConnected() never gets called(i waited for 1-2 minutes). I went with the debugger, it says google play services are available.
Does anyone know what i'm doing wrong? I'm stuck here for hours, reading everything, and can't get it to work.
Cheers!
You must call
mGoogleApiClient.connect();
try this:
#Override
protected void onStart() {
if(mGoogleApiClient!=null){
mGoogleApiClient.connect();
}
super.onStart();
}
#Override
protected void onStop() {
if(mGoogleApiClient!=null){
if(mGoogleApiClient.isConnected()){
mGoogleApiClient.disconnect();
}
}
super.onStop();
}
I got the same problem just updated my grade version :10.0.1' to
compile 'com.google.android.gms:play-services-location:10.2.1'
it works.

Categories

Resources