I try connecting to the Google API Client to achieve some functionality in my application. But for some reason I cannot connect to the Google API Client And because that I can not continue to use Google services.
After I initialize the GoogleApiClient I check if mGoogleApiClient.isConnected and always get it False and I don't know why. I would appreciate any help. Thanks.
Notice that everything happens on background service.
public class Background extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {
private String TAG = "Background";
private GoogleApiClient mGoogleApiClient;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"Start");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(ActivityRecognition.API)
.addApi(LocationServices.API)
.build();
if (!mGoogleApiClient.isConnected()) {
Log.e(TAG,"GoogleApiClient not yet connected");
} else {
Log.e(TAG,"GoogleApiClient connected");
}
return Service.START_STICKY;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
}
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.e(TAG, "Successfully added activity detection.");
} else {
Log.e(TAG, "Error: " + status.getStatusMessage());
}
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected");
mGoogleApiClient.connect();
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
Connect the googleApiClient in onStartCommand of your service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"Start");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(ActivityRecognition.API)
.addApi(LocationServices.API)
.build();
if (!mGoogleApiClient.isConnected()) {
Log.e(TAG,"GoogleApiClient not yet connected");
mGoogleApiClient.connect(); // connect it here..
} else {
Log.e(TAG,"GoogleApiClient connected");
}
return Service.START_STICKY;
}
you are not calling .connect() in the right place. You are building a client, and you must call .connect() after that. You are immediately checking if it is connected, which it will never be.
Please add .connect() after .build() in .onStartCommand() and remove this code:
if (!mGoogleApiClient.isConnected()) {
Log.e(TAG,"GoogleApiClient not yet connected");
} else {
Log.e(TAG,"GoogleApiClient connected");
}
Also, remove this since it might get you in an unwanted state:
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected");
// remove this -> mGoogleApiClient.connect();
}
Related
I can log in to Google Play Games, but I can't log out.I get the following error.
GoogleApiClient is not configured to use the Plus.API api.
Here my codes;
public void Glogin(View view) {
//HERE LOGIN
if (loginout==0)
{
apiClient = new GoogleApiClient.Builder(this)
.addApi(Games.API)
.addScope(Games.SCOPE_GAMES)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("HATA", "Google Play Oyun servisine bağlanamadı.Lütfen bağlantınızı kontrol ediniz.");
finish();
}
}).build();
btn_gLoginout.setBackgroundResource(R.drawable.logout);
loginout++;
}
//LOGOUT
else if(loginout==1){
if (apiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(apiClient);
apiClient.disconnect();
apiClient.connect();
Toast.makeText(this, "Google hesabınızdan çıkış yapıldı.", Toast.LENGTH_SHORT).show();
btn_gLoginout.setBackgroundResource(R.drawable.login);
loginout=0;
}
}
}
This is kinda a repost and I'm sorry for that, but the last time I posted it I thought I got it down but apparently not. When I tried to call the Service I use to get this error Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
Because I was trying to call LocationServices before GoogleApiClient was even connected. So after changing the code up a bit I wasn't getting the error anymore, in fact I wasn't getting anything in logcat anymore.
This is how I start my Service from SearchActivity.class:
SearchActivity.class
button = (Button)findViewById(R.id.buttonPressed);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startService(new Intent(getBaseContext(), LocationService.class));
}
});
This is the Service:
LocationService.class
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
// LogCat tag
private static final String TAG = LocationService.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 void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mGoogleApiClient != null) {
if(mGoogleApiClient.isConnected()) {
if (mLocationRequest != null) {
togglePeriodicLocationUpdates();
}
}
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
private void togglePeriodicLocationUpdates() {
mGoogleApiClient.connect();
if(mGoogleApiClient.isConnected()) {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
protected void startLocationUpdates() {
mGoogleApiClient.connect();
if(mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnected(Bundle arg0) {
createLocationRequest();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
}
#Override
public boolean stopService(Intent name) {
return super.stopService(name);
}
AndroidManifest.xml
</activity>
<service android:name=".LocationService">
</service>
Edit:
Well I figured how to get it working.
But now I'm facing the problem of having to click the button 2 times before it would start normally. Only had to change the onStartCommand() a bit.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
if(mGoogleApiClient.isConnected()) {
if (mLocationRequest != null) {
togglePeriodicLocationUpdates();
}
}
}
return START_NOT_STICKY;
}
You should read the documentation on GoogleApiClient, particularly (for the question at hand) the connect() method. I've highlighted the relevant portion:
Connects the client to Google Play services. This method returns
immediately, and connects to the service in the background. If the
connection is successful, onConnected(Bundle) is called and enqueued
items are executed. On a failure, onConnectionFailed(ConnectionResult)
is called.
If the client is already connected or connecting, this method does
nothing.
So, this is what currently happens with your code:
You click the button to launch the service.
You create the GoogleApiClient in onCreate().
You call connect() in onStartCommand which returns immediately while connection goes on in the background.
You check isConnected(), however, since connection is still going on, you do nothing and return from onStartCommand.
Later, you click the button the launch the service again.
As it has already been created, it goes directly to onStartCommand.
By this point, the GoogleApiClient has connected, so everything else works as expected.
What you should do is implement onConnected(). From there, call togglePeriodicLocationUpdates() instead of doing that in onStartCommand(). This will accomplish what you want:
Click button to launch service.
Service creates GoogleApiClient in onCreate().
Service initiates connection in onStartCommand().
Sometime in the future, the connection is established and service calls togglePeriodicLocationUpdates() from onConnected().
I've tried calling this Service in two different ways, but it didn't seem to work.
The first way was:
startService(new Intent(getBaseContext(), LocationService.class));
for which I get an error saying `
Caused by: `java.lang.IllegalStateException: GoogleApiClient is not connected yet.
Then I tried this:
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.parseapp.eseen.eseen.service.LocationService");
startService(serviceIntent);
Also it didn't work, in contrary absolutely nothing happens, nothing shows up in logcat. Can anyone help?
Here's the whole code:
LocationService.class
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
// LogCat tag
private static final String TAG = LocationService.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 void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
togglePeriodicLocationUpdates();
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
private void togglePeriodicLocationUpdates() {
mGoogleApiClient.connect();
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
startLocationUpdates();
Log.d(TAG, "Periodic location updates started!");
} else {
mRequestingLocationUpdates = false;
// Stopping the location updates
stopLocationUpdates();
Log.d(TAG, "Periodic location updates stopped!");
}
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
protected void startLocationUpdates() {
mGoogleApiClient.connect();
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnected(Bundle arg0) {
createLocationRequest();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
}
#Override
public boolean stopService(Intent name) {
return super.stopService(name);
}
SearchActivity.class
button = (Button)findViewById(R.id.buttonPressed);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.parseapp.eseen.eseen.service.LocationService");
startService(serviceIntent);
}
});
AndroidManifest.xml
<service android:name=".LocationService">
<intent-filter>
<action android:name=".LocationService"> </action>
</intent-filter>
</service>
Your first attempt to start the service using the class name worked:
startService(new Intent(getBaseContext(), LocationService.class));
The exception occurred after the service started executing. Your code cannot use LocationServices until the GoogleApi connection is successful, namely after onConnected() is called. Your code calls connect() multiple times before getting to startLocationUpdates(), but does not wait for onConnected() to be called. That method is the notification you receive when the connection has been made and LocationServices can be used.
This demo code is for an AsyncTask, not a Service, but gives an idea of how the connection processing can be done using a CountDownLatch.
you package name com.parseapp.eseen.eseen
and You are tryng to call using com.parseapp.eseen.eseen.service.LocationService as action but you mentioned in Manifest as .LocationService that means you should call using com.parseapp.eseen.eseen.LocationService
in startLocationUpdates(); you are calling connect again and requesting api before connecting
request for locationupdates from onConnected method
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
I'm trying to get the current GPS location of a phone inside a android service.
I try to do it like here:
Getting Repeated Current Location inside a Service in android?
My service looks like this:
public class MeasurementService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
private Feedback feedback;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
feedback = new Feedback();
if (isNetworkAvailable()) {
new MeasuringTask().execute();
}
return Service.START_NOT_STICKY;
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager
.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onConnected(Bundle arg0) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(2000);
...
}
#Override
public void onConnectionSuspended(int arg0) {
}
#Override
public void onDestroy() {
super.onDestroy();
mGoogleApiClient.disconnect();
}
#Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
private class MeasuringTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
//network access
}
}
I start my service through a broadcast receiver everytime the phone is started.
When I execute the app I get a java.lang.NoClassDefFoundError: packet.MeasurementService
If I try to change this part:
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
To this:
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(MeasurmentService.class)
.addOnConnectionFailedListener(MeasurmentService.class)
.addApi(LocationServices.API)
.build();
Like recommended in the other post, I get:
The method addConnectionCallbacks(GoogleApiClient.ConnectionCallbacks) in the type GoogleApiClient.Builder is not applicable for the arguments (Class)
Ideas? Thanks a lot!
Make sure the LocationListener your service implemented is from com.google.android.gms.location.
Move the code to onCreate function.
#Override
public void onCreate() {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
I have a sample application on github, please click here.
I finally figured it out, it was a build error which I wasn't able to resolve.
My solution:
I migrated the project from Eclipse to Android Studio.
I'm a bit confused in deciding the way i should implement my background custom service class.
What I need :
location updates and activity recognition.
REST API call and the Geofence API.
I'm new to background processing in Android and I'm not sure how to implement this.
Is it possible to make a ThreadPoolExecutor (a task manager class, runnables, etc.) and deal with inter-thread communication ?
If yes,is it possible to listen to location updates inside a Thread class ?
for now, I'm using this library ( Smart-location-lib ) to listen to location updates.
is there a better solution ?
Any help is greatly appreciated !
This is the best way using Google API in background service
And you didn't explain what do you mean by activity recognition?
public class MyLocationService extends Service implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
public MyLocationService() {
}
#Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API).
addConnectionCallbacks(this).
addOnConnectionFailedListener(this)
.build();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mGoogleApiClient.connect();
Toast.makeText(this, "Location services started", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onLocationChanged(Location location) {
System.out.println("MyLocationService.onLocationChanged");
// TODO with location updateshere
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(1000); // Update location every second
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
sendMyLocUpdate(loc, UserProfile.DRIVER);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onDestroy() {
Toast.makeText(this, "Location services stopped", Toast.LENGTH_LONG).show();
Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
sendMyLocUpdate(loc, UserProfile.PASSENGER);
mGoogleApiClient.disconnect();
super.onDestroy();
}
}