Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Crossing Platforms With Google+ Sign-In

Ian Barber
September 27, 2013

Crossing Platforms With Google+ Sign-In

A brief look at some of the challenges of existing in a multi-device world, the benefits of having an identity to transition state between environments, and how the Google identity infrastructure and Google+ sign-in can help with that.

#ota13

Ian Barber

September 27, 2013
Tweet

More Decks by Ian Barber

Other Decks in Programming

Transcript

  1. Crossing Platforms
    With Google+ Sign-In
    Ian Barber
    google.com/+IanBarber
    @ianbarber

    View full-size slide

  2. Many Apps / One Experience

    View full-size slide

  3. class="g-interactivepost"
    data-contenturl="https://plus.google.com/pages/"
    data-contentdeeplinkid="/pages"
    data-clientid="xxxxx.apps.googleusercontent.com"
    data-cookiepolicy="single_host_origin"
    data-calltoactionlabel="LISTEN"
    data-calltoactionurl="http://plus.google.com/pages/create"
    data-calltoactiondeeplinkid="/pages/create">
    Tell your friends

    View full-size slide

  4. class="g-interactivepost"
    data-contenturl="https://plus.google.com/pages/"
    data-contentdeeplinkid="/pages"
    data-clientid="xxxxx.apps.googleusercontent.com"
    data-cookiepolicy="single_host_origin"
    data-calltoactionlabel="LISTEN"
    data-calltoactionurl="http://plus.google.com/pages/create"
    data-calltoactiondeeplinkid="/pages/create">
    Tell your friends

    View full-size slide

  5. class="g-interactivepost"
    data-contenturl="https://plus.google.com/pages/"
    data-contentdeeplinkid="/pages"
    data-clientid="xxxxx.apps.googleusercontent.com"
    data-cookiepolicy="single_host_origin"
    data-calltoactionlabel="LISTEN"
    data-calltoactionurl="http://plus.google.com/pages/create"
    data-calltoactiondeeplinkid="/pages/create">
    Tell your friends

    View full-size slide

  6. google now card?

    View full-size slide

  7. <br/>{ "@context": "http://schema.org",<br/>"@type": "FlightReservation",<br/>"reservationNumber": "RXJ34P",<br/>"underName":<br/>{ "@type": "Person", "name": "Eva Green" },<br/>"reservationFor": {<br/>"@type": "Flight",<br/>"flightNumber": "110",<br/>"airline": {<br/>"@type": "Airline",<br/>"name": "United",<br/>"iataCode": "UA"<br/>}...<br/>

    View full-size slide

  8. Moments of transition

    View full-size slide

  9. PlusShare.Builder builder =
    new PlusShare.Builder(this, mPlusClient);
    builder.addCallToAction("APPLY",
    callToActionUrl,
    callToActionDeepLinkId);
    builder.setContentUrl(linkUrl);
    builder.setContentDeepLinkId(deepLinkId, null, null, null);
    builder.setText(mEditSendText.getText().toString());
    return builder.getIntent();

    View full-size slide

  10. // ... in didFinishLaunchingWithOptions
    [GPPDeepLink setDelegate:self];
    [GPPDeepLink readDeepLinkAfterInstall];
    - (BOOL)application:(UIApplication *)application
    openURL:(NSURL *)url
    sourceApplication:(NSString *)sourceApplication
    annotation:(id)annotation {
    return [GPPURLHandler handleURL:url
    sourceApplication:sourceApplication
    annotation:annotation];
    }

    View full-size slide

  11. gapi.signin.render(id, {
    'clientid': '123456789.apps.googleusercontent.com',
    'callback': 'signInCallback',
    'cookiepolicy': 'single_host_origin',
    'requestvisibleactions':
    'http://schemas.google.com/AddActivity',
    'scope': 'https://www.googleapis.com/auth/plus.login ' +
    'https://www.googleapis.com/auth/userinfo.email',
    'accesstype': 'offline',
    'apppackagename': 'deezer.android.app'
    });

    View full-size slide

  12. @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sign_in_activity);
    mPlusClient = new PlusClient.Builder(this, this, this)
    .setScopes(Scopes.PLUS_LOGIN)
    .setVisibleActivities(MomentUtil.VISIBLE_ACTIVITIES)
    .build();
    }
    @Override
    public void onStart() {
    super.onStart();
    mPlusClient.connect();
    }

    View full-size slide

  13. @Override
    public void onConnected(Bundle connectionHint) {
    String currentPersonName =
    mPlusClient.getCurrentPerson().getDisplayName();
    }
    @Override
    public void onConnectionFailed(ConnectionResult result) {
    mConnectionResult = result;
    }

    View full-size slide

  14. // In didFinishLaunchingWithOptions
    [[GPPSignIn sharedInstance]
    setClientID:@"YOUR_CLIENT_ID"];
    [[GPPSignIn sharedInstance] setDelegate:self];
    [[GPPSignIn sharedInstance] trySilentAuthentication];
    // In view controller, trigger sign in
    [[GPPSignIn sharedInstance] authenticate]

    View full-size slide

  15. // In the sign-in delegate
    - (void)finishedWithAuth:(GTMOAuth2Authentication *)auth
    error:(NSError *)error {
    if (error) {
    NSLog(@"Sign-In Error: %@", error);
    [[GPPSignIn sharedInstance] signOut];
    } else {
    // We're signed in!
    }
    }

    View full-size slide

  16. $opts = array(
    'http' => array(
    'method' => 'POST',
    'header' =>
    'Content-type: application/x-www-form-urlencoded',
    'content' => "client_id=" . $clientId .
    "&scope=https://www.googleapis.com/auth/plus.me"));
    $ctx = stream_context_create($opts);
    $result = file_get_contents(
    "https://accounts.google.com/o/oauth2/device/code",
    false, $ctx);
    $result = json_decode($result);
    $code = $result->user_code;

    View full-size slide

  17. Device
    Google User
    Request Device Code
    Device Code
    Request Token For Code
    Error
    Enter Code
    Display Consent
    Grant Consent
    Request Token For Code
    Access Token
    Google
    Display Code

    View full-size slide

  18. function OnLoadCallback() {
    sessionParams = {
    'client_id': 'YOUR_CLIENT_ID_HERE',
    'session_state': null
    };
    gapi.auth.checkSessionState(sessionParams,
    function(stateMatched) {
    if (stateMatched == true) {
    // Logged out
    } else {
    // Logged in
    }
    });
    }

    View full-size slide

  19. Cross-Device Experiences

    View full-size slide

  20. public void onStateLoaded(
    int statusCode, int stateKey, byte[] data) {
    if (statusCode == AppStateClient.STATUS_OK) {
    try {
    String s = new String(data,"UTF-8");
    SquashView sv =
    (SquashView)findViewById(R.id.squashView);
    sv.mScore = Integer.parseInt(s);
    } catch (Exception e) {
    e.printStackTrace();
    }
    } else {
    Log.e("MultiSquash", "failed because: " + statusCode);
    }
    }

    View full-size slide

  21. GPGAppStateModel *model =
    [GPGManager sharedInstance].applicationModel.appState;
    NSNumber *slot = @0;
    [model loadForKey:slot completionHandler:
    ^(GPGAppStateLoadStatus status, NSError *error) {
    if (status == GPGAppStateLoadStatusSuccess) {
    NSData *data = [model stateDataForKey:slot];
    NSString *str = [[NSString alloc]
    initWithData:data encoding:NSUTF8StringEncoding];
    NSInteger value = [str intValue];
    [self updatePreviousScoreWithData:value];
    }
    } conflictHandler:
    ^NSData *(NSNumber *key, NSData *local, NSData *remote)
    { return remoteState; }];

    View full-size slide

  22. App storage Drive file
    Cloud Save
    Cloud Datastore
    Cloud Storage
    YouTube
    User Control
    Size
    Cloud SQL

    View full-size slide

  23. Gameplay video

    View full-size slide

  24. Crossing Platforms

    View full-size slide

  25. developers.google.com/+ developers.google.com
    cloud.google.com github.com/nlathia/SensorManager

    View full-size slide

  26. Thank You
    Ian Barber
    google.com/+IanBarber
    developers.google.com/+

    View full-size slide