Chapter     2

Hello, Glass! Your First GDK App

In this chapter, I’ll first discuss how to set up your environment for GDK development, whether you use Mac, Linux, or Windows. I’ll then show you how to get your Glass ready for development, how to use the Android command-line tool adb to perform common operations on Glass, and how to run GDK samples on Glass. After that, I’ll walk you through a complete tutorial of the GDK app template and how to use it to quickly create your first GDK app. You will use the template in most of the following chapters to create all the new GDK apps.

Setting Up the Development Environment

In this section, I’ll discuss the system requirements for Glass development and how to install the Android Developer Tools (ADT) Bundle, which includes Eclipse + ADT plugin, Android SDK tools and platform tools. If you already have an Android development environment up and running, you can skip this section.

System Requirements

You can develop GDK Glassware with the ADT or Eclipse IDE on a computer running Windows, Mac, or Linux with the following requirements (see http://developer.android.com/sdk/index.html for more details):

  • Intel-based Mac OS X 10.5.8 or newer
  • Windows XP (32-bit), Vista (32/64-bit), or Windows 7 (32/64-bit) or newer
  • Linux (preferably Ubuntu Linux 8.04 or newer)

Android Developer Tools

The ADT Bundle is Google’s recommended tool for developing Android and GDK apps quickly. If you’re an experienced developer, you should be able to follow the instructions at http://developer.android.com/sdk and get it installed in less than an hour. If you experience any issues and can’t find the right answers on Google, you can refer to the following steps.

ADT on Mac

After you download the ADT bundle for Mac from http://developer.android.com/sdk, unzip it, and you’ll see two subfolders, as shown in Figure 2-1.

9781430267881_Fig02-01.jpg

Figure 2-1. File structure of ADT on Mac

Eclipse.app is the IDE you’ll use to develop all your GDK Glassware. Simply double-click it to launch the app. You may need to update the ADT plug-in to successfully import the template project later in the chapter; you can select Help image Check for Updates or Install New Software in Eclipse/ADT and then add https://dl-ssl.google.com/android/eclipse/ to update the ADT plug-in.

ADT on Windows

Follow these steps to install and set up ADT on Windows:

  1. Download the ADT bundle for Windows at http://developer.android.com/sdk.
  2. Unzip the downloaded file. The unzipped ADT bundle folder on Windows also has two subfolders, eclipse and sdk, with similar files in them as on Mac. There is an additional SDK Manager.exe file in the unzipped ADT folder on Windows. The first time you run eclipse.exe in ADT’s eclipse folder, you may see a dialog box like the one shown in Figure 2-2.

    9781430267881_Fig02-02.jpg

    Figure 2-2. Setting up Eclipse ADT on Windows

    If you see this dialog box, just click “Extract all.” This may take about 30 minutes and more than 1GB to uncompress all the files. After that, you can just double-click the eclipse.exe file again to start the IDE. If you don’t have the JRE or JDK installed on your computer, you’ll see message similar to Figure 2-3. (Note that on March 21, 2014, “20131030” in the adt package name was upgraded to “20140321,” which may be changed again by the time you’re reading the book.)

    9781430267881_Fig02-03.jpg

    Figure 2-3. Installing JRE or JDK for Eclipse to start on Windows

  3. If you see message shown in Figure 2-3, you need to go to Oracle’s web site at www.oracle.com/technetwork/java/javase/downloads to download the JDK (you don’t need to download the JDK; the JRE is enough to work with ADT). Remember to click the download link for Windows x86 if your Windows is 32-bit or the download link for Windows x64 if your Windows is 64-bit. You may have to register with Oracle or log in to be able to download it.

    Note  Although http://developer.android.com/sdk/index.html says that “JRE alone is not sufficient,” in my test on a clean Windows machine with no JDK or JRE installed, I found that you don’t have to download the JDK; JRE 6 or 7 is enough to work with ADT. This may be a little surprising, but the Eclipse message in Figure 2-3 does suggest that the JRE may be good enough. Also, the latest JDK/JRE 8 should work, but I haven’t tested it.

  4. Run the setup EXE file and then add the path to the JRE bin directory (C:Program FilesJavajre7in or C:Program FilesJavajre6in by default) to your computer’s PATH environment variable by selecting Start image Control Panel image System and Security image System image Advanced system settings image Advanced image Environment Variables image System Variables.
  5. Run eclipse.exe again, and you should see the ADT IDE up and running!

Note  If you accidently downloaded the 32-bit JRE EXE (all those x86 ones) for your 64-bit Windows, or vice versa, you may see an error message “Failed to load the JNI shared library ‘C:Program Files (x86)Javajre6clientjvm.dll.’” You can fix this by downloading and installing the right JRE for your Windows version.

ADT on Linux

If you have a Windows PC but prefer to run Ubuntu Linux, you can download the Ubuntu Windows installer at www.ubuntu.com/download/desktop/windows-installer and follow the installation steps at www.ubuntu.com/download/desktop/install-ubuntu-with-windows. After the installation is completed, simply restart and boot your computer to Ubuntu.

Note  If you have another Linux distribution or Ubuntu on a virtual machine, the steps to install ADT should be similar. The following steps have been tested on Ubuntu downloaded and installed from the previous URLs.

The steps to install and set up ADT on Ubuntu Linux are as follows:

  1. Download the ADT bundle called Linux 64-bit adt-bundle-linux-x86_64-20140321.zip or the latest ADT bundle at http://developer.android.com/sdk under Download for Other Platforms. (Notice that the browser on your Ubuntu distribution may automatically detect that you’re using Linux and therefore show a Download the SDK button.)
  2. Download the JRE for Linux x64 file, named jre-7u45-linux-x64.tar.gz, at www.oracle.com/technetwork/java/javase/downloads/jre7-downloads-1880261.html.
  3. Uncompress both archives and move the jre-7u45-linux-x64 folder to the eclipse directory of the ADT folder; you should see something like Figure 2-4. (I renamed the jre-7u45-linux-x64 folder to jre. If you prefer, you can also leave the jre-7u45-linux-x64 folder where it is and modify eclipse.ini; see http://wiki.eclipse.org/FAQ_How_do_I_run_Eclipse%3F#eclipse.ini for details.)

    9781430267881_Fig02-04.jpg

    Figure 2-4. File structure of Eclipse ADT on Ubuntu Linux

  4. Edit your .bashrc file in your home directory to update your PATH variable:
    PATH=$PATH:<path-to-adt-folder>/eclipse/jre/bin
  5. If you run the Eclipse program now and see the error message “./android: java: not found,” you can fix it by running a command similar to this:
    sudo ln -s <path-to-adt-folder>/eclipse/jre/bin/java /usr/bin/java
  6. Another possible error message, “platform-tools/adb: No such file or directory,” implies there is a missing shared library needed by adb (the powerful Android Debug Bridge command-line tool, which I’ll discuss in more detail in the next section) and can be fixed by running this:
    apt-get install ia32-libs

Note  As you can tell, installing Oracle’s JRE/JDK on Ubuntu is a nontrivial process. The earlier instructions have been tested on my Windows PC with Ubuntu Windows, but your environment may be different. For example, if you already have OpenJDK installed, then you can check out resources such as www.liberiangeek.net/2012/04/install-oracle-java-jdk-7-in-ubuntu-12-04-precise-pangolin. In other cases, Google should be your best friend for fixing installation-related issue.

Now that you have the ADT bundle (Eclipse plus the ADT plug-in) installed on your computer, you’re ready to start having fun with Glass as a developer—well, almost ready, if you use Windows.

Playing with Glass

In this section, I’ll cover how to use the powerful Android command-line tool adb to communicate with Glass, how to run GDK sample apps on your Glass, and, finally, how to see Glass screens on your computer.

Enabling Debugging Mode on Glass

To get your Glass ready for development purpose, you need first to enable USB debugging on Glass. After you turn on Glass and see the OK Glass menu, swipe your Glass backward on the touchpad until you see Settings; then, tap it and swipe forward to find “Device info,” as shown in Figure 2-5. Tap again and swipe to find and select “Turn on debug.” Now connect Glass to your computer via USB.

9781430267881_Fig02-05.jpg

Figure 2-5. Tap “Device info” to find and select “Turn on debug” on Glass

The adb Command

Android Debug Bridge (adb) is a handy command-line tool that you’ll use to communicate with Glass. Its main uses are listing connected Android devices (adb devices), browsing the device folders (adb shell), installing and uninstalling apps (adb install and adb uninstall), and copying files (adb pull and adb push). As a Glass developer, you should definitely check out its documentation at http://developer.android.com/tools/help/adb.html and get familiar with it.

Before you can run the adb command, you need to add the path to ADT’s platform-tools directory to your system’s PATH variable. If you use Windows, update the PATH variable at Start image Control Panel image System and Security image System image Advanced system settings image Advanced image Environment Variables image System Variables. If you use Mac or Linux, update your PATH variable in ~/.bashrc to be like this:

PATH=$PATH:<path-to-adt-folder>/sdk/platform-tools

Now launch a terminal window on Mac or Linux, and run the following command; you’ll see your Glass listed as shown here:

adb devices
List of devices attached
015xxxxxxxx17xxx device

Installing the USB Driver on Windows

Unfortunately on Windows, most likely you won’t see any devices listed with the adb devices command. This is because if you’re developing on Mac or Linux, you don’t need to install a USB driver, but on Windows, you need to manually install the right USB driver. The steps are as follows:

  1. Download the Google USB Driver package for Windows at http://developer.android.com/sdk/win-usb.html; you can either download the ZIP file at the URL directly or use ADT’s Android SDK Manager and select the Google USB Driver package to download, as shown in Figure 2-6.

    9781430267881_Fig02-06.jpg

    Figure 2-6. Installing Google USB Driver for Windows

  2. Unzip the file to a location you choose and find the usb_driver folder; or if you use the Android SDK Manager to download the driver, you can find your auto-unzipped files in ADT’s sdkextrasgoogleusb_driver folder.
  3. Double-click the android_winusb.inf file in the usb_driver folder and add the following lines to the [Google.NTx86] and [Google.NTamd64] sections:
    ;Google Glass
    %SingleAdbInterface% = USB_Install, USBVID_18D1&PID_9001&REV_0216
    %CompositeAdbInterface% = USB_Install, USBVID_18D1&PID_9001&MI_01

    You may want to verify those seemingly magic values by these steps: Right-click Computer and select Manage. Then select Device Manager, and on the right panel under Other Devices, right-click Glass 1 and switch to the Details tab. Finally, select Hardware Ids Property; now you should see something like Figure 2-7 and Figure 2-8. (You need to make the previous code lines the same as the values in Figure 2-8.)

    9781430267881_Fig02-07.jpg

    Figure 2-7. Device Manager on Windows

    9781430267881_Fig02-08.jpg

    Figure 2-8. Values for Google Glass USB setup info file on Windows

  4. Save the android_winusb.inf file, right-click Glass 1, and choose Update Driver Software image Browse my computer for driver software. Choose the path to the usb_driver folder described in step 2 and dismiss the warning message; you should see the message “Windows has successfully updated your driver software.” Your Glass1 device will also be changed to Android Composite ADB Interface.

    Note  Steps 3 and 4 were tested on Windows 7. For Windows XP and Vista, you may want to check the document at http://developer.android.com/tools/extras/oem-usb.html#InstallingDriver for more details.

  5. Open a command prompt window on Windows and run adb devices to verify your Glass is listed. You may have to run the command adb kill-server first and then adb devices to see your Glass listed. If you see a message saying “’adb’ is not recognized as an internal or external commands,” you should check your PATH variable as described earlier in “The adb Command.”

Showing the Glass Screen on a Bigger Screen

You can use tools to show your Glass screen on your computer running Mac, Windows, or Linux. This can make your development easier because you can look at the bigger computer screen most of the time instead of the small Glass screen. It can also make your demo, presentation, or training sessions much easier.

Before you continue, you should verify that the adb command, discussed in the previous section, works fine and shows your Glass in the “List of devices attached” area or the following tools won’t work.

There are at least two good tools to use here. You can download the latest Droid@Screen version at http://droid-at-screen.ribomation.com/download or Android Screen Monitor at https://code.google.com/p/android-screen-monitor. Droid@Screen has a better UI, but Android Screen Monitor has better frame rate. After downloading one of them (and unzipping it for Android Screen Manager), you can run one of the following commands to see on your computer something like Figure 2-9 and Figure 2-10:

java -jar droidAtScreen-1.0.2.jar
 
java -jar ASM_2_50/asm.jar

9781430267881_Fig02-09.jpg

Figure 2-9. Glass screens on your computer

9781430267881_Fig02-10.jpg

Figure 2-10. More Glass screens on your computer

Another great way to see your Glass screen content on a bigger screen is to install the MyGlass app on any Android and iOS device (preferably tablets) and use its Screencast feature. There are two ways to activate Screencast: You can pair with Glass via Bluetooth and turn on Personal Hotspot, or you can connect Glass and your Android/iOS devices to the same wi-fi network.

Developing with Simulated Devices or Emulators

If you have some experience with Android or iOS app development, most likely you have used simulators to speed up your development. The bad news is that there is no official support from Google for the Glass development with emulators or Android devices; the good news is that because Glass is an Android device, theoretically you can just extract the .apk files from the system image of Glass and install them to your non-Glass Android. The web page www.elekslabs.com/2013/11/google-glass-development-without-glass.html is a summary but hasn’t been updated for the GDK release as of May 2014.

Although there are some developers who don’t own Glass but are interested in learning Glass development, I decided not to cover the GDK Glass development with simulated devices in this book for two main reasons. A lot of non-Glass-development-related hacks would be needed, and the time spent there can be better used for learning about the exciting GDK and Mirror API development. In addition, by the time you are reading this book, chances are Google will have made, or soon make, Glass publicly available at an acceptable price of several hundred dollars. Google will likely also release an official way to do Glass development on emulators or other Android devices.

Testing with GDK Samples

Finally, you’re ready to see some samples working on Glass, whether you use Mac, Linux, or Windows. Compared to what it takes to get the development environment set up correctly, especially on Windows and Linux, and configure the Glass USB Driver package on Windows, testing the GDK samples is a lot easier. (After all, there’s a balance in everything.) Whether you’re an Android expert or beginner, just follow the well-documented GDK Quick Start instructions at https://developers.google.com/glass/develop/gdk/quick-start to install the Android 4.4.2 (API 19) SDK, the Glass Development Kit Preview add-on, and the three GDK samples (Compass, Stopwatch, and Timer).

After you select a sample from Eclipse to run as an Android app, if you have Glass connected to your computer via USB, you’ll see your Glass shown as a running Android device, as in Figure 2-11.

9781430267881_Fig02-11.jpg

Figure 2-11. Android Device Chooser showing Google Glass

Select the google-glass_1-xxx device and click OK; you’ll see the sample app gets installed to your Glass. Figure 2-12 shows the console output after running the Timer sample.

9781430267881_Fig02-12.jpg

Figure 2-12. Installing sample Glass app called Timer

Now tap Glass, say “OK Glass,” and then say “Start a timer.” The Timer app will get launched on Glass, displaying 00:00:00 for hour:minute:second. Tap the Glass touchpad, and the first menu item, “Set timer,” appears. Swipe forward, and you’ll see the Stop menu item. Figure 2-13 shows both screens.

9781430267881_Fig02-13.jpg

Figure 2-13. Showing menu items for the Timer sample

Tap the “Set timer” menu item; you’ll see the hours text with the first two 0s highlighted. Tap again to see 00 in a large font size centered in a new screen. You can swipe left and right to choose a value between 00 and 23. After you tap a number, it becomes your selected hour. You can then swipe to select minutes and seconds. Figure 2-14 shows the timer information before and after setting it (with 2 hours 30 minutes).

9781430267881_Fig02-14.jpg

Figure 2-14. Before and after timer setting

Now swipe down on the touchpad, and you’ll see the set timer 02:30:00; tap again, and this time a new menu item, Start, appears. Tap it, and you’ll see the timer gets updated every second. Tapping one more time will show the new menu items Pause, Reset, Change time, and Stop. Figure 2-15 shows two of these menu items.

9781430267881_Fig02-15.jpg

Figure 2-15. Timer in action with menu items

To play more with Glass, you can run the other two samples Compass and Stopwatch in the same way. You should also look into the samples’ source code. If you’re like me when I started to learn Glass GDK development, you probably hope there’s a step-by-step tutorial on how to create such a GDK app. That is exactly what you’ll get in the next section of this chapter.

The HelloGlass Glassware

In this section, I’ll answer two important questions to get you ready for the exciting journey ahead: Can you use a template for creating new GDK apps? How do you create a new GDK app project?

Step-by-Step Tutorial

Follow these steps to build a generic GDK template app that will be used as the basis to build your first HelloGlass app and all the GDK apps in the coming chapters:

  1. Launch Eclipse.
  2. In ADT’s Package Explorer, right-click to show the menu and then select Import. (You can also select File image Import.)
  3. Select Android image Existing Android Code Into Workspace and then click Next.
  4. In the Import Projects window, click Browse and select the GlasswareTemplate folder in the source code directory that comes with the book. Keep all the other defaults (the window should look like Figure 2-16) and click Finish.

    9781430267881_Fig02-16.jpg

    Figure 2-16. Importing GlasswareTemplate project to ADT

    Note  You may notice some slight differences between your Eclipse screens and the following screenshots. This is because the ADT looks on Mac, Windows, and Linux are not 100 percent the same, but the difference is so insignificant (for example, the order of Cancel and Finish buttons is different) that you shouldn’t have any trouble following the tutorial.

  5. An error may occur because an incorrect target could be set as Project Build Target when the project was imported. To fix this, simply right-click GlasswareTemplate in ADT’s left Package Explorer panel, select Properties, and then change Project Build Target to Glass Development Kit Preview, as shown in Figure 2-17. Click OK, and you’re ready to run the template Glassware.

    9781430267881_Fig02-17.jpg

    Figure 2-17. Fixing possible project target error after importing

  6. Connect Glass to your computer and turn it on if you haven’t (you may want to verify your Glass is connected by running adb devices). Right-click GlasswareTemplate and select Run As image Android Application. You’ll see the Android Device Chooser window with your Glass; select it and click OK.
  7. You should see a message that says “/GlasswareTemplate/bin/GlasswareTemplate.apk installed on device” in ADT’s console.

    Note  Sometimes after you import the GDK template app to Eclipse or create a new project based on it, you may get an error message when building the app: “Unable to execute dex: java.nio.BufferOverflowException.” You can fix this by right-clicking the project and then selecting Android Tools and Add Support Library.

  8. Tap your Glass, say “OK Glass,” and then say “Glassware.” Or tap the OK Glass screen and then tap again when you see #glassware#, which should be the first item in the menu (starting with XE 16, recent and frequently visited items are placed first). GlasswareTemplate will run and show the main screen with the “Hello Glass!” text. Tap it and swipe, and you’ll see the menu items STOP, TTS (for text-to-speech), ASR (for automated-speech-recognition). Tap STOP to close the app; tap TTS to listen to “Hello Glass!”; tap ASR and say “Hello Glass.” Glass will recognize your speech!

Congratulations! You have the generic Glassware template app up and running.

Next, follow these steps to build and test HelloGlass, your first GDK app created based on the template app. I’ll then explain the project, files, and code for both HelloGlass and GlasswareTemplate in detail in the next section.

  1. In ADT, select File image New image Android Application Project and enter the information shown in Figure 2-18.

    9781430267881_Fig02-18.jpg

    Figure 2-18. Creating your HelloGlass GDK app based on the template app

  2. Click Next three times and keep all the default settings.
  3. Uncheck Create Activity on the Create Activity screen, as shown in Figure 2-19, and then click Finish.

    9781430267881_Fig02-19.jpg

    Figure 2-19. Changed setting for your HelloGlass app

  4. Open GlasswareTemplate, as shown in Figure 2-20; the files showing are to be copied to your HelloGlass app.

    9781430267881_Fig02-20.jpg

    Figure 2-20. GlasswareTemplate project folders

  5. Right-click the HelloGlass app’s src, folder, select New image Package, and enter the name shown in Figure 2-21 (or change the package name to be other name you like better); click Finish.

    9781430267881_Fig02-21.jpg

    Figure 2-21. Creating a new package name for HelloGlass

  6. In Eclipse, copy the four files from GlasswareTemplate’s src folder and paste them to HelloGlass’s src folder. The first line in the four files of HelloGlass’s src folder should have been changed automatically by Eclipse from com.morkout.glasswaretemplate to com.morkout.helloglass; if not, change them manually. Ignore the errors in the HelloGlass project; they’ll all be fixed soon in the following steps.
  7. In Eclipse, copy the drawable, menu, and xml folders in GlasswareTemplate’s res folder and paste them to HelloGlass’s res folder; then copy the files in GlasswareTemplate’s res, layout, and values folders and paste them to HelloGlass’s res, layout, and values folders (you need to overwrite the strings.xml and styles.xml files in the HelloGlass res, layout, and values folders when you copy and paste). Replace the whole <application> ... </application> section in HelloGlass’s AndroidManifest.xml with that in GlasswareTemplate’s AndroidManifest.xml. Change android:name’s value in the service tag from com.morkout.glasswaretemplate.AppService to com.morkout.helloglass.AppService, and change android:name’s value in the activity tag from com.morkout.glasswaretemple.MenuActivity to com.morkout.helloglass.MenuActivity.
  8. Copy the line <uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />from GlasswareTemplate’s AndroidManifest.xml file to HelloGlass’s AndroidManifest.xml file. This is something new in XE 16 or later and is required when you develop your GDK apps; see https://developers.google.com/glass/develop/gdk/starting-glassware for more details.
  9. Finally, change the string value for say_glasswaretemplate in HelloGlass’s res/values/strings.xml file to #helloglass#. Run HelloGlass as an Android application while Glass is connected and turned on. You’ll see on your computer something like Figure 2-11 and Figure 2-12. Then on your Glass, you’ll see your #helloglass# app in the app list on the OK Glass screen. Tap the app to start it and see “Hello Glass,” where you can tap and then swipe to see the menu like in the GlasswareTemplate app.

Note  You may wonder why you went through all the previous steps to create a new app based on the template app without adding any exciting new features to the app. You’ll soon see in the coming chapters that the steps are repeated for each new category of apps, such as UI elements, image processing, video processing, audio processing, and so on. Creating a new app this way instead of importing and modifying the template app directly will help you organize your apps effectively.

What’s Going On

Now that you have both the template Glassware and HelloGlass app running, it’s time to delve into the details of the projects. Let’s first take a look at the big picture.

The Big Picture

A typical GDK app starts with a service (AppService) that runs when the app’s voice command is uttered or the app is tapped in the OK Glass app list. When the service is started, it creates a live card. A live card is one of the essential Glass UI elements that I’ll discuss in detail next chapter; for now you can just think of it as a card that gets created on the left side of the OK Glass item as the initial Timer card shown in Figure 2-14. (For a quick review of the Glass UI and live cards, you can also check out https://developers.google.com/glass/design/ui and https://developers.google.com/glass/develop/gdk/live-cards.) The live card then adds an instance of a class (AppDrawer) that implements SurfaceHolder.Callback for rendering, as well as a menu activity action (MenuActivity). AppDrawer creates an instance of a View subclass (AppViewer) that does the real rendering, sets the view’s layout, and requests the view to draw the content. AppViewer is similar to common Android app view class, drawing UI elements based on a layout XML; in the example, it simply sets the content for a TextView.

Figure 2-22 shows how the classes in the template Glassware interact with each other.

9781430267881_Fig02-22.jpg

Figure 2-22. Interactions of service, live card, drawer, viewer, menu, and Glass

Source Code

In the HelloGlass project’s src folder, there are four files copied from GlasswareTemplate’s src folder:

  • AppDrawer.java
  • AppService.java
  • AppViewer.java
  • MenuActivity.java

Detailed explanations for these files follow.

AppDrawer.java

The AppDrawer.java file in Listing 2-1 defines the class AppDrawer that implements the SurfaceHolder.Callback interface (SurfaceHolder allows you to access and control a display surface’s size and format and monitor its changes), which has three public abstract methods: surfaceChanged, surfaceCreated, and surfaceDestroyed.

Listing 2-1.  AppDrawer.java

package com.morkout.glasswaretemplate;
 
import android.content.Context;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
 
public class AppDrawer implements SurfaceHolder.Callback {
    private static final String TAG = "AppDrawer";
    private final AppViewer mView;
    private SurfaceHolder mHolder;
 
    public AppDrawer(Context context) {
        mView = new AppViewer(context);
    }
 
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // Measure and layout the view with the canvas dimensions.
        int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
        int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
        mView.measure(measuredWidth, measuredHeight);
        mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
        draw(mView);
    }
 
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mHolder = holder;
        mView.start();
        draw(mView);
    }
 
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mHolder = null;
    }
 
    private void draw(View view) {
        Canvas canvas;
        try {
            canvas = mHolder.lockCanvas();
        } catch (Exception e) {
            return;
        }
        if (canvas != null) {
            view.draw(canvas);
            mHolder.unlockCanvasAndPost(canvas);
        }
    }
}

AppDrawer first creates an instance of AppViewer, a View subclass, and then goes through the two-pass layout process (measure and layout), in surfaceChanged before actually drawing the view. The width and height passed to the surfaceChanged method are 640 and 360 pixels, the size of the Glass display. The view draw request is made between the canvas lock and unlock.

AppService.java

The AppService.java file in Listing 2-2 defines a Service subclass AppService, which in its onStartCommand method creates a live card if the card hasn’t been created. After that, an AppDrawer instance is created and set as the callback of the live card’s surface, on which drawing will happen; note that the direct rendering has to be enabled on the live card in order for it to return a valid surface holder and for the live card to be displayed. Another condition for the live card to be displayed is to provide it with an action; in the code here, the action is an activity that displays an options menu when the card is selected (after the app is started), but the action can also be any other activity.

Listing 2-2.  AppService.java

package com.morkout.glasswaretemplate;
 
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
 
import com.google.android.glass.timeline.LiveCard;
import com.google.android.glass.timeline.LiveCard.PublishMode;
 
public class AppService extends Service {
 
    private static final String TAG = "AppService";
    private static final String LIVE_CARD_ID = "HelloGlass";
 
    private AppDrawer mCallback;
    private LiveCard mLiveCard;
 
    @Override
    public void onCreate() {
        super.onCreate();
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mLiveCard == null) {
            mLiveCard = new LiveCard(this, LIVE_CARD_ID);
            mCallback = new AppDrawer(this);
            mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder().addCallback(mCallback);
            Intent menuIntent = new Intent(this, MenuActivity.class);
            mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));
 
            mLiveCard.publish(PublishMode.REVEAL);
        }
 
 
        return START_STICKY;
    }
 
    @Override
    public void onDestroy() {
        if (mLiveCard != null && mLiveCard.isPublished()) {
            if (mCallback != null) {
                mLiveCard.getSurfaceHolder().removeCallback(mCallback);
            }
            mLiveCard.unpublish();
            mLiveCard = null;
        }
        super.onDestroy();
    }
 
 
}

After the live card is published to the timeline, AppDrawer will receive the SurfaceHolder’s callbacks to draw its content via AppViewer. When the service is being destroyed, the AppDrawer callback interface needs to be removed from the surface holder and the live card unpublished.

AppViewer.java

AppViewer.java in Listing 2-3 defines a simple View subclass that instantiates the layout XML file and sets the “Hello Glass!” text in its TextView.

Listing 2-3.  AppViewer.java

package com.morkout.glasswaretemplate;
 
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.TextView;
 
public class AppViewer extends FrameLayout {
    private final TextView mTextView;
 
 
    public AppViewer(Context context) {
        this(context, null, 0);
    }
 
    public AppViewer(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
 
    public void start() {
    }
 
    public AppViewer(Context context, AttributeSet attrs, int style) {
        super(context, attrs, style);
        LayoutInflater.from(context).inflate(R.layout.start, this);
 
        mTextView =  (TextView) findViewById(R.id.hello_view);
        mTextView.setText("Hello Glass!");
    }
 
}

MenuActivity.java

MenuActivity in Listing 2-4 creates an activity with three options: the common Stop option that exits the app; an option to do text-to-speech (TTS) of “Hello Glass!”; and an option to do automated speech recognition (ASR) of any utterance, including of course “Hello, Glass.” The intent of this activity is to show you the standard way to close your GDK app and to give you a first glimpse at the power of GDK Glassware with just a few lines of Android code. You’ll soon see how to create your own custom menu options and associate your own unique activity with each option; this will open up all kinds of app features and opportunities.

Listing 2-4.  MenuActivity.java

package com.morkout.glasswaretemplate;
 
import java.util.Locale;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
 
public class MenuActivity extends Activity implements OnInitListener {
    private TextToSpeech tts;
    private boolean mAttachedToWindow;
    private boolean mTTSSelected;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mTTSSelected = false;
    }
 
    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        mAttachedToWindow = true;
        openOptionsMenu();
    }
 
    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mAttachedToWindow = false;
    }
 
    @Override
    public void openOptionsMenu() {
        if (mAttachedToWindow) {
            super.openOptionsMenu();
        }
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.stop:
            stopService(new Intent(this, AppService.class));
            return true;
 
        case R.id.tts:
                    mTTSSelected = true;
                    tts = new TextToSpeech(this, this);
                    tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                    // 1
                        @Override
                        public void onDone(String utteranceId) {
                            if (tts != null) {
                                tts.stop();
                                tts.shutdown();
                            }
                            finish();
                        }
 
                        @Override
                        public void onError(String utteranceId) {
                        }
 
                        @Override
                        public void onStart(String utteranceId) {
                        }
                    });
            return true;
 
        case R.id.asr:
            Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            startActivityForResult(i, 0);
            return true;
 
        default:
            return super.onOptionsItemSelected(item);
        }
    }
 
    @Override
    public void onOptionsMenuClosed(Menu menu) {
        if (!mTTSSelected)
            finish();
    }
 
    @Override
    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            int result = tts.setLanguage(Locale.US);
            if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
            } else {
                            HashMap<String, String> map = new HashMap<String, String>();
                            map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"helloID");
                            // 2
                               tts.speak("Hello Glass!", TextToSpeech.QUEUE_FLUSH, map);
                            // 3
            }
        }
    }
}

A quick note on the handling of TTS: Because TextToSpeech’s speak (#3) is an asynchronous call, which returns before TTS ends or even starts, you need to set up an UtteranceProgressListener (#1) to capture the speak completion event so you can close the menu activity and return to the live card screen (you don’t have to do that, but just assume in some cases you need to) when the speech is done. For UtteranceProgressListener to capture the onDone, onStart, or onError event, a dictionary with a used-defined ID (#2) needs to be provided as the third parameter of the speak method.

Resource Files

The following folders and files define the icons, layout, menu, string, and voice command XML files.

drawable

The icon files copied to drawable from GlasswareTemplate are for the app when shown in the “OK Glass” app list and for the menu items when you tap the app after it’s launched and when you swipe to show menu options. There’s nothing special here; you just need to create your own icon assets for your own Glassware.

start.xml in layout

Listing 2-5 shows the layout file used in AppViewer.java. A TextView is created within FrameLayout.

Listing 2-5.  start.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android "
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black" >
 
    <TextView
        android:id="@+id/hello_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_marginTop="-10px"
        android:gravity="center"
        android:textSize="100px" />
</FrameLayout>

main.xml in menu

Listing 2-6 is the XML file for menu item definitions. Title and icon in each item need to be defined in strings.xml in Listing 2-7 and exist in the drawable folder.

Listing 2-6.  main.xml

<?xml version="1.0" encoding="utf-8"?>
 
<menu xmlns:android="http://schemas.android.com/apk/res/android ">
    <item
        android:id="@+id/stop"
        android:title="@string/stop"
        android:icon="@drawable/ic_stop" />
        
    <item
        android:id="@+id/tts"
        android:title="@string/tts"
        android:icon="@drawable/ic_tts" />
    
    <item
        android:id="@+id/asr"
        android:title="@string/asr"
        android:icon="@drawable/ic_asr" />
</menu>

strings.xml in values

Listing 2-7 defines all the strings used in the app, including the app name, voice command (used after “OK Glass” to launch your app), voice prompt (which I’ll discuss in detail in Chapter 6), and menu items.

Listing 2-7.  strings.xml

<?xml version="1.0" encoding="utf-8"?>
 
<resources>
    <string name="app_name">Glassware!!!</string>
    <string name="say_glasswaretemplate">#Glassware#</string>
    <string name="glass_voice_prompt">Say Glassware Template to trigger the glassware</string>
    <string name="stop">STOP</string>
    <string name="tts">TTS</string>
    <string name="asr">ASR</string>
</resources>
      

voice_trigger_start.xml in xml

Listing 2-8 defines the voice command Glass users can use to launch your app.

Listing 2-8.  voice_trigger_start.xml

<?xml version="1.0" encoding="utf-8"?>
 
<trigger keyword="@string/say_glasswaretemplate" >
</trigger>

AndroidManifest.xml

This file describes essential information about an Android app. Listing 2-9 specifies a minimum SDK version and target SDK version, activities, and the service defined in the app. The service is the starting point of the app. The com.google.android.glass.action.VOICE_TRIGGER action and com.google.android.glass.VoiceTrigger metadata name are unique for each Glass app, allowing you to launch your app using a voice command, as defined in Listing 2-7 and Listing 2-8.

Listing 2-9.  AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android "
    package="com.morkout.glasswaretemplate"
    android:versionCode="5"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />
 
        <uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
          
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_app"
        android:label="@string/app_name" >
        <activity
            android:name="com.morkout.glasswaretemplate.MenuActivity"
            android:enabled="true"
            android:label="@string/app_name" >
        </activity>
 
        <service
            android:name="com.morkout.glasswaretemplate.AppService"
            android:enabled="true"
            android:exported="true"
            android:icon="@drawable/ic_app"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
 
            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger_start" />
        </service>
    </application>
 
</manifest>

If you don’t understand some of the concepts or code here, don’t worry. In the coming chapters, you’ll see a lot of examples on every Glass UI and development topic and get comfortable with Glass development quickly. What’s important, now that you have reached this point, is that you’re well prepared for exploring all kinds of Glass development topics.

Summary

In this chapter, I first covered the detailed steps of how to set up your GDK Glassware development environments, whether your favorite is Mac, Windows, or Linux. Then I discussed how to set up Glass to get it ready for development and how to run sample GDK apps on it. Finally, I introduced the generic template Glassware, which you’ll use to create new GDK apps, and I showed a step-by-step tutorial of building HelloGlass, your first GDK app, with nice features such as menu actions. I also presented the TTS and ASR versions of HelloGlass. All the code has been updated and tested for the Glass XE 16 and 17 with the Glassware Development Kit Preview, released on April 15, 2014, based on Android 4.4.2 (API Level 19).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.115.237