Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Android chat in the cloud


Published on

Android chat in the cloud

Alfredo Morresi - Mobile & Embedded - 12 febbraio 2014 GDG Firenze

Published in: Technology

Android chat in the cloud

  1. 1. Android chat in the cloud RESTful APIs, authentication, push notifications and some additional goodies Alfredo Morresi Developer Relations @ Google
  2. 2. Who I am Alfredo Morresi ROLE Developer Relations Program Manager COUNTRY Italy PASSIONS Community, Development, Snowboarding, Tiramisu' REACH ME @rainbowbreeze
  3. 3. Let’s start with the chat demo app Download from
  4. 4. In less than 40 minutes?
  5. 5. Forget about the backend!
  6. 6. Use Google Cloud Platform + Mobile Backend Starter Optional server-side coding: Control your cloud service using Android and iOS client libraries. Cloud Datastore: Store millions of objects in the cloud and manage them from your app. Push Notifications: Send and broadcast objects as messages via Apple Push Notifications and Google Cloud Messaging. Event Driven Programming: Create real-time interactive user experiences using Continuous Queries. User authentication: Authenticate users using Google Accounts and control access on private data. Built to scale: Mobile backend runs on App Engine infrastructure to scale to millions of users within hours.
  7. 7. Create your backend
  8. 8. Create your backend
  9. 9. Create your backend
  10. 10. Create your backend
  11. 11. Download Android app source code
  12. 12. Set some values in the source and you’ve done! Change ● ● ● PROJECT_ID PROJECT_NUMBER WEB_CLIENT_ID
  13. 13. Step 1 Accessing to the APIs
  14. 14. Google Cloud Endpoints: generate APIs from annotations
  15. 15. Explore the backend APIs Explore the APIs: http://<YOUR_PROJECT_ID>
  16. 16. Set Open authentication in the backend
  17. 17. Access to RESTful APIs, no authentication Set the Consts.IS_AUTH_ENABLED to false Set the Consts.PROJECT_ID to
  18. 18. It was easy!
  19. 19. Access to RESTful APIs, no authentication Google Cloud Endpoints automatically generates the Android code required to access the backend APIs Mobilebackend.Builder builder = new Mobilebackend.Builder( AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); Mobilebackend backend = builder.setRootUrl(Consts.ENDPOINT_ROOT_URL).build();
  20. 20. Access to RESTful APIs, no authentication Insert a new CloudEntity in the backend CloudEntity post = new CloudEntity("Guestbook"); post.put("message", "Your message here..."); EntityDto resultEntityDto = backend.endpointV1() .insert(post.getKindName(), post.getEntityDto()).execute(); CloudEntity resultCo = CloudEntity.createCloudEntityFromEntityDto (resultEntityDto); Log.i(Consts.TAG, "insert: inserted: " + resultCo);
  21. 21. Step 2 Accessing to the APIs with authentication
  22. 22. Authenticated access to the APIs Restrict the API access only to your application(s). ANDROID Client_ID: identifies your app in unique way (package name + SHA1 of signing key of the app) WEB Client_ID: establishes that the client and the server are from the same developer so the standard OAuth2 prompt is avoided (no 3rd party app). It’s a shared token.
  23. 23. Generate Android Client ID
  24. 24. Generate Android Client ID
  25. 25. Generate Web Client ID
  26. 26. Generate Web Client ID
  27. 27. Set Android and Web Client IDs in the backend
  28. 28. Authenticated access to the APIs Set the Consts.IS_AUTH_ENABLED to true Set the Consts.WEB_CLIENT_ID to Web Client ID
  29. 29. The Android client provides credentials! GoogleAccountCredential credential = GoogleAccountCredential.usingAudience( getActivity(), Consts.AUTH_AUDIENCE); if (credential.getSelectedAccountName() == null) { startActivityForResult( credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); credential.setSelectedAccountName(accountName); com/appengine/docs/java/endpoints/consume_android#Java_Making_aut henticated_calls
  30. 30. Authenticated access to the APIs Inject the credential in the backend manager class // check if credential has account name final GoogleAccountCredential gac = credential == null || credential.getSelectedAccountName() == null ? null : mCredential; // create HttpRequestInitializer HttpRequestInitializer httpRequestInitializer = new HttpRequestInitializer() { @Override public void initialize(HttpRequest request) throws IOException { if (gac != null) { gac.initialize(request); } } };
  31. 31. Authenticated access to the APIs Mobilebackend.Builder builder = new Mobilebackend.Builder( AndroidHttp.newCompatibleTransport(), new GsonFactory(), httpRequestInitializer); Mobilebackend backend = builder.setRootUrl(Consts.ENDPOINT_ROOT_URL).build(); … Now the API backend framework automatically authenticates the user and enforces the authorized clientIds whitelist, ultimately by supplying a valid User to the API parameters.
  32. 32. Step 3 Add push notifications
  33. 33. Google Cloud Messaging for Android
  34. 34. Enable GCM in the project
  35. 35. Generate a Server API Key
  36. 36. Generate a Server API Key
  37. 37. Enable GCM in the backend
  38. 38. Enable GCM in the client Set the Consts.PROJECT_NUMBER to
  39. 39. A look into GCM client code Register your app and store registration ID String regId = getRegIdFromPref(); if (registrationId.isEmpty()) { regid = GoogleCloudMessaging.getInstance(context) .register(PROJECT_ID); storeRegIdToPref(regId); }
  40. 40. Create a BroadcastReceiver to receive push messages @Override public void onReceive(Context context, Intent intent) { // Explicitly specify that GcmIntentService will handle the intent ComponentName comp = new ComponentName( context.getPackageName(), GCMIntentService.class.getName()); // Start service, keeping the device awake while it is launching startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); }
  41. 41. Handle the message with a Service protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); String msgType = gcm.getMessageType(intent); if (extras.isEmpty()) { // has effect of unparcelling Bundle … } if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) { … } // Release the wake lock provided by the WakefulBroadcastReceiver. GCMBroadcastReceiver.completeWakefulIntent(intent); }
  42. 42. And remember to... App registration is a network operation
  43. 43. Bonus Step App internal architecture
  44. 44. Because API calls are slow... EntityDto resultEntityDto = backend.endpointV1() .insert(post.getKindName(), post.getEntityDto()).execute();
  45. 45. Never forget!
  46. 46. CloudBackendASync extends CloudBackend // create a response handler that will receive the result or an error CloudCallbackHandler<List<CloudEntity>> handler = new CloudCallbackHandler<List<CloudEntity>>() { @Override public void onComplete(List<CloudEntity> results) { ... } @Override public void onError(IOException exception) { ... }
  47. 47. CloudBackendASync extends CloudBackend // execute the query with the handler mProcessingFragment.getCloudBackend().listByKind( "Guestbook", CloudEntity.PROP_CREATED_AT, Order.DESC, 50, Scope.FUTURE_AND_PAST, handler);
  48. 48. Why these two classes? Separate the logic (CloudBackend) from the sync management (CloudBackendAsync) makes the code more testable!
  49. 49. Activity lifecycle (you can do better!) // Check to see if we have retained the fragment which handles asynchronous backend calls mProcessingFragment = (CloudBackendFragment) mFragmentManager. findFragmentByTag(PROCESSING_FRAGMENT_TAG); // If not retained (or first time running), create a new one if (mProcessingFragment == null) { mProcessingFragment = new CloudBackendFragment(); mProcessingFragment.setRetainInstance(true); fragmentTransaction.add(mProcessingFragment, PROCESSING_FRAGMENT_TAG); } … // execute the insertion with the handler mProcessingFragment.getCloudBackend().insert(newPost, handler); mMessageTxt.setEnabled(false); mSendBtn.setEnabled(false);
  50. 50. Extends the data CloudEntity post = new CloudEntity("Guestbook"); post.put("message", "Your message here..."); post.put("alf_property", "Custom property value here..."); EntityDto resultEntityDto = backend.endpointV1() .insert(post.getKindName(), post.getEntityDto()).execute(); CloudEntity resultCo = CloudEntity.createCloudEntityFromEntityDto(resultEntityDto);
  51. 51. Curious about Google dev initiatives and event in Italy?
  52. 52. Thank you! Alfredo Morresi @rainbowbreeze