3

I am creating an android application which should have access to a google drive account in order to store and read files in/from google drive. I used google drive android API for this purpose. but the problem is that when the user signs in to the account through the application, the account is also added to the device and the account is accessible through drive, gmail,... applications and I need to restrict the access to that google account to only my application.

Is there anyway to restrict access to google account to just my application?

I show some code related to connecting to google drive below:

public class MainActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
    private GoogleApiClient mGoogleApiClient;
    // Request code to use when launching the resolution activity
    private static final int REQUEST_RESOLVE_ERROR = 1001;
    private boolean mResolvingError = false;
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_RESOLVE_ERROR) {
        mResolvingError = false;
        if (resultCode == RESULT_OK) {
            // Make sure the app is not already connected or attempting to connect
            if (!mGoogleApiClient.isConnecting() &&
                    !mGoogleApiClient.isConnected()) {
                mGoogleApiClient.connect();
            }
        }
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        //start connection to google play 
        mGoogleApiClient = new GoogleApiClient.Builder(this)
        .addApi(Drive.API)
        .addScope(Drive.SCOPE_FILE)
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .build();

    }
    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // TODO Auto-generated method stub
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (result.hasResolution()) {
            try {
                mResolvingError = true;
                result.startResolutionForResult(this,REQUEST_RESOLVE_ERROR);
            } catch (SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient.connect();
            }
         } else {
            // Show dialog using GooglePlayServicesUtil.getErrorDialog()
            showErrorDialog(result.getErrorCode());
            mResolvingError = true;
         }
    }

    @Override
    public void onConnected(Bundle arg0) {
        // TODO Auto-generated method stub
        showMessage("Connected to account");
    }

    protected void onPause()
    {
        showMessage("onPause");
        super.onPause();

    }

    protected void onStart() {
        super.onStart();
        showMessage("onStart");
        if (!mResolvingError && !mGoogleApiClient.isConnected()) {  // more about this later
            mGoogleApiClient.connect();
        }
    }

    @Override
    protected void onStop() {
        showMessage("OnStop");
        //mGoogleApiClient.disconnect();
        super.onStop();
    }

    protected void onRestart()
    {
        showMessage("onRestart");
        super.onRestart();
        if (!mResolvingError  && !mGoogleApiClient.isConnected()) {  // more about this later
            mGoogleApiClient.connect();
        }
    }
     public void showMessage(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

}

In fact I am making an application which we use to collect data from our users, and therefore we want the data to be stored in a central storage space which both we and other users of application can have access to data.(users have limited access to data through our application). we did the same with dropbox and it works well. but due to some restrictions on accessing dropbox by users, I am looking for alternative solutions. for now I am trying to do the same with google drive. does anyone have any solution about how should I do this??

in fact the google account has nothing to do with the users of application, it's my google account in which the data coming from application should be stored.

mahsa
  • 31
  • 3

2 Answers2

0

I can't say I fully understand your question, but I'll try to help anyway.

You probably know, that your app needs to be authorized to access the Drive.

Assuming that is working, you need valid gmail account to access the drive. Under normal circumstances, you pull the gmail account from the set of accounts on your device, i.e. myaccount@gmail, youraccount@gmail, .... The list of these accounts is visible in the settings, and you usually add / remove them through the Settings or your app can do it by invoking AccountPicker. I have a little demo here, that handles the issue (follow the MainActivity - REQ_ACCPICK - GDAA branch there). The AccountPicker/Setting either picks an account from the list, or adds a new account to the device.

Now, let's assume you would like to access Drive with a gmail account that is not in the device's list (i.e . NOT-IN-LIST@GMAIL.COM), bypassing account picker, and stick it directly to (see the method here):

mGoogleApiClient = new GoogleApiClient.Builder(this)
        .addApi(Drive.API)
        .addScope(Drive.SCOPE_FILE)
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .setAccountName("NOT-IN-LIST@GMAIL.COM")
        .build();

If you do this, you'll get 'INVALID ACCOUNT' in 'onConnectionFailed()'. It makes sense, since you've just set an account name not known to the device - effectively even without knowing it's password. I assume that would be a major problem for Google Drive security, right?

So the conclusion (or my best guess) is: Unless you can 'hardcode' the account / passsword info into GoogleApiClient builder, the only way to get the Drive connection is to use one of the 'registered' accounts - they have the correct password already.

UPDATE:

There may be a different way to implement it. Again, UNTESTED. I would try to use a "supervisor" Google account and share the files with users. Android REST Api under DRIVE scope should be able to access these shared files/folders. This way users would access the "supervisor's" files using their own accounts (I vaguely remember hitting 'shared-with-me' files when playing with the REST api). A long shot, but it can easily be tested using the playground - the bottom of the page. And I would even test the same hypothesis under GDAA. I don't know if GDAA can see the 'shared files' under the FILE scope.

Good Luck

seanpj
  • 6,735
  • 2
  • 33
  • 54
  • 1
    actually my problem is that I don't want the account which I sign into it, to be added to registered accounts in device. because users has nothing to do with this account. this account is just used to store the data in one google account's drive. – mahsa Apr 12 '15 at 16:51
  • I'm guessing it would be a no-go, But I understand GDAA better the Account Management, so there still may be somebody able to help you. Try to find tags related to Android Google Account Management. – seanpj Apr 12 '15 at 20:26
0

I had the same problem and after a lot of research and reading many posts from angry users about this "feature" I am under the impression that this cannot be done using GoogleApiClient.

Instead I used AppAuth to retrieve the authCode / token and then used that token with the Drive REST API to retrieve the users files.

Please note that WebView OAuth is no longer supported by Google as of 4/20/17 which is the reason I suggest AppAuth. AppAuth also works around other unpleasantries such as this.

You can find more details on this approach and a work around for a weird grant error here: invalid_grant trying to get oAuth token from google

Hope this helps.

Community
  • 1
  • 1
Justin Fiedler
  • 6,478
  • 3
  • 21
  • 25
  • I have to ask one question that is it possible to hardcode any gmail account in my android app and anyone can upload doc to google drive who is using my app? – Dante Jul 27 '17 at 04:47
  • I've had issues with appauth not working depending on the browser on the users device. Also, appauth isn't 1.0 yet and has received little to no attention in years. It has bugs, and they don't get fixed. – CamHart May 25 '19 at 15:05