Smartwatch - a watch for special tasks

Samsung Gear 2 smartwatch

Authors, scriptwriters and special effect specialists have long competed with each other to come up with ideas to attract movie fans. Some of the more popular franchises include movie about the ingenious MacGyver and Her Majesty’s super-agent, James Bond 007. Their toys have never failed to save the world or, at least, the lead character’s life (and that of his beautiful companion). Ideas such as supercars, laser in a contact lens, rockets fueled by baking powder and petrol used to stimulate the imagination of the audience, especially its younger members. These amazing gadgets have increasingly found their way into the real world.

Who of us, 10-15 years ago, didn’t dream of a fully waterproof superwatch featuring a laser beam that could cut through an inch of steel, a cord the width of a human hair that could hold the weight of a car, plus a builtin camera to top things off? Well, we might return to that later.

The digital watch, that technological wonder featuring a calculator, stopwatch and alarm clock, used to be the object of every primary schooler’s desire. Once en essential accessory, now it has become a thing of the past in favor of smartphones, tablet, and personal computer. Or has it? The former target group may not see it as something to be prod of and brag about among the neighborhood kids, but after switching the target group to a more aware user group, you can come up with a StarTreklike product

What’s it all about?

It’ about Samsung’s new idea. The Korean company will provide users with a device which, with a bit of imagination, may become just like a gadget from an Ian Fleming novel, and at the same time, will look great on your wrist. This article is not a review of the Samsung Gear 2 smartwatch, though, but a practical how-to description of developing an application for this device. Instead of focusing on the smartwatch alone, we are going to show how it can become part of an Android-connected structure. Why? Because the smartwatch itself is limited by its operating range (the Bluetooth range) and local resources. But there’s no reason why it shouldn’t be able to use the resources of another, more powerful device within its range, such as a smartphone, to increase its potential, let your imagination run free and bring global fun.

Note that Samsung Gear 2 supports only some of Samsung’s smartphones; these are known as Samsung Smart Devices.

Let’s do it!

What do you need? Let’s start with Android, as it’s going to be the interface between the smartwatch and the outside world.

The basic prerequisite is to install a development environment to build Android applications.

Our choice from among the major environments is Eclipse with the ADT plugin. Besides an advanced editor, this environment features integrated tool for application debugging and managing different versions of Android emulator platforms. Android developer have prepared suitable installation package for the major platforms: Windows, Linux, and Mac. You can download them directly at http://developer.android.com/sdk/index.html. But first, you should check if the Java SDK package is installed on your computer, as Eclipse will not run without it. To complete the installation, simply unpack the archive and run eclipse.exe from the folder

<ścieżka instalacyjna>/eclipse/eclipse.exe  

After the installation, install the SDK package for the selected Android platform. Note that Samsung has defined the minimum version of the Androic platform for developing smartwatch compatibile applications. Such applications should be developed for Android 4.1 Jelly Bean (SDK API 16) or later, and you will need this SDK version (or newer) to proceed with the article.

To install the SDK within Eclipse, go to Window -> Android SDK Manager, select the SDK Platform for the selected Android versions in the list of available SDK packages, and proceed with the installation by clicking Install Packages… Remember to check the SDK API level 16 or higher. It’s best to restart Eclipse after the SDK has been installed.

Android SDK Manager

At this stage, your environment is ready for Android application development.

Let’s get coding…

Our application will be a classic example of what Samsung developers call Integrated Apps: it will include both the host-side application (Android), and the smartwatch-side widget (Tizen platform). These are two separate entities integrated within a single Android application. We’re going to start with the host-side application.

Host-side application

A host-side application is a standard Android app which normally has no user interface on the device side, and its function is to install the widget on the smartwatch. Usually, this takes place after connecting the smartwatch via Bluetooth. So let’s create a standard application in Eclipse.

From the File menu, select New -> Android Application Project.

New Android Application

In the configuration window, enter the application name and select the minimum Android level it can be run on. In our case, the minimum version is Android 4.1 (Jelly Bean). In the Target SDK and Compile With drop-down lists, select the installed SDK version. In the next window, let Eclipse generate the default application icon without additional code for the main activity, as it won’t be necessary.

New Android Application-configure project

Do not modify any options in the next two windows to let the application generate the default icons for various screen parameters, and to not create activities.

New Android Application-configure launcher icon

New Android Application-create activity

Click Finish to close the wizard.

The application template is still not finished, though.

To develop an app for Samsung Smart Devices, you need to add Samsung libraries to the project. Go to http://developer.samsung.com/samsung-mobile#accessory for library sets that can be used for developing applications that take advantage of features found in Smart Devices, such as sensors, fingerprint reader, the pen feature and gesture recognition. There are 13 libraries available at the moment, but we will need only one of them, Accessory. It includes components necessary for establishing a connection and send messages between the smartwatch and a smart device using Samsung Accessory Framework.

Download to library file and copy the contents of the Libs folder to the libs folder of the project. After copying the libraries, they should be available in the libs folder.

Libs

Now that you have all the libraries that will be needed, proceed with the application code. First, modify the AndroidManifest.xml file by adding permissions to use the Accessory library and Samsung Accessory Service Framework mechanisms:

<uses-permission android:name="com.samsung.accessory.permission.ACCESSORY_FRAMEWORK" />  
    <uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY"/>

    <uses-permission android:name="com.samsung.wmanager.APP" />
    <uses-permission android:name="com.samsung.wmanager.ENABLE_NOTIFICATION" />

Another set of permissions will be necessary to allow the application to communicate via the Bluetooth interface:

<uses-permission android:name="android.permission.BLUETOOTH" />  
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Now, add declarations of the event receiver build in Samsung SDK: attempts to establish a connection with the smartwatch and register our application in the device after pairing. The receiver declarations should be included in the tag <application>.

<receiver android:name="com.samsung.android.sdk.accessory.ServiceConnectionIndicationBroadcastReceiver" >  
    <intent-filter>
    <action android:name="android.accessory.service.action.ACCESSORY_SERVICE_CONNECTION_IND" />
    </intent-filter>
    </receiver>

    <receiver android:name="com.samsung.android.sdk.accessory.RegisterUponInstallReceiver" >
    <intent-filter>
    <action android:name="android.accessory.device.action.REGISTER_AFTER_INSTALL" />
    </intent-filter>
    </receiver>

Finally, also in the tag <application> add the metadata required by the Samsung Accessory library:

<meta-data android:name="GearAppType" android:value="wgt" />  

Configuring device connection…

The next step is to determine the communication channel between the smartwatch and the smartphone.

Create an accessoryservices.xml file in the /res/xml folder of the project path. The file is partly shared by the widget and the host-side application, and includes data that enables the Samsung Accessory Framework to find and configure the connection between the devices. Samsung has prepared a snippet which enables easy validation of the user’s configuration specified later on in the file. The first portion of the file includes a series of DTD statements.

<!DOCTYPE resources [  
<!ELEMENT resources (application)>  
<!ELEMENT application (serviceProfile)+>  
<!ATTLIST application name CDATA #REQUIRED>  
<!ELEMENT serviceProfile (supportedTransports, serviceChannel+) >  
<!ATTLIST application xmlns:android CDATA #IMPLIED>  
<!ATTLIST serviceProfile xmlns:android CDATA #IMPLIED>  
<!ATTLIST serviceProfile serviceImpl CDATA #REQUIRED>  
<!ATTLIST serviceProfile role (PROVIDER | CONSUMER | provider | consumer) #REQUIRED>  
<!ATTLIST serviceProfile name CDATA #REQUIRED>  
<!ATTLIST serviceProfile id CDATA #REQUIRED>  
<!ATTLIST serviceProfile version CDATA #REQUIRED>  
<!ATTLIST serviceProfile serviceLimit (ANY | ONE_ACCESSORY | ONE_PEERAGENT | any | one_accessory | one_peeragent) #IMPLIED>  
<!ATTLIST serviceProfile serviceTimeout CDATA #IMPLIED>  
<!ELEMENT supportedTransports (transport)+>  
<!ATTLIST supportedTransports xmlns:android CDATA #IMPLIED>  
<!ELEMENT transport EMPTY>  
<!ATTLIST transport xmlns:android CDATA #IMPLIED>  
<!ATTLIST transport type (TRANSPORT_WIFI | TRANSPORT_BT | TRANSPORT_BLE | TRANSPORT_USB |  
    transport_wifi | transport_bt | transport_ble | transport_usb) #REQUIRED>
<!ELEMENT serviceChannel EMPTY>  
<!ATTLIST serviceChannel xmlns:android CDATA #IMPLIED>  
<!ATTLIST serviceChannel id CDATA #REQUIRED>  
<!ATTLIST serviceChannel dataRate (LOW | HIGH | low | high) #REQUIRED>  
<!ATTLIST serviceChannel priority (LOW | MEDIUM | HIGH | low | medium | high) #REQUIRED>  
<!ATTLIST serviceChannel reliability (ENABLE | DISABLE | enable | disable ) #REQUIRED>  
]>

The next portion includes the user’s configuration

<resources>  
<application name="IntegratedApp" >  
    <serviceProfile
id="/system/integratedapp"  
name="integratedapp"  
role="provider"  
serviceImpl="com.rst.integratedapp.GearProviderService"  
version="1.0"  
serviceLimit="ANY"  
serviceTimeout="10">

    <supportedTransports>
    <transport type="TRANSPORT_BT" />
    </supportedTransports>

    <serviceChannel
id="104"  
dataRate="low"  
priority="low"  
reliability= "enable"/>  
    </serviceProfile>
    </application>
    </resources>

The most important settings include:

The role attribute of the serviceProfile tag – specifies the role of the application. Two values are available:

Privider – accepts incoming connections from external devices (smartwatch) and initializes outgoing connections to external devices (Service Consumer)
Consumer – accepts incoming connections from a Smart Device (smartphone)
The serviceImpl attribute of the serviceProfile tag – specifies the full name of the class responsible for accepting connection on the Android application side.

The transport tag of the supportedTransports node – specifies the transmission medium of the connection. For Samsung Gear 2, it should be Bluetooth (TRANSPORT BT). If you plan to debug the application in an emulator (with the Tizen environment), set this parameter to TRANSPORT WIFI.

The id attribute of the serviceChannel tag – specifies the communication channel number. The number will be necessary for the devices to communicate with each other.

After completing the accessoryservices.xml file, add the file information to the metadata section of the manifest file in the tagb<application>.

<meta-data  
android:name="AccessoryServicesLocation"  
android:value="/res/xml/accessoryservices.xml" />  

Samsung Accessory API …

Now that the application template is ready, it’s time to put all the components together.

The Samsung libraries added earlier include a piece of code that we are going to use to build our own application.

First, create the GearProviderService class, which inherits from SAAgent. It will be responsible for creating outgoing connections to external devices and accepting incoming connections.

It must inherit from the SAAgent class, as the constructor needs a class type representing the connection between the Provider and Consumer (the smartphone and smartwatch). And that’s where the SASocket class comes in handy.

protected GearProviderService(String arg0, Class<? extends SASocket> arg1) {  
    super(arg0, arg1);
}

But the service must be instantiated using a parameter-less constructor, we will put the call to the base class constructor in a parameter-less constructor. The full definition of the class will be as follows:

public class GearProviderService extends SAAgent{  
    private static final String TAG = "GearProviderService";
    HashMap<Integer, PrividerConnection> mConnectionsMap = null;
    private final IBinder mBinder = new LocalBinder();

    public GearProviderService(){
        super(TAG, PrividerConnection.class);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        SA mAccessory = new SA();
        try {
            mAccessory.initialize(this);
        } catch (SsdkUnsupportedException e) {
            stopSelf();
        } catch (Exception e1) {
            stopSelf();
        }
    }
    @Override
    protected void onFindPeerAgentResponse(SAPeerAgent arg0, int arg1) {
}
@Override
protected void onServiceConnectionResponse(SASocket thisConnection,    int result) {  
    if (result == CONNECTION_SUCCESS) {
        if (thisConnection != null) {
            PrividerConnection myConnection = (PrividerConnection) thisConnection;
            if (mConnectionsMap == null) {
                mConnectionsMap = new HashMap<Integer, PrividerConnection>();
            }
            myConnection.mConnectionId = (int) (System.currentTimeMillis() &#038; 255);
            mConnectionsMap.put(myConnection.mConnectionId, myConnection);
        }
    } else if (result == CONNECTION_ALREADY_EXIST) {
        Log.e(TAG, "onServiceConnectionResponse, CONNECTION_ALREADY_EXIST");
    } else {
        Log.e(TAG, "onServiceConnectionResponse result error =" + result);
    }
}

@Override
protected void onServiceConnectionRequested(SAPeerAgent peerAgent) {  
    acceptServiceConnectionRequest(peerAgent);
}


public class LocalBinder extends Binder {  
    public GearProviderService getService() {
        return GearProviderService.this;
    }
}
@Override
public IBinder onBind(Intent arg0) {  
    return mBinder;
}

private class PrividerConnection extends SASocket{  
    private int mConnectionId;

    public PrividerConnection() {
        super(PrividerConnection.class.getName());
    }

        @Override
    public void onError(int channelId, String errorString, int error) {    }
@Override
public void onReceive(int channelId, byte[] data) {  
    PrividerConnection uHandler = mConnectionsMap
        .get(Integer.parseInt(String.valueOf(mConnectionId)));
    try {
        byte[] response = processRequest(data);
        uHandler.send(channelId, response);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
@Override
protected void onServiceConnectionLost(int errorCode) {  
    if (mConnectionsMap != null) {
        mConnectionsMap.remove(mConnectionId);
    }
}
private byte[] processRequest(byte[] data) throws JSONException{  
    String message = new String(data);
    JSONObject req = new JSONObject(message);
    final String cmd = req.getString("cmd");
    JSONObject response = new JSONObject();

    response = new JSONObject(){{
        put("response", "Echo:"+cmd);
    }};
    return response.toString().getBytes();
}

}
}

There are three things worth noting in the snippet above. First, in the constructor we call the base class contractor with parameters; the first one specifies the label for the messages generated by the class, so that they can be quickly identified when debugging; the second one specified the type of the class representing the connection between the devices. Also, note the skeleton class PrividerConnection representing the connection, which is declared as an inner class. And finally, there is the inner class LocalBinder, whose structure, commonly used in many Android applications, binds the service to the outside world. The class has only one method named getService(), which returns a GearProviderService class instance.

How does it work, then?

To get the full picture, we need to add the overloaded method onCreate() to the GearProviderService class. Everything will be clear in a moment.

The onCreate() class initializes the Accessory library (SA class).

The onCreate() method acts as a kind of safety catch. If the application is run on a device other than a Samsung Smart Device, the service will be stopped.

And how does it work?

Once the application has been installed, the system generates the signal android.accessory.device.action.REGISTER AFTER INSTALL, which is received by an inner receiver of the Samsung Accessory Service Framework, which in turn registers the application profile (the accessoryservices.xml file) on the device.

The smartwatch initializes the connection by executing the findPeerAgent within the widget. If notified that a provider exists, it sends a connection request to the smartphone. At this moment, the onServiceConnectionRequested is called in the provider, which decides whether the connection should be established.

After accepting the connection, the onServiceConnectionResponse is called, which includes mechanisms for storing information about the established connection. Since the application can manage multiple connections between different devices, subsequent connections are stored in the mConnectionsMap collection. On disconnection, the onServiceConnectionLost is called, and the connection information is removed from the mConnectionsMap collection.

Further communication is facilitated by the PrividerConnection class, which receives and can send data between devices. Messages are received using the onReceive method as a byte table and the communication channel identifier. The provider can send messages to the smartwatch using the send method on a specific connection (PrividerConnection) with two parameters: the channelId identifier and the byte table with the message content.

Our application receives messages from the smartwatch as a byte table, but in fact, it’s and encoded character string in JSON format. The watch sends the appropriate command containing “cmd”. The host-site application receives this data, decodes it, and sends a response. The response, comprising of the constant string “Echo:” and the incoming message content, is converted back to a byte table. The whole response logic is realized by the processRequest function. The encoded response is sent using the send function mentioned earlier.

For the GearProviderService class to play its part, it must be declared in the application manifest, in the tag <application>.

<service android:name="com.rst.integratedapp.GearProviderService" />  

We will return to our application in the end, because besides the code for handling communication, it also needs a widget in order to be actually Integrated.

Three, two, one… Tizen…

You need to download and install the Tizen for Wearable environment first. All the necessary components can be found at https://developer.tizen.org/downloads/tizen-sdk. You will need the installer (.exe file, about 5 MB large, depending on the platform) and the SDK Image package (.zip file, about 560 MB large). Download the necessary components and proceed with the installation.

Start the installer and click the Advanced button.

Tizen-advanced

Check the SDK Image option and select the downloaded SDK file (*.zip). Once the file contents have been loaded, the installation process begins. Go to subsequent screens using the Next button, and use the Install button to accept the settings.

Tizen-next

After completing the installation, you will be asked to restart the computer.

Tizen-insta;;ation completed

Tizen SDK for Wearable for dummies…

First, I’d like to point out that using the newest Tizen environment requires a large amount of patience and determination. As the application is based on the Eclipse environment, you should not expect a very smooth workflow. You may experience unexpected closing of the application and the whole operating system, which certainly doesn’t work in its favor. Still, we will try to use it for creating the widget for our app, and then we’ll integrate it with the Android component.

Widget design

As I mentioned in the beginning, our application is what Samsung calls an Integrated app, which means it includes the host-side application (for Android), and the smartwatch component or the widget.

To create the widget, first create a new project. From the File menu, select, New Tizen Wearable Web Project. In the template list, select Tizen Werable -> Wearable UI -> List Application

New Tizen Project

In a few moment, the project should be ready. The new application comprises of the homepage (index.xml), project configuration file (config.xml), default application icon (icon.png), and folder structure: libs – the library folder, css – the stylesheet folder, and js – the application logic folder.

The configuration settings of the application are included in the confit.xml file, but to make the customization process easier, Samsung has provided a graphical interface that will generate its content for us.
Tizen config-overview

Different configuration categories can be found in separate tags. We’re going to focus only on the settings that are necessary for our app.

In the Overview tab, change the value of the Identifier field. While this is not required, http://yourdomain does not read very professional… Skip the next two tabs and go to Privileges. This is where we add the widget’s privileges to the libraries enabling communication with the hostside application.

Tizen config-privileges

Next, go to the Tizen tab and add a new entry in the metadata field. Enter AccessoryServicesLocation as the key and res/xml/accessoryservices.xml as the value. These should be familiar if you paid attention to the Android component of the application.

Tizen config-metadata

Save the changes and exit the edit mode. Of course, the environment will return an error indicating that the accessoryservices.xml file was not found. To fix this problem, copy the file from the hostside application and make a few changes in it.

Start by adding the file from the Android app to the project. But it needs some change, since the widget is the “other side” of communication. Leave the validation rules unchanged, but modify the tag contents.

<resources>  
<application name="IntegratedApp" >  
    <serviceProfile
id="/system/integratedapp"  
name="integratedapp"  
role="consumer"  
version="1.0"  
serviceLimit="ANY"  
serviceTimeout="10">

    <supportedTransports>
    <transport type="TRANSPORT_BT" />
    </supportedTransports>

    <serviceChannel
id="104"  
dataRate="low"  
priority="low"  
reliability= "enable"/>  
    </serviceProfile>
    </application>
    </resources>

Remove the serviceImpl attribute from the copied file, and changed the value of the role attribute to consumer. Make sure that the value of the id attribute in the serviceChannel tag is identical in the two files.

At this point, we can build the widget itself. As I mentioned earlier, the index.html file represents the homepage. And it is where we’ll define two buttons, which will be send queries from the watch, and a field for displaying the reply. The index.html file looks as follows:

<!DOCTYPE html>  
<html>  
<head>  
<meta name="viewport" content="width=device-width,user-scalable=no"/>

    <link rel="stylesheet"  href="lib/tau/themes/default/tau.min.css">
    <!-- load theme file for your application -->
<link rel="stylesheet"  href="css/style.css">  
    <script src="./lib/tau/js/tau.js"></script>
    <script src="js/main.js"></script>
    </head>
    <body>
    <div class="ui-title">Integrated App</div>
<div >  
<input type=button value="CMD 1" onclick="send_cmd1();" class="title"/>  
    <input type=button value="CMD 2" onclick="send_cmd2();" class="title"/>
    </div>
    <div id="resultBoard">
    </div>
    </body>
    <script type="text/javascript" src="lib/tau/js/tau.min.js"></script>
    <script src="js/app.js"></script>
    <script src="js/lowBatteryCheck.js"></script>
    </html>

Define the buttons as tags with the title CSS class.

<input type=button value="CMD 1" onclick="send_cmd1();" class="title"/>  
    <input type=button value="CMD 2" onclick="send_cmd2();" class="title"/>

Application results will be resulted in the tag:

<div id="resultBoard"></div>  

To define the style of the buttons, add two classes to the stylesheet file css/style.css:

.tile {
    position: relative;
    float: left;
    height: 78px;
    width: 114px;
    margin: 20px 15px;
}
.tile .title {
    position: absolute;
    bottom: 0;
    width: 100%;
    text-align: center;
    color: #ff9100;
    font-weight: bold;
    font-size: 22px;
    line-height: 78px;
}

Create a file named main.js in the js folder. It will contain the business logic of the widget. The snippets presented below are taken from this file.

The point of entry is the window.onload method, called after loading the page document. First, it initializes connections with the smartphone using the ConnectionManager.init().connect() method, which is part of the Connect Manager (see below). Then it registers an event handler for the back button. The whole callback is as follows:

window.onload = function () {  
    ConnectionManager.init().connect();
    document.addEventListener('tizenhwkey', function(e) {
        if(e.keyName == "back"){
            tizen.application.getCurrentApplication().exit();
        }
    });
};

Next, define button event handlers:

function send_cmd1() {  
    ConnectionManager.send_cmd1();
};
function send_cmd2() {  
    ConnectionManager.send_cmd2();
};

What's the pupose of the Connect Manager?Connection Manager is a small class which manages the smartphone connection, and makes the methods for sending and receiving data over these connections available.

The _init method returns an object of its own class.

The _connect method establishes a smartphone connection by reading data from the accesoryservices.xml file and calling the requestSAAgent method. If the operation is successful, then an attempt is made to find a provider and the connection is established. This way, the widget can listen for incoming data and send requests to the smartphone.

The _send cmd1 and _send cmd2 are triggered by pressing buttons, and _on send cmd response is a handler method called after receiving a response from the smartphone.

The method reads the data received from the smartphone and isolates the response field included in the return packets (host-side application). Then it displays its content on the homepage in the resultBoard element (createHTML method).

var _on_send_cmd_response = function(channelId, data){  
        data = data.split('/').join('');
        console.log(data);
        var json = JSON.parse(data);
        createHTML(json.response);
    }

The widget application is ready.

Once the widget is ready, it only needs to be copied to host-side application. Copy the widget file *.wgt (in our case, IntegratedApp.wgt) from the Tizen environment project to the assets folder of the Android application folder. That’s all! Now, compile the project and upload it to your smartphone.

After connecting the watch, the widget should be installed automatically.

Summary

By introducing its Gear line-up of products, Samsung has provided developers with much fun. On the other hand, while the device itself is quite interesting, the Tizen environment and the developer tools have a long way to go yet. Still, the available smartwatch support libraries make it relatively easy to integrate smartwatches with other Smart Devices.

Download

Download source code from repository