Slide 1

Slide 1 text

Johnny Sung Developing 2014.08.27 @ Android Taipei

Slide 2

Slide 2 text

Johnny Sung https://fb.com/j796160836 Mobile devices Developer https://plus.google.com/+JohnnySung

Slide 3

Slide 3 text

這是什麼? 好酷喔 這要怎麼⽤用 Ok, Glass Ok, Glass 怎麼沒有螢幕? 你可以幫我測⼀一下戰⾾鬥⼒力嗎? 他有什麼功能? 要怎麼拍照? 要怎麼開? 你怎麼會有 真假 要抬頭啦 抬頭才有螢幕

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

⼀一窺Google 眼鏡 的 內部構造

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

rrr

Slide 9

Slide 9 text

MyGlass 連接 Google Glass

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Timeline (時間軸) https://www.youtube.com/watch?v=jK3WLILYhQs

Slide 12

Slide 12 text

Clock Live Card Static Card

Slide 13

Slide 13 text

Clock Static Card Now Past

Slide 14

Slide 14 text

Clock Live Card Settings

Slide 15

Slide 15 text

Glass development • Mirror API • Glass Development Kit (GDK)

Slide 16

Slide 16 text

Glass development • Mirror API • Periodic notifications & Static Card
 (Push notifications) • Glass Development Kit (GDK) • Ongoing task & Live Card (活動卡⽚片,即時卡⽚片) • Immersion (沉浸式體驗,獨佔式體驗) • Hybrid

Slide 17

Slide 17 text

Periodic notifications (Static Card)

Slide 18

Slide 18 text

Ongoing task (Live Card)

Slide 19

Slide 19 text

Hybrid Model

Slide 20

Slide 20 text

Glass Development Kit (GDK)

Slide 21

Slide 21 text

Glass Development Kit Sneak Peek 4.0.3 (API 15 Glass Development Kit Preview
 4.4.2 (API 19) Glass Development Kit Sneak Peek
 4.0.3 (API 15) Android 4.4.2 KitKat (API 19) Android L

Slide 22

Slide 22 text

= . .

Slide 23

Slide 23 text

等⼀一下,先不要這麼著急... 開新專案 :)

Slide 24

Slide 24 text

因為會變成這副德性

Slide 25

Slide 25 text

What the …

Slide 26

Slide 26 text

Glass development • Glass Development Kit (GDK) • Ongoing task & Live Card (活動卡⽚片,即時卡⽚片) • Low Frequency Rendering • High Frequency Rendering • Immersion (沉浸式體驗,獨佔式體驗)

Slide 27

Slide 27 text

LiveCard

Slide 28

Slide 28 text

Low Frequency Rendering

Slide 29

Slide 29 text

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 (因版⾯面限制,故隱藏省略部分內容)

Slide 30

Slide 30 text

! mLiveCardView.setTextViewText(R.id.sample_text, "Hello, World."); mLiveCard.setViews(mLiveCardView); Update Remote Views http://developer.android.com/reference/android/widget/RemoteViews.html

Slide 31

Slide 31 text

Code Examples http://goo.gl/ceX1QI Referance: https://developers.google.com/glass/develop/gdk/live-cards Low-frequency Livecard Demo

Slide 32

Slide 32 text

High Frequency Rendering

Slide 33

Slide 33 text

@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 (因版⾯面限制,故隱藏省略部分內容)

Slide 34

Slide 34 text

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 (因版⾯面限制,故隱藏省略部分內容)

Slide 35

Slide 35 text

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 (因版⾯面限制,故隱藏省略部分內容)

Slide 36

Slide 36 text

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 (因版⾯面限制,故隱藏省略部分內容)

Slide 37

Slide 37 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 (因版⾯面限制,故隱藏省略部分內容)

Slide 38

Slide 38 text

Code Examples Referance: https://developers.google.com/glass/develop/gdk/live-cards http://goo.gl/6M4gnG HelloGlass

Slide 39

Slide 39 text

Immersion ?

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Voice trigger ok glass, show me a demo

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

Voice trigger • res/xml/voice_trigger_start.xml • res/values/strings.xml ! Hello Glass Activity

Slide 44

Slide 44 text

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 song Pick one you like !

Slide 45

Slide 45 text

Layout

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

Layout

Slide 48

Slide 48 text

Touch input

Slide 49

Slide 49 text

Keypad Swipe down translates to KEYCODE_BACK. A camera button press
 translates to KEYCODE_CAMERA. Tap translates to KEYCODE_DPAD_CENTER.

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

! @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

Slide 52

Slide 52 text

! 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

Slide 53

Slide 53 text

• 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

Slide 54

Slide 54 text

Q & A

Slide 55

Slide 55 text

http://fb.com/groups/glassdev.taiwan Google glass developer Taiwan