简体   繁体   English

在Android中使用Google OAuth 2.0

[英]working with the google OAuth 2.0 in android

I have a android app that requires permission from the user to access its google spreadsheets (the scope is google spreadsheet API). 我有一个Android应用,需要用户许可才能访问其Google电子表格(范围为Google电子表格API)。

At the first time the app is launched its all good, I can acces the spreadsheets just fine. 第一次启动该应用程序时,一切正常,我可以很好地访问电子表格。 I am saving the email address the user chooses to the Shared Preferences. 我正在将用户选择的电子邮件地址保存到“共享首选项”中。

What I want is that in the next time that the user launches the app (after the first time), the app will only get the token (because I already have the email address of the user) without the user having to go through the account picker again. 我想要的是,在用户下次启动该应用程序(第一次之后)时,该应用程序将仅获得令牌(因为我已经拥有该用户的电子邮件地址),而无需用户通过该帐户再次选择。

I imagine this has been done before, because the user should only choose his account once. 我想这是以前做过的,因为用户只能选择一次他的帐户。 none the less, I couldn't figure what is the best practice for it. 尽管如此,我不知道什么是最佳实践。

He is the Google OAuth 2.0 class 他是Google OAuth 2.0班

straight from here http://developer.android.com/google/auth/http-auth.html 直接从这里http://developer.android.com/google/auth/http-auth.html

public class GoogleAccountActivity extends Activity {

    static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
    static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1001;
    static final int REQUEST_CODE_RECOVER_FROM_AUTH_ERROR = 1002;

    String mEmail; 
    private static final String SCOPE =
            "oauth2:https://spreadsheets.google.com/feeds/";
    private Intent homeIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        homeIntent=new Intent(this, HomeActivity.class); 
         // next activity tto launch
        pickUserAccount();
    }


    private void getUsername() {
        if (mEmail == null) {
            pickUserAccount();
        } else {
            if (isDeviceOnline()) {
                new GetUsernameTask(this, mEmail, SCOPE).execute();
            } else {
                Toast.makeText(this, R.string.not_online, Toast.LENGTH_LONG).show();
            }
        }
    }

    public boolean isDeviceOnline() {
        ConnectivityManager connMgr = (ConnectivityManager) 
            getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
            // Receiving a result from the AccountPicker
            if (resultCode == RESULT_OK) {
                mEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                // With the account name acquired, go get the auth token
                getUsername();
            } else if (resultCode == RESULT_CANCELED) {
                // The account picker dialog closed without selecting an account.
                // Notify users that they must pick an account to proceed.
                Toast.makeText(this, R.string.pick_account, Toast.LENGTH_SHORT).show();
            }
        } else if ((requestCode == REQUEST_CODE_RECOVER_FROM_AUTH_ERROR ||
                requestCode == REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR)
                && resultCode == RESULT_OK) {
            // Receiving a result that follows a GoogleAuthException, try auth again
            getUsername();
        }
    }

    private void pickUserAccount() {
        String[] accountTypes = new String[]{"com.google"};
        Intent intent = AccountPicker.newChooseAccountIntent(null, null,
                accountTypes, false, null, null, null, null);
        startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
    }



    public void handleException(final Exception e) {
        // Because this call comes from the AsyncTask, we must ensure that the following
        // code instead executes on the UI thread.
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (e instanceof GooglePlayServicesAvailabilityException) {
                    // The Google Play services APK is old, disabled, or not present.
                    // Show a dialog created by Google Play services that allows
                    // the user to update the APK
                    int statusCode = ((GooglePlayServicesAvailabilityException)e)
                            .getConnectionStatusCode();
                    Dialog dialog = GooglePlayServicesUtil.getErrorDialog(statusCode,
                            GoogleAccountActivity.this,
                            REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
                    dialog.show();
                } else if (e instanceof UserRecoverableAuthException) {
                    // Unable to authenticate, such as when the user has not yet granted
                    // the app access to the account, but the user can fix this.
                    // Forward the user to an activity in Google Play services.
                    Intent intent = ((UserRecoverableAuthException)e).getIntent();
                    startActivityForResult(intent,
                            REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR);
                }
            }
        });
    }

    public class GetUsernameTask extends AsyncTask<Void, Void, String>{
        Activity mActivity;
        String mScope;
        String mEmail;

        GetUsernameTask(Activity activity, String name, String scope) {
            this.mActivity = activity;
            this.mScope = scope;
            this.mEmail = name;
        }

        /**
         * Executes the asynchronous job. This runs when you call execute()
         * on the AsyncTask instance.
         */
        @Override
        protected String doInBackground(Void... params) {
            try {
                String token = fetchToken();
                if (token != null) {
                    homeIntent.putExtra("userToken", token);
                    startActivity(homeIntent); // starting the Home Activity
                }
            } catch (IOException e) {
                // The fetchToken() method handles Google-specific exceptions,
                // so this indicates something went wrong at a higher level.
                // TIP: Check for network connectivity before starting the AsyncTask.
            }
            return null;
        }

        /**
         * Gets an authentication token from Google and handles any
         * GoogleAuthException that may occur.
         */
        protected String fetchToken() throws IOException {
            try {
                return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
            } catch (UserRecoverableAuthException userRecoverableException) {
                // GooglePlayServices.apk is either old, disabled, or not present
                // so we need to show the user some UI in the activity to recover.
                handleException(userRecoverableException);
            } catch (GoogleAuthException fatalException) {
                // Some other type of unrecoverable exception has occurred.
                // Report and log the error as appropriate for your app.
            }
            return null;
        }
    }



}

It works fine for the first launch, but I am not sure what to do in the next time. 第一次启动时效果很好,但是我不确定下次该怎么做。

To sum up: 总结一下:

  1. I want to understand if I need to get a token every time I launch the app?? 我想了解一下我每次启动该应用程序是否需要获得令牌吗?

  2. and if so, How do I do only the fetching of the token (and handling exceptions) without the account picking and the other stuff required in the first launch. 如果是这样,我该如何只提取令牌(和处理异常),而没有选择帐户以及第一次启动时所需的其他内容。

  3. Do I need to work with a refresh token? 我需要使用刷新令牌吗? because I read about it but didn't see any example for it in the do. 因为我读过它,但是在执行过程中没有看到任何示例。

any help would be appreciated. 任何帮助,将不胜感激。

Thanks, Ofek 谢谢,Ofek

In Case of android phone or any device which has google+, You can just check for google+ login. 如果是Android手机或具有google +的任何设备,则只需检查google +登录即可。

If you are using any other device or android device without gmail, First time you need to fetch a token from google. 如果您使用的是没有gmail的其他任何设备或android设备,则首次需要从Google提取令牌。 Later on you need to refresh your token as it might expire. 稍后,您需要刷新令牌,因为令牌可能会过期。

Ref: https://developers.google.com/accounts/docs/OAuth2ForDevices 参考: https : //developers.google.com/accounts/docs/OAuth2ForDevices

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM