Developing Google Glass

Post on 19-Jun-2015

410 views 0 download

description

Developing Google Glass 2014.08.27 @ Android Taipei

Transcript of Developing Google Glass

Johnny Sung

Developing2014.08.27 @ Android Taipei

Johnny Sung

https://fb.com/j796160836

Mobile devices Developer

https://plus.google.com/+JohnnySung

這是什麼?好酷喔

這要怎麼⽤用

Ok, Glass

Ok, Glass

怎麼沒有螢幕?

你可以幫我測⼀一下戰⾾鬥⼒力嗎?

他有什麼功能?

要怎麼拍照?

要怎麼開?

你怎麼會有真假

要抬頭啦

抬頭才有螢幕

⼀一窺Google 眼鏡 的 內部構造

http://www.catwig.com/google-glass-teardown/

rrr

MyGlass 連接 Google Glass

Timeline (時間軸)

https://www.youtube.com/watch?v=jK3WLILYhQs

ClockLive Card Static Card

Clock

Static Card

Now Past

Clock

Live Card

Settings

Glass development

• Mirror API

• Glass Development Kit (GDK)

Glass development• Mirror API

• Periodic notifications & Static Card(Push notifications)

• Glass Development Kit (GDK)

• Ongoing task & Live Card (活動卡⽚片,即時卡⽚片)

• Immersion (沉浸式體驗,獨佔式體驗)

• Hybrid

Periodic notifications (Static Card)

Ongoing task (Live Card)

Hybrid Model

Glass Development Kit (GDK)

Glass Development Kit Sneak Peek4.0.3 (API 15

Glass Development Kit Preview4.4.2 (API 19)

Glass Development Kit Sneak Peek4.0.3 (API 15)

Android 4.4.2 KitKat (API 19)

Android L

=..

等⼀一下,先不要這麼著急...

開新專案 :)

因為會變成這副德性

What the …

Glass development

• Glass Development Kit (GDK)

• Ongoing task & Live Card (活動卡⽚片,即時卡⽚片)

• Low Frequency Rendering

• High Frequency Rendering

• Immersion (沉浸式體驗,獨佔式體驗)

LiveCard

Low Frequency Rendering

public class LiveCardService extends Service {! private LiveCard mLiveCard; private RemoteViews mLiveCardView;! @Override public int onStartCommand(Intent intent, int flags, int startId) { if (mLiveCard == null) { mLiveCard = new LiveCard(this, "LiveCardDemo"); mLiveCardView = new RemoteViews(getPackageName(), R.layout.main_layout); // ... Intent menuIntent = new Intent(this, MenuActivity.class); menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0)); mLiveCard.publish(PublishMode.REVEAL); } return START_STICKY; }! @Override public void onDestroy() { if (mLiveCard != null && mLiveCard.isPublished()) { mLiveCard.unpublish(); mLiveCard = null; } super.onDestroy(); } // ...}

Low-frequency Livecard

AndroidManifest.xml(因版⾯面限制,故隱藏省略部分內容)

!mLiveCardView.setTextViewText(R.id.sample_text, "Hello, World.");mLiveCard.setViews(mLiveCardView);

Update Remote Views

http://developer.android.com/reference/android/widget/RemoteViews.html

Code Examples

http://goo.gl/ceX1QI

Referance: https://developers.google.com/glass/develop/gdk/live-cards

Low-frequency Livecard Demo

High Frequency Rendering

@Override public int onStartCommand(Intent intent, int flags, int startId) { if (mLiveCard == null) { mLiveCard = new LiveCard(this, LIVE_CARD_TAG);! mLiveCard.setDirectRenderingEnabled(true).getSurfaceHolder() .addCallback(mHelloDrawer);! Intent menuIntent = new Intent(this, MenuActivity.class); menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0)); mLiveCard.attach(this); mLiveCard.publish(PublishMode.REVEAL); } else { mLiveCard.navigate(); }! return START_STICKY; } @Override public void onDestroy() { if (mLiveCard != null && mLiveCard.isPublished()) { mLiveCard.unpublish(); } super.onDestroy(); } HelloService.java

onStartCommand() & publish live card

(因版⾯面限制,故隱藏省略部分內容)

public class HelloDrawer implements DirectRenderingCallback {! private SurfaceHolder mHolder;! @Override public void surfaceCreated(SurfaceHolder holder) { mHolder = holder; }! @Override public void surfaceDestroyed(SurfaceHolder holder) { mHolder = null; }! public void draw() { Canvas canvas; try { canvas = mHolder.lockCanvas(); } catch (Exception e) { return; } mHolder.unlockCanvasAndPost(canvas); }! // ...} HelloDrawer.java

SurfaceHolder

(因版⾯面限制,故隱藏省略部分內容)

public HelloDrawer(Context context) { mView = new HelloView(context); mView.setListener(mListener); this.context = 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(); } ! public void draw() { Canvas canvas = mHolder.lockCanvas(); // ... mView.draw(canvas); // ... mHolder.unlockCanvasAndPost(canvas); } HelloDrawer.java

Init HelloView & Drawing

(因版⾯面限制,故隱藏省略部分內容)

public HelloView(Context context, AttributeSet attrs, int style) { super(context, attrs, style);! LayoutInflater.from(context).inflate(R.layout.card_main, this); sampleTextview = (TextView) findViewById(R.id.sample_txt); updateText(); }! protected void updateText() { if (mChangeListener != null) { mChangeListener.onChange(); // call draw() to update view } }! public void changeText(String text) { sampleTextview.setText(text); updateText(); }

HelloView.java

Inflate View & Change text

(因版⾯面限制,故隱藏省略部分內容)

@Override public void surfaceCreated(SurfaceHolder holder) { // ... context.registerReceiver(mBroadcast, new IntentFilter(MY_MESSAGE)); }! @Override public void surfaceDestroyed(SurfaceHolder holder) { // ... context.unregisterReceiver(mBroadcast); }! private BroadcastReceiver mBroadcast = new BroadcastReceiver() { @Override public void onReceive(Context mContext, Intent mIntent) { if (mIntent.getAction().equals("change_text")) { mView.changeText("I'm lovin' it."); } } };

HelloDrawer.java

BroadcastReceiver

(因版⾯面限制,故隱藏省略部分內容)

Code Examples

Referance: https://developers.google.com/glass/develop/gdk/live-cards

http://goo.gl/6M4gnGHelloGlass

Immersion ?

public class HelloActivity extends Activity {! private TextView sampleTextview;! @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.card_main);! sampleTextview = (TextView) findViewById(R.id.sample_txt); } }

As same as android :D

Voice triggerok glass, show me a demo

Voice trigger

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloglass" android:versionCode="1" android:versionName="1.0" >! <uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />! <application> <service android:name=".HelloService" android:icon="@drawable/ic_note" 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>

(因版⾯面限制,故隱藏省略部分內容)

Voice trigger• res/xml/voice_trigger_start.xml

• res/values/strings.xml

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

<?xml version="1.0" encoding="utf-8"?><resources> <string name="glass_voice_trigger">Hello Glass Activity</string></resources>

VoiceTriggers.Command• add an event

• calculate

• call me a car

• capture a panorama

• check me in

• check this out

• control my car

• control my home

• explore nearby

• explore the stars

• find a bike

• find a dentist

• find a doctor

• find a hospital

• find a passage

• find a place

• find a place to stay

• find a product

• find a recipe

• find a video

• find a website

• find reviews

• find the exchange rate

• find the price

• flip a coin

• give me feedback

• help me sign in

• keep me awake

• learn an instrument

• learn a songPick one you like !

Layout

Layout

• https://developers.google.com/glass/develop/gdk/ui-widgets • https://developers.google.com/glass/design/style

• Screen Size: 640 x 320 • Padding: 40 x 40 • Bottom Bar: 560 x 40

Layout

Touch input

Keypad

Swipe down translates to KEYCODE_BACK.

A camera button press translates to KEYCODE_CAMERA.

Tap translates to KEYCODE_DPAD_CENTER.

Keypad @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_CAMERA) { // ... return true; } return false; }

@Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_CAMERA) { // ... return true; } return false; }

@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_CAMERA) { // ... return true; } return false; }

MainActivity.java

! @Override public boolean onGenericMotionEvent(MotionEvent event) { if (mGestureDetector != null) { return mGestureDetector.onMotionEvent(event); } return false; }

! public GestureDetector mGestureDetector;! @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.control_main);! mGestureDetector = createGestureDetector(this); }

GestureDetector

MainActivity.java

! private GestureDetector createGestureDetector(Context context) { GestureDetector gestureDetector = new GestureDetector(context); // Create a base listener for generic gestures gestureDetector.setBaseListener(new GestureDetector.BaseListener() { @Override public boolean onGesture(Gesture gesture) { if (gesture == Gesture.TAP) { Log.v(TAG, "TAP");! return true; } else if (gesture == Gesture.TWO_TAP) { Log.v(TAG, "TWO_TAP");! return true; } return false; } }); return gestureDetector; }

GestureDetector

MainActivity.java

• SWIPE_DOWN

• TWO_SWIPE_DOWN

• SWIPE_LEFT

• TWO_SWIPE_LEFT

• SWIPE_RIGHT

• TWO_SWIPE_RIGHT

• SWIPE_UP

• TWO_SWIPE_UP

Gestures

• TAP

• TWO_TAP

• THREE_TAP

• LONG_PRESS

• TWO_LONG_PRESS

• THREE_LONG_PRESS

Q & A

http://fb.com/groups/glassdev.taiwanGoogle glass developer Taiwan