page.title=Standalone Apps meta.keywords="wear-preview" page.tags="wear-preview" page.image=images/cards/card-n-sdk_2x.png @jd:body
In Android Wear 2.0, apps can work independently of a phone. Users can complete more tasks on a watch, without access to an Android or iOS phone.
A watch APK targeting Wear 2.0 should not be embedded in a phone APK. For more information, see App Distribution.
Generally, the minimum and target API level for a standalone app, and for Wear 2.0, is level 24. The minimum SDK level can be 23 only if you are using the same APK for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK).
If you build a standalone Wear 2.0 APK and will continue to have a Wear 1.0 APK, please do both of the following:
Caution: For the Wear 2.0 Developer Preview, if you publish an update to your production phone APK that has removed an embedded Wear APK, production users who update the phone APK before installing your standalone Wear APK will lose their existing Wear app and its data. Therefore, it's important that you continue to embed your watch APK into your phone APK.
Run-time permissions are required for standalone apps.
Code can be shared between a Wear app and a phone app. Optionally, code that is specific to a form factor can be in a separate module.
For example, common code for networking can be in a shared library.
You can use standard Android storage APIs to store data locally. For example, you can use the SharedPreferences APIs, SQLite, or internal storage (as you would in the case of a phone).
If a user of your watch app needs your phone app, your watch app can
detect if the phone app is available. Using the
CapabilityApi, your phone app or watch app can advertise its presence
to a paired device. It can do so statically and dynamically. When an app
is on a node in a user's Wear network (i.e., on a phone, paired watch, or
in the cloud), the CapabilityApi
enables another
app to detect if it is installed. For more information, see
Advertise capabilities.
If your phone app is unavailable, your can check if the Play Store is available on the phone, as described below, before directing the user to go to the Play Store (to install your phone app).
iPhones and some Android phones lack the Play Store. A standalone Wear
app can check if the paired phone has the Play Store, before directing a
user to go there to install your phone app. The
PlayStoreAvailability
class contains a
getPlayStoreAvailabilityOnPhone()
method that enables your
Wear app to check if a companion phone has the Play Store.
More information about the PlayStoreAvailability
class is
available when you
download the Android Wear 2.0 Preview Reference. Here is a snippet
that uses the getPlayStoreAvailabilityOnPhone()
method to
determine if the paired phone has the Play Store:
int playStoreAvailabilityOnPhone = PlayStoreAvailability.getPlayStoreAvailabilityOnPhone(context);
The value returned by the getPlayStoreAvailabilityOnPhone()
method is one of the following:
Return value | Description |
---|---|
PLAY_STORE_ON_PHONE_AVAILABLE
|
The Play Store is available on the companion phone. |
PLAY_STORE_ON_PHONE_UNAVAILABLE
|
The Play Store is not available on the companion phone. |
PLAY_STORE_ON_PHONE_ERROR_UNKNOWN
|
An error occurred in the check for the Play Store; another check should be made later. |
Android Wear apps can make their own network requests. When a watch has a Bluetooth connection to a phone, the watch's network traffic is proxied through the phone. When a phone is unavailable, Wi-Fi and cellular networks are used, depending on the hardware. The Wear platform handles transitions between networks. A watch's network access thus does not require the Wearable Data Layer API.
For sending notifications, apps can directly use Firebase Cloud Messaging (FCM), which replaces Google Cloud Messaging, or continue to use GCM.
No APIs for network access or FCM are specific to Android Wear. Refer to the existing documentation about connecting to a network and cloud messaging.
You can use protocols such as HTTP, TCP, and UDP. However, the android.webkit APIs are not available. Therefore, use of cookies is available by reading and writing headers on requests and responses, but the CookieManager class is not available.
FCM works well with Doze.
Additionally, we recommend using the following:
For foreground use cases, we currently recommend that you make a request for an unmetered network. Here is an example of using the multi-networking APIs to request an unmetered network:
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { // access network } }; ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); connectivityManager.requestNetwork(new NetworkRequest.Builder() .addCapability(NET_CAPABILITY_NOT_METERED) .build(), networkCallback);
We also recommend setting a timer for frontend scenarios to prevent a user from potentially waiting for a long time. When the network is no longer needed, or if the timer fires, the network callback needs to be unregistered:
connectivityManager.unregisterNetworkCallback(networkCallback):
A Wear app can communicate with a phone app using the Wearable Data Layer API, but connecting to a network using that API is discouraged.
When obtaining data from the cloud, get only the necessary data. Otherwise, you may introduce unnecessary latency, memory use, and battery use.
When a watch is connected over a Bluetooth LE connection, your app may have access to a bandwidth of only 10 kilobytes per second. Therefore, the following steps are recommended:
To ensure that background tasks are correctly executed, they must account for Doze. In Android 6.0, Doze and App Standby resulted in significant improvements to battery life by allowing devices to enter deep sleep when idle and stationary.
Doze is enhanced in Android Nougat and Android Wear 2.0. When a screen turns off or enters ambient mode for a long enough time, a subset of Doze can occur and background tasks may be deferred for certain periods. Later, when a device is stationary for an extended time, regular Doze occurs.
You should schedule jobs with the JobScheduler API, which enables your app to register for Doze-safe code execution. When scheduling jobs, you can select constraints such as periodic execution and the need for connectivity or device charging. It is important to configure jobs in a way that does not adversely impact battery life. Jobs should use a JobInfo.Builder object to provide constraints and metadata, e.g. with one or more of the following methods for a task:
setRequiredNetworkType(int networkType)
, specifying
NETWORK_TYPE_ANY
or NETWORK_TYPE_UNMETERED
;
note that NETWORK_TYPE_UNMETERED
is for large data transfers
while NETWORK_TYPE_ANY
is for small transfers
setRequiresCharging(boolean requiresCharging)
setRequiresDeviceIdle(boolean requiresDeviceIdle)
; this
method can be useful for lower-priority background work or
synchronization, especially when used with
setRequiresCharging
Note that some low-bandwidth networks, such as Bluetooth LE, are considered metered.
You can schedule a task that requires constraints. In the example below,
a JobScheduler
object activates MyJobService
when the following constraints are met:
You can use the builder method setExtras
to attach a bundle
of app-specific metadata to the job request. When your job executes, this
bundle is provided to your job service. Note the MY_JOB_ID
value passed to the JobInfo.Builder
constructor. This
MY_JOB_ID
value is an app-provided identifier. Subsequent
calls to cancel, and subsequent jobs created with that same value, will
update the existing job:
JobInfo jobInfo = new JobInfo.Builder(MY_JOB_ID, new ComponentName(this, MyJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .setExtras(extras) .build(); ((JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE)) .schedule(jobInfo);
Below is an implementation of
JobService to handle the job above. When the job executes, a
JobParameters
object is passed into the
onStartJob
method. The JobParameters
object
enables you to get the job ID value along with any extras bundle provided
when scheduling the job. The onStartJob
method is called on
the main application thread, and therefore any expensive logic should be
run from a separate thread. In the example, an AsyncTask
is
used to run code in the background. When work is complete, you would call
the jobFinished
method to notify JobScheduler
that the task is done:
public class MyJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { new JobAsyncTask().execute(params); return true; } private class JobAsyncTask extends AsyncTask
FCM is the recommended way to send notifications to a watch.
Provide for messages from FCM by collecting a registration token for a device when your Wear app runs. Then include the token as part of the destination when your server sends messages to the FCM REST endpoint. FCM sends messages to the device identified by the token.
An FCM message is in JSON format and can include one or both of the following payloads:
For more information and examples of payloads, see About FCM Messages.
By default, notifications are bridged (shared) from a phone app to a watch. If you have a standalone Wear app and a corresponding phone app, duplicate notifications can occur. For example, the same notification from FCM, received by both a phone and a watch, could be displayed by both devices independently.
For information about preventing duplicate notifications, see Bridging Mode for Notifications.