Search code examples
androidgoogle-drive-apigoogle-drive-android-api

How to perform background sync task if I were using GoogleSignIn + DriveClient


Our users have a chance to login, to authorize the app access to their Google Drive. We implement based on GoogleSignIn and DriveClient. (Not the yet another deprecated API GoogleApiClient)

https://developers.google.com/drive/android/auth

After the users quit the app, we would like to Google Drive sync process still work seamlessly in background, without further user/UI interaction. (Able to handle case when login token is expired/invalid after few days/hours)

May I know how to achieve so. Any code example is appreciated.


Solution

  • silentSignIn is the key to the solution. We also need to handle edge case, when silentSignIn failed. Here's the real world code snippet.


    public static GoogleSignInClient buildGoogleSignInClient() {
        GoogleSignInOptions signInOptions =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .requestScopes(Drive.SCOPE_APPFOLDER)
                        .build();
        return GoogleSignIn.getClient(WeNoteApplication.instance(), signInOptions);
    }
    
    public static boolean silentSignInThenSync(SyncViewModel syncViewModel, boolean handleSignInRequired) {
        GoogleSignInClient googleSignInClient = buildGoogleSignInClient();
    
        Task<GoogleSignInAccount> task = googleSignInClient.silentSignIn();
    
        if (task.isSuccessful()) {
            syncViewModel.getSlientSignInSuccessLiveData().postValue(true);
    
            return sync(task.getResult(), syncViewModel);
        } else {
    
            try {
                Tasks.await(task);
                try {
                    GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);
    
                    syncViewModel.getSlientSignInSuccessLiveData().postValue(true);
    
                    return sync(googleSignInAccount, syncViewModel);
                } catch (ApiException e) {
                    Log.e(TAG, "", e);
    
                    if (handleSignInRequired) {
                        if (e.getStatusCode() == GoogleSignInStatusCodes.SIGN_IN_REQUIRED) {
                            syncViewModel.getSignInRequiredLiveData().postValue(true);
                            return false;
                        }
                    }
    
                    String message = WeNoteApplication.instance().getString(R.string.sync_with_google_drive_failed_template, e.getLocalizedMessage());
                    syncViewModel.getMessageLiveData().postValue(message);
                }
            } catch (ExecutionException e) {
                Log.e(TAG, "", e);
    
                if (handleSignInRequired) {
                    if (e.getCause() instanceof ApiException) {
                        if (((ApiException) e.getCause()).getStatusCode() == GoogleSignInStatusCodes.SIGN_IN_REQUIRED) {
                            syncViewModel.getSignInRequiredLiveData().postValue(true);
                            return false;
                        }
                    }
                }
    
                String message = WeNoteApplication.instance().getString(R.string.sync_with_google_drive_failed_template, e.getLocalizedMessage());
                syncViewModel.getMessageLiveData().postValue(message);
            } catch (InterruptedException e) {
                Log.e(TAG, "", e);
    
                String message = WeNoteApplication.instance().getString(R.string.sync_with_google_drive_failed_template, e.getLocalizedMessage());
                syncViewModel.getMessageLiveData().postValue(message);
            }
        }
    
        return false;
    }