【问题标题】:How to use sync token on Google People API如何在 Google People API 上使用同步令牌
【发布时间】:2019-11-27 14:59:06
【问题描述】:

我真的找不到如何使用它的示例。

现在,我正在这样做:

    // Request 10 connections.
    ListConnectionsResponse response = peopleService.people().connections()
            .list("people/me")
            .setRequestSyncToken(true)
            .setPageSize(10)
            .setPersonFields("names,emailAddresses")
            .execute();

我对我的联系人进行了一些更改(添加、删除、更新),然后我这样做:

    // Request 10 connections.
    ListConnectionsResponse response2 = peopleService.people().connections()
            .list("people/me")
            .setSyncToken(response.getNextSyncToken())
            .setPageSize(10)
            .setPersonFields("names,emailAddresses")
            .execute();

但似乎我无法获得我之前所做的更改,即使我直接从 UI 进行更改也是如此。我很确定我以错误的方式使用了同步令牌。

更新(19/02/2020):在这个例子中,我在第一个请求中调用了请求同步令牌的 API(我成功获取了联系人),暂停执行(通过断点),删除一个联系人并更新另一个联系人(从网页),恢复执行,然后我使用从上一次调用中提取的同步令牌再次调用 API。结果是由于某种原因没有进行任何更改:

   // Build a new authorized API client service.
    final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
    PeopleService peopleService = new PeopleService.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
            .setApplicationName(APPLICATION_NAME)
            .build();

    // Request 10 connections.
    ListConnectionsResponse response = peopleService.people().connections()
            .list("people/me")
            .setPageSize(10)
            .setPersonFields("names,emailAddresses")
            .setRequestSyncToken(true)
            .execute();

    // Print display name of connections if available.
    List<Person> connections = response.getConnections();
    if (connections != null && connections.size() > 0) {
        for (Person person : connections) {
            List<Name> names = person.getNames();
            if (names != null && names.size() > 0) {
                System.out.println("Name: " + person.getNames().get(0)
                        .getDisplayName());
            } else {
                System.out.println("No names available for connection.");
            }
        }
    } else {
        System.out.println("No connections found.");
    }
    // CORRECT: 2 CONTACTS PRINTED

    // CORRECT: THE SYNC TOKEN IS THERE
    String syncToken = response.getNextSyncToken();
    System.out.println("syncToken = "+syncToken);

    // I SETUP A BREAKPOINT BELOW, I DELETE ONE CONTACT AND EDIT ANOTHER AND THEN I RESUME THE EXECUTING
    // Request 10 connections.
    response = peopleService.people().connections()
            .list("people/me")
            .setPageSize(10)
            .setPersonFields("names,emailAddresses")
            .setSyncToken(syncToken)
            .execute();

    // Print display name of connections if available.
    connections = response.getConnections();
    if (connections != null && connections.size() > 0) {
        for (Person person : connections) {
            List<Name> names = person.getNames();
            if (names != null && names.size() > 0) {
                System.out.println("Name: " + person.getNames().get(0)
                        .getDisplayName());
            } else {
                System.out.println("No names available for connection.");
            }
        }
    } else {
        System.out.println("No connections found.");
    }
    // WRONG: I GET "NO CONNECTIONS FOUND"

【问题讨论】:

    标签: google-people-api


    【解决方案1】:

    我发现,在请求或设置同步令牌时,您必须迭代整个联系人以填充 nextSyncToken。

    也就是说只要有nextPageToken(wink wink setPageSize(10)),同步令牌就不会被填充。

    你可以:

    A) 使用您当前的循环遍历所有联系人 分页,做任何你需要做的事情 迭代,并在最后一次调用后检索填充的 同步令牌。

    B) 一次遍历所有联系人,使用最大值 页面大小为 2000 和单个 personField,检索 令牌,然后做任何你需要做的事情。请注意,如果 您期望用户拥有超过 2000 个 联系人,您仍然需要使用 下一个PageToken。

    这里是一个同步循环的例子,改编自Synchronize Resources Efficiently。请注意,我通常使用 Python 客户端,因此此 Java 代码可能不是 100% 无错误:

    private static void run() throws IOException {
        Request request = people_service.people().connections()
                .list("people/me")
                .setPageSize(10)
                .setPersonFields("names,emailAddresses");
    
        // Load the sync token stored from the last execution, if any. 
        // The syncSettingsDataStore is whatever you use for storage.
        String syncToken = syncSettingsDataStore.get(SYNC_TOKEN_KEY);
    
        String syncType = null;
    
        // Perform the appropiate sync
        if (syncToken == null) {
            // Perform a full sync
            request.setRequestSyncToken(true);
            syncType = "FULL";
        } else {
            // Try to perform an incremental sync.
            request.setSyncToken(syncToken);
            syncType = "INCREMENTAL";
        }
    
        String pageToken = null;
        ListConnectionsResponse response = null;
        List<Person> contacts = null;
    
        // Iterate over all the contacts, page by page.
        do {
            request.setPageToken(pageToken);
    
            try {
                response = request.execute();
            } catch (GoogleJsonResponseException e) {
                if (e.getStatusCode() == 410) {
                    // A 410 status code, "Gone", indicates that the sync token is 
                    // invalid/expired.
                    // WARNING: The code is 400 in the Python client. I think the 
                    //  Java client uses the correct code, but be on the lookout.
    
                    // Clear the sync token.
                    syncSettingsDataStore.delete(SYNC_TOKEN_KEY);
                    // And anything else you need before re-syncing.
                    dataStore.clear();
                    // Restart
                    run();
                } else {
                  throw e;
                }
            }
    
            contacts = response.getItems();
            if (contacts.size() == 0) {
                System.out.println("No contacts to sync.");
            } else if (syncType == "FULL"){
                //do full sync for this page.
            } else if (syncType == "INCREMENTAL") {
                //do incremental sync for this page.
            } else {
                // What are you doing here???
            }
    
            pageToken = response.getNextPageToken();
        } while (pageToken != null);
    
        // Store the sync token from the last request for use at the next execution.
        syncSettingsDataStore.set(SYNC_TOKEN_KEY, response.getNextSyncToken());
    
        System.out.println("Sync complete.");
    }
    

    【讨论】:

    • 您好,谢谢您的回答!既然您似乎了解了它的工作原理,您能否分享一个有关如何使用此同步令牌的实际示例?我真的很困惑我应该如何结合.setRequestSyncToken(true).setSyncToken(response.getNextSyncToken()),尤其是当你第一次调用 APi 时。我正在编写一个迁移应用程序,我需要确保我的源联系人在 Google 中是最新的。此外,不确定这是否对您或其他人有用,但我发现资源名称可以更改。这让事情变得更加复杂。
    • 好的,我稍后再添加。我实际上正在开发一个供内部使用的联系人同步烧瓶应用程序,设置起来真的很痛苦。
    • @CapitanoGiovarco 添加了示例。
    • 嘿,谢谢你的好例子!我已经阅读了文档。 Google Calendar API 的代码与 People API 的代码非常相似。尽管如此,我仍有几个疑问(1)您如何区分更新的联系人和已删除的联系人?我的理解是最终在同一个结果池中(2)当你的令牌过期时你应该怎么做?因为,如果是这种情况,您没有其他方法可以同步您的联系人列表 (3) 您如何处理 ResourceName 会随时间变化的事实?
    • 我希望我们可以继续合作,以便最后我可以将我的 Java 代码发布给后代:)
    猜你喜欢
    • 1970-01-01
    • 2021-10-14
    • 2021-12-13
    • 2015-03-11
    • 2016-01-14
    • 2017-07-24
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    相关资源
    最近更新 更多