Synchronizing notifications to the wearable provides an easy means to extend an app to the wearable; however, sometimes, an entirely customized or fully-featured wearable experience is required.
All the wearable apps require an app to first be installed on the handheld. Here, we can assume that we have an existing project to which we are adding a wearable companion. Although, automatically installed when creating a new Android Wear project, we do need to have the Xamarin.Android.Wear NuGet installed in the wearable project.
Wearable apps require a companion app on the handheld. Usually, we already have an existing app to which we can simply add a new wearable app:
Android Wear App
project just as we would for any other app. The only thing that we need to do is to ensure that the Identifier field exactly matches that of the companion app.Once the wearable app is created, we need to add it as a project reference to the handheld companion app:
References
folder under the handheld app project, and select Edit References….Once the project references are set up, we can run the app on the handheld and the wearable:
Because some devices have round screens and others have square, we need to be able to specify different layouts for each screen type:
Main.axml
layout file, we will create a proxy layout using WatchViewStub
, and use the rectLayout
and roundLayout
attributes to specify the real layout to load depending on the screen type:<android.support.wearable.view.WatchViewStub xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/watch_view_stub" android:layout_width="match_parent" android:layout_height="match_parent" app:rectLayout="@layout/RectangleMain" app:roundLayout="@layout/RoundMain" />
RectangleMain.axml
and RoundMain.axml
layout files for the app in the layout folder:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" <Button android:id="@+id/myButton" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Click Me!" /> </LinearLayout>
LayoutInflated
event of WatchViewStub
:protected override void OnCreate(Bundle bundle) { // load normally base.OnCreate(bundle); SetContentView(Resource.Layout.Main); // wait until the stub loads the real layout var id = Resource.Id.watch_view_stub; var stub = FindViewById<WatchViewStub>(id); stub.LayoutInflated += delegate { // now we can access the button var buttonId = Resource.Id.myButton; var button = FindViewById<Button>(buttonId); }; }
An Android Wear app is the most powerful method to provide a wearable experience for Android users. These apps are fully-featured Android apps that run on a wearable device with only a few differences.
One of the most notable things is the design and usability. Although running on Android, the wearable has a much smaller screen size as well as more limited hardware. Due to these limitations, wearable apps are often reduced in functionality and complement the handheld apps.
Wearable apps are not distributed via Google Play directly, but are embedded within a handheld app. To install an app on the wearable, the handheld must have the wearable app package embedded as a raw resource. When the app is installed on the handheld, Android copies the embedded package onto the wearable.
When creating a wearable app, we just need to select the Android Wear App
project template. This template is very similar to the normal app template, but has a few extra packages installed by default. We can, in fact, create a normal app and use it as a wearable app, but as we are starting out, using the template is simpler.
One extra difference is that instead of a single layout file, it provides the proxy layout via the WatchViewStub
type. This is not required and can usually just be replaced with the normal layout files. The WatchViewStub
type is a special view that loads another layout depending on the screen shape. The two typical screen shapes are square and round, and often the layout has to be slightly adjusted for each.
When we use the WatchViewStub
type, instead of handling the initialization logic in the OnCreate()
method, we attach it to the LayoutInflated
event. Then, when the view is initialized by Android, this event is fired, allowing us to perform the remainder of the initialization logic. Using the WatchViewStub
type is, in fact, similar to what would happen when creating different layout resources for different device configurations.
Once we have the wearable app project created (or if we chose to use a normal app project), we can then set it as a wearable app for the main app. We can do this by simply adding it as a project reference, just as we would for any other library project. The difference happens during the compile time when the compiler packages the app. Instead of including the wearable app as a reference, it adds it as a wearable app resource. No extra logic is required; and when the handheld app is deployed to a device, the wearable app is deployed to the wearable.
When debugging wearable apps, we can simply deploy the wearable app directly to the wearable device via a USB cable. This is simple to do and usually works; however, if the wearable device does not support a USB debugging, we can forward the ports used to debug the wearable through the Android Wear app.
More information on forwarding the port can be found on the Google website, available at http://developer.android.com/training/wearables/apps/bt-debugging.html.
Sometimes, the layouts for the round and square screens are so similar that creating multiple screens using the WatchViewStub
type is not even necessary. We can make use of various other views that will adjust depending on the screen type. One such view is the BoxInsetLayout
view:
<android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="@drawable/background" android:layout_height="match_parent" android:layout_width="match_parent"> <FrameLayout android:id="@+id/frame_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_box="bottom" /> </android.support.wearable.view.BoxInsetLayout>
Whatever we place inside the FrameLayout
view will automatically receive the correct padding to ensure that the content is not outside of the visible screen area. Sometimes, the views are so simple we can just use one of the pre-defined template layouts, such as the CardFragment
instance. This is a special Fragment
instance that renders content in the Card
format:
var cardFragment = CardFragment.Create( "The Title", "This is a nice description for the cool title."); FragmentManager.BeginTransaction() .Add(Resource.Id.frame_layout, cardFragment) .Commit();
There are a few other views that can be used to automatically adjust its appearance depending on the wearable's screen. Other views include the CardScrollView
view and the CardFrame
instance. For other layout types, there is the WearableListView
type with WearableListItemLayout
view for each item, or the GridViewPager
instance. There are also many activities such as the ConfirmationActivity
instance.