android chat in the cloud

Post on 10-May-2015

13.613 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Android chat in the cloud Alfredo Morresi - Mobile & Embedded - 12 febbraio 2014 GDG Firenze

TRANSCRIPT

Alfredo MorresiDeveloper Relations @ Google

Android chat in the cloudRESTful APIs, authentication, push notifications and some additional goodies

ROLE

Developer Relations Program Manager

COUNTRY

Italy

PASSIONS

Community, Development, Snowboarding, Tiramisu'

REACH ME

alfredomorresi@google.complus.google.com/+AlfredoMorresi@rainbowbreeze

Alfredo Morresi

Who I am

Download from https://play.google.com/store/apps/details?id=org.alexismp.cloud.backend

Let’s start with the chat demo app

In less than 40 minutes?

Forget about the backend!

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.

https://developers.google.com/cloud/samples/mbs

Create your backend

Create your backend

Create your backend

Create your backend

http://goo.gl/0FLRPp

Download Android app source code

Change● PROJECT_ID● PROJECT_NUMBER● WEB_CLIENT_ID

Set some values in the source and you’ve done!

Step 1Accessing to the APIs

Google Cloud Endpoints: generate APIs from annotations

https://developers.google.com/appengine/docs/java/endpoints/

Explore the APIs:http://<YOUR_PROJECT_ID>.appspot.com/_ah/api/explorer

Explore the backend APIs

Set Open authentication in the backend

Set the Consts.IS_AUTH_ENABLED to false

Set the Consts.PROJECT_ID to

Access to RESTful APIs, no authentication

It was easy!

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();

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);

Access to RESTful APIs, no authentication

Step 2Accessing to the APIs with authentication

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.

https://developers.google.com/appengine/docs/java/endpoints/auth

Authenticated access to the APIs

Generate Android Client ID

Generate Android Client ID

Generate Web Client ID

Generate Web Client ID

Set Android and Web Client IDs in the backend

Set the Consts.IS_AUTH_ENABLED to true

Set the Consts.WEB_CLIENT_ID to Web Client ID

Authenticated access to the APIs

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);

https://developers.google.com/appengine/docs/java/endpoints/consume_android#Java_Making_authenticated_calls

The Android client provides credentials!

Inject the credential in the backend manager class

// check if credential has account namefinal GoogleAccountCredential gac = credential == null || credential.getSelectedAccountName() == null ? null : mCredential;

// create HttpRequestInitializerHttpRequestInitializer httpRequestInitializer = new HttpRequestInitializer() { @Override public void initialize(HttpRequest request) throws IOException { if (gac != null) { gac.initialize(request); } }};

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.

Authenticated access to the APIs

Step 3Add push notifications

Google Cloud Messaging for Android

http://developer.android.com/google/gcm/index.html

Enable GCM in the project

Generate a Server API Key

Generate a Server API Key

Enable GCM in the backend

Set the Consts.PROJECT_NUMBER to

Enable GCM in the client

http://developer.android.com/google/gcm/client.html

Register your app and store registration ID

String regId = getRegIdFromPref();if (registrationId.isEmpty()) { regid = GoogleCloudMessaging.getInstance(context) .register(PROJECT_ID); storeRegIdToPref(regId);}

A look into GCM client code

@Overridepublic 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);}

Create a BroadcastReceiver to receive push messages

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);}

Handle the message with a Service

And remember to...

App registration is a network operation

Bonus StepApp internal architecture

EntityDto resultEntityDto = backend.endpointV1() .insert(post.getKindName(), post.getEntityDto()).execute();

Because API calls are slow...

Never forget!

// create a response handler that will receive the result or an errorCloudCallbackHandler<List<CloudEntity>> handler = new CloudCallbackHandler<List<CloudEntity>>() { @Override public void onComplete(List<CloudEntity> results) { ... }

@Override public void onError(IOException exception) { ... }

CloudBackendASync extends CloudBackend

// execute the query with the handlermProcessingFragment.getCloudBackend().listByKind( "Guestbook", CloudEntity.PROP_CREATED_AT, Order.DESC, 50, Scope.FUTURE_AND_PAST, handler);

CloudBackendASync extends CloudBackend

Why these two classes?

Separate the logic (CloudBackend) from the sync management (CloudBackendAsync) makes the code more testable!

// Check to see if we have retained the fragment which handles asynchronous backend callsmProcessingFragment = (CloudBackendFragment) mFragmentManager. findFragmentByTag(PROCESSING_FRAGMENT_TAG);// If not retained (or first time running), create a new oneif (mProcessingFragment == null) { mProcessingFragment = new CloudBackendFragment(); mProcessingFragment.setRetainInstance(true); fragmentTransaction.add(mProcessingFragment, PROCESSING_FRAGMENT_TAG);}…// execute the insertion with the handlermProcessingFragment.getCloudBackend().insert(newPost, handler);mMessageTxt.setEnabled(false);mSendBtn.setEnabled(false);

Activity lifecycle (you can do better!)

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);

Extends the data

https://developersitalia.blogspot.com

Curious about Google dev initiatives and event in Italy?

Thank you!http://developers.google.com

Alfredo Morresiplus.google.com/+AlfredoMorresi@rainbowbreeze

top related