android - Always get 401 log in required from Gmail API -


ok, had working @ 1 point, wanted add silent login (optional) @ app startup. going crazy , getting following error

com.google.api.client.googleapis.json.googlejsonresponseexception: 401 unauthorized { "code": 401, "errors": [ { "domain": "global", "location": "authorization", "locationtype": "header", "message": "login required", "reason": "required" } ], "message": "login required" }

this occurs on line (should using "me"?)

message messageresult = mgmailservice.users().messages().send("me", message).execute(); 

whenever try send (in case above) or read email (not shown). ultimately, want app read user emails , send on behalf. app registered, has keys, permissions, etc.

i setting data (you can see various comments tried things working):

    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 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 connect right away      mgmailservice = new com.google.api.services.gmail.gmail.builder(             androidhttp.newcompatibletransport(), gsonfactory.getdefaultinstance(), null)             .setapplicationname("com.company.appname")             .build(); 

the silent login done in onstart() method of embedded fragment as:

    // try silently sign in ...     optionalpendingresult<googlesigninresult> pendingresult =             auth.googlesigninapi.silentsignin(mgoogleapiclient);      if (pendingresult.isdone()) {         // there's immediate result available.         msigninacct = pendingresult.get().getsigninaccount();         memailacct = msigninacct.getemail();     } else {         // there's no immediate result ready, wait async callback.         pendingresult.setresultcallback(new resultcallback<googlesigninresult>() {             @override             public void onresult(@nonnull googlesigninresult result) {                 msigninacct = result.getsigninaccount();                 memailacct = msigninacct.getemail();             } // if fails, forget , force real login later.         });     }      mgoogleapiclient.connect(googleapiclient.sign_in_mode_optional);     boolean b = mgoogleapiclient.isconnected(); 

which connects right away valid user account , not. see b ...isconnected() call false, although isconnected() returns true later in later calls.

login button code:

        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 sign-in button, begin sign-in process , automatically                 // attempt resolve errors occur.                 mshouldresolve = true;                  // connect if unconnected...                 if (!mgoogleapiclient.isconnected()) {                     mgoogleapiclient.connect();                      tv_email_status.settext("g+ connecting");                     // show message user 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 code (in part):

    public void onactivityresult(int requestcode, int resultcode, intent data) {         super.onactivityresult(requestcode, resultcode, data);          // g+         if (requestcode == constants.rc_sign_in) {             // if error resolution not successful 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);             //}         //} 

ok, onactivityresult , valid signinacct , emailacct values. it seems logged in fine, gmail service fails 401 error explained above.

to silent login made me have add google_sign_in_api seems require googleapiclient connect sign_in_mode_optional doesn't make sense me.

i see accountpicker nothing well. story/problem, said thought had working until tried add silent feature.

whew, have made harder is, can steer me in right direction? said want is:

  1. silently log in if user has done so
  2. allow user log in or re-log in if needed
  3. read users emails , contacts
  4. send email on behalf.

ok, figured out, usual simple wrong. credential in gmailservice constructor must set, don't have until try connect. have code this

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();  } 

to set gmailservice object. called onconnected, have code in result success block:

    try {          // try silently sign in ...         optionalpendingresult<googlesigninresult> pendingresult =                 auth.googlesigninapi.silentsignin(mgoogleapiclient);          if (pendingresult.isdone()) {             // there's immediate result available.             setgmailaccess(pendingresult.get());          } else {             // there's no immediate result ready, wait async callback.             pendingresult.setresultcallback(new resultcallback<googlesigninresult>() {                 @override                 public void onresult(@nonnull googlesigninresult result) {                     setgmailaccess(result);                 } // if fails, forget , force real login later.             });         }     } catch(exception e) {         string me = e.getlocalizedmessage();     } 

and in activity result starting new login. seems work.


Comments

Popular posts from this blog

c# - How Configure Devart dotConnect for SQLite Code First? -

c++ - Clear the memory after returning a vector in a function -

erlang - Saving a digraph to mnesia is hindered because of its side-effects -