How to use sync token on Google People API

2019-11-27 google-people

I cannot really find an example on how to use this.

Right now, I'm doing like this:

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

I make some changes to my contacts (adding, removing, updating), then I do this:

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

But it seems like I cannot get the changes I've done earlier, not even if I do them directly from the UI. I'm pretty sure I'm using the sync token in the wrong way.

Update (19/02/2020): In this example I call the API requesting the sync token in the first request (I successfully get the contacts), pause the execution (by breakpoint), delete a contact and update another one (from the web page), resume the execution and then I call the API again with the sync token that I extracted from the previous call. The result is that no change was made for some reason:

   // 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"

Answers

Qualcosa che ho scoperto è che, quando si richiede o si imposta un token di sincronizzazione, è necessario ripetere l'intera interazione dei contatti affinché venga popolato il prossimo SyncToken.

Ciò significa che fino a quando c'è un nextPageToken (wink wink setPageSize (10)), il token di sincronizzazione non verrà popolato.

Puoi:

A) Passa in rassegna tutti i contatti usando la tua corrente impaginazione, facendo tutto ciò che è necessario fare ad ogni iterazione e dopo l'ultima chiamata recuperare il popolato token di sincronizzazione.

B) Scorrere su tutti i contatti in una volta sola, utilizzando il dimensione della pagina di 2000 e una sola persona Campo, recuperare il file token, quindi fai tutto ciò che devi fare. Si noti che se ti aspetti che un utente ne abbia più di 2000 contatti, dovrai comunque chiamare le pagine successive utilizzando the nextPageToken.

Ecco un esempio di un ciclo di sincronizzazione, adattato da Sincronizza risorse in modo efficiente . Nota che di solito uso il client Python, quindi questo codice Java potrebbe non essere privo di errori al 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.");
}

Related