I am working on service in android but I am facing an error which is
Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.common.api.zzf.zzb(Unknown Source)
at com.google.android.gms.common.api.zzg.zzb(Unknown Source)
at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
at com.example.mine4.newapp.MyService.startLocationUpdates(MyService.java:180)
at com.example.mine4.newapp.MyService.togglePeriodicLocationUpdates(MyService.java:123)
at com.example.mine4.newapp.MyService.onCreate(MyService.java:62)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2716)
at android.app.ActivityThread.access$1600(ActivityThread.java:165)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1455)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5391)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
and my code is here:
public class MyService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = MyService.class.getSimpleName();
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
displayLocation();
togglePeriodicLocationUpdates();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
// #Override
// protected void onResume() {
// super.onResume();
//
// checkPlayServices();
//
// // Resuming the periodic location updates
// if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
// startLocationUpdates();
// }
// }
//
// #Override
// protected void onStop() {
// super.onStop();
// if (mGoogleApiClient.isConnected()) {
// mGoogleApiClient.disconnect();
// }
// }
// #Override
// protected void onPause() {
// super.onPause();
// stopLocationUpdates();
// }
/**
* Method to display `location` on UI
* */
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
} else {
}
}
private void togglePeriodicLocationUpdates() {
if (!mRequestingLocationUpdates) {
// Changing the button text
mRequestingLocationUpdates = true;
// Starting the location updates
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
// Changing the button text
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorString(resultCode);
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
}
return false;
}
return true;
}
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
// Once connected with google api, get the location
displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
and error is here:
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
I am first time using service and I need to work my service like my gps locator which work on background.
Simply, you need to uncomment the following part which is responsible for connecting to the Google API when the service or the activity starts and stop onStop()
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
// Resuming the periodic location updates
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
Related
I am developing an app that should send gps data to a server once every 10 minutes. The problem is that when I kill the app when the GPS is ON, the GPS icon disappear from the status bar (while the GPS is still ON) and the data are not sent anymore. If I do the same with the google maps app the icon doesn't disappear.
Can someone explain me why this is happening?
here is the code that I use
AlarmManager
/**
* ALARM_MANAGER_GPS_TIME_INTERVAL = 10 min
*/
PendingIntent mPendingIntent = PendingIntent
.getService(
context,
PENDING_INTENT_REQUEST_CODE_FOR_GPS,
new Intent(context, GpsDataService.class),
PendingIntent.FLAG_IMMUTABLE);
AlarmManager mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mAlarmManager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
ALARM_MANAGER_GPS_TIME_INTERVAL,
mPendingIntent);
Service
public class GpsDataService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
private String mPayLoad;
private GpsPojoBuilder mGpsPojoBuilder;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mGoogleApiClient == null)
buildGoogleApiClient();
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected())
startLocationUpdates();
return Service.START_NOT_STICKY;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
/**
* UPDATE_INTERVAL_IN_MILLISECONDS = 4 sec
* FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 2 sec
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest
.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS)
.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. Call connect() to
// attempt to re-establish the connection.
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
checkForPermission();
}
private void checkForPermission() {
Location location;
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//permission denied
} else {
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location != null)
handleLocation(location);
else
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}else {
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(location != null)
handleLocation(location);
else
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onLocationChanged(Location location) {
handleLocation(location);
}
private void handleLocation(Location location){
mCurrentLocation = location;
Toast.makeText(this, "location foound: " + location.toString(), Toast.LENGTH_SHORT).show();
Thread thread = new Thread() {
#Override
public void run() {
try {
mGpsPojoBuilder = new GpsPojoBuilder(getApplicationContext());
mPayLoad = mGpsPojoBuilder
.getCheckInJson(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
sendJSON(mPayLoad, CHECKINS_URL);
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(mGoogleApiClient.isConnected()) {
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
}
}
};
thread.start();
}
public void sendJSON(String payLoadData, String url_suffix) {
HttpConnectionCreator mHttpConncectionClass = new HttpConnectionCreator(payLoadData, url_suffix);
mHttpConncectionClass.connect();
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
super.onDestroy();
}
}
According to android.developer, if you want to keep your services alive, you need to use START_STICKY.
int START_STICKY
Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service.
inside the following function:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mGoogleApiClient == null)
buildGoogleApiClient();
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected())
startLocationUpdates();
return Service.START_NOT_STICKY;
}
change to this:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(mGoogleApiClient == null)
buildGoogleApiClient();
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected())
startLocationUpdates();
return Service.START_STICKY;
}
In my project i create background service which is get location using google api client.
my problem is when app destroyed,service is running but google api client automatically disconnected and cannot get lat-lang. i don't want lost a connection.
This is my service class code
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
String lat, lon;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}else{
mGoogleApiClient.connect();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setInterval(100); // Update location every second
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = String.valueOf(mLastLocation.getLatitude());
lon = String.valueOf(mLastLocation.getLongitude());
}
updateUI();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
lat = String.valueOf(location.getLatitude());
lon = String.valueOf(location.getLongitude());
updateUI();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
buildGoogleApiClient();
}
synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
//setUpLocationClientIfNeeded();
if(!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting())
{
mGoogleApiClient.connect();
}
return START_STICKY;
}
void updateUI() {
Log.d("LatLongGPS", lat + "==========" + lon);
Toast.makeText(getApplicationContext(), "Service"+lat + "==========" + lon, Toast.LENGTH_LONG).show();
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I want to make a program on my phone (android) for a user to find his a own_ship position and orientation, so I used App Inventor in order to make an application to do that. So can any one help me to make this application because I am new to Android programming.
I would not use Appinventor to build such an application. Use native Android and get the location of the object through longitude and latitude. The best example for this is the following.
Don't forget to add this permission to the manifest file:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
The code for the java class needs to be something similar to the following:
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener {
// LogCat tag
private static final String TAG = MainActivity.class.getSimpleName();
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
// UI elements
private TextView lblLocation;
private Button btnShowLocation, btnStartLocationUpdates;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lblLocation = (TextView) findViewById(R.id.lblLocation);
btnShowLocation = (Button) findViewById(R.id.btnShowLocation);
btnStartLocationUpdates = (Button) findViewById(R.id.btnLocationUpdates);
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
// Show location button click listener
btnShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayLocation();
}
});
// Toggling the periodic location updates
btnStartLocationUpdates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
togglePeriodicLocationUpdates();
}
});
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
// Resuming the periodic location updates
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
/**
* Method to display the location on UI
* */
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
lblLocation.setText(latitude + ", " + longitude);
} else {
lblLocation
.setText("(Couldn't get the location. Make sure location is enabled on the device)");
}
}
/**
* Method to toggle periodic location updates
* */
private void togglePeriodicLocationUpdates() {
if (!mRequestingLocationUpdates) {
// Changing the button text
btnStartLocationUpdates
.setText(getString(R.string.btn_stop_location_updates));
mRequestingLocationUpdates = true;
// Starting the location updates
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
// Changing the button text
btnStartLocationUpdates
.setText(getString(R.string.btn_start_location_updates));
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
// Once connected with google api, get the location
displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
Can this code be turned into an service which can be called from a activity using a button so that it runs in background even when the app i not running? If so how? I want to make an on/off switch in a separate class which will control the Service and get location data from it.
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener {
// LogCat tag
private static final String TAG = MainActivity.class.getSimpleName();
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
// UI elements
private TextView lblLocation;
private Button btnShowLocation, btnStartLocationUpdates;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lblLocation = (TextView) findViewById(R.id.lblLocation);
btnShowLocation = (Button) findViewById(R.id.btnShowLocation);
btnStartLocationUpdates = (Button) findViewById(R.id.btnLocationUpdates);
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
// Show location button click listener
btnShowLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayLocation();
}
});
// Toggling the periodic location updates
btnStartLocationUpdates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
togglePeriodicLocationUpdates();
}
});
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
// Resuming the periodic location updates
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
/**
* Method to display the location on UI
* */
private void displayLocation() {
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
lblLocation.setText(latitude + ", " + longitude);
} else {
lblLocation
.setText("(Couldn't get the location. Make sure location is enabled on the device)");
}
}
/**
* Method to toggle periodic location updates
* */
private void togglePeriodicLocationUpdates() {
if (!mRequestingLocationUpdates) {
// Changing the button text
btnStartLocationUpdates
.setText(getString(R.string.btn_stop_location_updates));
mRequestingLocationUpdates = true;
// Starting the location updates
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
// Changing the button text
btnStartLocationUpdates
.setText(getString(R.string.btn_start_location_updates));
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
// Once connected with google api, get the location
displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
Instead of
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
you can use
public abstract PendingResult requestLocationUpdates(GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)
that accepts PendingIntent as a last argument.
Your code will look like follows:
PendingIntent serviceIntent = PendingIntent(
context, requestCode, new Intent(context, MyService.class), 0/*flag*/);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, serviceIntent);
You also need to implement MyService by extending IntentService and add it to AndroidManifest.
I'm developing an application that it use the geolocation. The problem is that when the user doesn't close it and the app is in background, it drain a lot of battery and I don't know where is the problem.
My location activity is this:
public abstract class LocationActivity extends FragmentActivity implements LocationListener, GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {
/**
* Variables.
*/
private AppGlobal global;
private String TAG = "LOCATIONACTIVITY";
private LocationRequest mLocationRequest;
private LocationClient mLocationClient;
private LocationListener listener;
/**
*
*/
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(getLayoutResourceId());
global = ((AppGlobal)getApplicationContext());
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setSmallestDisplacement(1);
mLocationClient = new LocationClient(this, this, this);
if(GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS)
mLocationClient.connect();
}
/**
*
*/
protected abstract int getLayoutResourceId();
/**
*
*/
#Override
public void onStop() {
Log.v(TAG, "onStop");
if (mLocationClient.isConnected()) {
stopPeriodicUpdates();
}
mLocationClient.disconnect();
super.onStop();
}
/**
*
*/
#Override
public void onPause() {
super.onPause();
Log.v(TAG, "onPause");
if (mLocationClient.isConnected()) {
//mLocationClient.removeLocationUpdates(listener);
stopPeriodicUpdates();
}
}
/**
*
*/
#Override
public void onResume() {
Log.v(TAG, "onResume");
super.onResume();
if(mLocationClient.isConnected()) {
if(listener == null)
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
global.latitude = location.getLatitude();
global.longitude = location.getLongitude();
}
};
mLocationClient.requestLocationUpdates(mLocationRequest, listener);
} else
mLocationClient.connect();
}
/**
*
*/
private boolean servicesConnected() {
Log.v(TAG, "servicesConnected");
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == resultCode) {
Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available));
return true;
} else {
return false;
}
}
/**
*
*/
public void getLocation(View v) {
Log.v(TAG, "getLocation");
if (servicesConnected()) {
Location currentLocation = mLocationClient.getLastLocation();
global.latitude = currentLocation.getLatitude();
global.longitude = currentLocation.getLongitude();
}
}
/**
*
*/
#Override
public void onConnected(Bundle bundle) {
Log.v(TAG, "onConnected");
startPeriodicUpdates();
}
/**
*
*/
#Override
public void onDisconnected() {
Log.v(TAG, "onDisconnected");
}
/**
*
*/
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.v(TAG, "onConnectionFailed");
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this, LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
//void
}
}
/**
*
*/
#Override
public void onLocationChanged(Location location) {
Log.v(TAG, "onLocationChanged");
global.latitude = location.getLatitude();
global.longitude = location.getLongitude();
Log.v(TAG, "lat:" + global.latitude);
Log.v(TAG, "lon:" + global.longitude);
}
/**
*
*/
public void startPeriodicUpdates() {
Log.v(TAG, "startPeriodicUpdates");
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
/**
*
*/
private void stopPeriodicUpdates() {
Log.v(TAG, "stopPeriodicUpdates");
mLocationClient.removeLocationUpdates(this);
}
}
I think this should work fine but I'm not sure. Thank you very much for your help.
You could try tuning the accuracy of your LocationRequest to PRIORITY_BALANCED_POWER_ACCURACY and set a longer setInterval() and a faster setFasterInterval() to something like 60000 millisecondes (one minute). Right now you're asking your provider to refresh the location every second. If the information is not that sensitive and you don't require such a quick update, it would be a great way to reduce your power consumption.
Also, an app can go in the background in the onPause() method, try disconnecting your client
mLocationClient.disconnect();
I hope this helps!