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

Developing for Android Wear, welcome to the wrist world

Developing for Android Wear, welcome to the wrist world

With Android Wear, Google has extended their flagship OS to the smallest form factor. Thanks to Xamarin, this means your C# code can now reach your users all the way down their sleeves with the proliferation of Android Wear-based smartwatches.

In this session, we will see how to develop full-blown Android Wear apps from the specificities of the platform, to the data communication challenges and how to best use the UI toolkit given to developers by Google.

Jérémie Laval

March 17, 2015
Tweet

More Decks by Jérémie Laval

Other Decks in Technology

Transcript

  1. Developing For
    Android Wear
    Welcome to the wrist world

    View full-size slide

  2. Hi!
    +
    I’m Jérémie
    @jeremie_laval

    View full-size slide

  3. Agenda
    What’s Android Wear?
    Designing for Wear
    Coding for Wear

    View full-size slide

  4. What’s Android Wear?

    View full-size slide

  5. What’s Android Wear?
    An Android-based platform
    for every type of wearables
    → Smartwatches

    View full-size slide

  6. Hardware
    Ex: Moto 360
    TI OMAP 3 SoC
    1 GHz ARM CPU
    512 MB RAM
    → Droid 2 (circa 2010)
    iFixit

    View full-size slide

  7. Hardware
    The Fun Stuff
    - Bluetooth LE
    - Microphone
    - Pedometer
    - Heart rate monitor (some)
    - GPS (some)
    - Accelerometer, gyroscope, barometer…

    View full-size slide

  8. Software
    - Android 5.0 Lollipop*
    - Paired with an Android phone
    - OTA updates pushed via phone app
    - Wear apps are regular Android apps
    *minus some packages (webkit, print, backup, appwidget, …)

    View full-size slide

  9. Targeting Wear

    View full-size slide

  10. Enhanced Notifications

    View full-size slide

  11. Custom Watchfaces

    View full-size slide

  12. Google Fit Apps

    View full-size slide

  13. Full-blown Apps

    View full-size slide

  14. Designing for Wear

    View full-size slide

  15. User Experience
    The right information
    ↳ at the right time
    ↳ at the right place
    → Context is king

    View full-size slide

  16. Design Challenges

    View full-size slide

  17. Screens
    Size 280-320 pixels
    Density
    y
    hdpi

    View full-size slide

  18. Interactions
    Touch
    Un-precise
    Gestures favored
    Sound
    Input only
    Commands
    Dictation

    View full-size slide

  19. Glanceable Design

    View full-size slide

  20. Glanceable Design
    Micro Interactions
    5s attention span
    Self-contained task
    Usage on-the-go
    Random movements
    Hands unavailable
    Vision is vital

    View full-size slide

  21. App Navigation
    - No accessible backstack
    - Touch is tedious
    - Swipe already a dominant gesture
    - Probably too much

    View full-size slide

  22. App Navigation
    Multiple activities =
    App drawer as your top navigation
    → Discoverable and voice triggerable

    View full-size slide

  23. A Bad Wear App
    Too much information
    Too much functionality
    Too much list/hierarchy
    → Don’t shrink it, break it down

    View full-size slide

  24. Coding for Wear

    View full-size slide

  25. Moyeu
    https://github.com/garuma/Moyeu/

    View full-size slide

  26. Coding for Wear
    It’s just Android

    View full-size slide

  27. Wearable UI toolkit
    Xamarin.Android.Wear
    An extra set of UI helpers
    optimized for Android Wear

    View full-size slide

  28. Cards
    CardFragment
    CardScrollView
    CardFrame

    View full-size slide

  29. Standard Cards
    var cardFragment = CardFragment.Create ("Hello!",

    "This is a standard card",

    Resource.Drawable.Icon);

    FragmentManager.BeginTransaction ()

    .Add (Resource.Id.frame, cardFragment, "card")

    .Commit ();


    View full-size slide

  30. Custom Cards
    /garuma/Moyeu/blob/master/MoyeuWear/StationCardFragment.cs
    public class StationCardFragment : CardFragment

    {

    public override void OnCreate (Bundle savedInstanceState)

    {

    base.OnCreate (savedInstanceState);

    SetExpansionEnabled (false);

    SetCardGravity ((int)GravityFlags.Bottom);

    }


    protected override View OnCreateContentView (LayoutInflater inflater,
    ViewGroup container,
    Bundle state)

    {

    return inflater.Inflate (Resource.Layout.StationCardLayout, container, false);

    }

    }


    View full-size slide

  31. Action Buttons
    /garuma/Moyeu/blob/master/MoyeuWear/ActionButtonFragment.cs

    View full-size slide

  32. Standard Animations
    AndroidManifest.xml

    var intent = new Intent (this, typeof(ConfirmationActivity));

    intent.PutExtra (ConfirmationActivity.ExtraAnimationType,
    ConfirmationActivity.SuccessAnimation);

    intent.PutExtra (ConfirmationActivity.ExtraMessage, "Great Success!");

    StartActivity (intent);
    Code

    View full-size slide

  33. 2D Picker
    Layout
    android:layout_width=“fill_parent" android:layout_height="fill_parent"/>

    public class StationGridAdapter : FragmentGridPagerAdapter

    {

    public override int RowCount { get { … } }


    public override Drawable GetBackgroundForRow (int row) …;


    public override int GetColumnCount (int row) …;


    public override Fragment GetFragment (int row, int column) …;

    }

    Code
    /garuma/Moyeu/blob/master/MoyeuWear/StationGridAdapter.cs

    View full-size slide

  34. More Widgets
    WatchViewStub
    WearableListView
    DotPageIndicator
    DelayedConfirmationView

    View full-size slide

  35. Voice Triggers
    [Activity (Label = "Shopping", MainLauncher = true, …)]

    public class MainActivity : Activity

    {
    “Ok Google, Start ”
    “Ok Google, start shopping”
    /garuma/xamarin-store-app/blob/wear-support/XamarinStore.Droid.Wear/MainActivity.cs

    View full-size slide

  36. Voice triggers
    Full list: developer.android.com/training/wearables/apps/voice.html#SystemProvided
    [IntentFilter (new[] { "vnd.google.fitness.TRACK" },

    DataMimeType = "vnd.google.fitness.activity/biking",

    Categories = new string[] { "android.intent.category.DEFAULT" })]

    public class MainActivity : Activity
    BikeActionStatus ActionStatus {

    get {

    return Intent.GetStringExtra ("actionStatus") == "CompletedActionStatus" ?

    BikeActionStatus.Stop : BikeActionStatus.Start;

    }

    }
    /garuma/Moyeu/blob/master/MoyeuWear/MainActivity.cs

    View full-size slide

  37. Communication
    = Battery Consuming + Slow
    ~ % adb pull /sdcard/foo .
    10 KB/s (17539200 bytes in 1597.854s)
    17M 26m

    View full-size slide

  38. Communication
    Forget HttpClient

    View full-size slide

  39. Communication Library
    Google Play Services
    2 APIs
    Message API
    Low-level path-based messages
    Data API
    Phone ↔ Watch Dropbox
    Xamarin.Android.Wear
    (phone)
    (watch)

    View full-size slide

  40. Setup
    var client = new GoogleApiClientBuilder (this, this, this)

    .AddApi (WearableClass.Api)
    …

    .Build ();
    /garuma/Moyeu/blob/master/MoyeuWear/MainActivity.cs
    /garuma/Moyeu/blob/master/Moyeu/WearService.cs

    View full-size slide

  41. Node API
    void GetStations ()

    {

    WearableClass.NodeApi.GetConnectedNodes (client)

    .SetResultCallback (this);

    }


    public void OnResult (Java.Lang.Object result)

    {

    var apiResult = result.JavaCast ();

    var nodes = apiResult.Nodes;

    phoneNode = nodes.FirstOrDefault ();

    }

    Peer to peer mesh network
    /garuma/Moyeu/blob/master/MoyeuWear/MainActivity.cs

    View full-size slide

  42. Message API
    var path = "/moyeu/Action/Favorite/";

    path += stationId + "?" + (cked ? "add" : "remove");

    WearableClass.MessageApi.SendMessage (client,
    phoneNode.Id,
    path,
    new byte[0]);
    /garuma/Moyeu/blob/master/MoyeuWear/MainActivity.cs
    - Targeted fire-and-forget
    - Path-based
    - Small payloads

    View full-size slide

  43. Data API
    /garuma/Moyeu/blob/master/Moyeu/WearService.cs
    Putting stuff in
    var request = PutDataMapRequest.Create (SearchStationPath + "/Answer");

    var map = request.DataMap;


    var stationMap = new List ();

    foreach (var station in nearestStations) {

    var itemMap = new DataMap ();

    itemMap.PutInt ("Id", station.Id);

    var asset = await CreateWearAssetFrom (station);

    itemMap.PutAsset ("Background", asset);

    itemMap.PutString ("Primary", primary);

    itemMap.PutDouble ("Distance", distance);


    stationMap.Add (itemMap);

    }

    map.PutDataMapArrayList ("Stations", stationMap);

    map.PutLong ("UpdatedAt", DateTime.UtcNow.Ticks);


    WearableClass.DataApi.PutDataItem (client, request.AsPutDataRequest ());

    View full-size slide

  44. Data API
    Getting it back out
    /garuma/Moyeu/blob/master/MoyeuWear/MainActivity.cs
    public void OnDataChanged (DataEventBuffer dataEvents)

    {

    var dataEvent = Enumerable.Range (0, dataEvents.Count)

    .Select (i => dataEvents.Get (i).JavaCast ())

    .First (de => de.Type == DataEvent.TypeChanged
    && de.DataItem.Uri.Path == SearchStationPath + "/Answer");

    var dataMapItem = DataMapItem.FromDataItem (dataEvent.DataItem);

    var map = dataMapItem.DataMap;

    var stations = new List ();

    var data = map.GetDataMapArrayList ("Stations");

    foreach (var d in data) {

    stations.Add (new SimpleStation {

    Id = d.GetInt ("Id", 0),

    Primary = d.GetString ("Primary", ""),

    Background = GetBitmapForAsset (d.GetAsset ("Background")),

    Distance = d.GetDouble ("Distance", 0),

    });

    }

    View full-size slide

  45. Receiving Messages
    [Service]

    [IntentFilter (new[] { "com.google.android.gms.wearable.BIND_LISTENER" })]

    public class WearService : WearableListenerService

    {
    - Passive helper
    - One Wear service allowed
    - Instantiated on-demand by Wear
    - Messages automatically forwarded
    WearableClass.DataApi.AddListener (client, this);
    /garuma/Moyeu/blob/master/Moyeu/WearService.cs

    View full-size slide

  46. Useful stuff
    - blog.xamarin.com/tips-for-your-first-android-wear-app/
    - developer.xamarin.com/guides/android/wear/
    - developer.xamarin.com/samples/android/Android%20Wear/
    - github.com/garuma/Moyeu
    - github.com/garuma/xamarin-store-app/tree/wear-support
    - https://github.com/jamesmontemagno/DaysUntilXmas
    - www.google.com/events/io/io14videos

    View full-size slide