For this tutorial I will go over creating a custom watch face for the Android Wear. There are rumors that Google will be releasing a watch face builder class, but right now no one is sure when/if that will happen. The point of this tutorial is to be a central place for information on building custom watch faces with the current system, as the information is currently scattered across Reddit and Google+ posts.
This demo app allows the user to select a school from a list and then displays the time in the corner with the school logo below it. The settings activity for selecting the school is not a requirement for the watch face, as you can choose to only display one type of face, but I included it to show an additional feature. I also removed the mobile activity launcher, as it's not a necessity for the app. The code for this app is available on GitHub.
Watch face for Fresno State |
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
In the wear AndroidManifest.xml file, add the following properties to the application tag:
<application
android:allowBackup="true"
android:icon="@drawable/bulldog_wallpaper"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault" >
and the following properties to the activity tag for the watch face activity. Note the intent-filter and meta-data tags in the activity section, as those are required for determining if the activity should be selectable as a watch face. I use a general icon for the preview here, but generally a screen shot of the actual watch face (like above) should be used:
<activity
android:name=".WatchFaceActivity"
android:label="@string/app_name"
android:enabled="true"
android:taskAffinity=""
android:allowEmbedded="true"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.google.android.clockwork.home.category.HOME_BACKGROUND" />
</intent-filter>
<meta-data
android:name="com.google.android.clockwork.home.preview"
android:resource="@drawable/bulldog_wallpaper"/>
</activity>
Preview icon for the watch face |
In order to have the list of schools in the application area, we need to have an intent-filter added to the SettingsActivity activity tag:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Once the manifest is put together, we can go ahead and fill in SettingsActivity to display a list of schools and save the selected school in a shared preference. In this example I use an object called SchoolObj that simply loads a list of school names and codes for organizing data:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_settings );
final SchoolObj schools = new SchoolObj();
ListView listView = (ListView) findViewById( R.id.list );
ArrayAdapter<String> adapter = new ArrayAdapter( this, android.R.layout.simple_list_item_1, schools.schoolList );
listView.setAdapter( adapter );
listView.setOnItemClickListener( new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SharedPreferences pref = getSharedPreferences( WatchFaceActivity.SHARED_PREFERENCE, Context.MODE_PRIVATE );
SharedPreferences.Editor editor = pref.edit();
editor.putString( SHARED_PREFERENCE_SCHOOL, schools.schoolCodeList.get( position ) );
editor.commit();
finish();
}
});
}
List of schools for customizing the watch face |
@Override
protected void onResume() {
super.onResume();
SharedPreferences pref = getSharedPreferences( SHARED_PREFERENCE, Context.MODE_PRIVATE );
if( pref.contains( SettingsActivity.SHARED_PREFERENCE_SCHOOL ) ) {
String schoolCode = pref.getString( SettingsActivity.SHARED_PREFERENCE_SCHOOL, "" );
loadSchoolWatchFace( schoolCode );
} else {
mBackground.setImageResource( R.drawable.bulldog_wallpaper );
mClock.setTextColor(getResources().getColor(android.R.color.holo_red_dark));
mContainer.setBackgroundColor(getResources().getColor( android.R.color.white ) );
}
}
It is important that we set these properties every time that the activity resumes, as we must set the watch face to a "blank state" when the watch is put into a power conserving off state and onPause() is called
@Override
protected void onPause() {
super.onPause();
mBackground.setImageDrawable( null );
mClock.setTextColor( getResources().getColor( android.R.color.white ) );
mContainer.setBackgroundColor( getResources().getColor( android.R.color.black ) );
}
Watch Blank State |
private void loadSchoolWatchFace( String schoolCode ) {
if( "cuboulder".equals( schoolCode ) ) {
mBackground.setImageResource( R.drawable.cuboulder_wallpaper );
mClock.setTextColor(getResources().getColor(android.R.color.holo_orange_light));
} else if( "fsu".equals( schoolCode ) ) {
mBackground.setImageResource( R.drawable.floridastate_wallpaper );
mClock.setTextColor(getResources().getColor(android.R.color.holo_red_dark));
} else if( "ucsc".equals( schoolCode ) ) {
mBackground.setImageResource( R.drawable.bananaslugs_logo );
mClock.setTextColor(getResources().getColor(android.R.color.holo_orange_light));
} else if( "berkeley".equals( schoolCode ) ) {
mBackground.setImageResource( R.drawable.berkeley_wallpaper );
mClock.setTextColor(getResources().getColor(android.R.color.holo_orange_light ) );
} else {
//Default to Fresno
mBackground.setImageResource( R.drawable.bulldog_wallpaper );
mClock.setTextColor(getResources().getColor(android.R.color.holo_red_dark));
}
mContainer.setBackgroundColor(getResources().getColor(android.R.color.white));
}
Florida State University watch face |
UC Santa Cruz Banana Slugs watch face |
And that's all there is to it. The important parts to add are the manifest intent-filter and metadata items, and onResume()/onPause() for the watch face, then the rest adds functionality to the app. This can also work with an analog watch face and other views, so there's a lot more possibilities for developers to add some great features.