Enable an IoT wearable app with Android Gear Live and Kii (Part 1)

How to connect a smart watch to the cloud

The Internet of Things is transforming how we live and work, quickly becoming part of our everyday lives. Wearables are a perfect example, so in this demo I’m going to show you how Kii fits into an IoT scenario using the Samsung Gear Live smart watch. Packing a heart rate sensor, it’s one of the hottest fitness watches on the market right now.

This demo involves three different endpoints communicating with each other:

  • LG Nexus 4 mobile phone (running Android KitKat with API 19)
  • Samsung Gear Live smart watch (running Android 4.4W with API 20)
  • Kii platform (our scalable, secure cloud-connected backend platform)

Here’s how it’ll work: The watch will send heart rate data packets to the phone and then the phone will send them to Kii’s cloud. To follow along, you’ll need:

A possible use case for this kind of application is monitoring the elder and notifying other people if things go wrong (besides heart rate you could also monitor the accelerometer in the wearable to detect someone falling).

Rule of three endpoints

For the most part, customers don’t care how things work as long as they do work. But creating a seamless experience isn’t easy. Infrastructure, of course, is one of the biggest IoT challenges across verticals. It needs to meet the changing requirements of scale and data management, run on standards, and be highly secure and interoperable. As an AllSeen Alliance member, Kii believes in an open standard, integrated architecture from the cloud to end devices, with exceptional reliability and security.

Obviously we trust on our cloud platform to make IoT initiatives work smoothly. Kii is accessed on-demand by a high level API, secure, fast and able to scale to millions of devices without service interruption. Plus, development teams benefit from no server management, maintenance, installations or upgrades.

Another very practical challenge is moving data from IoT hardware to the cloud. Due to size or other design requirements, many simple smart devices don’t have Wi-Fi or Ethernet. Instead they rely on an internet capable device such as a mobile phone or tablet to exchange data with a cloud (such as Kii). The IoT device hardware does not access the internet directly. All cloud requests are handled by the phone or tablet, which acts as a hub. Users also get to enjoy nifty apps that chart endurance and time spent in a target heart rate zone, for example.


pingheart

Let’s start by taking a closer look at how the mobile phone (Nexus 4) and smart watch (Gear Live) communicate using low-level communication via Bluetooth. Google provides an app for the phone called Android Wear that, together with the latest Google Play Services, provide all you need to work with the watch.

Teleporting data for two-way communication

Google does a good job at explaining how to move data between the phone and the watch. But there’s an easier, more straightforward way to use the same Google infrastructure with a higher level API: the Teleport library. After you set up your watch and mobile phone to talk to each other, take Teleport for a spin to check it out.

Here’s a simplified version of how Teleport helps us on the mobile phone side. A main activity on the phone sends messages to start an activity on the watch and receive messages back:

public class MobileActivity extends Activity {

	private static final String STARTACTIVITY = "startActivity";
	TeleportClient mTeleportClient;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mTeleportClient = new TeleportClient(this);
		mTeleportClient.setOnGetMessageTask(new ShowHRFromOnGetMessageTask());

		Button mStartButton = (Button) findViewById(R.id.start_button);
		mStartButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				mTeleportClient.sendMessage(STARTACTIVITY, null);
			}
		});
	}

	public class ShowHRFromOnGetMessageTask extends TeleportClient.OnGetMessageTask {
		@Override
		protected void onPostExecute(String path) {
			//HR value received from watch, do something with it
			//let's reset the task (otherwise it will be executed only once)
			mTeleportClient.setOnGetMessageTask(new ShowHRFromOnGetMessageTask());
		}
	}

	@Override
	protected void onStart() {
		super.onStart();
		mTeleportClient.connect();
	}

	@Override
	protected void onStop() {
		super.onStop();
		mTeleportClient.disconnect();
	}
}

Initialization is one line in the onCreate() method. Connection and disconnection are automatically handled on onStop() and onStart(). The STARTACTIVITY message is received on the watch by a Teleport service and used to start a heart rate monitor. The message task extension allows us to receive messages from the watch (heart rate values) and process them locally on the phone (e.g. saving the data in the cloud with Kii).

We also use Teleport on the watch to send and receive messages. Additionally, a basic background service runs on the watch that’s always ready to receive and process messages from the phone to start an activity:

public class WearService extends TeleportService {

    @Override
    public void onCreate() {
        super.onCreate();
        setOnGetMessageTask(new ActivityManagementTask());
    }

    //Task that shows the path of a received message
    public class ActivityManagementTask extends TeleportService.OnGetMessageTask {
        @Override
        protected void onPostExecute(String  path) {
            if (path.equals("startActivity")){
                Intent startIntent = new Intent(getBaseContext(), WearActivity.class);
                startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                startIntent.putExtra("keep", true);
                startActivity(startIntent);
            } else {
                Log.i(TAG, "Got a message with path: " + path);
            }
            //let's reset the task (otherwise it will be executed only once)
            setOnGetMessageTask(new ActivityManagementTask());
        }
    }
}

When the mobile client sends a message to start the activity, Teleport launches the activity on the watch via an intent. The launched activity reads the heart rate values and sends the data to the phone:

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        try {
            latch.await();
            if(sensorEvent.values[0] > 0){
                mTeleportClient.sendMessage(String.valueOf(sensorEvent.values[0]), null);
                Log.d(TAG, "sensor event: " + sensorEvent.accuracy + " = " + sensorEvent.values[0]);
            }

        } catch (InterruptedException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

We could have crafted a more complex protocol for message exchange between the watch and phone but want to keep things uncomplicated here by assuming any message sent by the watch is a heart rate value. Once the heart rate values get to the phone, we will send them to Kii for later analysis (more on that below).

Pin based authentication using a device id

To make it easy for users who sign in and register on their mobile phones, we’re using 4-digit pin authentication. A device id is generated the first time the app runs and persists throughout the app installation as recommended by Google. Since the device id serves as a username, we can correlate Kii users to actual devices. Simply provide that 4-digit pin to the user to sign in.

Once you properly initialize Kii with something like Kii.initialize(KII_APP_ID, KII_APP_KEY, Kii.Site.US), you’re ready to do the pin based sign in using Kii’s synchronous API in an Android AsyncTask:

        @Override
        protected Boolean doInBackground(Void... params) {
            // attempt sign in against Kii Cloud
            try {
                String id = Installation.id(mContext);
                Log.d(TAG, "Attempting sign in with id: " + id);
                KiiUser.logIn(id, mPassword);
                if(mRememberMe) {
                    Log.d(TAG, "Storing access token...");
                    String accessToken = KiiUser.getCurrentUser().getAccessToken();
                    // Now we store the token in a local file
                    Installation.saveAccessToken(mContext, accessToken);
                }
            } catch (Exception e) {
                return false;
            }
            Log.d(TAG, "Sign in successful");
            return true;
        }

The id is fetched if it already exists or created on the first run. Kii assigns each user an access token upon sign in or registration so anyone who checks “remember me” will not be required to re-enter a pin. Similarly, we allow a user to register their 4-digit pin the first time the app is opened:

        @Override
        protected Boolean doInBackground(Void... params) {
            // attempt registration against Kii Cloud
            try {
                String id = Installation.id(mContext);
                Log.d(TAG, "Attempting registration with id: " + id);
                KiiUser.Builder builder = KiiUser.builderWithName(id);
                KiiUser user = builder.build();
                user.register(mPassword);
                if(mRememberMe) {
                    Log.d(TAG, "Storing access token...");
                    String accessToken = KiiUser.getCurrentUser().getAccessToken();
                    // Now we store the token in a local file
                    Installation.saveAccessToken(mContext, accessToken);
                }
            }
              catch (Exception e) {
                return false;
            }
            Log.d(TAG, "Registration successful");
            return true;
        }

Running a service to request data

Once the app is talking to the cloud, we can take a look at how the phone requests heart rate data from the watch. Ideally we want to run a background service on the mobile phone that will request heart rate data to the watch periodically. The DataService class takes care of that by sending timer assisted start/stop requests to the heart rate monitor app in the watch while waiting for incoming heart rate data using Teleport. By default the project is configured to avoid timers, requiring you to manually start or stop the heart rate monitor on the watch via phone app settings. Be sure to remember this step while testing your app.

Since the service runs on separate process and is flagged as remote on the manifest, it uses the stored access token to sign in the user. Think of it as different app space. KiiUser.getCurrentUser() will return null if you don’t sign in within the service.

Sending device data to the Kii platform

Communications with Kii Cloud is probably the easiest part of this demo. We create a user scope bucket and store the raw heart rate value on it:

   KiiBucket bucket = Kii.user().bucket("heartrates");
   KiiObject object = bucket.object();
   object.set("value", heartrate);
   object.save(new KiiObjectCallBack() {
      @Override
      public void onSaveCompleted(int token, KiiObject object, Exception exception) {
         Log.d(TAG, "Heart rate data saved to the cloud");
      }
   });

Although heart rate data comes in quick bursts, it’s not a problem for the Kii storage API. We use an async callback to save each object (as seen above) so we can keep up with the burst rate and prevent the app from blocking. In fact, we could have attached other data to the object (think of it as a key/value store) such as the current geolocation coordinates. For the sake of simplicity, though, I’ve focused on the heart rate value and implicit information (owner, created time, etc). Values are aggregated on Kii, accessible at developer.kii.com, and can be used to trigger alerts or gain insights from analytics.

Download the demo source code

That’s it. Grab the full source code for this demo from our GitHub to modify and reuse however you want.  We’re also completely open to suggestions and improvements.

Coming soon…

Kii has a few other demos in the works, including part 2 this one, with useful ways to process watch data once its stored in the cloud. You’ll learn how to:

  • Use Kii Platform Extensions to trigger real time responses. For example, to execute when certain parameters are met, such as the creation or modification of an object or when a heart rate is too low.
  • Use push-to-app to tell your application when a new event occurs on the cloud such as a change to a data bucket. For example to set an alarm when an object is deleted.
  • Use analytics to slice and dice your data in the cloud, setting up rules for analysis and visualization in your Kii Developer Portal.

I’m also working on a way to adapt projects like this to use an open standard IoT framework called AllJoyn by the AllSeen Alliance. From mobile phones to computers (including Raspberry Pi) to Arduino boards, all devices using it can talk to each other right away using the same “language.”

Keep on eye on our blog for details. Until next time, happy coding!

- Share -

German Viscuso

More posts from

  • Kii IoT platform enables customers to create smart, connected solutions and services
  • Long track record of supporting customers like Docomo, Toshiba, Kyocera and many others
  • Strong ecosystem partners across the globe, consisting of carriers, device/sensor manufacturers, system integrators, network/infrastructure providers, chip vendors and solution developers
  • HQ in Tokyo, US HQ in Silicon Valley & offices in China, Taiwan, Hong Kong and Europe (UK, Spain, Germany)
  • www.kii.com