SlideShare a Scribd company logo
The Glass Class: Mirror API
July 7th – 11th 2014
Mark Billinghurst, Gun Lee
HIT Lab NZ
University of Canterbury
An Introduction to
Glassware Development
Mirror API
using Java Servlet
Gun Lee
* Images in the slides are from variety of sources,
including http://developer.android.com and http://developers.google.com/glass
Glassware Development
 Mirror API
 Server programming, online/web application
 Static cards / timeline management
 GDK
 Android programming, Java (+ C/C++)
 Live cards & Immersions
 https://developers.google.com/glass/
Mirror API
 REST API
 Java servlet, PHP, Go,
Python, Ruby, .NET
 Timeline based apps
 Static cards
- Text, HTML, media attachment (image & video)
- Standard and custom menu items
 Manage timeline
- Subscribe to timeline notifications
- Sharing with contacts
- Location based services
https://developers.google.com/glass/develop/mirror/index
Mirror API based Web App
3. Insert a static card
User sees the card
Glassware Web app
https://developers.google.com/glass/develop/mirror/stories
Develop with Mirror API
 Prepare a web server
 https callback required for OAuth 2.0
 Minimum storage for credentials
 Create a Google APIs Console project
 Enable Mirror API and get Client ID & secret
 Create a web application
 Java servlet, PHP, Go, Python, Ruby, .NET
 Implement OAuth 2.0 authorization
 Use Mirror API to make REST API calls
- Wrapper classes/methods provided
Google App Engine
 Free web server space!
 You can skip this step if you have another server
 Upgrade to paid service based on storage and traffic
needed
 https://developers.google.com/appengine/
 Python, Java, PHP, Go
 Cloud Storage
 Easy integration with Google APIs
Google APIs Console
 http://console.developers.google.com
 Login with your own Google account
 Create a New Project
 The Project ID becomes your URL
- http://your-project-id.appspot.com
Google APIs Console
 In the project’s APIs & auth section,
enable Google Mirror API
Google APIs Console
 APIs & auth > Credentials > OAuth: Create
New Client ID
 Choose "Web Application"
 Type in your website and OAuth callback
address
 https://your-app-id.appspot.com
 https://your-app-id.appspot.com/oauth2callback
Google APIs Console
 Note both Client ID and Client secret
Google APIs Console
 APIs & auth > Consent screen
 Fill in the Product Name and Homepage URL
 This information is shown when users
authorizing your web app
Live Demo
- Setup Google App Engine
- Setup Google APIs Console
Dev. Env. Setup
 ADT Bundle (Eclipse + Andriod SDK)
 http://developer.android.com/sdk/index.html
 GAE plugin for Eclipse
 http://dl.google.com/eclipse/plugin/4.2
- Google App Engine Tools for Android
- Google Plugin for Eclipse
- SDK > Google App Engine Java SDK
 Sign in on Eclipse GAE plugin
 Use the Google account that will host your
web app on GAE
Create a Web App for GAE
 File > New > (Other > Google > )
Web Application Project
 Fill in the Project name and Java package
namespace to use
 Check on option Use Google App Engine
 Uncheck option Use Google Web Toolkit
 Select option Use App Id then click Browse
button to choose your app id
 Check on Generate project sample code
 Click Finish
Anatomy of a Web App Project
 Web App Project
 src (source folder)
- Java classes organized in namespaces
 war (web application archive)
- WEB-INF (settings and JAR libraries)
• appengine-web.xml
• web.xml
• lib
- index.html
- favicon.ico
Deploying to GAE
 Right click on the Project
 Google > Deploy to App Engine
 Uncheck option Launch app in browser ...
 Click Deploy
 Open your GAE site on a browser
 http://your-app-id.appspot.com
Live Demo
- Creating a new Web App project
- Anatomy of a Web App project
- Deploy to GAE
Adding Mirror API library
 Right click on the Project
 Google > Add Google APIs
 Choose Google Mirror API
 Click Finish
Authorization with OAuth 2.0
 Authorizing your web app to access timeline on user’s
Google account
Programming Google Glass - The Mirror API by Eric Redmond
http://pragprog.com/book/erpgg/programming-google-glass
Authorization with OAuth 2.0
 Enable HTTP sessions on GAE
 Force https access only
 Filter out inappropriate access
 Implement OAuth 2.0 callback servlets
 Code from Quick Start sample project
- https://developers.google.com/glass/develop/mirror
/quickstart/index
 Add a new servlet to logout
https://developers.google.com/glass/develop/mirror/authorization
Enable sessions on GAE
 war/WEB-INF/appengine-web.xml
<appengine-web-app ...>
...
<sessions-enabled>true</sessions-enabled>
</appengine-web-app>
Force https access only
 war/WEB-INF/web.xml
<web-app ...>
...
<!-- force https only -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
...
</web-app>
Define Auth Filters
 war/WEB-INF/web.xml
<web-app ...>
...
<!-- filters -->
<filter>
<filter-name>authFilter</filter-name>
<filter-class>com.google.glassware.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>authFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
<filter>
<filter-name>reauthFilter</filter-name>
<filter-class>com.google.glassware.ReauthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>reauthFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
</web-app>
Define Auth Servlet
 war/WEB-INF/web.xml
<webapp ...>
…
<servlet>
<servlet-name>oauth2callback</servlet-name>
<servlet-class>com.google.glassware.AuthServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>oauth2callback</servlet-name>
<url-pattern>/oauth2callback</url-pattern>
</servlet-mapping>
...
</webapp>
Add Java classes for Auth
 Create com.google.glassware package in
the src folder
 Right click on src folder > New > Package
 Copy Java classes for Auth
 Drag and drop the following .java files into the
created package
 AuthFilter.java, AuthServlet.java,
AuthSettings.java, AuthUtil.java,
ReauthFilter.java, WebUtil.java
Add Java classes for Auth
 In AuthSettings.java
 Fill in your CLIENT_ID and CLIENT_SECRET
strings you’ve noted from Google APIs
Console’s credential section
public static String CLIENT_ID =
"567615950876-14k9b9sggrtpulhu9s72le4vsejjscak.apps.googleusercontent.com";
public static String CLIENT_SECRET = "lo9hajhpQFneXP5K8YR0gEVK";
Add a New Servlet for Logout
 Add LogoutServlet class
 Right click on your app package in src folder
 New > Class
 Name: LogoutServlet
 Superclass: javax.servlet.http.HttpServlet
Add a New Servlet for Logout
 Implement LogoutServlet class
 Open LogoutServlet.java
 Source > Override/Implement Methods ...
 Check on doGet(…) the click OK
 Call AuthUtil.clearUserId(req) in the method
// log out
AuthUtil.clearUserId(req);
// print out results on the web browser
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().println(
"<html><head><meta http-equiv="refresh" content="3;url=/index.html"></head> " +
"<body>Good bye!<br></body></html>" );
Add a New Servlet for Logout
 Add servelt tag to war/WEB-INF/web.xml
<webapp ...>
…
<servlet>
<servlet-name>Logout</servlet-name>
<servlet-class>org.hitlabnz.hw.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
...
</webapp>
Add a New Servlet for Logout
 Add a link to the LogoutServlet in
index.html
<a href="logout">Logout</a>
Live Demo
- Enable HTTP sessions on GAE
- Filter out inappropriate access
- Implement OAuth 2.0 callback
- Add logout servlet
Get Access to Mirror API
 In HelloWorldServlet class
 Add method getMirror(req)
private Mirror getMirror(HttpServletRequest req) throws IOException {
// get credential
Credential credential = AuthUtil.getCredential(req);
// build access to Mirror API
return new Mirror.Builder( new UrlFetchTransport(),
new JacksonFactory(), credential)
.setApplicationName("Hello Glass!")
.build();
}
Insert a Card to Timeline
 In HelloWorldServlet class
 Add code in doGet(...) method
// get access to Mirror API
Mirror mirror = getMirror(req);
// get access to the timeline
Timeline timeline = mirror.timeline();
// create a timeline item (card)
TimelineItem timelineItem = new TimelineItem()
.setText( "Hello World!" )
.setDisplayTime(new DateTime(new Date()))
.setNotification(new NotificationConfig().setLevel("DEFAULT"));
// insert the card into the timeline
timeline.insert(timelineItem).execute();
Insert a Card to Timeline
 In HelloWorldServlet class
 Modify code in doGet(...) method for richer
response on the web browser
// print out results on the web browser
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().println(
"<html><head>“ +
"<meta http-equiv="refresh"content="3;url=/index.html">" +
"</head> " +
"<body>A card is inserted to your timeline.<br></body></html>" );
Live Demo
- Access to Mirror API
- Insert a Card into Timeline
HTML in a Card
 Follows CSS for the Glass UI
 https://mirror-api-playground.appspot.com/assets/css/base_style.css
String html = "<article><section><p class="text-auto-size">" +
"<em class="yellow">Hello World!</em><br>" +
"Welcome to the <strong class="blue">Glass Class</strong> at HIT Lab NZ." +
"</p></section></article>";
timelineItem.setHtml(html);
Google Mirror API Playground
 https://developers.google.com/glass/tools-
downloads/playground
 To try it with your Glass
 Go to Google API console
- https://console.developers.google.com
- Login and open your project
 Create a new Client ID with the following URL
- https://mirror-api-playground.appspot.com
 Use the generated Client ID to authorize
access on the Playground site
Multiple Pages in a Card
 Auto paginate
 Manually paginate
 Multiple articles
<article class="auto-paginate">
Very long article ...
</article>
<article class="cover-only">
<section>
<p class="text-auto-size">This is the cover
page.</p>
</section>
</article>
<article>
<section>
This is second page.
</section>
</article>
<article>
<section>
Third page.
</section></article>
https://developers.google.com/glass/develop/mirror/timeline
Grouping Multiple Cards
 Bundle – a set of cards grouped under a
cover card (or the latest card)
timelineItem.setBundleId( “UniqueBundleID” )
timelineItem.setIsBundleCover( true );
https://developers.google.com/glass/develop/mirror/timeline
Built-in Actions with Menu
 READ_ALOUD, DELETE, OPEN_URI, PLAY_VIDEO,
TOGGLE_PINNED, VOICE_CALL, NAVIGATE, REPLY,
SHARE
List<MenuItem> menuItemList = new ArrayList<MenuItem>();
menuItemList.add(new MenuItem().setAction("READ_ALOUD"));
timelineItem.setSpeakableText("Hello World!");
menuItemList.add(new MenuItem().setAction("TOGGLE_PINNED"));
menuItemList.add(new MenuItem().setAction("DELETE"));
timelineItem.setMenuItems(menuItemList);
https://developers.google.com/glass/develop/mirror/static-cards#creating_menu_items
Live Demo
- Cards with HTML
- Add Menu Items
Say hello to me
 Add web form in index.html
 Override doPost(...) method and get
parameter from the request
<form action="helloworld" method="post">
Hello <input type="text" name="custom_name" value="World"> !
<input type="submit" value="Submit">
</form>
String custom_name = req.getParameter("custom_name");
String message = "Hello " + custom_name = "!";
Image attachment
 Adding static resources to the server
 Edit war/WEB-INF/web.xml
 Add a folder named static under the war
folder and add image files in it
<web-app ...>
...
<static-files>
<include path="/static/*" />
</static-files>
...
</web-app>
Image attachment
 Attached image will be used as the
background of the card
 In low-level HTTP Multipart attachment
// get an image to use with the card
URL url = new URL("http://hello-world-mirror.appspot.com/static/hitlabnz.jpg");
InputStreamContent attachment =
new InputStreamContent("image/jpeg", url.openStream());
// insert the card into the timeline
timeline.insert(timelineItem, attachment).execute();
https://developers.google.com/glass/develop/mirror/static-cards#inserting_a_timeline_item_with_media
Live Demo
- Input from web forms
- Image attachment
Managing Timeline Items
 List
 Delete
https://developers.google.com/glass/v1/reference/timeline/list
// request for list of the timeline items
Mirror.Timeline.List listRequest = timeline.list();
listRequest.setMaxResults(5L);
TimelineListResponse listResponse = listRequest.execute();
// retrieve results
List<TimelineItem> timelineItemList = listResponse.getItems();
mirror.timeline().delete(deleteItemId).execute();
Update Pinned Timeline Item
 Simulating Live Cards with Mirror API
 Ask the user to pin the item
 Update the item regularly
TimelineItem timelineItem = getSavedTimelineItem();
// If a saved item exists, isn't deleted, and is pinned
if (timelineItem != null
&& !(timelineItem.getIsDeleted() != null && timelineItem.getIsDeleted()) &&
(timelineItem.getIsPinned() != null && timelineItem.getIsPinned()))
{
// update the pinned item
timelineItem.setHtml( new_html );
timeline.update( timelineItem.getId(), timelineItem ).execute();
} else {
// create a new one and save the id for latter use
}
https://developers.google.com/glass/v1/reference/timeline/update#examples
Live Demo
- List Timeline Items
- Delete Timeline Items
Location
 Get latest known location
 Draw maps in your card
Location location = mirror.locations().get("latest").execute();
double latitude = location.getLatitude();
double longitude = location.getLongitude();
https://developers.google.com/glass/develop/mirror/location
<article>
<figure>
<img src="glass://map?w=240&h=360&marker=0;42.369590,-71.107132"
height="360" width="240">
</figure>
<section>
<div class="text-auto-size">
<p>Map shown on the left</p>
</div>
</section>
</article>
Navigate Menu Item
 Set Location to the timeline item and add the
NAVIGATE menu item
...
timelineItem.setLocation(
new Location()
.setLatitude( -43.522087 )
.setLongitude( 172.582823 )
.setAddress("University of Canterbury, Ilam, Christchurch")
.setDisplayName("HIT Lab NZ") );
// add menu items with built-in actions
List<MenuItem> menuItemList = new ArrayList<MenuItem>();
menuItemList.add(new MenuItem().setAction("NAVIGATE"));
timelineItem.setMenuItems(menuItemList);
// insert the card to the timeline
timeline.insert(timelineItem).execute();
Live Demo
- Locate My Glass
- Add a Navigation Card
Subscriptions
 Mirror API (server) calls back your web app with
notification POST
 Your web app can subscribe to
 Location updates
 Timeline updates
- Share, reply, delete, custom menu item, launch with voice
 Your web app must respond with a 200 OK
HTTP status code if no error occurred.
 If not, Mirror API might resend notifications.
https://developers.google.com/glass/develop/mirror/static-cards#subscriptions
Subscribe
 Add subscription to the mirror api
 Better check if already subscribing
Subscription subscription = new Subscription();
subscription.setCollection("locations"); // or "timeline"
subscription.setCallbackUrl("https://your_web_app/notification");
subscription.setUserToken( AuthUtil.getUserId(req) );
mirror.subscriptions().insert(subscription).execute();
Unsubscribe
 Add subscription to the mirror api
// find subscription to delete
SubscriptionsListResponse subslist_resp =
mirror.subscriptions().list().execute();
List<Subscription> subsclist = subslist_resp.getItems();
String subscription_id_to_delete = null;
for (Subscription subsc : subsclist) {
if (subsc.getId().equals("locations")) { // or “timeline"
subscription_id_to_delete = subsc.getId();
break;
}
}
// delete the subscription
mirror.subscriptions().delete(subscription_id_to_delete).execute();
Handle Notification Callback
 Create a callback Servlet that
 handles notification POST
 responds with a 200 OK HTTP status code
 Make sure your callback Servlet URL is
not filtered in AuthFilter.java
 Use the user ID provided by
notification.getUserToken() to call Mirror
APIs subsequently
Handle Notification Callback
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
// Respond with OK and status 200 to prevent redelivery
resp.setContentType("text/html");
Writer writer = resp.getWriter();
writer.append("OK");
writer.close();
// extract notification object
JsonFactory jsonFactory = new JacksonFactory();
Notification notification =
jsonFactory.fromInputStream(req.getInputStream(), Notification.class);
// Figure out the impacted user and get their credentials for API calls
String userId = notification.getUserToken();
Credential credential = AuthUtil.getCredential(userId);
Mirror mirror = new Mirror.Builder(new UrlFetchTransport(),
new JacksonFactory(), credential)
.setApplicationName("Hello World")
.build();
if (notification.getCollection().equals("locations")) { // or “timeline“
...
Handle Notification Callback
 Handling location updates
 Handling timeline updates
 User action type
- REPLY, DELETE, CUSTOM, LAUNCH, SHARE
// get notified location
Location location = mirror.locations().get(notification.getItemId()).execute();
location.getLatitude();
location.getLongitude();
...
// Get the timeline item which triggered notification
TimelineItem notifiedItem = mirror.timeline().get(notification.getItemId()).execute();
if(notification.getUserActions().contains(new UserAction().setType("REPLY")))
{
String message = "Hello " + notifiedItem.getText() + "!";
...
https://developers.google.com/glass/develop/mirror/subscriptions
Live Demo
- Subscribe to Location Updates
- Subscribe to Timeline Updates:
REPLY
Contact
 LAUNCH and SHARE user actions need
contact of your web app
Contact helloWorldContact = new Contact();
helloWorldContact.setId("org.hitlabnz.helloworld");
helloWorldContact.setDisplayName("Hello World");
ArrayList<String> imageUrlList = new ArrayList<String>();
imageUrlList.add("http://hello-world-mirror.appspot.com/static/hitlabnz.jpg");
helloWorldContact.setImageUrls(imageUrlList);
ArrayList<Command> commandList = new ArrayList<Command>();
commandList.add(new Command().setType("POST_AN_UPDATE")); // TAKE_A_NOTE
helloWorldContact.setAcceptCommands(commandList);
https://developers.google.com/glass/develop/mirror/contacts
https://developers.google.com/glass/develop/mirror/subscriptions
Live Demo
- Subscribe to LAUNCH
DIY
- CUSTOM menu item
- Subscribe to SHARE
https://developers.google.com/glass/develop/mirror/contacts
https://developers.google.com/glass/develop/mirror/subscriptions
More Tips
 Templates
 JSP
 http://freemarker.org
 Scheduled jobs on server
 CRON settings on GAE
 Programming Google Glass - The Mirror API
 By Eric Redmond
 http://pragprog.com/book/erpgg/programming-google-glass
 Quick Start Samples
 https://developers.google.com/glass/develop/mirror/quickstart/in
dex
Sample Code Online
 Mirror-QuickStartSample-Java-GAE
 https://glass-mirror-java-sample.appspot.com
 Mirror0-HelloGlass
 https://hello-glass-mirror.appspot.com
 Mirror1-HelloWorld
 https://hello-world-mirror.appspot.com
More Information
 Website
 https://developers.google.com/glass
 http://arforglass.org
 http://www.hitlabnz.org
 Gun Lee
 gun.lee@hitlabnz.org
 Mark Billinghurst
 mark.billinghurst@hitlabnz.org

More Related Content

What's hot (20)

PPTX
What's new in android jakarta gdg (2015-08-26)
Google
 
PDF
Being Epic: Best Practices for Android Development
Reto Meier
 
PDF
Android development 1july
Edureka!
 
PPTX
MongoDB.local Dallas 2019: MongoDB Stitch Tutorial
MongoDB
 
PDF
Introduction to React for Frontend Developers
Sergio Nakamura
 
PDF
Day In A Life Of A Node.js Developer
Edureka!
 
PPTX
MongoDB.local Seattle 2019: MongoDB Stitch Tutorial
MongoDB
 
PDF
Vaadin 7 CN
jojule
 
PPT
Beginning Native Android Apps
Gil Irizarry
 
PDF
How to enhance Email with Embedded Experiences
IBM Connections Developers
 
PPTX
Android Data Binding
Oswald Campesato
 
PPTX
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
Gil Irizarry
 
PPTX
Mean stack Magics
Aishura Aishu
 
PDF
Introduction to Android Development
Edureka!
 
PDF
Get Ready for Target SDK Version 29 and 30
Somkiat Khitwongwattana
 
PPT
Getting started with android dev and test perspective
Gunjan Kumar
 
PDF
Animation And Testing In AngularJS
Edureka!
 
PPTX
Life After Mobilegeddon: App Deep Linking Strategies - Pubcon October 2015
Suzzicks
 
PDF
How to add your own OpenSocial Gadgets to IBM Connections
IBM Connections Developers
 
PDF
jsf2 Notes
Rajiv Gupta
 
What's new in android jakarta gdg (2015-08-26)
Google
 
Being Epic: Best Practices for Android Development
Reto Meier
 
Android development 1july
Edureka!
 
MongoDB.local Dallas 2019: MongoDB Stitch Tutorial
MongoDB
 
Introduction to React for Frontend Developers
Sergio Nakamura
 
Day In A Life Of A Node.js Developer
Edureka!
 
MongoDB.local Seattle 2019: MongoDB Stitch Tutorial
MongoDB
 
Vaadin 7 CN
jojule
 
Beginning Native Android Apps
Gil Irizarry
 
How to enhance Email with Embedded Experiences
IBM Connections Developers
 
Android Data Binding
Oswald Campesato
 
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
Gil Irizarry
 
Mean stack Magics
Aishura Aishu
 
Introduction to Android Development
Edureka!
 
Get Ready for Target SDK Version 29 and 30
Somkiat Khitwongwattana
 
Getting started with android dev and test perspective
Gunjan Kumar
 
Animation And Testing In AngularJS
Edureka!
 
Life After Mobilegeddon: App Deep Linking Strategies - Pubcon October 2015
Suzzicks
 
How to add your own OpenSocial Gadgets to IBM Connections
IBM Connections Developers
 
jsf2 Notes
Rajiv Gupta
 

Viewers also liked (7)

PPT
Java servlet
philipsinter
 
PDF
JavaScript Objects
Hazem Hagrass
 
PPT
JavaScript Objects
Reem Alattas
 
PDF
Java servlets
Mukesh Tekwani
 
PPT
Java Servlets
BG Java EE Course
 
PPT
Java servlet life cycle - methods ppt
kamal kotecha
 
PPT
Java Servlets
Nitin Pai
 
Java servlet
philipsinter
 
JavaScript Objects
Hazem Hagrass
 
JavaScript Objects
Reem Alattas
 
Java servlets
Mukesh Tekwani
 
Java Servlets
BG Java EE Course
 
Java servlet life cycle - methods ppt
kamal kotecha
 
Java Servlets
Nitin Pai
 
Ad

Similar to The Glass Class - Tutorial 2 - Mirror API (20)

PDF
Introduction to Google App Engine
Kanda Runapongsa Saikaew
 
PPTX
Raspberry pi and Google Cloud
Faisal Mehmood
 
PDF
RICOH THETA x IoT Developers Contest : Cloud API Seminar
contest-theta360
 
PDF
OAuth 2.0
marcwan
 
PDF
The Glass Class - Tutorial1 - Introduction to Glassware Development
Gun Lee
 
PPTX
SSO with Social Login Integration & FastAPI Simplified
techprane
 
PPTX
Google Glasses Integration with SAP
Gh14Cc10
 
PDF
Developing for Google Glass
Mark Billinghurst
 
PDF
Android chat in the cloud
firenze-gtug
 
PDF
Build an AI/ML-driven image archive processing workflow: Image archive, analy...
wesley chun
 
PPT
Developing Java Web Applications In Google App Engine
Tahir Akram
 
PDF
google drive and the google drive sdk
firenze-gtug
 
PDF
Hooking SharePoint APIs with Android
Kris Wagner
 
PPTX
Goa tutorial
Bruce McPherson
 
PPTX
Selenium Automation in Java Using HttpWatch Plug-in
Sandeep Tol
 
PDF
Workshop: Building Vaadin add-ons
Sami Ekblad
 
PDF
Cross-Platform Authentication with Google+ Sign-In
Peter Friese
 
PDF
Google App Engine (Introduction)
Praveen Hanchinal
 
PDF
Front End Development for Back End Developers - vJUG24 2017
Matt Raible
 
PDF
CCICI CIP 1.0 Testbed - Security access implementation and reference - v1.0
Krishna-Kumar
 
Introduction to Google App Engine
Kanda Runapongsa Saikaew
 
Raspberry pi and Google Cloud
Faisal Mehmood
 
RICOH THETA x IoT Developers Contest : Cloud API Seminar
contest-theta360
 
OAuth 2.0
marcwan
 
The Glass Class - Tutorial1 - Introduction to Glassware Development
Gun Lee
 
SSO with Social Login Integration & FastAPI Simplified
techprane
 
Google Glasses Integration with SAP
Gh14Cc10
 
Developing for Google Glass
Mark Billinghurst
 
Android chat in the cloud
firenze-gtug
 
Build an AI/ML-driven image archive processing workflow: Image archive, analy...
wesley chun
 
Developing Java Web Applications In Google App Engine
Tahir Akram
 
google drive and the google drive sdk
firenze-gtug
 
Hooking SharePoint APIs with Android
Kris Wagner
 
Goa tutorial
Bruce McPherson
 
Selenium Automation in Java Using HttpWatch Plug-in
Sandeep Tol
 
Workshop: Building Vaadin add-ons
Sami Ekblad
 
Cross-Platform Authentication with Google+ Sign-In
Peter Friese
 
Google App Engine (Introduction)
Praveen Hanchinal
 
Front End Development for Back End Developers - vJUG24 2017
Matt Raible
 
CCICI CIP 1.0 Testbed - Security access implementation and reference - v1.0
Krishna-Kumar
 
Ad

Recently uploaded (20)

PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PDF
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
PDF
Biography of Daniel Podor.pdf
Daniel Podor
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
Presentation - Vibe Coding The Future of Tech
yanuarsinggih1
 
PDF
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PDF
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
Biography of Daniel Podor.pdf
Daniel Podor
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
Presentation - Vibe Coding The Future of Tech
yanuarsinggih1
 
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 

The Glass Class - Tutorial 2 - Mirror API

  • 1. The Glass Class: Mirror API July 7th – 11th 2014 Mark Billinghurst, Gun Lee HIT Lab NZ University of Canterbury
  • 2. An Introduction to Glassware Development Mirror API using Java Servlet Gun Lee * Images in the slides are from variety of sources, including http://developer.android.com and http://developers.google.com/glass
  • 3. Glassware Development  Mirror API  Server programming, online/web application  Static cards / timeline management  GDK  Android programming, Java (+ C/C++)  Live cards & Immersions  https://developers.google.com/glass/
  • 4. Mirror API  REST API  Java servlet, PHP, Go, Python, Ruby, .NET  Timeline based apps  Static cards - Text, HTML, media attachment (image & video) - Standard and custom menu items  Manage timeline - Subscribe to timeline notifications - Sharing with contacts - Location based services https://developers.google.com/glass/develop/mirror/index
  • 5. Mirror API based Web App 3. Insert a static card User sees the card Glassware Web app https://developers.google.com/glass/develop/mirror/stories
  • 6. Develop with Mirror API  Prepare a web server  https callback required for OAuth 2.0  Minimum storage for credentials  Create a Google APIs Console project  Enable Mirror API and get Client ID & secret  Create a web application  Java servlet, PHP, Go, Python, Ruby, .NET  Implement OAuth 2.0 authorization  Use Mirror API to make REST API calls - Wrapper classes/methods provided
  • 7. Google App Engine  Free web server space!  You can skip this step if you have another server  Upgrade to paid service based on storage and traffic needed  https://developers.google.com/appengine/  Python, Java, PHP, Go  Cloud Storage  Easy integration with Google APIs
  • 8. Google APIs Console  http://console.developers.google.com  Login with your own Google account  Create a New Project  The Project ID becomes your URL - http://your-project-id.appspot.com
  • 9. Google APIs Console  In the project’s APIs & auth section, enable Google Mirror API
  • 10. Google APIs Console  APIs & auth > Credentials > OAuth: Create New Client ID  Choose "Web Application"  Type in your website and OAuth callback address  https://your-app-id.appspot.com  https://your-app-id.appspot.com/oauth2callback
  • 11. Google APIs Console  Note both Client ID and Client secret
  • 12. Google APIs Console  APIs & auth > Consent screen  Fill in the Product Name and Homepage URL  This information is shown when users authorizing your web app
  • 13. Live Demo - Setup Google App Engine - Setup Google APIs Console
  • 14. Dev. Env. Setup  ADT Bundle (Eclipse + Andriod SDK)  http://developer.android.com/sdk/index.html  GAE plugin for Eclipse  http://dl.google.com/eclipse/plugin/4.2 - Google App Engine Tools for Android - Google Plugin for Eclipse - SDK > Google App Engine Java SDK  Sign in on Eclipse GAE plugin  Use the Google account that will host your web app on GAE
  • 15. Create a Web App for GAE  File > New > (Other > Google > ) Web Application Project  Fill in the Project name and Java package namespace to use  Check on option Use Google App Engine  Uncheck option Use Google Web Toolkit  Select option Use App Id then click Browse button to choose your app id  Check on Generate project sample code  Click Finish
  • 16. Anatomy of a Web App Project  Web App Project  src (source folder) - Java classes organized in namespaces  war (web application archive) - WEB-INF (settings and JAR libraries) • appengine-web.xml • web.xml • lib - index.html - favicon.ico
  • 17. Deploying to GAE  Right click on the Project  Google > Deploy to App Engine  Uncheck option Launch app in browser ...  Click Deploy  Open your GAE site on a browser  http://your-app-id.appspot.com
  • 18. Live Demo - Creating a new Web App project - Anatomy of a Web App project - Deploy to GAE
  • 19. Adding Mirror API library  Right click on the Project  Google > Add Google APIs  Choose Google Mirror API  Click Finish
  • 20. Authorization with OAuth 2.0  Authorizing your web app to access timeline on user’s Google account Programming Google Glass - The Mirror API by Eric Redmond http://pragprog.com/book/erpgg/programming-google-glass
  • 21. Authorization with OAuth 2.0  Enable HTTP sessions on GAE  Force https access only  Filter out inappropriate access  Implement OAuth 2.0 callback servlets  Code from Quick Start sample project - https://developers.google.com/glass/develop/mirror /quickstart/index  Add a new servlet to logout https://developers.google.com/glass/develop/mirror/authorization
  • 22. Enable sessions on GAE  war/WEB-INF/appengine-web.xml <appengine-web-app ...> ... <sessions-enabled>true</sessions-enabled> </appengine-web-app>
  • 23. Force https access only  war/WEB-INF/web.xml <web-app ...> ... <!-- force https only --> <security-constraint> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> ... </web-app>
  • 24. Define Auth Filters  war/WEB-INF/web.xml <web-app ...> ... <!-- filters --> <filter> <filter-name>authFilter</filter-name> <filter-class>com.google.glassware.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> <filter> <filter-name>reauthFilter</filter-name> <filter-class>com.google.glassware.ReauthFilter</filter-class> </filter> <filter-mapping> <filter-name>reauthFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> </web-app>
  • 25. Define Auth Servlet  war/WEB-INF/web.xml <webapp ...> … <servlet> <servlet-name>oauth2callback</servlet-name> <servlet-class>com.google.glassware.AuthServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>oauth2callback</servlet-name> <url-pattern>/oauth2callback</url-pattern> </servlet-mapping> ... </webapp>
  • 26. Add Java classes for Auth  Create com.google.glassware package in the src folder  Right click on src folder > New > Package  Copy Java classes for Auth  Drag and drop the following .java files into the created package  AuthFilter.java, AuthServlet.java, AuthSettings.java, AuthUtil.java, ReauthFilter.java, WebUtil.java
  • 27. Add Java classes for Auth  In AuthSettings.java  Fill in your CLIENT_ID and CLIENT_SECRET strings you’ve noted from Google APIs Console’s credential section public static String CLIENT_ID = "567615950876-14k9b9sggrtpulhu9s72le4vsejjscak.apps.googleusercontent.com"; public static String CLIENT_SECRET = "lo9hajhpQFneXP5K8YR0gEVK";
  • 28. Add a New Servlet for Logout  Add LogoutServlet class  Right click on your app package in src folder  New > Class  Name: LogoutServlet  Superclass: javax.servlet.http.HttpServlet
  • 29. Add a New Servlet for Logout  Implement LogoutServlet class  Open LogoutServlet.java  Source > Override/Implement Methods ...  Check on doGet(…) the click OK  Call AuthUtil.clearUserId(req) in the method // log out AuthUtil.clearUserId(req); // print out results on the web browser resp.setContentType("text/html; charset=utf-8"); resp.getWriter().println( "<html><head><meta http-equiv="refresh" content="3;url=/index.html"></head> " + "<body>Good bye!<br></body></html>" );
  • 30. Add a New Servlet for Logout  Add servelt tag to war/WEB-INF/web.xml <webapp ...> … <servlet> <servlet-name>Logout</servlet-name> <servlet-class>org.hitlabnz.hw.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Logout</servlet-name> <url-pattern>/logout</url-pattern> </servlet-mapping> ... </webapp>
  • 31. Add a New Servlet for Logout  Add a link to the LogoutServlet in index.html <a href="logout">Logout</a>
  • 32. Live Demo - Enable HTTP sessions on GAE - Filter out inappropriate access - Implement OAuth 2.0 callback - Add logout servlet
  • 33. Get Access to Mirror API  In HelloWorldServlet class  Add method getMirror(req) private Mirror getMirror(HttpServletRequest req) throws IOException { // get credential Credential credential = AuthUtil.getCredential(req); // build access to Mirror API return new Mirror.Builder( new UrlFetchTransport(), new JacksonFactory(), credential) .setApplicationName("Hello Glass!") .build(); }
  • 34. Insert a Card to Timeline  In HelloWorldServlet class  Add code in doGet(...) method // get access to Mirror API Mirror mirror = getMirror(req); // get access to the timeline Timeline timeline = mirror.timeline(); // create a timeline item (card) TimelineItem timelineItem = new TimelineItem() .setText( "Hello World!" ) .setDisplayTime(new DateTime(new Date())) .setNotification(new NotificationConfig().setLevel("DEFAULT")); // insert the card into the timeline timeline.insert(timelineItem).execute();
  • 35. Insert a Card to Timeline  In HelloWorldServlet class  Modify code in doGet(...) method for richer response on the web browser // print out results on the web browser resp.setContentType("text/html; charset=utf-8"); resp.getWriter().println( "<html><head>“ + "<meta http-equiv="refresh"content="3;url=/index.html">" + "</head> " + "<body>A card is inserted to your timeline.<br></body></html>" );
  • 36. Live Demo - Access to Mirror API - Insert a Card into Timeline
  • 37. HTML in a Card  Follows CSS for the Glass UI  https://mirror-api-playground.appspot.com/assets/css/base_style.css String html = "<article><section><p class="text-auto-size">" + "<em class="yellow">Hello World!</em><br>" + "Welcome to the <strong class="blue">Glass Class</strong> at HIT Lab NZ." + "</p></section></article>"; timelineItem.setHtml(html);
  • 38. Google Mirror API Playground  https://developers.google.com/glass/tools- downloads/playground  To try it with your Glass  Go to Google API console - https://console.developers.google.com - Login and open your project  Create a new Client ID with the following URL - https://mirror-api-playground.appspot.com  Use the generated Client ID to authorize access on the Playground site
  • 39. Multiple Pages in a Card  Auto paginate  Manually paginate  Multiple articles <article class="auto-paginate"> Very long article ... </article> <article class="cover-only"> <section> <p class="text-auto-size">This is the cover page.</p> </section> </article> <article> <section> This is second page. </section> </article> <article> <section> Third page. </section></article> https://developers.google.com/glass/develop/mirror/timeline
  • 40. Grouping Multiple Cards  Bundle – a set of cards grouped under a cover card (or the latest card) timelineItem.setBundleId( “UniqueBundleID” ) timelineItem.setIsBundleCover( true ); https://developers.google.com/glass/develop/mirror/timeline
  • 41. Built-in Actions with Menu  READ_ALOUD, DELETE, OPEN_URI, PLAY_VIDEO, TOGGLE_PINNED, VOICE_CALL, NAVIGATE, REPLY, SHARE List<MenuItem> menuItemList = new ArrayList<MenuItem>(); menuItemList.add(new MenuItem().setAction("READ_ALOUD")); timelineItem.setSpeakableText("Hello World!"); menuItemList.add(new MenuItem().setAction("TOGGLE_PINNED")); menuItemList.add(new MenuItem().setAction("DELETE")); timelineItem.setMenuItems(menuItemList); https://developers.google.com/glass/develop/mirror/static-cards#creating_menu_items
  • 42. Live Demo - Cards with HTML - Add Menu Items
  • 43. Say hello to me  Add web form in index.html  Override doPost(...) method and get parameter from the request <form action="helloworld" method="post"> Hello <input type="text" name="custom_name" value="World"> ! <input type="submit" value="Submit"> </form> String custom_name = req.getParameter("custom_name"); String message = "Hello " + custom_name = "!";
  • 44. Image attachment  Adding static resources to the server  Edit war/WEB-INF/web.xml  Add a folder named static under the war folder and add image files in it <web-app ...> ... <static-files> <include path="/static/*" /> </static-files> ... </web-app>
  • 45. Image attachment  Attached image will be used as the background of the card  In low-level HTTP Multipart attachment // get an image to use with the card URL url = new URL("http://hello-world-mirror.appspot.com/static/hitlabnz.jpg"); InputStreamContent attachment = new InputStreamContent("image/jpeg", url.openStream()); // insert the card into the timeline timeline.insert(timelineItem, attachment).execute(); https://developers.google.com/glass/develop/mirror/static-cards#inserting_a_timeline_item_with_media
  • 46. Live Demo - Input from web forms - Image attachment
  • 47. Managing Timeline Items  List  Delete https://developers.google.com/glass/v1/reference/timeline/list // request for list of the timeline items Mirror.Timeline.List listRequest = timeline.list(); listRequest.setMaxResults(5L); TimelineListResponse listResponse = listRequest.execute(); // retrieve results List<TimelineItem> timelineItemList = listResponse.getItems(); mirror.timeline().delete(deleteItemId).execute();
  • 48. Update Pinned Timeline Item  Simulating Live Cards with Mirror API  Ask the user to pin the item  Update the item regularly TimelineItem timelineItem = getSavedTimelineItem(); // If a saved item exists, isn't deleted, and is pinned if (timelineItem != null && !(timelineItem.getIsDeleted() != null && timelineItem.getIsDeleted()) && (timelineItem.getIsPinned() != null && timelineItem.getIsPinned())) { // update the pinned item timelineItem.setHtml( new_html ); timeline.update( timelineItem.getId(), timelineItem ).execute(); } else { // create a new one and save the id for latter use } https://developers.google.com/glass/v1/reference/timeline/update#examples
  • 49. Live Demo - List Timeline Items - Delete Timeline Items
  • 50. Location  Get latest known location  Draw maps in your card Location location = mirror.locations().get("latest").execute(); double latitude = location.getLatitude(); double longitude = location.getLongitude(); https://developers.google.com/glass/develop/mirror/location <article> <figure> <img src="glass://map?w=240&h=360&marker=0;42.369590,-71.107132" height="360" width="240"> </figure> <section> <div class="text-auto-size"> <p>Map shown on the left</p> </div> </section> </article>
  • 51. Navigate Menu Item  Set Location to the timeline item and add the NAVIGATE menu item ... timelineItem.setLocation( new Location() .setLatitude( -43.522087 ) .setLongitude( 172.582823 ) .setAddress("University of Canterbury, Ilam, Christchurch") .setDisplayName("HIT Lab NZ") ); // add menu items with built-in actions List<MenuItem> menuItemList = new ArrayList<MenuItem>(); menuItemList.add(new MenuItem().setAction("NAVIGATE")); timelineItem.setMenuItems(menuItemList); // insert the card to the timeline timeline.insert(timelineItem).execute();
  • 52. Live Demo - Locate My Glass - Add a Navigation Card
  • 53. Subscriptions  Mirror API (server) calls back your web app with notification POST  Your web app can subscribe to  Location updates  Timeline updates - Share, reply, delete, custom menu item, launch with voice  Your web app must respond with a 200 OK HTTP status code if no error occurred.  If not, Mirror API might resend notifications. https://developers.google.com/glass/develop/mirror/static-cards#subscriptions
  • 54. Subscribe  Add subscription to the mirror api  Better check if already subscribing Subscription subscription = new Subscription(); subscription.setCollection("locations"); // or "timeline" subscription.setCallbackUrl("https://your_web_app/notification"); subscription.setUserToken( AuthUtil.getUserId(req) ); mirror.subscriptions().insert(subscription).execute();
  • 55. Unsubscribe  Add subscription to the mirror api // find subscription to delete SubscriptionsListResponse subslist_resp = mirror.subscriptions().list().execute(); List<Subscription> subsclist = subslist_resp.getItems(); String subscription_id_to_delete = null; for (Subscription subsc : subsclist) { if (subsc.getId().equals("locations")) { // or “timeline" subscription_id_to_delete = subsc.getId(); break; } } // delete the subscription mirror.subscriptions().delete(subscription_id_to_delete).execute();
  • 56. Handle Notification Callback  Create a callback Servlet that  handles notification POST  responds with a 200 OK HTTP status code  Make sure your callback Servlet URL is not filtered in AuthFilter.java  Use the user ID provided by notification.getUserToken() to call Mirror APIs subsequently
  • 57. Handle Notification Callback protected void doPost(HttpServletRequest req, HttpServletResponse resp) { // Respond with OK and status 200 to prevent redelivery resp.setContentType("text/html"); Writer writer = resp.getWriter(); writer.append("OK"); writer.close(); // extract notification object JsonFactory jsonFactory = new JacksonFactory(); Notification notification = jsonFactory.fromInputStream(req.getInputStream(), Notification.class); // Figure out the impacted user and get their credentials for API calls String userId = notification.getUserToken(); Credential credential = AuthUtil.getCredential(userId); Mirror mirror = new Mirror.Builder(new UrlFetchTransport(), new JacksonFactory(), credential) .setApplicationName("Hello World") .build(); if (notification.getCollection().equals("locations")) { // or “timeline“ ...
  • 58. Handle Notification Callback  Handling location updates  Handling timeline updates  User action type - REPLY, DELETE, CUSTOM, LAUNCH, SHARE // get notified location Location location = mirror.locations().get(notification.getItemId()).execute(); location.getLatitude(); location.getLongitude(); ... // Get the timeline item which triggered notification TimelineItem notifiedItem = mirror.timeline().get(notification.getItemId()).execute(); if(notification.getUserActions().contains(new UserAction().setType("REPLY"))) { String message = "Hello " + notifiedItem.getText() + "!"; ... https://developers.google.com/glass/develop/mirror/subscriptions
  • 59. Live Demo - Subscribe to Location Updates - Subscribe to Timeline Updates: REPLY
  • 60. Contact  LAUNCH and SHARE user actions need contact of your web app Contact helloWorldContact = new Contact(); helloWorldContact.setId("org.hitlabnz.helloworld"); helloWorldContact.setDisplayName("Hello World"); ArrayList<String> imageUrlList = new ArrayList<String>(); imageUrlList.add("http://hello-world-mirror.appspot.com/static/hitlabnz.jpg"); helloWorldContact.setImageUrls(imageUrlList); ArrayList<Command> commandList = new ArrayList<Command>(); commandList.add(new Command().setType("POST_AN_UPDATE")); // TAKE_A_NOTE helloWorldContact.setAcceptCommands(commandList); https://developers.google.com/glass/develop/mirror/contacts https://developers.google.com/glass/develop/mirror/subscriptions
  • 62. DIY - CUSTOM menu item - Subscribe to SHARE https://developers.google.com/glass/develop/mirror/contacts https://developers.google.com/glass/develop/mirror/subscriptions
  • 63. More Tips  Templates  JSP  http://freemarker.org  Scheduled jobs on server  CRON settings on GAE  Programming Google Glass - The Mirror API  By Eric Redmond  http://pragprog.com/book/erpgg/programming-google-glass  Quick Start Samples  https://developers.google.com/glass/develop/mirror/quickstart/in dex
  • 64. Sample Code Online  Mirror-QuickStartSample-Java-GAE  https://glass-mirror-java-sample.appspot.com  Mirror0-HelloGlass  https://hello-glass-mirror.appspot.com  Mirror1-HelloWorld  https://hello-world-mirror.appspot.com
  • 65. More Information  Website  https://developers.google.com/glass  http://arforglass.org  http://www.hitlabnz.org  Gun Lee  [email protected]  Mark Billinghurst  [email protected]