I have an Android Wear watch face that I'm trying to have vibrate the watch on the hour. It is working except in cases where the watch screen is off. According to the log statements, the handler method is called every minute and the chime method is called on the hour. If I'm debugging over bluetooth with the Moto 360, it works even with the screen off. If I install a release apk, it only vibrates if the screen is on. If the screen is off at the top of the hour, it wont vibrate until the screen comes back on. I have tried acquiring a wake lock before the vibrate with no luck. I'm thinking it may work if I acquire a wake lock in the onCreate and release it in the onDestroy but I would rather not do that to preserve battery. Another interesting tidbit is that I have another function that vibrates when certain data changes in the wearable data api and that is working with the screen off. Maybe the WearableListenerService wakes the watch up long enough for the vibrate to occur. Is there something wrong with my logic or is this a limitation of certain Android Wear devices?
Time change handler:
final Handler mUpdateTimeHandler = new Handler() {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case MSG_UPDATE_TIME:
MyLog.d("Time Tick Message Handler");
doTimeTickStuff();
long timeMs = System.currentTimeMillis();
long delayMs = mInteractiveUpdateRateMs - (timeMs % mInteractiveUpdateRateMs);
mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
break;
}
}
};
doTimeTickStuff()
private void doTimeTickStuff()
{
MyLog.d("timetickstuff");
try {
mCalendar = Calendar.getInstance();
int currMin = mCalendar.get(Calendar.MINUTE);
if (currMin == 0) {
hourlyChime();
}
}
catch(Exception ex)
{
MyLog.e(ex, "Error occurred in time tick handler");
}
if (mIsVisible) {
invalidate();
}
}
hourlyChime()
private void hourlyChime(){
Vibrator v = (Vibrator) getBaseContext().getSystemService(VIBRATOR_SERVICE);
if (v.hasVibrator()) {
MyLog.d("vibrating");
v.vibrate(1000);
}
else {
MyLog.d("No vibrator");
}
}
Update The solution that worked was to create an AlarmManager and register it with a broadcast receiver in the watch face onCreate then unregister the receiver in onDestroy
onCreate()
@Override
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
mChimeAlarmManager =
(AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent ambientStateIntent = new Intent("packagename.HOURLY_CHIME");
mChimePendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
1234, ambientStateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
WeatherTime.this.registerReceiver(chimeReceiver,
new IntentFilter("packagename.HOURLY_CHIME"));
long alarmMs = getMsTillNextHour() + System.currentTimeMillis();
mChimeAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
alarmMs,
mChimePendingIntent);
}
Broadcast Receiver
private BroadcastReceiver chimeReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
hourlyChime();
mChimeAlarmManager.setExact(
AlarmManager.RTC_WAKEUP,
getMsTillNextHour() + System.currentTimeMillis(),
mChimePendingIntent);
}
};
onDestroy()
@Override
public void onDestroy() {
mChimeAlarmManager.cancel(mChimePendingIntent);
super.onDestroy();
}