Creating, Debugging, and Packaging Wearable Apps - Android Wearable Programming (2015)

Android Wearable Programming (2015)

Chapter 3. Creating, Debugging, and Packaging Wearable Apps

This chapter will provide you with the background and understanding of how you can build and package your own apps for Android Wear. We will learn how we can draw our own Android watch face using Google's official API, and also to present information within the watch area.

We will learn how to create a custom class that inherits from Google's latest watch face service API that will enable us to respond to watch face events to handle screen updates, draw watch face elements, and respond to changes between the interactive and ambient modes.

Finally, we will learn how we can effectively debug an Android wearable application over Bluetooth, and then take a look at the Android design principles to ensure that our application conforms to these. Then we will move on to learn how to package an Android wearable application so that it can communicate and be used by our handheld device.

This chapter includes the following topics:

· Creating a custom Android Wear watch face service class

· Presenting information inside a custom watch face

· Using Bluetooth to debug your Android wearable app

· Running your app directly on the Android wearable device

· Introducing the Android wearable user interface guidelines

· Packaging your Android wearable app within a handheld device

Creating an Android wearable watch face app

Prior to Google releasing the official Android watch face API in December 2014, developers had to find alternative ways to present information inside the watch face layout. In this section, we will take a look at the steps required to create a custom watch face service that will enable us to communicate with our watch and present information within the watch face area on the home screen.

Firstly, create a new project in Android Studio by following these simple steps:

1. Launch Android Studio, and then navigate to the File | New Project menu option.

2. Next, enter in CustomWatchFace for the Application name field.

3. Then, provide the name for the Company Domain field.

4. Next, choose Project location where you would like to save your application code:

Creating an Android wearable watch face app

5. Click on the Next button to proceed to the next step.

Next, we will need to specify the form factors for our phone/tablet and Android Wear devices that our application will run on. On this screen, we will need to choose the minimum SDK version for our phone/tablet and Android Wear.

6. Click on the Phone and Tablet option and choose API 19: Android 4.4 (KitKat) for Minimum SDK.

7. Click on the Wear option and choose the API 21: Android 5.0 (Lollipop) option for Minimum SDK as we want to use the watch face service API:

Creating an Android wearable watch face app

8. Click on the Next button to proceed to the next step.

In the next step, we need to specify that we don't want to add an activity for both the mobile and wear sections of our application.

9. From the Add an activity to Mobile screen, choose the Add No Activity option from the list of activities shown, and click on the Next button to proceed to the next step:

Creating an Android wearable watch face app

Next, we need to specify that we don't want to add an activity for the wear section of our Android wearable application.

10. From the Add an activity to Wear screen, choose the Add No Activity option from the list of activities shown, and click on the Finish button:

Creating an Android wearable watch face app

At this point, the wizard will generate your project, and after a few moments the Android Studio window will appear with your project displayed in it. In the next section, we proceed by creating a custom Android WatchFace class that will be used to present content and update the watch face user interface.

Presenting information inside the WatchFace class

In this section, we will proceed to create our custom WatchFace class that will be used to invoke the methods within the watch face service and this class will be responsible for allocating and initializing the resources that our watch face requires.

First, we need to create a new class called CustomWatchFace, as follows:

1. From the Project Navigator window, expand the wear section and select and expand the java section.

2. Next, right-click and choose the New | Java Class menu option.

3. Then, enter CustomWatchFace to be used as the name for our class and click on the OK button to open the Android Studio code editor window.

Our next step is to write the code that will communicate with our Android wearable device. For this, we will need to create a new class that will act as our watch service.

4. Open CustomWatchFace.java as shown in the preceding screenshot.

5. Next, enter the import statements as shown in the following code snippet:

6. import android.content.Context;

7. import android.graphics.Canvas;

8. import android.graphics.Color;

9. import android.graphics.Paint;

10.import android.graphics.Rect;

11.import java.util.TimeZone;

12.import java.text.SimpleDateFormat;

import java.util.Calendar;

13. Now, modify the CustomWatchFace class as shown in the following code snippet:

14.public class CustomWatchFace {

15. private final Paint timeObject;

16. private final Paint dateObject;

17. private final Paint batteryObject;

18. private String dateText;

19. private String timeText;

20. public String batteryText;

21.

22. private static final String TIME_FORMAT = "kk:mm:ss a";

23. private static final String DATE_FORMAT = "EEE, dd MMM yyyy";

24.

25. // Declare our class constructor

26. public static CustomWatchFace newInstance(Context context) {

27. Paint batteryObject = new Paint();

28. batteryObject.setColor(Color.RED);

29. batteryObject.setTextSize(25);

30. Paint timeObject = new Paint();

31. timeObject.setColor(Color.GREEN);

32. timeObject.setTextSize(35);

33. Paint dateObject = new Paint();

34. dateObject.setColor(Color.WHITE);

35. dateObject.setTextSize(35);

36.

37. return new CustomWatchFace(timeObject, dateObject, batteryObject);

38. }

39. CustomWatchFace(Paint objTime, Paint objDate, Paint

40. objBattery) {

41. this.timeObject = objTime;

42. this.dateObject = objDate;

43. this.batteryObject = objBattery;

44.

45. // Initialize our Battery Information

46. batteryText = "Level: 0%";

47. }

48.// Method to update the watch face each time an update

49.// has occurred

50.public void draw(Canvas canvas, Rect bounds) {

51. canvas.drawColor(Color.BLACK);

52. timeText = new

53. SimpleDateFormat(TIME_FORMAT).format(Calendar.getInstance().

54. getTime());

55. dateText = new

56. SimpleDateFormat(DATE_FORMAT).format(Calendar.getInstance().

57. getTime());

58. float timeXOffset = calculateXOffset(timeText, timeObject,

59. bounds);

60. float timeYOffset = calculateTimeYOffset(timeText,

61. timeObject, bounds);

62. canvas.drawText(timeText, timeXOffset, timeYOffset,

63. timeObject);

64. float dateXOffset = calculateXOffset(dateText, dateObject,

65. bounds);

66. float dateYOffset = calculateDateYOffset(dateText,

67. dateObject);

68. canvas.drawText(dateText, dateXOffset, timeYOffset +

69. dateYOffset, dateObject);

70. float batteryXOffset = calculateXOffset(batteryText,

71. batteryObject, bounds);

72. float batteryYOffset = calculateBatteryYOffset(batteryText,

73. batteryObject);

74.canvas.drawText(batteryText, batteryXOffset, dateYOffset + batteryYOffset, batteryObject);

75. }

76. // Calculate our X-Offset using our Time Label as the offset

77. private float calculateXOffset(String text, Paint paint,

78.Rect watchBounds) {

79.float centerX = watchBounds.exactCenterX();

80. float timeLength = paint.measureText(text);

81. return centerX - (timeLength / 2.0f);

82. }

83. // Calculate our Time Y-Offset

84. private float calculateTimeYOffset(String timeText, Paint

85. timePaint, Rect watchBounds) {

86. float centerY = watchBounds.exactCenterY();

87. Rect textBounds = new Rect();

88. timePaint.getTextBounds(timeText, 0,

89. timeText.length(), textBounds);

90. int textHeight = textBounds.height();

91. return centerY + (textHeight / 2.0f);

92. }

93. // calculate our Date Label Y-Offset

94. private float calculateDateYOffset(String dateText, Paint

95. datePaint) {

96. Rect textBounds = new Rect();

97. datePaint.getTextBounds(dateText, 0,

98. dateText.length(), textBounds);

99. return textBounds.height() + 10.0f;

100. }

101. // Calculate our Battery Label Y-Offset

102. private float calculateBatteryYOffset(String batteryText,

103. Paint batteryPaint) {

104. Rect textBounds = new Rect();

105. batteryPaint.getTextBounds(batteryText, 0,

106. batteryText.length(), textBounds);

107. return textBounds.height() + 40.0f;

108. }

109. public void setAntiAlias(boolean antiAlias) {

110. batteryObject.setAntiAlias(antiAlias);

111. timeObject.setAntiAlias(antiAlias);

112. dateObject.setAntiAlias(antiAlias);

113. }

114. // Set each of our objects colors

115. public void setColor(int red, int green, int white) {

116. batteryObject.setColor(red);

117. timeObject.setColor(green);

118. dateObject.setColor(white);

119. }

120. // method to get our current timezone and update the time field

121. public void updateTimeZoneWith(String timeZone) {

122. // Set our default time zone

123. TimeZone.setDefault(TimeZone.getTimeZone(timeZone));

124. // Get the current time for our current timezone

125. timeText = new

126. SimpleDateFormat(TIME_FORMAT).format(Calendar.getInstance().

127. getTime());

128. }

}

In the preceding code snippet, we started by adding the import statements that are responsible for communicating. Also, we declared our CustomWatchFace class and the variables that will be responsible for holding our date, time, and battery data as well as the date and time formats defined by our TIME_FORMAT and DATE_FORMAT variables. Next, we declared our class constructor that will be called when the class is instantiated by our WatchFaceService class and will be responsible for setting the font sizes and colors for our Date, Time, and Battery objects.

The draw method is called whenever an update is required for the watch face canvas defined by our WatchFaceService class, which is handled by the onTimeTick callback that fires every 60 seconds by default. This also handles any UI updates when our watch face goes into ambient mode. We use the Calendar object declared in our java.util.Calendar package to obtain the current time and format using the TIME_FORMAT and DATE_FORMAT formatters.

Next, we make a call to each of the calculateXOffset, calculateTimeYOffset, calculateDateYOffset, and calculateBatteryYOffset methods to position each of our labels within our watch face using the watch face dimensions, and then make a call to our drawText method on our WatchFace canvas for each of our elements to add these to the watch face view.

The setAntiAlias method is used to minimize the pixels used in ambient mode that is being drawn within the watch face area so that the content is smooth. Our WatchFaceService class calls the setColor method whenever the view enters ambient or interactive mode and updates the colors accordingly. The updateTimeZoneWith method updates when the users adjust their time zone; the system broadcasts this event and the time will be automatically updated accordingly.

In our next section, we will create a custom Android watch face service class that will be used to communicate with our Google wear API, so that we can configure our system user interface.

Creating a custom watch face service class

In this section, we will proceed to create our custom watch face service class that will be used to invoke the methods within the watch face service API. This class will be responsible for allocating and initializing the resources that our watch face requires. Watch faces are services and shouldn't be confused with activities, as these types of services only accept touch input and voice commands as a form of interaction.

First, we need to create a new class called WatchFaceService:

1. From the Project Navigator window, expand the wear section and select and expand the java section.

2. Next, right-click and choose the New | Java Class menu option:

Creating a custom watch face service class

3. Then, enter WatchFaceService to be used as the name for our class and click on the OK button:

Creating a custom watch face service class

4. Upon clicking the OK button, the Android Studio code editor will open, as shown in the following screenshot:

Creating a custom watch face service class

Our next step is to write the code that will communicate with our Android wearable device. For this, we will need to create a new class that will act as our watch service.

5. Open WatchFaceService.java as shown in the preceding screenshot.

6. Next, enter the import statements as shown in the following code snippet:

7. import android.content.BroadcastReceiver;

8. import android.content.Context;

9. import android.content.Intent;

10.import android.content.IntentFilter;

11.import android.graphics.Canvas;

12.import android.graphics.Color;

13.import android.graphics.Rect;

14.import android.os.BatteryManager;

15.import android.os.Handler;

16.import android.os.Looper;

17.import android.support.wearable.watchface.CanvasWatchFaceService;

18.import android.support.wearable.watchface.WatchFaceStyle;

19.import android.view.SurfaceHolder;

import java.util.Calendar;

20. Now, modify the WatchFaceService class as follows:

21.// Create our WatchFaceService Class

22.public class WatchFaceService extends CanvasWatchFaceService {

23.@Override

24. public Engine onCreateEngine() {

25. return new WatchFaceEngine();

26. }

27. // Create our WatchFaceEngine Class

28. private class WatchFaceEngine extends

29. CanvasWatchFaceService.Engine {

30. }

31.......

}

32. In this step, we need to add the code for our WatchFaceEngine class by creating an onCreate(SurfaceHolder holder) method that will be called when the watch is instantiated and this will initialize the watch face, as shown in the following code snippet:

33. private CustomWatchFace watchFace;

34. private Handler clockTick;

35.

36.@Override

37. public void onCreate(SurfaceHolder holder) {

38. super.onCreate(holder);

39. setWatchFaceStyle(new

40. WatchFaceStyle.Builder(WatchFaceService.this)

41..setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)

42..setAmbientPeekMode(WatchFaceStyle.

43.AMBIENT_PEEK_MODE_HIDDEN)

44..setBackgroundVisibility(WatchFaceStyle.BACKGROUND_

45. VISIBILITY_INTERRUPTIVE)

46..setShowSystemUiTime(false)

47..build());

48.

49. clockTick = new Handler(Looper.myLooper());

50.registerBatteryInfoReceiver();

51.startTimerIfNecessary();

52.watchFace =

53.CustomWatchFace.newInstance(WatchFaceService.this);

}

54. Next, we need to create a method for the WatchFaceEngine class that will be called to update the watch display when the number of seconds has incremented. This can be done as follows:

55. private void startTimerIfNecessary() {

56. clockTick.removeCallbacks(timeRunnable);

57. if (isVisible() && !isInAmbientMode()) {

58. clockTick.post(timeRunnable);

59. }

}

60. Now, we need to create and implement a new class instance of a runnable object and include a method called run that starts executing the active class. The following code snippet shows how to do this:

61.private final Runnable timeRunnable = new Runnable() {

62. @Override

63. public void run() {

64.onSecondTick();

65.if (isVisible() && !isInAmbientMode()) {

66. long TICK_PERIOD_MILLIS =

67. Calendar.getInstance().get(Calendar.MILLISECOND);

68. clockTick.postDelayed(this, TICK_PERIOD_MILLIS);

69. }

70. }

71. };

72. // Method to handle when the seconds are updating

73. private void onSecondTick() {

74. invalidateIfNecessary();

75. }

76. // stops any updates to the view, at which point the

77. // onDraw method will be called at some point in the

78. // future to refresh the view.

79.private void invalidateIfNecessary() {

80.if (isVisible() && !isInAmbientMode())

81.invalidate();

}

82. Here, we create the onVisibilityChanged method that is called when the watch face is visible and is responsible for registering the receiving methods when the time zone changes and starts the custom timer if the device is in interactive mode. When the watch face is not visible, this method stops the custom timer and unregisters the receiver for time zone changes. The registerReceiver and unregisterReceiver methods are implemented, for example, when the battery level changes. Have a look at the following code snippet:

83.@Override

84. public void onVisibilityChanged(boolean visible) {

85. super.onVisibilityChanged(visible);

86. if (visible) {

87.registerTimeZoneReceiver();

88.registerBatteryInfoReceiver();

89. }

90. else {

91. unregisterTimeZoneReceiver();

92. unregisterBatteryInfoReceiver();

93. }

94.startTimerIfNecessary();

95. }

96. private void registerTimeZoneReceiver() {

97. IntentFilter timeZoneFilter = new

98.IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);

99. registerReceiver(timeZoneChangedReceiver,

100. timeZoneFilter);

101. }

102. private BroadcastReceiver timeZoneChangedReceiver = new

103. BroadcastReceiver() {

104. @Override

105. public void onReceive(Context context, Intent intent){

106. if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {

107. watchFace.updateTimeZoneWith(intent.getStringExtra("time-zone"));

108. }

109. }

110. };

111. // method to unregister our detected timezone receiver

112. private void unregisterTimeZoneReceiver() {

113. unregisterReceiver(timeZoneChangedReceiver);

114. }

115. // Register a broadcast message to get the battery level

116. private void registerBatteryInfoReceiver() {

117. IntentFilter batteryInfoFilter = new

118. IntentFilter(Intent.ACTION_BATTERY_CHANGED);

119. registerReceiver(batteryInfoChangedReceiver,

120. batteryInfoFilter);

121. }

122. // Method to receive the message sent by the battery info

123. // receiver class

124. private BroadcastReceiver batteryInfoChangedReceiver = new

125. BroadcastReceiver() {

126. @Override

127. public void onReceive(Context context, Intent intent){

128. if

129. (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction()))

130. {

131. watchFace.batteryText =

132. String.valueOf("Battery: " +

133. intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) + "%");

134. }

135. }

136. };

137. // method to unregister our battery information receiver

138. private void unregisterBatteryInfoReceiver() {

139. unregisterReceiver(batteryInfoChangedReceiver);

}

140. In the following step, we create the onDraw method that will be responsible for handling and updating the watch face on the main runnable thread when the view comes out of the ambient mode. The onTimeTick method is called whenever the timer ticks and calls the invalidate method, which tells the system to call the onDraw method to redraw the watch face as shown in the following code snippet:

141. @Override

142. public void onDraw(Canvas canvas, Rect bounds) {

143. super.onDraw(canvas, bounds);

144. watchFace.draw(canvas, bounds);

145. }

146. @Override

147. public void onTimeTick() {

148. super.onTimeTick();

149. invalidate();

}

150. Next, we create the onAmbientModeChanged method that determines when the device changes between ambient and interactive modes. We perform a check to see if we are in ambient mode, and change the color of our display labels for Date, Time, and Batterylabels before calling the invalidate method so that the system will redraw the watch face. This is done as follows:

151. @Override

152. public void onAmbientModeChanged(boolean inAmbientMode) {

153. super.onAmbientModeChanged(inAmbientMode);

154. watchFace.setAntiAlias(!inAmbientMode);

155. if (!inAmbientMode) {

156. watchFace.setColor(Color.RED, Color.GREEN,

157. Color.WHITE);

158. }

159. else watchFace.setColor(Color.GRAY, Color.GRAY,

160. Color.GRAY);

161. invalidate();

162. startTimerIfNecessary();

}

163. Now, we create the onDestroy method that handles the destroying of our callback methods declared by the register methods as follows:

164. @Override

165. public void onDestroy() {

166. clockTick.removeCallbacks(timeRunnable);

167. super.onDestroy();

168. }

}

In the preceding code snippets, we started by adding the import statements that will be responsible for allowing our application to communicate with the Android wearable. Then we added the code for our WatchFaceEngine class by creating onCreate(SurfaceHolder holder) that will be called when the watch is instantiated, as this will initialize the watch face.

In our next step, we create a startTimerIfNecessary method that will be called to update the watch display when the number of seconds has incremented and proceed to implement runnable class that includes a method called run that starts executing the active class. The onVisibilityChanged method is called when the watch face is visible, and is responsible for registering the receiving methods when the time zone changes, and starts the custom timer if the device is in interactive mode.

When the watch face is not visible, this method stops the custom timer and unregisters the receiver for time zone changes. The registerReceiver and unregisterReceiver methods are implemented for instance, when the battery level changes. The onDraw method is responsible for handling updates to the watch face on the main runnable thread when the view comes out of the ambient mode. The onTimeTick method is called whenever the timer ticks and calls the invalidate method, which tells the system to call the onDrawmethod to redraw the watch face.

We proceed to implement the onAmbientModeChanged method that will be responsible for determining whenever the device changes between the ambient and interactive modes. Next, we check to see if we are in ambient mode and change the color of our display labels for Date, Time, and Battery labels before calling the invalidate method, so that the system will redraw the watch face before finally destroying all of our callback methods declared by the register methods in the onDestroy method.

Debug your Android wearable app over Bluetooth

In this section, we will be taking a look at the steps involved in debugging your wearable application over Bluetooth. This process uses the Android debug bridge to facilitate communications between the handheld and the wearable devices by routing its debug output to the handheld device that is connected to your development machine.

To set up your device for debugging, follow these simple steps:

1. Enable USB debugging on the handheld device by opening the Settings app and then scrolling down till until you see Developer options.

2. From the Developer options section, scroll down to and enable USB debugging as shown in the following screenshot:

Debug your Android wearable app over Bluetooth

3. Next, open the Android Wear companion app on the handheld device.

4. Click on the Settings cog that is located on the top right-hand corner of the screen, scroll down, and enable Debug over Bluetooth, which is shown in the following screenshot:

Debug your Android wearable app over Bluetooth

5. Next, connect your handheld device to your machine using USB and enter the following command line options, which are shown in the following screenshot:

6. $ ./adb forward tcp:4444 localabstract:/adb-hub

7. $ ./adb connect localhost:4444

Debug your Android wearable app over Bluetooth

8. If you open the Android wearable app on your handheld device, you should see that the host and target statuses should have now changed to connected, as shown in the following screenshot:

Debug your Android wearable app over Bluetooth

Running apps directly on an Android Wear device

In this section, we will be taking a look at the steps involved in running an Android wearable app directly on the wearable device, instead of running this inside the Android simulator.

Before we can run the apps on our Android wearable device, first we need to make some changes to our project configuration as follows:

1. This can be achieved by choosing Run | Edit Configurations… from Android Studio menu as shown in the following screenshot:

Running apps directly on an Android Wear device

Next, since our project doesn't contain any activity modules, we need to make some adjustments to our project configuration.

2. From the Run/Debug Configurations screen, select the wear configuration option located within the Android Application section.

3. Then, select the Do not launch Activity option located within the Activity section.

4. Next, select the Show chooser dialog option located within the Target Device section, and click on the OK button to proceed to save your changes as shown in the following screenshot:

Running apps directly on an Android Wear device

5. From the Project Navigator window, choose the wear section and then select the manifests folder.

6. Select the AndroidManifest.xml file as shown in the following screenshot:

Running apps directly on an Android Wear device

7. Next, under the manifest section of the wearable app we need to include permissions to allow our app to run within the wearable device. Enter the permissions as shown in the following code snippet:

8. <uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND"/>

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

9. Now modify the <application> section of the wearable app, as follows:

10.<application

11. android:allowBackup="true"

12. android:label="@string/app_name"

13. android:icon="@mipmap/ic_launcher"

14. android:theme="@android:style/Theme.DeviceDefault">

15.<service

16.android:name=".WatchFaceService"

17.android:label="@string/app_name"

18.android:permission="android.permission.

19.BIND_WALLPAPER">

20.<meta-data

21.android:name="android.service.wallpaper"

22.android:resource="@xml/watch_face" />

23.<meta-data

24.android:name="com.google.android.wearable.

25.watchface.preview"

26.android:resource="@mipmap/ic_launcher" />

27.<meta-data

28.android:name="com.google.android.wearable.

29.watchface.preview_circular"

30.android:resource="@mipmap/ic_launcher" />

31.<intent-filter>

32.<action

33.android:name="android.service.wallpaper.

34. WallpaperService"/>

35.<category

36.android:name="com.google.android.wearable.

37. watchface.category.WATCH_FACE"/>

38.</intent-filter>

39.</service>

</application>

40. Now, we can finally begin to compile, build, and run our application. Simply press CMD + F9, and choose your AVD or your Android wearable device from the list of available devices as shown in the following screenshot:

Running apps directly on an Android Wear device

Once the wearable app has been installed on the Android wearable device, you should see our custom watch face being displayed, as shown in the following screenshot:

Running apps directly on an Android Wear device

As you can see, creating Android watch faces is quite simple and you can create some really cool watch face designs. From the preceding screenshot, the image to the left shows the non-ambient version and the one to the right shows the image when the screen has dimmed, thus conserving battery life.

In our next section, we will take a look at the Android design principles, and the importance of designing user interfaces that are intuitive, consistent, and are designed with battery considerations in mind to conserve power.

The Android wearable user interface guidelines

The approach to designing apps for Android wearable devices, especially custom watch faces, needs to be substantially different from how you go about designing apps for phones or tablets, as these contain a different user experience. It is important to keep in mind and follow the Android UI design principles documentation that Google has provided.

This document describes the guidelines and principles that help you to design consistent user interfaces and experiences for your Android wearable apps, ensure that your application runs efficiently on the Android Wear platform, and it also involves considering the screen sizes of your custom layouts, memory limitations, and the ease of use of your app.

Other areas covered by the document are guidelines to ensure the consistency of your application as you navigate from screen to screen, as well as principles to design good user interfaces. This document also includes the following design guidelines that you will need to follow in your application, such as:

· Your application works for the round and square watch face designs, as well as their different screen resolutions.

· Your Android Wear app supports ambient mode when it is not being used, as this will conserve battery power. This involves dimming the screen and only using limited color, while keeping most of the pixels black. When the user taps on the screen to exit ambient mode, the screen can revert back to using full color and animations.

· Your app functionality allows the user to swipe down on the home screen to reveal the date and battery display, while providing the ability for further swiping down to turn off device sounds as well as preventing notifications from being displayed on the home screen.

There is also information relating to the proper use and appearance of system UI elements and controls for navigation, as well as creation of custom icons and images.

Note

To obtain further information about these guidelines, it is worthwhile to check the Android Wear Design Principles documentation at https://developer.android.com/design/wear/principles.html.

Packaging your Android wearable application

After you have finished testing your application to ensure that it is free of bugs, you are ready to publish your app to the world. Before this can happen, you must publish your wearable app directly inside a handheld application. This is due to the fact that your users cannot directly install your app to the wearable device.

Fortunately, this process is not that difficult, and in just a few steps you will be able to package your application using Android Studio. Let's get started by following these simple steps:

1. From the Gradle Scripts section of the Project Navigator window, select the build.gradle (Module: mobile) option as shown in the following screenshot:

Packaging your Android wearable application

2. Next, under the dependencies section, enter the following code snippet:

compile 'com.android.support:support-v4:21.0.+'

Note

You need to ensure that both your wearable and handheld app modules contain the same package name and version, otherwise you will experience build errors.

3. From the mobile section of the Project Navigator window, select the manifests folder and then the AndroidManifest.xml file as follows:

Packaging your Android wearable application

4. Next, under the manifest section of the handheld app, we need to include all permissions declared in our wearable app module in the manifest file of the handheld app module.

5. Then, enter the following permissions:

6. <uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND"/>

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

7. Now, navigate to Build | Generate Signed APK… as shown in the following screenshot:

Packaging your Android wearable application

8. From the Module drop-down menu, choose the mobile option, and click on the Next button as shown in the following screenshot:

Packaging your Android wearable application

9. Next, from the Generate Signed APKWizard screen, click on the Create new… button, and then click on the Next button as follows:

Packaging your Android wearable application

10. From the New Key Store screen, specify the location where you would like to store your key by clicking on the button beside the Key store path text field.

Note

It is extremely important that you don't lose this key, otherwise you won't be able to upload new updates to the Google Play Store if the keys are different.

11. Then, provide a password to use for your key store file, an alias name to use for your application, populate the Certificate information, click on the OK button to dismiss the screen, and return back to the Generate Signed APK Wizard screen.

12. From the Generate Signed APK Wizard screen, click on the Next button, and then under the Build Type drop-down menu, choose the release option, and click on the Finish button.

13. Once the wizard has finished packaging your application, you will see the Signed APK's generated successfully dialog appear. Click on the Reveal in Finder button to show your mobile-release.apk packaged app as shown in the following screenshot:

Packaging your Android wearable application

The preceding screenshot shows the workflow when generating a signed APK with the associated screens. As you can see, the APK will export your signed handheld application using Android Studio for your packaging process, and through this process, automatically include the wearable application portion embedded inside it.

Note

When a user downloads and installs your app, they will be installing the mobile component on their handheld device, which automatically pushes the wearable app to their smartwatch.

Summary

In this chapter, we learned how we can build a custom watch face by using Google's official API so that we can create our very own custom watch face service and custom watch face class to handle the presentation of a digital clock with date and time, as well as battery usage within the watch face layout.

Then we looked at how we can debug our wearable applications with Bluetooth that are running in the wearable device. Next, we spent some time learning about the design guidelines for Android wearable and the design considerations developers need to consider when designing their user interfaces, specifically to conserve battery power when running resource-intensive tasks.

In closing, we looked at the steps involved when packaging our wearable application so that it can be sent to users to be installed and used within the handheld mobile device.

In the next chapter, we will learn more about the data layer API and how we can synchronize data from the Android wearable with the handheld mobile device. We will learn about the message API that will provide us with the ability to send and receive messages, and finally we will learn how to build an Android Wear watch service to communicate with the data layer events.