4

I had an app that could detect when an android wear device disconnected by using a WearableListenerService and onPeerConnected/onPeerDisconnected.

It seems these have been deprecated, so I am now trying to use onCapabilityChanged, but I cannot get this function called. I use this in my manifest for my service. Documentation on these features are not very good.

<intent-filter>
            <action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
</intent-filter>
Anthony Barrera
  • 472
  • 3
  • 11
  • 1
    If the device is connected in the wear device using nodes, then you can use the [CapabilityApi](https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi) to determine when devices enter or leave the network or device becomes disconnected from a phone. For more information about this, check this related [SO question](http://stackoverflow.com/questions/25619190). – KENdi Apr 12 '17 at 15:01

1 Answers1

7

So I finally got it to work. It took a combination of things that needed to be set up, but I'll list them all.

  1. The Gradle. You need to make sure the mobile version and the wearable version has the same application id, the same version code, the same version name, and possibly the same play-services version. This is easier to handle if you use the project gradle file to hold these values and have each module reference these values.

In the Root build.gradle file have:

ext {
    TARGET_SDK_VERSION = 25
    VERSION_CODE = 7
    VERSION_NAME = '2.0'

    COMPILE_SDK_VERSION = 25
    BUILD_TOOLS_VERSION = '25.0.2'

    APPLICATION_ID = "com.example.projectname"

    PLAY_SERVICES_WEARABLE =  'com.google.android.gms:play-services-wearable:9.4.0'
}

In each of the module build.gradle files, these can be referenced as shown below:

apply plugin: 'com.android.application'

android {
    compileSdkVersion rootProject.ext.COMPILE_SDK_VERSION
    buildToolsVersion rootProject.ext.BUILD_TOOLS_VERSION

    defaultConfig {
        applicationId rootProject.ext.APPLICATION_ID
        minSdkVersion 20
        targetSdkVersion rootProject.ext.TARGET_SDK_VERSION
        versionCode rootProject.ext.VERSION_CODE
        versionName rootProject.ext.VERSION_NAME
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    provided 'com.google.android.wearable:wearable:2.0.1'
    compile 'com.google.android.support:wearable:2.0.1'
    compile rootProject.ext.PLAY_SERVICES_WEARABLE
}
  1. The Manifest. With the new updates to the play services, a WearableListenerService must now have an intent-filter defined for each overrided function to be called by the android system. In the case of the onCapabilityChanged function, the intent filter should be defined as:
    <service
        android:name=".MyWearableListenerService"
        android:enabled="true"
        android:exported="true" >
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
            <data android:scheme="wear" android:host="*"/>
        </intent-filter>
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
            <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
            <data android:scheme="wear" android:host="*" android:pathPrefix="/PREF"/>
            <data android:scheme="wear" android:host="*" android:pathPrefix="/start"/>
        </intent-filter>
    </service>

The intent-filter for onCapabilityChanged is com.google.android.gms.wearable.CAPABILITY_CHANGED. Along with that, the intent-filter also needs to be told the data scheme and host. This can simply be data android:scheme="wear" android:host="*". The pathPrefix can be omitted for this intent-filter. Notice that the intent-filter for the com.google.android.gms.wearable.DATA_CHANGED and com.google.android.gms.wearable.MESSAGE_RECEIVED needs the pathPrefix defined to be able to have their respective functions called in the service.

  1. The capability file. In order for the onCapabilityChanged function to launch, the system needs to detect a device with a capability being connected. To do this, we must have the capability defined in an xml file in each module.

To do this, in each module, save a file named wear.xml in the res/values directory. The file must have a string array named android_wear_capabilities with items that describe the capabilities you wish your module to advertise to another device. Below is an example of a wear.xml file included in a wearable module.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="android_wear_capabilities">
        <item>verify_remote_wear_app</item>
    </string-array>
</resources>

First, It is important to note that the file must be named wear.xml and must be placed in the values directory. Secondly, the string-array must be named android_wear_capabilities. Also make sure that every capability in each module has a unique name.

If any of the above is not correct, then the onCapabilityChanged function will never be called, and you will be pulling your hair out in frustration.

Now, to actually tell if a device was disconnected, use the onCapabilityChanged function:

public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
        super.onCapabilityChanged(capabilityInfo);
        if(capabilityInfo.getNodes().size() > 0){
            Log.d(TAG, "Device Connected");
        }else{
            Log.d(TAG, "No Devices");
        }
    }

This function will tell you when a device has connected or disconnected, assuming only 1 device is connected at a time.

Anthony Barrera
  • 472
  • 3
  • 11
  • 1
    Will onCapabilityChanged function work for both mobile and wear? The documentation and sample apps seem to demonstrate it only with the wear (Wear detects whether the phone's state is changed). Have you tried the same with mobile? (Can your phone detect whether wear's state is changed) –  Jun 23 '17 at 13:26
  • Yes it will as long as the wearable device also has a capability for the mobile device to detect. So make sure the wearable module has the wear.xml file in the res/value directory. – Anthony Barrera Jun 24 '17 at 14:03
  • 1
    are you serious about same version code, the same version name? I never knew this. is it documented somewhere? – Emil Mar 20 '22 at 01:21
  • Followed by this instruction I solved same task. After several experiments I can definitely say that unnecessary points are: "Same version name", "Same version code" and "wear.xml file name". – Anrimian Jul 22 '23 at 18:05