始终从Gmail API

时间:2016-02-29 04:41:49

标签: android google-plus gmail-api

好的,我有一点工作,但后来想在app启动时添加静默登录(可选)。我现在发疯了,并且遇到了错误

com.google.api.client.googleapis.json.GoogleJsonResponseException:401 Unauthorized {   “代码”:401,   “错误”:[     {       “域名”:“全球”,       “location”:“授权”,       “locationType”:“标题”,       “message”:“需要登录”,       “理由”:“必需”     }   ]   “message”:“需要登录” }

这发生在线上(我应该使用“我”吗?)

Message messageResult = mGmailService.users().messages().send("me", message).execute();

每当我尝试发送(在上面的情况下)或阅读电子邮件(未显示)。最终,我想要对应用程序做的只是阅读用户的电子邮件并代表他们发送。该应用已注册,具有密钥,权限等。

我正在设置数据(当我尝试工作时你可以看到我的各种评论):

    mGso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestScopes(new Scope(Scopes.PROFILE))
            .requestScopes(new Scope(GmailScopes.GMAIL_READONLY))
            .requestScopes(new Scope(GmailScopes.GMAIL_SEND))
            .requestScopes(new Scope(GmailScopes.GMAIL_COMPOSE))
            .requestScopes(new Scope(GmailScopes.GMAIL_LABELS))
            .requestScopes(Plus.SCOPE_PLUS_LOGIN)
            .requestScopes(new Scope(Scopes.EMAIL))
            .requestScopes(new Scope(Scopes.PLUS_ME))
            .build();

    // set up Google client
//        mGoogleApiClient = new GoogleApiClient.Builder(this)
//                .addConnectionCallbacks(this)
//                .addOnConnectionFailedListener(this)
//                .addApi(Plus.API)
//                .addApi(Auth.GOOGLE_SIGN_IN_API, mGso)
//                .build();
    mGoogleApiClient = new GoogleApiClient.Builder(this)
    //        .enableAutoManage(this, this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(Plus.API)
            .addApi(Auth.GOOGLE_SIGN_IN_API, mGso)
            .build();

    //mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_REQUIRED); // try to connect right away

    mGmailService = new com.google.api.services.gmail.Gmail.Builder(
            AndroidHttp.newCompatibleTransport(), GsonFactory.getDefaultInstance(), null)
            .setApplicationName("com.company.appname")
            .build();

静默登录在嵌入式片段的onStart()方法中完成:

    // try to silently sign in ...
    OptionalPendingResult<GoogleSignInResult> pendingResult =
            Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);

    if (pendingResult.isDone()) {
        // There's an immediate result available.
        mSignInAcct = pendingResult.get().getSignInAccount();
        mEmailAcct = mSignInAcct.getEmail();
    } else {
        // There's no immediate result ready, wait for the async callback.
        pendingResult.setResultCallback(new ResultCallback<GoogleSignInResult>() {
            @Override
            public void onResult(@NonNull GoogleSignInResult result) {
                mSignInAcct = result.getSignInAccount();
                mEmailAcct = mSignInAcct.getEmail();
            } // if fails, forget it and force a real login later.
        });
    }

    mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
    boolean b = mGoogleApiClient.isConnected();

有时会使用有效的用户帐户进行连接,有时则不会。我确实看到...来自...的isConnected()调用是假的,虽然isConnected()稍后在后面的调用中返回true。

登录按钮代码:

        gmail_signin_button = (com.google.android.gms.common.SignInButton) rootView.findViewById(R.id.gmail_sign_in_button);
        gmail_signin_button.setScopes(mGso.getScopeArray());
        gmail_signin_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // User clicked the sign-in button, so begin the sign-in process and automatically
                // attempt to resolve any errors that occur.
                mShouldResolve = true;

                // connect if unconnected...
                if (!mGoogleApiClient.isConnected()) {
                    mGoogleApiClient.connect();

                    tv_email_status.setText("G+ connecting");
                    // Show a message to the user that we are signing in.
                    Log.d(Constants.TAG, "Google API connecting ...");
                }
                else {
                    // sign in anew ...
                    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                    startActivityForResult(signInIntent, Constants.RC_SIGN_IN);
                }
            }
        });

onActivityResult代码(部分):

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // G+
        if (requestCode == Constants.RC_SIGN_IN) {
            // If the error resolution was not successful we should not resolve further.

            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);

            if (!result.isSuccess()) {
                mShouldResolve = false;
                Log.d(Constants.TAG, "Error: code: " + resultCode);
                tv_email_status.setText("Error: code: " + resultCode);
            } else {
                mSignInAcct = result.getSignInAccount();
                mEmailAcct = mSignInAcct.getEmail();
                Log.d(Constants.TAG, "Gmail signin OK - " + mEmailAcct);
                tv_email_status.setText("Email: " + mEmailAcct);
            }

            mIsResolving = false;
            if(!mGoogleApiClient.isConnected()) {
                mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
            }

        } else if (requestCode == Constants.REQUEST_ACCOUNT_PICKER) {
            if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
                mEmailAcct = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                if (mEmailAcct != null) {
                    //mCredential.setSelectedAccountName(accountName);
                    SharedPreferences settings = mActivity.getPreferences(Context.MODE_PRIVATE);
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putString(Constants.PREF_ACCOUNT_NAME, mEmailAcct);
                    editor.commit();

                    Log.d(Constants.TAG, "Gmail: account: " + mEmailAcct);
                    tv_email_status.setText("Gmail: account: " + mEmailAcct);

                }
            } else if (resultCode == RESULT_CANCELED) {
                tv_email_status.setText("Account unspecified.");
            }
        }
        //else if (requestCode == Constants.REQUEST_AUTHORIZATION) {
            //if (mCredential != null && resultCode != RESULT_OK) {
            //    startActivityForResult(mCredential.newChooseAccountIntent(), Constants.REQUEST_ACCOUNT_PICKER);
            //}
        //}

好的,我会得到一个好的onActivityResult并获得有效的SignInAcct和EmailAcct值。 似乎我们已经登录正常,但是gMail服务总是因为401错误而失败,如上所述。

要进行静音登录,我必须添加GOOGLE_SIGN_IN_API,然后似乎需要GoogleApiClient与SIGN_IN_MODE_OPTIONAL连接,这对我来说没有意义。

我也看到我的AccountPicker现在也没有做任何事情。但这是另一个故事/问题,正如我所说,我认为这一切都有效,直到我尝试添加该静音功能。

哇,好吧,我可能比这更难,有人能引导我朝着正确的方向前进吗?正如我所说,我想做的就是:

  1. 如果用户之前已经这样做,则默默登录
  2. 允许用户登录或重新登录(如果需要)
  3. 阅读用户的电子邮件和联系人
  4. 代表他们发送电子邮件。

1 个答案:

答案 0 :(得分:0)

好吧,我想通了,像往常一样简单的错误。必须设置GmailService构造函数中的凭据,但在尝试连接之前,您不会设置此凭据。所以我有这样的代码

void setGmailAccess(GoogleSignInResult result) {
    mSignInAcct = result.getSignInAccount();
    mEmailAcct = mSignInAcct.getEmail();

    final Thread task = new Thread()
    {
        @Override
        public void run()
        {
            try {
                // run in background thread
                String token = GoogleAuthUtil.getToken(MainActivity.this, Plus.AccountApi.getAccountName(mGoogleApiClient), "oauth2:profile email");
                GoogleCredential credential = new GoogleCredential().setAccessToken(token);
                mGmailService = new com.google.api.services.gmail.Gmail.Builder(
                        AndroidHttp.newCompatibleTransport(), GsonFactory.getDefaultInstance(), credential)
                        .setApplicationName("com.company.appname")
                        .build();
            }
            catch (Exception e) {
                // ignore errors
                String error = e.getMessage();
            }
        }
    };

    task.start();

}

设置GmailService对象。它是从onConnected调用的,我在结果成功块中有这样的代码:

    try {

        // try to silently sign in ...
        OptionalPendingResult<GoogleSignInResult> pendingResult =
                Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);

        if (pendingResult.isDone()) {
            // There's an immediate result available.
            setGmailAccess(pendingResult.get());

        } else {
            // There's no immediate result ready, wait for the async callback.
            pendingResult.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                @Override
                public void onResult(@NonNull GoogleSignInResult result) {
                    setGmailAccess(result);
                } // if fails, forget it and force a real login later.
            });
        }
    } catch(Exception e) {
        String me = e.getLocalizedMessage();
    }

在开始新登录的活动结果中。似乎工作。