Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Drive API await() UI Thread Error

I am implementing the Google Drive APIs in my android application. I do not want to use PendingResult#setResultCallback(), rather, I want to use PendingResult#await() so I can get the result in the next line and not have to wait. This isn't an issue because everything is running in the background.

However, every time I call await(), I get the following error. I have tried running a single call to the Google Drive API that uses await() in an AsyncTask, Thread, IntentService, Service with AsyncTask, and a Service with a Thread. I have received the following error every time. I tried calling Looper.prepare() in my Thread implementations, but it didn't solve anything.

Has anyone else ran into this issue?

java.lang.IllegalStateException: await must not be called on the UI thread
        at com.google.android.gms.internal.hm.a(Unknown Source)
        at com.google.android.gms.common.api.a$a.await(Unknown Source)
        at [OMITTED].GoogleDriveManager$2.onConnected(GoogleDriveManager.java:83)
        at com.google.android.gms.internal.hc.c(Unknown Source)
        at com.google.android.gms.common.api.c.eK(Unknown Source)
        at com.google.android.gms.common.api.c.d(Unknown Source)
        at com.google.android.gms.common.api.c$2.onConnected(Unknown Source)
        at com.google.android.gms.internal.hc.c(Unknown Source)
        at com.google.android.gms.internal.hc.cp(Unknown Source)
        at com.google.android.gms.internal.hb$h.b(Unknown Source)
        at com.google.android.gms.internal.hb$h.d(Unknown Source)
        at com.google.android.gms.internal.hb$b.fv(Unknown Source)
        at com.google.android.gms.internal.hb$a.handleMessage(Unknown Source)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5146)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
        at dalvik.system.NativeStart.main(Native Method)

This is the code I am using to test the API:

     apiClient = new GoogleApiClient.Builder(mContext)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_APPFOLDER)
            .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                @Override
                public void onConnected(Bundle bundle) {
                    LogUtil.log(TAG, "onConnected()");
                    connected = true;

                    DriveApi.ContentsResult result = Drive.DriveApi.newContents(apiClient).await();

                }
                @Override
                public void onConnectionSuspended(int i) {
                    LogUtil.log(TAG, "onConnectionSuspended()");
                    connected = false;
                }
            })
            .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                @Override
                public void onConnectionFailed(ConnectionResult result) {
                    LogUtil.log(TAG, "onConnectionFailed()");
                    connected = false;
                }
            })
            .build();
    apiClient.connect();
like image 325
Timothy Miko Avatar asked Oct 10 '14 15:10

Timothy Miko


1 Answers

apiClient.connect() is an asynchronous operation, hence why calling it within an AsyncTask does not help (running connect on a background thread doesn't help when onConnected() is being called on the UI thread).

Instead, you could start an AsyncTask from your onConnected() callback - that AsyncTask's doInBackground() could then call Drive.DriveApi.newContents(apiClient).await().

Of course, there's no need to ever call await() - use setResultCallback() to asynchronously wait for newContents() to complete:

@Override
public void onConnected(Bundle bundle) {
  LogUtil.log(TAG, "onConnected()");
  connected = true;

  Drive.DriveApi.newContents(apiClient).setResultCallback(
       new ResultCallback<DriveApi.ContentsResult>() {
     @Override
     public void onResult(DriveApi.ContentsResult result) {
       // Use result
     }
  });
}
like image 116
ianhanniballake Avatar answered Nov 09 '22 08:11

ianhanniballake