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

Getting Started with Android Wear

Getting Started with Android Wear

Talk given at the Charlotte Android Developers meetup, Jul 14, 2015.

jebstuart

July 15, 2015
Tweet

More Decks by jebstuart

Other Decks in Programming

Transcript

  1. Outline • Step 1: Design Considerations • Step 2: Code

    Samples • Step 3: ?? • Step 4: Profit
  2. Why Care About Wear? • Use Android APIs • Easy

    sync w/ phone • 720k shipments in 2014 Source: http://www.canalys.com/newsroom/over-720000-android-wear-devices-shipped-2014
  3. Do I Need A Wear App? • Android notification automatically

    mirrored • NotificationCompat • Actions • “Big View”
  4. Good Use Cases • Reply to a text • Show

    directions to meeting • Add a reminder
  5. Do I Need A Wear App? • Figure out your

    user’s tasks • Then decide between rich notifications or a full-on Wear App
  6. • Launcher is rarely used • Use Voice, but have

    a fallback • Automatic, contextual cues
 (be like Google Now) User Interface
  7. • Very small screen • gross motor skills
 (swipes, not

    pinpoint taps) • max 1 or 2 tap targets on-screen User Interface
  8. Gradle apply plugin: 'com.android.application'
 
 android {
 compileSdkVersion 22
 buildToolsVersion

    "22.0.1"
 
 defaultConfig {
 applicationId "com.jebware.weardemo"
 minSdkVersion 18
 targetSdkVersion 22
 versionCode 1
 versionName "1.0"
 }
 }
 
 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 wearApp project(':wear')
 compile 'com.android.support:appcompat-v7:22.2.0'
 compile 'com.google.android.gms:play-services-wearable:7.5.0'
 compile 'com.android.support:recyclerview-v7:22.2.0'
 compile 'com.jakewharton:butterknife:6.1.0'
 } apply plugin: 'com.android.application'
 
 
 android {
 compileSdkVersion 22
 buildToolsVersion "22.0.1"
 
 defaultConfig {
 applicationId "com.jebware.weardemo"
 minSdkVersion 20
 targetSdkVersion 22
 versionCode 1
 versionName "1.0"
 }
 }
 
 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 compile 'com.google.android.support:wearable:1.2.0'
 compile 'com.google.android.gms:play-services-wearable:7.5.0'
 compile 'com.android.support:recyclerview-v7:22.2.0'
 compile 'com.jakewharton:butterknife:6.1.0'
 } mobile/build.gradle wear/build.gradle
  9. Gradle apply plugin: 'com.android.application'
 
 android {
 compileSdkVersion 22
 buildToolsVersion

    "22.0.1"
 
 defaultConfig {
 applicationId "com.jebware.weardemo"
 minSdkVersion 18
 targetSdkVersion 22
 versionCode 1
 versionName "1.0"
 }
 }
 
 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 wearApp project(':wear')
 compile 'com.android.support:appcompat-v7:22.2.0'
 compile 'com.google.android.gms:play-services-wearable:7.5.0'
 compile 'com.android.support:recyclerview-v7:22.2.0'
 compile 'com.jakewharton:butterknife:6.1.0'
 } apply plugin: 'com.android.application'
 
 
 android {
 compileSdkVersion 22
 buildToolsVersion "22.0.1"
 
 defaultConfig {
 applicationId "com.jebware.weardemo"
 minSdkVersion 20
 targetSdkVersion 22
 versionCode 1
 versionName "1.0"
 }
 }
 
 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 compile 'com.google.android.support:wearable:1.2.0'
 compile 'com.google.android.gms:play-services-wearable:7.5.0'
 compile 'com.android.support:recyclerview-v7:22.2.0'
 compile 'com.jakewharton:butterknife:6.1.0'
 } mobile/build.gradle wear/build.gradle
  10. Gradle apply plugin: 'com.android.application'
 
 android {
 compileSdkVersion 22
 buildToolsVersion

    "22.0.1"
 
 defaultConfig {
 applicationId "com.jebware.weardemo"
 minSdkVersion 18
 targetSdkVersion 22
 versionCode 1
 versionName "1.0"
 }
 }
 
 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 wearApp project(':wear')
 compile 'com.android.support:appcompat-v7:22.2.0'
 compile 'com.google.android.gms:play-services-wearable:7.5.0'
 compile 'com.android.support:recyclerview-v7:22.2.0'
 compile 'com.jakewharton:butterknife:6.1.0'
 } apply plugin: 'com.android.application'
 
 
 android {
 compileSdkVersion 22
 buildToolsVersion "22.0.1"
 
 defaultConfig {
 applicationId "com.jebware.weardemo"
 minSdkVersion 20
 targetSdkVersion 22
 versionCode 1
 versionName "1.0"
 }
 }
 
 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 compile 'com.google.android.support:wearable:1.2.0'
 compile 'com.google.android.gms:play-services-wearable:7.5.0'
 compile 'com.android.support:recyclerview-v7:22.2.0'
 compile 'com.jakewharton:butterknife:6.1.0'
 } mobile/build.gradle wear/build.gradle
  11. GoogleApiClient @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_grocery_list);
 


    googleApiClient = new GoogleApiClient.Builder(this)
 .addApi(Wearable.API)
 .addConnectionCallbacks(connectionCallbacks)
 .addOnConnectionFailedListener(onConnectionFailedListener)
 .build();
 googleApiClient.connect();
 } private GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
 @Override
 public void onConnected(Bundle bundle) {
 // connection ready, now load your data
 }
 
 @Override
 public void onConnectionSuspended(int i) {
 //NOOP
 }
 };
 
 private GoogleApiClient.OnConnectionFailedListener onConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener() {
 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) {
 //NOOP
 }
 };
  12. GoogleApiClient @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_grocery_list);
 


    googleApiClient = new GoogleApiClient.Builder(this)
 .addApi(Wearable.API)
 .addConnectionCallbacks(connectionCallbacks)
 .addOnConnectionFailedListener(onConnectionFailedListener)
 .build();
 googleApiClient.connect();
 } private GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
 @Override
 public void onConnected(Bundle bundle) {
 // connection ready, now load your data
 }
 
 @Override
 public void onConnectionSuspended(int i) {
 //NOOP
 }
 };
 
 private GoogleApiClient.OnConnectionFailedListener onConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener() {
 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) {
 //NOOP
 }
 };
  13. GoogleApiClient @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_grocery_list);
 


    googleApiClient = new GoogleApiClient.Builder(this)
 .addApi(Wearable.API)
 .addConnectionCallbacks(connectionCallbacks)
 .addOnConnectionFailedListener(onConnectionFailedListener)
 .build();
 googleApiClient.connect();
 } private GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
 @Override
 public void onConnected(Bundle bundle) {
 // connection ready, now load your data
 }
 
 @Override
 public void onConnectionSuspended(int i) {
 //NOOP
 }
 };
 
 private GoogleApiClient.OnConnectionFailedListener onConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener() {
 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) {
 //NOOP
 }
 };
  14. GoogleApiClient @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_grocery_list);
 


    googleApiClient = new GoogleApiClient.Builder(this)
 .addApi(Wearable.API)
 .addConnectionCallbacks(connectionCallbacks)
 .addOnConnectionFailedListener(onConnectionFailedListener)
 .build();
 googleApiClient.connect();
 } private GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
 @Override
 public void onConnected(Bundle bundle) {
 // connection ready, now load your data
 }
 
 @Override
 public void onConnectionSuspended(int i) {
 //NOOP
 }
 };
 
 private GoogleApiClient.OnConnectionFailedListener onConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener() {
 @Override
 public void onConnectionFailed(ConnectionResult connectionResult) {
 //NOOP
 }
 }; Async All The Things!
  15. Put Data @OnClick(android.R.id.button1)
 void addItem() {
 Grocery grocery = new

    Grocery(inputField.getText().toString());
 inputField.setText(null);
 
 //every item needs a unique path
 String path = String.format("/item/%d", grocery.id);
 PutDataMapRequest request = PutDataMapRequest.create(path);
 request.getDataMap().putInt("id", grocery.id);
 request.getDataMap().putString("value", grocery.value);
 PendingResult<DataApi.DataItemResult> result =
 Wearable.DataApi.putDataItem(googleApiClient, request.asPutDataRequest());
 result.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
 @Override
 public void onResult(DataApi.DataItemResult dataItemResult) {
 refreshList();
 }
 });
 }
  16. Get Data private void refreshList() {
 Wearable.DataApi.getDataItems(googleApiClient).setResultCallback(new ResultCallback<DataItemBuffer>() {
 @Override


    public void onResult(DataItemBuffer dataItems) {
 groceries.clear();
 for (DataItem dataItem : dataItems) {
 DataMapItem mapItem = DataMapItem.fromDataItem(dataItem);
 int id = mapItem.getDataMap().getInt("id");
 String value = mapItem.getDataMap().getString("value");
 groceries.add(new Grocery(id, value, dataItem));
 }
 adapter.notifyDataSetChanged();
 }
 });
 }
  17. Delete Data private void deleteItem(DataItem dataItem) {
 PendingResult<DataApi.DeleteDataItemsResult> result =

    
 Wearable.DataApi.deleteDataItems(googleApiClient, dataItem.getUri());
 
 result.setResultCallback(new ResultCallback<DataApi.DeleteDataItemsResult>() {
 @Override
 public void onResult(DataApi.DeleteDataItemsResult deleteDataItemsResult) {
 refreshList();
 }
 });
 }
  18. Data Listeners private GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
 @Override


    public void onConnected(Bundle bundle) {
 refreshList();
 // subscribe to updates to the data model
 Wearable.DataApi.addListener(googleApiClient, dataListener);
 }
 
 @Override
 public void onConnectionSuspended(int i) {
 //NOOP
 }
 }; private DataApi.DataListener dataListener = new DataApi.DataListener() {
 @Override
 public void onDataChanged(DataEventBuffer dataEventBuffer) {
 refreshList();
 }
 };
  19. Data Listeners private GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
 @Override


    public void onConnected(Bundle bundle) {
 refreshList();
 // subscribe to updates to the data model
 Wearable.DataApi.addListener(googleApiClient, dataListener);
 }
 
 @Override
 public void onConnectionSuspended(int i) {
 //NOOP
 }
 }; private DataApi.DataListener dataListener = new DataApi.DataListener() {
 @Override
 public void onDataChanged(DataEventBuffer dataEventBuffer) {
 refreshList();
 }
 };
  20. Notifications PendingIntent openListPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, GroceryListActivity.class), 0);


    
 NotificationCompat.Action action = new NotificationCompat.Action.Builder(
 R.drawable.ic_action_reload, "Reload", openListPendingIntent)
 .build();
 
 Notification notif = new NotificationCompat.Builder(this)
 .setSmallIcon(R.mipmap.ic_launcher)
 .setContentTitle("WearDemo")
 .setContentText("List Updated")
 .setContentIntent(openListPendingIntent)
 .setAutoCancel(true)
 .extend(new android.support.v4.app.NotificationCompat.WearableExtender().addAction(action))
 .build();
 
 NotificationManagerCompat mgr = NotificationManagerCompat.from(this);
 mgr.notify(NOTIFICATION_ID, notif);
  21. Notifications PendingIntent openListPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, GroceryListActivity.class), 0);


    
 NotificationCompat.Action action = new NotificationCompat.Action.Builder(
 R.drawable.ic_action_reload, "Reload", openListPendingIntent)
 .build();
 
 Notification notif = new NotificationCompat.Builder(this)
 .setSmallIcon(R.mipmap.ic_launcher)
 .setContentTitle("WearDemo")
 .setContentText("List Updated")
 .setContentIntent(openListPendingIntent)
 .setAutoCancel(true)
 .extend(new android.support.v4.app.NotificationCompat.WearableExtender().addAction(action))
 .build();
 
 NotificationManagerCompat mgr = NotificationManagerCompat.from(this);
 mgr.notify(NOTIFICATION_ID, notif);
  22. Notifications PendingIntent openListPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, GroceryListActivity.class), 0);


    
 NotificationCompat.Action action = new NotificationCompat.Action.Builder(
 R.drawable.ic_action_reload, "Reload", openListPendingIntent)
 .build();
 
 Notification notif = new NotificationCompat.Builder(this)
 .setSmallIcon(R.mipmap.ic_launcher)
 .setContentTitle("WearDemo")
 .setContentText("List Updated")
 .setContentIntent(openListPendingIntent)
 .setAutoCancel(true)
 .extend(new android.support.v4.app.NotificationCompat.WearableExtender().addAction(action))
 .build();
 
 NotificationManagerCompat mgr = NotificationManagerCompat.from(this);
 mgr.notify(NOTIFICATION_ID, notif);
  23. Activities & Manifest <activity
 android:name=".GroceryListActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN"

    />
 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity> package com.jebware.weardemo;
 
 import android.app.Activity;
 
 public class GroceryListActivity extends Activity {
 
 ….
 
 }

  24. Activities & Manifest <activity
 android:name=".GroceryListActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN"

    />
 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity> package com.jebware.weardemo;
 
 import android.app.Activity;
 
 public class GroceryListActivity extends Activity {
 
 ….
 
 }
 Same as phone app