Save 37% off PRO during our Black Friday Sale! »

Crossing Platforms With Google+ Sign-In

47d1af0e885746e39195c8ff3234f47d?s=47 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

47d1af0e885746e39195c8ff3234f47d?s=128

Ian Barber

September 27, 2013
Tweet

Transcript

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

  2. Websites

  3. Web Apps

  4. Mobile Apps

  5. And...

  6. And...

  7. And...

  8. And...

  9. Many Apps / One Experience

  10. None
  11. None
  12. <button 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 </button>
  13. <button 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 </button>
  14. <button 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 </button>
  15. None
  16. None
  17. google now card?

  18. <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "FlightReservation", "reservationNumber": "RXJ34P", "underName":

    { "@type": "Person", "name": "Eva Green" }, "reservationFor": { "@type": "Flight", "flightNumber": "110", "airline": { "@type": "Airline", "name": "United", "iataCode": "UA" }...
  19. Moments of transition

  20. None
  21. 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();
  22. None
  23. // ... 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]; }
  24. None
  25. None
  26. 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' });
  27. None
  28. @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(); }
  29. @Override public void onConnected(Bundle connectionHint) { String currentPersonName = mPlusClient.getCurrentPerson().getDisplayName();

    } @Override public void onConnectionFailed(ConnectionResult result) { mConnectionResult = result; }
  30. // In didFinishLaunchingWithOptions [[GPPSignIn sharedInstance] setClientID:@"YOUR_CLIENT_ID"]; [[GPPSignIn sharedInstance] setDelegate:self]; [[GPPSignIn

    sharedInstance] trySilentAuthentication]; // In view controller, trigger sign in [[GPPSignIn sharedInstance] authenticate]
  31. // 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! } }
  32. None
  33. $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;
  34. 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
  35. Context

  36. None
  37. None
  38. 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 } }); }
  39. None
  40. Cross-Device Experiences

  41. None
  42. 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); } }
  43. 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; }];
  44. App storage Drive file Cloud Save Cloud Datastore Cloud Storage

    YouTube User Control Size Cloud SQL
  45. Gameplay video

  46. Crossing Platforms

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

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