Colonizing Wearables (part 3)

In Landing on Wearables we have approached wearables devices extending our existing app’s notifications and explaining briefly how to bind them to our development machine for debugging purposes. Now it is time to study more in deep what we can achieve directly on a device running Android Wear, understanding the constraints and the possibilities that the platform introduces. We will continue to keep as reference the Books application previously developed and we will try to create an Android Wear module.

Before going straight to that, there are some considerations those have to be done in order to understand better the platform that we are trying to target. First of all, we have to be sure that the wearable app is really needed. Most of the times, the notification based approach from the handheld device to the Context Stream might be a better solution. Its intrinsic simplicity and its immediacy tend to preserve the scarce wearable resources, allowing to defer all the heavy computations back to the more powerful handheld device.

One thing to keep in mind when we want to develop on Android Wear is that we don’t have all the packages available in the Android SDK. Some of them like webkit, appwidget or printing are missing. If our app is using some special functionalities it would be probably safer to check through the PackageManager if the system has got that particular feature.

Furthermore, even if Android Wear allows more or less to use the elements available in the SDK, the user interaction is totally different and it’s meant to be as simple and as effective as possible. Just to give a simple and quick demonstration of what we should avoid, here are the screenshots of the Books handheld app installed and running directly on an Android Wear emulator with the round screen.

Apart from being unusable, both screens look a lot more complex than what they should be and the content in the second one cannot even scroll. Our target in this and the next tutorial is to create a wearable experience that allows the user to see what matters with the smallest level of complexity possible. Beside that, it is important to keep in mind that any insane choice will be taken just for the sake of learning what is offered by the platform but it should probably be avoided in a real application.

Going back to the wearable app that we want to build, we need to take the following steps:

  1. create a wearable module in our project
  2. write the application (of course!)
  3. make it accessible
  4. bundle the wearable app inside the handheld one

In order to create the wearable module that will contain all the code of our Android Wear app, we need to add a new module to the existing project. Android Studio and Gradle become really handy helping us to set up the folder structure and the related build settings with a simple and intuitive GUI.

In fact, if we try to create a new module from a pre-existing project, we are prompted with the following screen and we can simply pick the “Android Wear Module” option.

 

Android Studio - Create new module

 

After having gone through the entire flow, the tab “Project” shows now the new module that is referenced even in the project’s settings.gradle. The wearable module contains its own build.gradle and all the folders and files that we should be already used to see in a handheld module created with Android Studio. Now, if we take a look at the build.gradle file, we can find the following dependencies:

dependencies {       
    compile('com.google.android.support:wearable:1.1.0)
    compile('com.google.android.gms:play-services-wearable:6.5.87')
}

The first one includes the Wearable Support Library that contains the set of new wearable elements that will be widely used in the next tutorial. The most important ones are definitely the new ad-hoc Views that can be used to provide constant feedback to the user and the WatchFaces. If we have a look at the package description for the support library, in particular at  the activity sub-package, we can easily find ConfirmationActivity. This activity allows us to provide a consistent feedback across different apps to the user, giving a sense of completion. This can be then invoked starting the activity with an Intent holding the following parameters:

  • EXTRA_ANIMATION_TYPE (mandatory)
    • SUCCESS_ANIMATION
    • OPEN_ON_THE_PHONE_ANIMATION
    • FAILURE_ANIMATION
  • EXTRA_MESSAGE (optional)

The second dependency is the Google Play Services module for wearables and it contains all the elements that will be explained in the fifth tutorial when we will have to deal with the data exchange and synchronization between the two paired devices. Regarding the version 6.5.87 of the Play Services, Google has finally modularized its massive library allowing developers to include only the elements specifically needed by their apps. This option becomes really useful and extremely handy when a compiled application reaches the limit of 65536 methods in the underlying dex file.

Moving forward and opening the AndroidManifest.xml, we can find declared the following feature:

 <uses-feature android:name="android.hardware.type.watch" />

As the name suggests this feature is used to inform that application is built for a device that provides a Watch UI.

If we ticked “Blank Wear Activity” during the creation of the module, Android Studio has created the related Activity.class and three layouts. Looking at the latter ones, should give us an idea of the way in which we have to handle round and rect screens. We can notice that the main layout has a WatchViewStub that holds respectively one reference to the round layout and another one to the rect one. In addition to that, if we open the generated activity class that inflates the main layout, we can notice that an OnLayoutInflatedListener is registered on the WatchViewStub. Even if this looks a clumsy solution, the framework needs to figure out at runtime if the rect layout has to be used instead of the the round one and viceversa. In our BooksActivity we simply load the number of available books and we use a different layout based on the type of Watch screen. All the code previously written to handle the data persistence and access can be easily recycled and adapted if needed.

In order to take advantage of the previous elements developed for our existing application, a library module called ‘common’ has been created and added to the project. All the utilities, the elements related to the data persistence and the model have been moved in it. To make the names of the modules more exhaustive and in line with the new wearable one, the existing app module has been also renamed in ‘mobile’.

The code that refers to our previous chapters is still available and tagged “v1.1” on GitHub at:
https://github.com/SimoneCasagranda/android-wear-tutorial/releases

Now that we have developed this simple wearable application, we want to make it accessible to our user. In fact, if we just install the app on the wearable device and we try to look for it, there is no easy way to find it. As said earlier, a wearable device doesn’t work like a tablet or a phone!

If we play a little bit with an Android Wear device, a user can launch an application in three different ways:

  • through a notification shown in the Context Stream
    • the application has to fire a notification on the wearable device that has to hold a PendingIntent pointing to the expected Activity
    • this option should be used when there is content that really matters to the user like an email or an important update
    • it works in the same way as when we extended our handheld application but it can use directly the notification api without the support library
  • through the voice recognition system, saying “Ok Google” followed by:
    • a System-Provided action like “What’s my heart rate?” or “Take a Note”.
      The element that declares in the AndroidManifest an IntentFilter with the correct Action and/or Category can then be called by the platform when the user tries to access the particular functionality.
      Something similar happens when an implicit intent is fired and the operating system needs to figure out what are the apps those can handle  it.
    • an App-Provided action like “Start <label>”
      Similar to the System-Provided one but the check is against the label of the Activity that has to be invoked (along with an IntentFilter for the “MAIN” action and the “LAUNCHER” category).
  • selecting manually an application in the Cue Card
    • this option is more likely to happen when the user couldn’t be able to find a notification in the Context Stream
    • the Activity that has to be invoked needs to be exposed in order to be shown

In the Books app, the user can access the app through the App-Provided voice action “Ok Google… start Books”. He can also achieve the same result by tapping on the launcher element embedded in the Cue Card.
The BooksActivity has been exposed in the AndroidManifest.xml in the following way:

<activity android:name=".activity.BooksActivity"
      android:exported="true"
      android:allowEmbedded="true"
      android:taskAffinity="" 
      android:label="@string/app_name"> 
       <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
</activity>

After having added the previous highlighted lines, the launcher finally appears in the Cue Card.

An important aspect when developing for Android Wear is that the user cannot install an app directly on his wearable device. Instead, he has to download it on his handheld one and then the Android Wear Companion app takes care of deploying it to the the wearable device. To make this succeed, the application must also be signed with a non-debug certificate, otherwise it will be ignored. Even if there are these production constraints, during the development, it is still possible to install an unpacked wearable build using the ADB commands or an IDE like Android Studio. As soon as the wearable device is connected to our local machine, it appears in the devices list as any other device even if it is connected with the bluetooth via the handheld device.

Regarding the inclusion of our wearable app into the handheld one, if we are using Android Studio we have to include the following line in our dependencies for the mobile build.gradle:

dependencies {
   …
   wearApp project(':wearable')
}

Last but not least, we have to be aware of the fact that any permission in the Wearable AndroidManifest.xml has to be added in the Mobile one if it is not already included. Both modules must also have the same package name and version code. If we have a look at the gradle files, the values those are shared between the modules are declared in the top build.gradle and then used in the module ones. In this way when we increase the version code or  change any other element, the update is automatically applied on each module that depends on it.

Project build.gradle:

ext { 
    compileSdkVersion = 21 
    buildToolsVersion = '21.1.2' 
    applicationId = 'com.alchemiasoft.android_wear_tutorial' 
    versionCode = 3 
    versionName = '1.2'
}

Module build.gradle:

android {
    compileSdkVersion project.compileSdkVersion 
    buildToolsVersion project.buildToolsVersion 
    defaultConfig { 
        applicationId project.applicationId 
        minSdkVersion 9 
        targetSdkVersion 21 
        versionCode project.versionCode 
        versionName project.versionName 
    } 
}

That’s all for our third tutorial on this Android Wear journey.
Personally, I suggest you to come back for the next one that will be definitely more dense!

If you have appreciated this post, I invite you to share it wherever you want 🙂

See you at the next tutorial,
Simone

Advertisements

About alchemiasoft

Android Developer at Bloomberg LP. Algorithms and performance passionate. Curious. Eager to learn.

Posted on January 16, 2015, in Android, Development and tagged , , , , , , , , , , , , , , , , , , . Bookmark the permalink. 7 Comments.

  1. Hi ,
    i am working on android wear.Successfully develop the app.But i m facing a problem i.e i am not able to install app to moto 360 watch with signed apk. So can anyone help me out.Do i have to upload app to google play first so that i automatically gets install to watch?

    see attached screenshot what i got after generating signed apk

    1.All permissions are there in the mobile app manifest which i defined in the wear manifest.
    2.application ID is same as well.
    3.version code and version number also same.

    but embedded apk not getting automatically installed on the wearable

    • Hi Kamal, where can I find the screenshot of what you’re getting on the screen?

      Did you use Android Studio to package the wearable app into the handheld one?
      If 1,2 and 3 are the same… you might not have installed the companion app(I doubt it) or the build tool is trying to recompress the wear apk that is already compressed making it unrecognizable when installing.

  1. Pingback: Introduction to Wearables (part 1) | Alchemiasoft

  2. Pingback: Pimp my Wear (part 4) | Alchemiasoft

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: