Android Wear Watchface Settings on host

android, android-wear-data-api, wear-os

Solution

You can use the `DataApi` or `MessageApi` to sync your watchface configuration between Phone and Watch devices.

Please take a look at the documentation and choose the one more appropriate to your needs: https://developer.android.com/training/wearables/data-layer/index.html https://developer.android.com/training/wearables/data-layer/data-items.html https://developer.android.com/training/wearables/data-layer/messages.html

Here is an example with the use of `DataApi`.

Everything pushed to the `DataApi` is shared between devices and available of both of them. You can change this data on both sides and the other side will be notified about such change immediately (when devices are connected to each other). You can also read this data at any moment (for example when user will choose your watchface on the Watch - the configuration data will be already waiting for you there).

On the phone side:

public class WatchfaceConfigActivity extends Activity {
    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(new ConnectionCallbacks() {
                    @Override
                    public void onConnected(Bundle connectionHint) {
                    }
                    @Override
                    public void onConnectionSuspended(int cause) {
                    }
            })
            .addOnConnectionFailedListener(new OnConnectionFailedListener() {
                    @Override
                    public void onConnectionFailed(ConnectionResult result) {
                    }
                })
            .addApi(Wearable.API)
            .build();
        mGoogleApiClient.connect();
    }

and every time you want to sync new fconfiguration with the Android Wear device you have to put a DataRequest via Wearable `DataApi`:

    private void syncConfiguration() {
        if(mGoogleApiClient==null)
            return;

        final PutDataMapRequest putRequest = PutDataMapRequest.create("/CONFIG");
        final DataMap map = putRequest.getDataMap();
        map.putInt("mode", 1);
        map.putInt("color", Color.RED);
        map.putString("string_example", "MyWatchface");
        Wearable.DataApi.putDataItem(mGoogleApiClient,  putRequest.asPutDataRequest());
    }
}

On the Watch side:

You need to create a class that extends `WearableListenerService`:

public class DataLayerListenerService extends WearableListenerService {

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        super.onDataChanged(dataEvents);

        final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
        for(DataEvent event : events) {
            final Uri uri = event.getDataItem().getUri();
            final String path = uri!=null ? uri.getPath() : null;
            if("/CONFIG".equals(path)) {
                final DataMap map = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
                // read your values from map:
                int mode = map.getInt("mode");
                int color = map.getInt("color");
                String stringExample = map.getString("string_example");
            }
        }
    }
}

and declare it in your `AndroidManifest`:

<service android:name=".DataLayerListenerService" >
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
    </intent-filter>
</service>

Notice that this is only an example of usage. Maybe (instead of registering an instance of `WearableListenerService`) there will be better for you to create an instance of `mGoogleApiClient` inside your Watchface directly and add a `DataListener` there:

    Wearable.DataApi.addListener(mGoogleApiClient, new DataListener() {
        @Override
        public void onDataChanged(DataEventBuffer dataEvents) {
            // read config here and update the watchface
        }
    });

Maybe you don't need shared data - then you can communicate using `MessageApi` and send messages only when new configuration is saved or then watch wants to read current configuration from phone.

Problem

I currently have an android wear watchface developed. I however would now like to create a settings section on the host app that would allow the user to customize the watchface. I am new to the android development so I am curious on the correct way to do this. Is there a way to update a sharedpreference on the host and then push or sync that with the sharedpreference on the wear device? Or is there a totally different way I should be looking at this?

Original source