Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Developing Google Glass

Developing Google Glass

Developing Google Glass
2014.08.27 @ Android Taipei

Johnny Sung

August 27, 2014
Tweet

More Decks by Johnny Sung

Other Decks in Technology

Transcript

  1. rrr

  2. Glass development • Mirror API • Periodic notifications & Static

    Card
 (Push notifications) • Glass Development Kit (GDK) • Ongoing task & Live Card (活動卡⽚片,即時卡⽚片) • Immersion (沉浸式體驗,獨佔式體驗) • Hybrid
  3. 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
  4. Glass development • Glass Development Kit (GDK) • Ongoing task

    & Live Card (活動卡⽚片,即時卡⽚片) • Low Frequency Rendering • High Frequency Rendering • Immersion (沉浸式體驗,獨佔式體驗)
  5. 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 (因版⾯面限制,故隱藏省略部分內容)
  6. @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 (因版⾯面限制,故隱藏省略部分內容)
  7. 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 (因版⾯面限制,故隱藏省略部分內容)
  8. 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 (因版⾯面限制,故隱藏省略部分內容)
  9. 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 (因版⾯面限制,故隱藏省略部分內容)
  10. @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 (因版⾯面限制,故隱藏省略部分內容)
  11. 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
  12. 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> (因版⾯面限制,故隱藏省略部分內容)
  13. 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>
  14. 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 !
  15. Keypad Swipe down translates to KEYCODE_BACK. A camera button press


    translates to KEYCODE_CAMERA. Tap translates to KEYCODE_DPAD_CENTER.
  16. 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
  17. ! @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
  18. ! 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
  19. • 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