問題描述
GoogleApiClient onConnected 未被調用,在服務中使用 (GoogleApiClient onConnected not being called, using in a Service)
當我在 Activity 中使用 GoogleApiClient 但將其移至服務並且未調用 onConnected 時正在工作。
public class StepsMonitoringService extends Service implements GoogleApiClient.ConnectionCallbacks {
private GoogleApiClient mClient;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mClient = new GoogleApiClient.Builder(this).addApi(Fitness.HISTORY_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addConnectionCallbacks(this).build();
mClient.connect();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
mClient.disconnect();
}
@Override
public void onConnected(Bundle connectionHint) {
// NOT being called!! WHY??
}
@Override
public void onConnectionSuspended(int cause) {
}
}
有什麼想法嗎?我究竟做錯了什麼?有沒有人讓 GoogleApiClient 在 Service 中工作?
服務是從 Activity 調用的
public class MainActivity extends FragmentActivity {
private TextView mStepsView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, StepsMonitoringService.class);
startService(intent);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("StepMonitoringServiceIntent"));
mStepsView = (TextView) findViewById(R.id.steps);
}
private void displayOnUI(String msg) {
mStepsView.setText(msg + "\n" + mStepsView.getText());
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long steps = intent.getLongExtra("steps", 0);
displayOnUI(steps + " steps");
}
};
}
在調試過程中,我可以看到服務的 onCreate 被調用,但是 onConnected 從未被調用。就我所見,日誌中沒有什麼特別之處。
參考解法
方法 1:
First implement these interfaces:
- GoogleApiClient.ConnectionCallbacks
- GoogleApiClient.OnConnectionFailedListener
Then you will have to add these methods to your class:
- public void onConnected(final Bundle bundle)
- public void onConnectionSuspended(final int i)
- public void onConnectionFailed(final ConnectionResult connectionResult)
As soon as you connect, the OnConnected method will be called. In this method can you do whatever you want, like getting the current location, the location address, add a marker point to map, etc.
But you cannot do anything without establishing a connection to the Google API client. To connect to the GoogleAPIClient, you can add this method to your class and call it in your onCreate method.
private synchronized void buildGoogleAPIClient(){
googleApiclient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiclient.connect();
Toast.makeText(getActivity(), "connected", Toast.LENGTH_SHORT).show();
}
方法 2:
Add addOnConnectionFailedListener
to GoogleApiClient
to track the error. As per doc addOnConnectionFailedListener
called when there was an error connecting the client to the service.
public class StepsMonitoringService extends Service implements GoogleApiClient.ConnectionCallbacks {
private GoogleApiClient mClient;
@Override
public void onCreate() {
super.onCreate();
mClient = new GoogleApiClient.Builder(this).addApi(Fitness.HISTORY_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addConnectionCallbacks(this)
//Add Connection Failed Listener to track error.
.addOnConnectionFailedListener(this)
.build();
mClient.connect();
}
@Override
public void onConnected(Bundle connectionHint) {
// NOT being called!! WHY??
}
@Override
public void onConnectionSuspended(int cause) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
//Called called when there was an error connecting the client to the service.
Log.i(LOG_TAG,"onConnectionFailed:"+connectionResult.getErrorCode()+","+connectionResult.getErrorMessage());
}
}
方法 3:
try this.
public class StepsMonitoringService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mClient;
/**
* Builds a GoogleApiClient. Uses the addApi() method to request the
* Fitness API.
*/
protected synchronized void buildGoogleApiClient() {
mClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Fitness.HISTORY_API)
.build();
}
@Override
public void onCreate() {
super.onCreate();
if (mClient == null) {
buildGoogleApiClient();
}
mClient.connect();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onConnected(Bundle connectionHint) {
// NOT being called!! WHY??
}
@Override
public void onConnectionSuspended(int cause) {
mClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Called called when there was an error connecting the client to the
// service.
Log.i(LOG_TAG,
"onConnectionFailed:" + connectionResult.getErrorCode() + "," + connectionResult.getErrorMessage());
}
}
方法 4:
I had a same issue when I was using useDefaultAccount() to create a client. I then replaced it with setAccountName() and it starts working. I think for some reasons accountpicker doesn't work in service that's why googleapiclient's connect() silently failed since you need specify which account you use for retrieving Fitness info. Noted that you need to have an account picker in your activity and pass the email account to your service in some way.
(by rukiman、Ashana.Jackol、Dhaval Patel、Kasim Rangwala、Naofumi)