ScouterFM Beta Release

My first native Glassware, ScouterFM, is now available for download. This application allows you to listen to playlists assembled from music made available on SoundCloud. Just say "Okay Glass, listen to" followed by your desired genres (or the keyword likes) and enjoy.

I strived to create a music Glassware with a different asthetic then those that are currently available. All while creating an intuitive and enjoyable experience.

ScouterFM is currently only available as a side-loaded application but I hope to have it in the MyGlass Glassware gallery soon.

Customizing hosts file in Docker

In a project recently I had a need to add an entry to /etc/hosts and being new to Docker I was surprised to find that hosts is read only. Turns out this is a known issue, but I was able to find a work around. Essentially creating a copy of the library that handles hostname resolution and editing it to replace /etc/hosts with the path of a writable hosts file. Sounds daunting but it isn't all that scary, here's the step by step:

  1. Create a writable copy of /etc/hosts somewhere where the path will be the same length. I used /tmp/hosts:

    RUN cp /etc/hosts /tmp/hosts
  2. Then you need to make a copy of that you can edit:

    RUN mkdir -p -- /lib-override && cp /lib/x86_64-linux-gnu/ /lib-override
  3. Now edit the binary to replace /etc/hosts with the path to the writable hosts file (ex. /tmp/hosts):

    RUN perl -pi -e 's:/etc/hosts:/tmp/hosts:g' /lib-override/
  4. Finish up by letting the system know where to find the edited binary:

    ENV LD_LIBRARY_PATH /lib-override

BuildBorg for Glass

I have been excited to write something for Glass ever since I received it and now I am proud to announce my first project. BuildBorg allows developers who wear Glass to receive notifications from their build server directly on their Glass. By adding BuildBorg as a web hook to your build server you will receive timeline cards for successful, failed, and fixed builds. From the BuildBorg settings you can enable/disable any of the notifications, that way if you only care about failed builds that will be the only timeline cards you will receive.

Right now BuildBorg supports CircleCI, Jenkins, Semaphore, TeamCity, and Travis CI. I am open to suggestions and hope to expand the service in the near future.

Google Glass and Windows 8.1

I recently received my Google Glass as a part of the Explorer Program. So what was the first thing I tried to do? Connect to it with adb of course. I was anxious to get started with the GDK but, as is commonly the issue, Windows 8.1 chose to not play nicely. Here are the steps I took to get my installation of Windows 8.1 Pro 64-bit edition to recognize my Google Glass.

  1. Locate the folder containing the Google USB Driver, it will be something similar to this:

    C:\<ADT install location>\sdk\extras\google\usb_driver\
  2. Edit the file named android_winusb.inf and add the following PID and VID for Google Glass to both the [Google.NTamd64] and [Google.NTx86] sections:

    ;Google Glass
    %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E11&REV_0216
    %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E11&MI_01
    %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_9001&REV_0216
    %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_9001&MI_01
  3. Disable Driver Signature Verification, excellent instructions can be found on How-To Geek.

  4. Open Device Manager and locate your Glass device. Right click the device and select Update Driver Software.

  5. Choose "Browse my computer for driver software".

  6. In the prompt labeled "Search for driver software on your computer:" enter the folder containing android_winusb.inf as found in step 1.

  7. A Windows Security dialog will pop up, choose "Install this driver software anyway".

After these steps you should have the drivers install properly. To verify run 'adb devices' and you should see your Glass listed. You can now use adb to sideload applications to you device. You can also use Droid@Screen to mirror the Glass display to your PC.

Google Glass for Rubyist

Disclaimer: I do not have access to the Google Glass Explorer Program. The code in this blog post is purely speculative, it is not production ready.

Google has recently made the developer documentation for it's Google Glass product publicly available. Named the Mirror API, it allows developers to create applications called Glassware that interacts with user's Glass devices via a RESTful interface. Developers authenticate to the API on the users behalf using OAuth v2. Once authorized, Glassware applications can publish timeline notifications to the user's Glass devices and subscribe to receive notifications of actions preformed on the devices.


Since Glassware applications do not get installed directly onto Glass devices the first step to interacting with a user's device is the authorization process. This web based process has the user accessing your site and authenticating with their Google account by way of OAuth v2.

require 'google/api_client'
require 'sinatra'

  # Add other requested scopes.

enable :sessions

def api_client; settings.api_client; end
def mirror_api; settings.mirror_api; end   
def oauth2_api; settings.oauth2_api; end

def store_credentials(user_id, credentials)
  raise NotImplementedError, 'store_credentials not implemented'

def get_stored_credentials(user_id)
  raise NotImplementedError, 'get_stored_credentials not implemented'

def get_user_info
  result = api_client.execute!(api_method: oauth2_api.userinfo.get,
                               authorization: user_credentials)
  user_info = nil
  if result.status == 200
    user_info =
    puts "An error occurred: #{['error']['message']}"

def bootstrap_user
  # TODO: Welcome the user to your Glassware

def user_credentials
  @authorization ||= (
    auth = api_client.authorization.dup
    auth.redirect_uri = to('/oauth2callback')

configure do
  client =
  client.authorization.client_id = CLIENT_ID
  client.authorization.client_secret = CLIENT_SECRET
  client.authorization.scope = SCOPES

  mirror = client.discovered_api('mirror', 'v1')
  oauth2 = client.discovered_api('oauth2', 'v2')

  set :api_client, client
  set :mirror_api, mirror
  set :oauth2_api, oauth2

before do
  unless user_credentials.access_token || request.path_info =~ /^\/oauth2/
    redirect to('/oauth2authorize')

get '/oauth2authorize' do
  redirect user_credentials.authorization_uri.to_s, 303

get '/oauth2callback' do
  user_credentials.code = params[:code] if params[:code]

  user_info = get_user_info
  session[:user_id] =
  store_credentials, user_credentials

  redirect to('/')

get '/' do
  "<h1>Welcome to my Glassware</h1>"

The above Sinatra application authenticates the user and stores their authentication for later use. Storing the user's authentication isn't required but it could prove important as most of the time you will be pushing timeline updates to a user's device when they are away from their computer.

Timeline Cards

Timeline cards allow developers to present information to their users. As timeline cards are added through the API they are presented as a queue the that the user can read through as they wish. You may have notice the # TODO comment in the above example, lets use that method to push a timeline card that welcomes the user to our Glassware application.

def insert_timeline_item(timeline_item, opts)
  if opts[:filename]
    media =[:filename], opts[:content_type])
    result = api_client.execute(
      api_method: mirror_api.timeline.insert,
      body_object: timeline_item,
      media: media,
      parameters: {
        'uploadType' => 'multipart',
        'alt' => 'json'}
      authorization: user_credentials)
    result = api_client.execute(
      api_method: mirror_api.timeline.insert,
      body_object: timeline_item,
      authorization: user_credentials)
  if result.success?
    puts "An error occurred: #{['error']['message']}"

def bootstrap_user
  text = "Welcome to JasonInCode's Mirror API for Rubyist"
  timeline_item ={ 'text' => text })

Now when a user authenticates to the application they receive a timeline card welcoming them. You may have noticed that the insert_timeline_item method has a set of optional parameters. This implementation of insert_timeline_item allows the developer to upload images and other media to a user's timeline.

get '/send_image' do
  text = "Sample image upload"
  timeline_item ={ 'text' => text })
      filename: 'sample.png',
      content_type: 'image/png'

In addition to adding images, audio, and video a developer can also upload a list of actions the user can perform on a timeline card. There are a number of system provided menu items built into Glass devices:

  • REPLY and REPLY_ALL: Initiates a reply to the timeline item using the voice recording UI.
  • DELETE: Deletes the timeline item.
  • SHARE: Allows the Glass user to share the timeline item with their contacts.
  • READ_ALOUD: Tells the device to read the item's speakableText to the user, if that is not set it will read the item's text instead.
  • VOICE_CALL: Calls the phone number in the item's creator.phone_number.
  • NAVIGATE: Starts navigation to the item's location.
  • TOGGLED_PINNED: Toggles the item's isPinned state.

Developers can also provide custom menu items that are specific to the individual Glassware application. The custom menu items can have custom display text and an icon image. Each custom menu item has an id that is returned to the application via the application's registered subscription URL.

get '/item-with-actions' do
  text = "How much wood could a woodchuck chuck?"
  speakableText = "If a woodchuck could chuck wood."
  timeline_item ={
    'text' => text, 'speakableText' => speakableText

  menuItems = []

  menuItems << { 'action' => 'READ_ALOUD' }

  menuItems << {
    'action' => 'CUSTOM',
    'id' => 'id-for-notification',
    'values' => [{
      'displayName' => 'JasonInCode Action',
      'iconUrl' => 'path/to/icon.png'

  timeline_item.menuItems = menuItems


As mentioned above a Glassware application can register to receive a notifications from a user's Glass device. When creating a subscription the developer specifies a URL for Google to send a request to about the user's actions.

def subscribe_to_notification(collection, callback_url)
  subscription ={
    'collection' => collection,
    'userToken' => session[:user_id],
    'callbackUrl' => callback_url

  result = api_client.execute(
    api_method: mirror_api.subscription.insert,
    body_object: subscription,
    authorization: user_credentials)

  if result.success?
    puts "An error occurred: #{['error']['message']}"

def bootstrap_user
  # ...

  subscribe_to_notification('timeline', to('/notify'))

The code above tells Google to let your application know when a user does an UPDATE, INSERT, or DELETE on their timeline. Google will send a POST request to the specified callbackUrl containing a minimal JSON ping that contains the information to retrieve the full information about. It is important to note that Google requires that the callbackUrl be secured via HTTPS.

post '/notify' do
  request = JSON.parse(

  session[:user_id] = request['userToken']

  text = "Got a notification: #{request}"
  timeline_item ={ 'text' => text })

I hope by now you can see the possiblities that Ruby and the Mirror API make available to developers. There are stil topics I didn't touch on such as the Contacts and Location APIs, perhaps in a future post.