【问题标题】:working with the google OAuth 2.0 in android在 android 中使用 google OAuth 2.0
【发布时间】:2015-03-18 08:23:00
【问题描述】:

我有一个需要用户许可才能访问其谷歌电子表格的安卓应用(范围是谷歌电子表格 API)。

应用程序第一次启动时一切正常,我可以很好地访问电子表格。 我正在将用户选择的电子邮件地址保存到共享首选项中。

我想要的是,在用户下次启动应用程序时(第一次之后),应用程序只会获得令牌(因为我已经有了用户的电子邮件地址),而用户不必去再次通过帐户选择器。

我想这已经完成了,因为用户应该只选择他的帐户一次。尽管如此,我还是不知道什么是最好的做法。

他是 Google OAuth 2.0 类

直接从这里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;
        }
    }



}

第一次启动时效果很好,但我不确定下次要做什么。

总结一下:

  1. 我想了解每次启动应用时是否需要获取令牌?

  2. 如果是这样,我如何只获取令牌(并处理异常)而不选择帐户以及首次启动所需的其他内容。

  3. 我需要使用刷新令牌吗?因为我读过它,但在做的时候没有看到任何例子。

任何帮助将不胜感激。

谢谢,Ofek

【问题讨论】:

    标签: android oauth-2.0 google-api token google-spreadsheet-api


    【解决方案1】:

    如果是 android 手机或任何具有 google+ 的设备, 你可以只检查 google+ 登录。

    如果您使用任何其他设备或没有 gmail 的 Android 设备, 第一次您需要从 google 获取令牌。 稍后您需要刷新您的令牌,因为它可能会过期。

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

    【讨论】:

    • 感谢您的回答!几个问题:使用 google+ 登录按钮,用户是否只需登录一次?在他第一次启动应用程序并登录后,它总是会登录吗?如果是这样,我应该如何在 not-google-auth 活动中获取访问令牌(比如说,我的 HomeActivity)?因为在第一次启动时,用户将登录并获得一个令牌,但在接下来的时间里,我想将用户引导到另一个活动(到我的 homeActivity 正确 wawy,没有再次看到谷歌活动),所以我想要知道如何在另一个活动中获取令牌?谢谢
    • 您必须通过 google + 登录才能从 google 个人资料中获取信息。您需要将令牌发送到您的服务器,然后在那里检查验证。稍后您将自己的令牌发送给您的客户,谷歌将不会参与其中。谷歌的令牌有一些到期时间。
    • 您也可以从谷歌获取刷新令牌到您的服务器并将其保存在您的应用程序中,并通过您的服务器访问它以进一步登录。
    • 我不想从 Google 个人资料中获取信息。我想做的就是访问和写入电子表格。在第一次启动时它工作正常(参见上面的代码),帐户选择器显示帐户列表,用户选择一个并收到访问令牌。问题是,在用户下次启动应用程序时,我只想为他获取一个令牌,而他不必通过帐户选择器(因为我已经有了电子邮件地址)。所以我的问题基本上是如何单独获得令牌? (来自另一个活动)。谢谢
    • 澄清一下,我没有服务器端,我只想通过手机上的应用程序访问电子表格。
    猜你喜欢
    • 2015-01-30
    • 2011-08-30
    • 2011-10-21
    • 2013-05-01
    • 2013-05-10
    • 2021-12-25
    • 1970-01-01
    • 2016-09-14
    • 2012-09-19
    相关资源
    最近更新 更多