代码之家  ›  专栏  ›  技术社区  ›  evenro

Google API with GoogleSignIn-错误401-未经授权

  •  1
  • evenro  · 技术社区  · 7 年前

    我在这件事上坐了将近一个星期,找不到任何文档来解释如何将GoogleSignIn连接到Google API。。。

    我正在尝试使用Google验证用户身份(使用GoogleSignIn框架),然后阅读特定日历。类似的方法在iOS上“开箱即用”,现在我正尝试在Android上也这样做。

    我通过以下方式验证用户:

    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestScopes(new Scope("https://www.googleapis.com/auth/calendar.readonly"))
                    .requestIdToken(getString(R.string.default_web_client_id))
                    .requestEmail()
                    .build();
    signInClient = GoogleSignIn.getClient(getContext(), gso);
    signIn.setSize(SignInButton.SIZE_STANDARD);
    signIn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        Intent signInIntent = signInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
      }
    });
    GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(getContext());
    if (account == null) {
      setSignInVisible(true);
    } else {
      setSignInVisible(false);
      if (account.getIdToken() != null) {
        AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
        FirebaseAuth mAuth = FirebaseAuth.getInstance();
        mAuth.signInWithCredential(credential);
      }
    }
    

    稍后,尝试通过以下方式访问日历API:

    Calendar HttpTransport transport = AndroidHttp.newCompatibleTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
    GoogleSignInAccount gsia = GoogleSignIn.getLastSignedInAccount(getContext());
    GoogleCredential gc = new GoogleCredential().setAccessToken(gsia.getIdToken());
    mService = new com.google.api.services.calendar.Calendar.Builder(
                        transport, jsonFactory, gc)
                        .setApplicationName("MyApp")
                        .build();
    Events events = mService.events().list(CalendarActivity._dataStore.getConfigString(CalendarActivity.instance.getString(R.string.config_google_calendar_key)))
                        .setTimeMin(dtFourDaysBack)
                        .setTimeMax(dtTwoMonthFuture)
                        .setOrderBy("startTime")
                        .setSingleEvents(true)
                        .execute();
    

    但是,执行会导致401-未经授权的错误。。。 我做错什么了吗? 重要的是,我确实从帐户对象获取了用户信息(我看到了电子邮件,我得到了令牌等)

    2 回复  |  直到 7 年前
        1
  •  4
  •   evenro    7 年前

    我刚刚解决了这个问题,我希望这将帮助所有那些遭受无法解释的401-未经授权错误之苦的人。

    问题是凭据的生成。 创建它的方式是:

    private static final String[] SCOPES = { CalendarScopes.CALENDAR_READONLY };
    final GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(getContext());
    GoogleAccountCredential mCredential = GoogleAccountCredential.usingOAuth2(
                                           mainActivity.instance, Arrays.asList(SCOPES))
                                          .setSelectedAccountName(account.getAccount().name)
                                          .setBackOff(new ExponentialBackOff());
    

    请注意凭据的用法。事实并非如此 GoogleCredentials .我在任何地方都找不到的是 setSelectedAccountName 这是我通过实验得到的(糟糕的是,我花了大约一周的时间才尝试了这一点……)。

    在实施时,确保它干净(使用 account 仅当对象不是 null

    祝我们大家好运。。。

        2
  •  0
  •   Farmer    7 年前

    可能是您正在尝试调用日历代码,而没有任何同步过程。尝试以下集成google日历的代码。 处理Google日历API调用的异步任务。将API调用放在自己的任务中可以确保UI保持响应。

    private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
            private com.google.api.services.calendar.Calendar mService = null;
            private Exception mLastError = null;
    
            MakeRequestTask(GoogleAccountCredential credential) {
                HttpTransport transport = AndroidHttp.newCompatibleTransport();
                JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
                mService = new com.google.api.services.calendar.Calendar.Builder(
                        transport, jsonFactory, credential)
                        .setApplicationName("Google Calendar API Android Quickstart")
                        .build();
            }
    
            @Override
            protected List<String> doInBackground(Void... params) {
                try {
                    return getDataFromApi();
                } catch (Exception e) {
                    mLastError = e;
                    cancel(true);
                    return null;
                }
            }
    
            private List<String> getDataFromApi() throws IOException {
                // List the next 10 events from the primary calendar.
                DateTime now = new DateTime(System.currentTimeMillis());
                List<String> eventStrings = new ArrayList<String>();
                Events events = mService.events().list("primary")
                        .setMaxResults(10)
                        .setTimeMin(now)
                        .setOrderBy("startTime")
                        .setSingleEvents(true)
                        .execute();
                List<Event> items = events.getItems();
    
                for (Event event : items) {
                    DateTime start = event.getStart().getDateTime();
                    if (start == null) {
                        // All-day events don't have start times, so just use
                        // the start date.
                        start = event.getStart().getDate();
                    }
                    eventStrings.add(
                            String.format("%s (%s)", event.getSummary(), start));
                }
                return eventStrings;
            }
    
    
            @Override
            protected void onPreExecute() {
                mOutputText.setText("");
                mProgress.show();
            }
    
            @Override
            protected void onPostExecute(List<String> output) {
                mProgress.hide();
                if (output == null || output.size() == 0) {
                    //"No results returned
                } else {
                    //Data retrieved using the Google Calendar API
                }
            }
    }
    

    有关更多详细信息,请查看 google documentation description