Георги Ангелов Георги Ангелов - 2 months ago 13
Android Question

Watch Face is not syncing to wearable

I'm developing a watch face. The project consists of watch face and handheld app to report the mobile battery. There is no actual companion app - the app is even hidden from the drawer.
I'm encountering the issue that when I install the app on the phone the face is not syncing on the watch.
I'm compliant with almost everything I've found on the internet:


  1. The apk is generated by Android Studio - release version, signed, the wear app is in the res/raw folder.

  2. Permissions are the same for mobile and wear app.

  3. The dependencies are set correctly.

  4. APK is installed via ADB, Watch app are force synced ...



It is worth mentioning that the mobile app does not have an activity or something. So there is no way to manually start it.

Is there anything I'm missing. From my perspective there is not reason not to work ...

Mobile Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="name.name" >

<uses-sdk android:minSdkVersion="18"
android:targetSdkVersion="21" />

<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
<uses-permission android:name="android.permission.BATTERY_STATS"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" >
<!--android:theme="@style/AppTheme" >-->

<service android:name="name.name.BatteryListener"
android:permission="android.permission.BIND_WALLPAPER" >>

<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
<category android:name="com.google.android.wearable.watchface.category.COMPANION_CONFIGURATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>

<meta-data android:name="com.google.android.wearable.beta.app"
android:resource="@xml/wearable_app_desc"/>

<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

</application>

</manifest>


Mobile Gradle:

buildscript {
repositories {
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
}
}

apply plugin: 'com.android.application'

repositories {
jcenter()
}

dependencies {
compile "com.android.support:support-v4:21.0.2"
compile "com.android.support:support-v13:21.0.2"
compile "com.android.support:cardview-v7:21.0.2"
compile "com.google.android.support:wearable:1.1.+"
compile 'com.google.android.gms:play-services-wearable:6.5.+'
compile 'com.android.support:support-v13:21.0.+'

}

// The sample build uses multiple directories to
// keep boilerplate and common code separate from
// the main sample code.
List<String> dirs = [
'main', // main sample code; look here for the interesting stuff.
'common', // components that are reused by multiple samples
'template'] // boilerplate code that is generated by the sample template process

android {
compileSdkVersion 21
buildToolsVersion "20"

defaultConfig {
applicationId "name.name"
minSdkVersion 18
targetSdkVersion 21
}

sourceSets {
main {
dirs.each { dir ->
java.srcDirs "src/${dir}/java"
res.srcDirs "src/${dir}/res"
}
}
androidTest.setRoot('tests')
androidTest.java.srcDirs = ['tests/src']

}


Wear Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="qualiss.qualissfacewatch" >

<uses-sdk android:minSdkVersion="21"
android:targetSdkVersion="21" />

<uses-feature android:name="android.hardware.type.watch" />

<!-- Required to act as a custom watch face. -->
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
<uses-permission android:name="android.permission.BATTERY_STATS"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault">

<service
android:name="name.name.MyWatchFace"
android:label="Name"
android:permission="android.permission.BIND_WALLPAPER" >
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/preview_square"/>
<meta-data
android:name="com.google.android.wearable.watchface.preview_circular"
android:resource="@drawable/preview_circle" />
<meta-data
android:name="com.google.android.wearable.watchface.companionConfigurationAction"
android:value="com.example.android.wearable.watchface.CONFIG_ANALOG" />

<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
<category android:name="com.google.android.wearable.watchface.category.COMPANION_CONFIGURATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

</service>

<service android:name="name.name.BatteryActivity">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
<category android:name="com.google.android.wearable.watchface.category.COMPANION_CONFIGURATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>

<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

</application>

</manifest>


Wear Gradle:

}
buildscript {
repositories {
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
}
}

apply plugin: 'com.android.application'



dependencies {


compile 'com.google.android.gms:play-services-wearable:6.5.+'
compile 'com.android.support:support-v13:21.0.+'
compile 'com.google.android.support:wearable:1.1.+'
compile 'com.google.android.support:wearable:1.1.0'
}

// The sample build uses multiple directories to
// keep boilerplate and common code separate from
// the main sample code.
List<String> dirs = [
'main', // main sample code; look here for the interesting stuff.
'common', // components that are reused by multiple samples
'template'] // boilerplate code that is generated by the sample template process

android {
compileSdkVersion 21

buildToolsVersion "20"

defaultConfig {
applicationId "name.name"
versionCode 1
versionName "1.0"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
}
sourceSets {
main {
dirs.each { dir ->
java.srcDirs "src/${dir}/java"
res.srcDirs "src/${dir}/res"
}
}
androidTest.setRoot('tests')
androidTest.java.srcDirs = ['tests/src']

}
}
}


Both Gradle files were closely matched to Android Watch Face sample ... I was just desperate.

Answer

I've removed those 2 from Wear manifest:

< uses-permission android:name="android.permission.SET_TIME_ZONE"/>
< uses-permission android:name="android.permission.BATTERY_STATS"/>

To me it seems like the correct procedure for permissions should not be to have the same in mobile and wear manifest, but to inherit the wear permissions in mobile and not (also) vice versa.

Thanks for the help!