Build your app

You can define and create your app UI that will be shown on the SmartWatch 2 screen by using the Control API. What you need to create your app UI is covered in the following:

  • Control API – What it is and what can be done with it.
  • App life cycle – The states of an app, analogous to Activity states.
  • How to register your application so that it can be run on SmartWatch 2.
  • How to handle events such as screen taps, key presses and menus.

Control API

The Control API is the most advanced API and it lets your SmartWatch 2 app take full control over the accessory display. This API renders images, handles touch events, key presses and more.

App life cycle

Similar to an Android Activity, an app that uses the Control API follows a life cycle as described in the following diagram:

AppLifeCycle_400x200

The basics

To start building your app UI, you will need to do the following:

  1. Register your app.
  2. Update your AndroidManifest.xml.
  3. Include the common Smart Extensions classes.
  4. Create a layout to be displayed.
  5. Create a class that extends the ControlExtension class to handle your app logic.

1. Register your app

First, you need to register your app by extending the RegistrationInformation class in the SmartExtensionUtil Android library. See the Registration guide for more details.

2. Update your AndroidManifest.xml

Next, you need to update your AndroidManifest.xml file. See the Android Manifest guide for more details.

3. Include the common classes for Smart Extensions

Now, add the common classes for Smart Extensions in your project. See the Common classes guide for more details.

4. Create a layout to be displayed

To start building your layout, note that a SmartWatch 2 layout is very similar to a standard Android layout with the following exceptions:

  1. Only a subset of the standard Android ViewGroups and Views are supported. For details, see EXTRA_DATA_XML_LAYOUT.
  2. All dimensions should be specified as absolute pixels (px) and not in density independent pixels (dp). This is because the watch screen size is fixed, but the screen size and density of the phone or tablet that your app is running on can vary. Since the app itself runs on the phone or tablet and not on the watch, if you use density independent pixels, then the layout will try to scale based on the screen values of the device and your layout will look different on the watch, depending on the phone or tablet.
  3. For text sizes, scaled pixels (sp) can be used so that text size will vary according to the user preference settings on the accessory.

The following is a code snippet of a Control app layout for SmartWatch 2. For other accessories that support Control API, creating a layout should be analogous.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="@dimen/smart_watch_2_control_width"
    android:layout_height="@dimen/smart_watch_2_control_height"
    tools:ignore="ContentDescription,PxUsage" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:src="@drawable/sample_control_widget_anim" />…
    <TextView
        android:id="@+id/sample_control_text_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="12px"
        android:layout_marginTop="10px"
        android:textColor="@android:color/black"
        android:textSize="@dimen/smart_watch_2_text_size_large" />
…
</RelativeLayout>

The layout will appear as follows on a SmartWatch 2:

SW2_ControlAPI

5. Implement your app logic

Now that you have defined your layout in XML, you need to implement the logic to show it on the SmartWatch 2. This is done by creating a class that extends the ControlExtension class. In this class, you can:

  • Show your layout or bitmap on the display.
  • Handle key press events.
  • Handle clicks on views.
  • Show an options menu.

Show your UI on the display

There are two ways to show a UI for SmartWatch 2. You can use either showLayout() or showBitmap().

Use showLayout() to show UI
To use showLayout(), you just need to call the showLayout() method passing in the layout ID and a Bundle containing data for the layout.

showLayout(R.layout.sample_control_2, data);

The data bundle can contain things to be set at runtime like Strings to populate the TextViews:

Bundle b1 = new Bundle();
         b1.putInt(Control.Intents.EXTRA_LAYOUT_REFERENCE, R.id.sample_control_text_1);
         b1.putString(Control.Intents.EXTRA_TEXT, "1");

Full example of showing a layout:

Bundle b1 = new Bundle();
        b1.putInt(Control.Intents.EXTRA_LAYOUT_REFERENCE, R.id.sample_control_text_1);
        b1.putString(Control.Intents.EXTRA_TEXT, "1");
        Bundle b2 = new Bundle();
        b2.putInt(Control.Intents.EXTRA_LAYOUT_REFERENCE, R.id.sample_control_text_2);
        b2.putString(Control.Intents.EXTRA_TEXT, "2");
        Bundle b3 = new Bundle();
        b3.putInt(Control.Intents.EXTRA_LAYOUT_REFERENCE, R.id.sample_control_text_3);
        b3.putString(Control.Intents.EXTRA_TEXT, "3");
        Bundle b4 = new Bundle();
        b4.putInt(Control.Intents.EXTRA_LAYOUT_REFERENCE, R.id.sample_control_text_4);
        b4.putString(Control.Intents.EXTRA_TEXT, "4");
        Bundle[] data = new Bundle[4];
        data[0] = b1;
        data[1] = b2;
        data[2] = b3;
        data[3] = b4;
        showLayout(R.layout.sample_control_2, data);

Use showBitmap() to show UI
To use showBitmap(), which directly shows a bitmap on the accessory, you just need to call showBitmap() with the Bitmap to be displayed:

            // Create background bitmap for animation.
            mBackground = Bitmap.createBitmap(width, height, BITMAP_CONFIG);
            // Set default density to avoid scaling.
            mBackground.setDensity(DisplayMetrics.DENSITY_DEFAULT);
            LinearLayout root = new LinearLayout(mContext);
            root.setLayoutParams(new LayoutParams(width, height));
            LinearLayout sampleLayout = (LinearLayout)LinearLayout.inflate(mContext,
                    R.layout.sample_control, root);
            ((TextView)sampleLayout.findViewById(R.id.sample_control_text)).setText(packageName);
            sampleLayout.measure(width, height);
            sampleLayout.layout(0, 0, sampleLayout.getMeasuredWidth(),
                    sampleLayout.getMeasuredHeight());
            Canvas canvas = new Canvas(mBackground);
            sampleLayout.draw(canvas);
            showBitmap(mBackground);

In general, it is recommended that if your accessory supports Control API v2.0 that you use showLayout() rather than showBitmap() since your code will be cleaner and less complex. However, if your app needs to be backwards compatible with Control API v1.0, then it is better to use showBitmap() so you don’t need to handle your UI logic in two different ways.

How to handle key press events
To handle key press events, override the onKey() method:

    @Override
    public void onKey(final int action, final int keyCode, final long timeStamp) {
        Log.d(SampleExtensionService.LOG_TAG, "onKey()");
        if (action == Control.Intents.KEY_ACTION_RELEASE
                && keyCode == Control.KeyCodes.KEYCODE_OPTIONS) {
            toggleMenu();
        }
        else if (action == Control.Intents.KEY_ACTION_RELEASE
                && keyCode == Control.KeyCodes.KEYCODE_BACK) {
            Log.d(SampleExtensionService.LOG_TAG, "onKey() - back button intercepted.");
        }
    }

How to handle clicks on views
To handle click events when a user touches a view on the display, you can setup an OnClickListener for the view:

ControlView upperLeft = mLayout.findViewById(R.id.sample_control_object_1);
            upperLeft.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick() {
                    sendImage(R.id.sample_control_object_1, R.drawable.left_top_selected);
                    mHandler.postDelayed(new SelectToggler(R.id.sample_control_object_1,
                            R.drawable.left_top), SELECT_TOGGLER_MS);
                }
            });

Then override the onObjectClick() method to call the click handler:

@Override
    public void onObjectClick(final ControlObjectClickEvent event) {
        Log.d(SampleExtensionService.LOG_TAG, "onObjectClick() " + event.getClickType());
        if (event.getLayoutReference() != -1) {
            mLayout.onClick(event.getLayoutReference());
        }
    }

How to show an Options menu
For some Smart Accessories such as SmartWatch 2, you can also implement an options menu that pops up on the screen when the user presses the menu hard key. To create an options menu, you must first populate the items in the menu by creating Bundles:

mMenuItemsText[0] = new Bundle();
        mMenuItemsText[0].putInt(Control.Intents.EXTRA_MENU_ITEM_ID, MENU_ITEM_0);
        mMenuItemsText[0].putString(Control.Intents.EXTRA_MENU_ITEM_TEXT, "Item 1");
        mMenuItemsText[1] = new Bundle();
        mMenuItemsText[1].putInt(Control.Intents.EXTRA_MENU_ITEM_ID, MENU_ITEM_1);
        mMenuItemsText[1].putString(Control.Intents.EXTRA_MENU_ITEM_TEXT, "Item 2");
        mMenuItemsText[2] = new Bundle();
        mMenuItemsText[2].putInt(Control.Intents.EXTRA_MENU_ITEM_ID, MENU_ITEM_2);
        mMenuItemsText[2].putString(Control.Intents.EXTRA_MENU_ITEM_TEXT, "Item 3");

Then you can show the menu by calling showMenu():

showMenu(mMenuItemsText);

Control API code example

For the full code example showing the topics above, see the SampleControlExtension project in the Sony Add-on SDK.