Contenu connexe Similaire à Developing Google Glass (20) Developing Google Glass16. Glass development
• Mirror API
• Periodic notifications & Static Card
(Push notifications)
• Glass Development Kit (GDK)
• Ongoing task & Live Card (活動卡⽚片,即時卡⽚片)
• Immersion (沉浸式體驗,獨佔式體驗)
• Hybrid
21. 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
26. Glass development
• Glass Development Kit (GDK)
• Ongoing task & Live Card (活動卡⽚片,即時卡⽚片)
• Low Frequency Rendering
• High Frequency Rendering
• Immersion (沉浸式體驗,獨佔式體驗)
29. 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
(因版⾯面限制,故隱藏省略部分內容)
33. @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
(因版⾯面限制,故隱藏省略部分內容)
34. 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
(因版⾯面限制,故隱藏省略部分內容)
35. 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
(因版⾯面限制,故隱藏省略部分內容)
36. 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
(因版⾯面限制,故隱藏省略部分內容)
37. @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
(因版⾯面限制,故隱藏省略部分內容)
40. 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
43. 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>
44. 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 !
49. Keypad
Swipe down translates to KEYCODE_BACK.
A camera button press
translates to KEYCODE_CAMERA.
Tap translates to KEYCODE_DPAD_CENTER.
50. 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
51. !
@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
52. !
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
53. • 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