Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Introduction to Android Wear

4.117 Aufrufe

Veröffentlicht am

In this session, I will give an overview of Android Wear and how to integrate it in your product strategy. We will look at the underlying design principles and discuss a number of use cases for apps that connect to wearable devices. After that, we will take a look at some code examples and learn how to use the Android Wear SDK.

Veröffentlicht in: Geräte & Hardware, Software
  • How we discovered the real reason nice guys don't get laid, and a simple "fix" that allows you to gain the upper hand with a girl... without changing your personality or pretending to be someone you're not. learn more... ♣♣♣ https://tinyurl.com/y52uv4vq
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Unlock Her Legs(Official) $69 | Get 90% Off + 8 Special Bonus?  https://tinyurl.com/y52uv4vq
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Hey guys! Who wants to chat with me? More photos with me here 👉 http://www.bit.ly/katekoxx
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier

Introduction to Android Wear

  1. 1. +Peter Friese @peterfriese #AndroidWear
  2. 2. REAL LIFE GET PHONE LOST IN PHONE
  3. 3. Design Principles
  4. 4. Design Principles • Launched automatically
  5. 5. Design Principles • Launched automatically • Glanceable
  6. 6. Design Principles • Launched automatically • Glanceable • Suggest and Demand
  7. 7. Design Principles • Launched automatically • Glanceable • Suggest and Demand • Zero or low interaction
  8. 8. Developing for Android Wear
  9. 9. Simple Notifications Look, ma - no work required!
  10. 10. Simple Notifications sendNotification() Intent viewIntent = new Intent(context, DummyActivity.class); PendingIntent viewPendingIntent = PendingIntent.getActivity(context, 0, viewIntent, 0); Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.plane) .setContentTitle(String.format("Flight AW123 is ready to board", notificationId)) .setContentText("Please proceed to gate C 17 to board. Have a nice flight!") .setContentIntent(viewPendingIntent) .build(); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.notify(notificationId++, notification);
  11. 11. Can we do better?
  12. 12. Enhanced Notifications BigPictureStyle
  13. 13. BigPictureStyle sendNotification() Intent viewIntent = new Intent(context, DummyActivity.class); PendingIntent viewPendingIntent = PendingIntent.getActivity(context, 0, viewIntent, 0); Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.plane) .setContentTitle(String.format("Flight AW123 is ready to board", notificationId)) .setContentText("Please proceed to gate C 17 to board. Have a nice flight!") .setStyle( new NotificationCompat.BigPictureStyle() .bigPicture(BitmapFactory.decodeResource(context.getResources(), R.drawable.sanfrancisco)) .setBigContentTitle("Flight AW123 is ready to board.") .setSummaryText("Please proceed to gate C 17 to board. Have a nice flight!")) .setContentIntent(viewPendingIntent) .build(); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.notify(notificationId++, notification);
  14. 14. Enhanced Notifications Pages
  15. 15. Pages sendNotification() ArrayList<Notification> pages = new ArrayList<Notification>(); pages.add(new NotificationCompat.Builder(context) .setContentTitle("Your seat") .setContentText("17A") .extend(new NotificationCompat.WearableExtender() .setBackground(BitmapFactory.decodeResource(context.getResources(), R.drawable.a380_seat))) .build());
  16. 16. Background Only Pages sendNotification() pages.add(new NotificationCompat.Builder(context) .extend(new NotificationCompat.WearableExtender() .setHintShowBackgroundOnly(true) .setBackground(BitmapFactory.decodeResource(context.getResources(), R.drawable.qrcode))) .build());
  17. 17. Adding Pages to Notifications sendNotification() Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.plane) .setContentTitle(String.format("Flight AW123 is ready to board", notificationId)) .setContentText("Please proceed to gate C 17 to board. Have a nice flight!") .setContentIntent(viewPendingIntent) .extend(new NotificationCompat.WearableExtender() .addPages(pages)) .build(); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.notify(notificationId++, notification);
  18. 18. Enhanced Notifications Voice Input
  19. 19. Voice Input sendNotification() // Feedback intent Intent replyIntent = new Intent(context, DummyActivity.class); PendingIntent replyPendingIntent = PendingIntent.getActivity(context, 0, replyIntent, 0); String replyLabel = context.getResources().getString(R.string.reply_label); String[] cannedResponses = context.getResources().getStringArray(R.array.canned_responses); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(cannedResponses) .build(); NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder( R.drawable.chatbubble_working, replyLabel, replyPendingIntent) .addRemoteInput(remoteInput) .build();
  20. 20. Sending a Voice Input Notification sendNotification() Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.plane) .setContentTitle(String.format("Flight AW123 is ready to board", notificationId)) .setContentText("Please proceed to gate C 17 to board. Have a nice flight!") .extend(new NotificationCompat.WearableExtender() .addPages(pages) .addAction(replyAction)) .build(); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.notify(notificationId++, notification);
  21. 21. Receiving Voice Input onCreate() Bundle remoteInputResults = RemoteInput.getResultsFromIntent(intent); if (remoteInputResults != null) { CharSequence utterance = remoteInputResults.getCharSequence(Constants.EXTRA_VOICE_REPLY); Toast.makeText(this, utterance, Toast.LENGTH_LONG).show(); }
  22. 22. Enhanced Notifications Actions
  23. 23. Actions sendNotification() Intent mapIntent = new Intent(Intent.ACTION_VIEW); Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode("London Heathrow")); mapIntent.setData(geoUri); PendingIntent mapPendingIntent = PendingIntent.getActivity(context, 0, mapIntent, 0); NotificationCompat.Action walkingDirectionsAction = new NotificationCompat.Action.Builder( R.drawable.ic_full_directions_walking, "Directions to gate", mapPendingIntent) .build(); ! Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_launcher) .setSmallIcon(R.drawable.plane) .setContentTitle(String.format("Flight AW123 is ready to board", notificationId)) .setContentText("Please proceed to gate C 17 to board. Have a nice flight!") .addAction(walkingDirectionsAction) .extend(new NotificationCompat.WearableExtender() .addPages(pages) .addAction(replyAction) .addAction(walkingDirectionsAction)) .build();
  24. 24. Wearable apps Launching Using app-provided voice actions Using the start menu
  25. 25. Launching AndroidManifest.xml <application android:icon="@drawable/greenlinelogo" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault" > <activity android:name="de.peterfriese.weartravel.MainActivity" android:label="@string/app_name_voice" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
  26. 26. Wearable Apps Custom Layouts
  27. 27. Layout - List activity_checkin.xml <android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_height="match_parent" android:layout_width="match_parent"> <FrameLayout android:id="@+id/frame_layout" android:layout_height="match_parent" android:layout_width="match_parent" app:layout_box="left|bottom|right"> <android.support.wearable.view.WearableListView android:id="@+id/checkin_list" android:layout_height="match_parent" android:layout_width="match_parent"> </android.support.wearable.view.WearableListView> </FrameLayout> </android.support.wearable.view.BoxInsetLayout>
  28. 28. Layout - Item checkin_listview_item.xml <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.wearable.view.CircledImageView android:id="@+id/image" android:alpha="0.5" android:layout_height="52dp" android:layout_marginLeft="16dp" android:layout_width="52dp" app:circle_border_color="#FFFFFFFF" app:circle_border_width="2dp" app:circle_color="#00000000" /> <TextView android:id="@+id/text" android:alpha="0.5" android:fontFamily="sans-serif-condensed-light" android:gravity="center_vertical" android:layout_height="52dp" android:layout_marginLeft="72dp" android:layout_marginRight="16dp"
  29. 29. <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" Layout - Item checkin_listview_item.xml xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.wearable.view.CircledImageView android:id="@+id/image" android:alpha="0.5" android:layout_height="52dp" android:layout_marginLeft="16dp" android:layout_width="52dp" app:circle_border_color="#FFFFFFFF" app:circle_border_width="2dp" app:circle_color="#00000000" /> <TextView android:id="@+id/text" android:alpha="0.5" android:fontFamily="sans-serif-condensed-light" android:gravity="center_vertical" android:layout_height="52dp" android:layout_marginLeft="72dp" android:layout_marginRight="16dp" android:layout_width="wrap_content" android:textColor="@color/white" android:textSize="14sp" /> </merge>
  30. 30. MyViewItem CheckInActivity.java private final class MyItemView extends FrameLayout implements WearableListView.Item { final CircledImageView image; final TextView text; private float mScale; public MyItemView(Context context) { super(context); View.inflate(context, R.layout.checkin_listview_item, this); image = (CircledImageView) findViewById(R.id.image); text = (TextView) findViewById(R.id.text); } @Override public float getProximityMinValue() { return mDefaultCircleRadius; } @Override public float getProximityMaxValue() { return mSelectedCircleRadius; }
  31. 31. private float mScale; public MyItemView(Context context) { MyViewItem super(context); View.inflate(context, R.layout.checkin_listview_item, this); image = (CircledImageView) findViewById(R.id.image); text = (TextView) findViewById(R.id.text); CheckInActivity.java } @Override public float getProximityMinValue() { return mDefaultCircleRadius; } @Override public float getProximityMaxValue() { return mSelectedCircleRadius; } @Override public float getCurrentProximityValue() { return mScale; } @Override public void setScalingAnimatorValue(float value) { mScale = value; image.setCircleRadius(mScale); image.setCircleRadiusPressed(mScale); } @Override
  32. 32. @Override public float getProximityMaxValue() { MyViewItem return mSelectedCircleRadius; } @Override public float getCurrentProximityValue() { CheckInActivity.java return mScale; } @Override public void setScalingAnimatorValue(float value) { mScale = value; image.setCircleRadius(mScale); image.setCircleRadiusPressed(mScale); } @Override public void onScaleUpStart() { image.setAlpha(1f); text.setAlpha(1f); } @Override public void onScaleDownStart() { image.setAlpha(0.5f); text.setAlpha(0.5f); } }
  33. 33. Adapter - Bind ViewHolder CheckInActivity.java public class MyListAdapter extends WearableListView.Adapter { @Override public WearableListView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { return new WearableListView.ViewHolder(new MyItemView(CheckInActivity.this)); } @Override public void onBindViewHolder(WearableListView.ViewHolder viewHolder, int i) { MyItemView myItemView = (MyItemView) viewHolder.itemView; TextView textView = (TextView) myItemView.findViewById(R.id.text); textView.setText(String.format("Seat %d", i)); Integer resourceId = R.drawable.ic_action_done; CircledImageView imageView = (CircledImageView) myItemView.findViewById(R.id.image); imageView.setImageResource(resourceId); } @Override public int getItemCount() { return 17; }
  34. 34. Adapter - Bind ViewHolder public class MyListAdapter extends WearableListView.Adapter { CheckInActivity.java @Override public WearableListView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { return new WearableListView.ViewHolder(new MyItemView(CheckInActivity.this)); } @Override public void onBindViewHolder(WearableListView.ViewHolder viewHolder, int i) { MyItemView myItemView = (MyItemView) viewHolder.itemView; TextView textView = (TextView) myItemView.findViewById(R.id.text); textView.setText(String.format("Seat %d", i)); Integer resourceId = R.drawable.ic_action_done; CircledImageView imageView = (CircledImageView) myItemView.findViewById(R.id.image); imageView.setImageResource(resourceId); } @Override public int getItemCount() { return 17; } }
  35. 35. Activity CheckInActivity.java public class CheckInActivity extends Activity implements WearableListView.ClickListener { private WearableListView mListView; private MyListAdapter mAdapter; private float mDefaultCircleRadius; private float mSelectedCircleRadius; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_checkin); mDefaultCircleRadius = getResources().getDimension(R.dimen.default_settings_circle_radius); mSelectedCircleRadius = getResources().getDimension(R.dimen.selected_settings_circle_radius); mAdapter = new MyListAdapter(); mListView = (WearableListView) findViewById(R.id.checkin_list); mListView.setAdapter(mAdapter); mListView.setClickListener(CheckInActivity.this); }
  36. 36. private float mDefaultCircleRadius; private float mSelectedCircleRadius; @Override protected void onCreate(Bundle savedInstanceState) { Activity super.onCreate(savedInstanceState); setContentView(R.layout.activity_checkin); mDefaultCircleRadius = CheckInActivity.java getResources().getDimension(R.dimen.default_settings_circle_radius); mSelectedCircleRadius = getResources().getDimension(R.dimen.selected_settings_circle_radius); mAdapter = new MyListAdapter(); mListView = (WearableListView) findViewById(R.id.checkin_list); mListView.setAdapter(mAdapter); mListView.setClickListener(CheckInActivity.this); } @Override public void onClick(WearableListView.ViewHolder viewHolder) { Toast.makeText(this, String.format("You selected item #%s”, viewHolder.getPosition()), Toast.LENGTH_SHORT).show(); } @Override public void onTopEmptyRegionClick() { Toast.makeText(this, "You tapped into the empty area above the list”, Toast.LENGTH_SHORT).show(); }
  37. 37. Data Layer Performing a Check-In on Your Watch
  38. 38. Transferring Assets sendDataToWearable() final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream); Asset asset = Asset.createFromBytes(byteStream.toByteArray()); PutDataMapRequest dataMap = PutDataMapRequest.create(Constants.FLIGHT_PATH + "/" + Uri.encode("SFO")); dataMap.getDataMap().putString(Constants.EXTRA_FLIGHTNUMBER, "AC123"); dataMap.getDataMap().putString(Constants.EXTRA_GATE, "C 17"); dataMap.getDataMap().putAsset(Constants.EXTRA_DESTINATION, imageAssetDestination); PutDataRequest request = dataMap.asPutDataRequest(); // Send the data over DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleApiClient, request).await();
  39. 39. Sending Messages sendDataToWearable() // If successful store the data path // Construct an array of all successfully sent data paths DataMap itemPathMap = new DataMap(); itemPathMap.putString(Constants.EXTRA_UPDATED_FLIGHTS, result.getDataItem().getUri().toString()); // Convert to bytes to be send with the message byte[] dataMapBytes = itemPathMap.toByteArray();
  40. 40. Sending Messages sendDataToWearable() // If successful store the data path // Construct an array of all successfully sent data paths DataMap itemPathMap = new DataMap(); itemPathMap.putString(Constants.EXTRA_UPDATED_FLIGHTS, result.getDataItem().getUri().toString()); // Convert to bytes to be send with the message byte[] dataMapBytes = itemPathMap.toByteArray(); Iterator<String> itr = Utilities.getNodes(googleApiClient).iterator(); while (itr.hasNext()) { // Notify all nodes to "start", providing the data paths of all // transmitted tourist attractions. What "start" does will be up // to the wearable. ! }
  41. 41. Sending Messages sendDataToWearable() // If successful store the data path // Construct an array of all successfully sent data paths DataMap itemPathMap = new DataMap(); itemPathMap.putString(Constants.EXTRA_UPDATED_FLIGHTS, result.getDataItem().getUri().toString()); // Convert to bytes to be send with the message byte[] dataMapBytes = itemPathMap.toByteArray(); Iterator<String> itr = Utilities.getNodes(googleApiClient).iterator(); while (itr.hasNext()) { // Notify all nodes to "start", providing the data paths of all // transmitted tourist attractions. What "start" does will be up // to the wearable. Wearable.MessageApi.sendMessage(googleApiClient, itr.next(), Constants.START_PATH, dataMapBytes); }
  42. 42. Receiving Data AndroidManifest.xml (wearable) <service android:name="de.peterfriese.weartravel.ListenerService"> <intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter> </service>
  43. 43. Receiving Data ListenerService.java public class ListenerService extends WearableListenerService { @Override public void onDataChanged(DataEventBuffer dataEvents) { Log.d(TAG, "onDataChanged: " + dataEvents); final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents); for (DataEvent event : events) { if (event.getType() == DataEvent.TYPE_CHANGED) { // Not doing anything here but logging Uri uri = event.getDataItem().getUri(); DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); String title = dataMapItem.getDataMap().getString("extra_flightnumber"); Log.v(TAG, "Data changed: " + uri + ", " + title); } } } @Override public void onMessageReceived(MessageEvent messageEvent) { Log.v(TAG, "onMessageReceived: " + messageEvent);
  44. 44. if (event.getType() == DataEvent.TYPE_CHANGED) { // Not doing anything here but logging Uri uri = event.getDataItem().getUri(); DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); String title = dataMapItem.getDataMap().getString("extra_flightnumber"); Log.v(TAG, "Data changed: " + uri + ", " + title); Receiving Data } ListenerService.} java } @Override public void onMessageReceived(MessageEvent messageEvent) { Log.v(TAG, "onMessageReceived: " + messageEvent); if (Constants.START_PATH.equals(messageEvent.getPath())) { DataMap dataMap = DataMap.fromByteArray(messageEvent.getData()); GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this) .addApi(Wearable.API) .build(); ConnectionResult connectionResult = googleApiClient.blockingConnect( Constants.GOOGLE_API_CLIENT_TIMEOUT, TimeUnit.SECONDS); if (!connectionResult.isSuccess() || !googleApiClient.isConnected()) { Log.e(TAG, Constants.GOOGLE_API_CLIENT_ERROR_MSG); return; } String flightUri = dataMap.getString(Constants.EXTRA_UPDATED_FLIGHTS);
  45. 45. ConnectionResult connectionResult = googleApiClient.blockingConnect( Constants.GOOGLE_API_CLIENT_TIMEOUT, TimeUnit.SECONDS); Receiving Data if (!connectionResult.isSuccess() || !googleApiClient.isConnected()) { Log.e(TAG, Constants.GOOGLE_API_CLIENT_ERROR_MSG); return; } String flightUri = dataMap.getString(Constants.EXTRA_UPDATED_FLIGHTS); Uri uri = Uri.parse(flightUri); DataApi.DataItemResult dataItemResult = ListenerService.java Wearable.DataApi.getDataItem(googleApiClient, uri).await(); DataItem dataItem = dataItemResult.getDataItem(); if (dataItem != null) { DataMap flightDataMap = DataMapItem.fromDataItem(dataItem).getDataMap(); String flightNumber = flightDataMap.getString(Constants.EXTRA_FLIGHTNUMBER); String gate = flightDataMap.getString(Constants.EXTRA_GATE); Bitmap destinationBitmap = Utilities.loadBitmapFromAsset( googleApiClient, flightDataMap.getAsset(Constants.EXTRA_DESTINATION)); sendNotification(flightNumber, gate, destinationBitmap); } googleApiClient.disconnect(); } }
  46. 46. Demo
  47. 47. Thank you! +PeterFriese @ #AndroidWear
  48. 48. Q & A +PeterFriese @ #AndroidWear

×