Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Introduction to Android Wear

4.118 visualizaciones

Publicado el

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.

  • 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
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí
  • Unlock Her Legs(Official) $69 | Get 90% Off + 8 Special Bonus?  https://tinyurl.com/y52uv4vq
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí
  • Hey guys! Who wants to chat with me? More photos with me here 👉 http://www.bit.ly/katekoxx
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí

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

×