1

I'm looking for an example of code for an android watch that uses the AlarmManager class to update the face in ambient mode.

Please provide a link or past the code.

Thank you.

kjl
  • 311
  • 3
  • 13

2 Answers2

1

I have developed an Android watch face that also needed to run a method periodically (e.g. every hour). At first a handler seemed to be a good solution, but it stops working when the Android Wear device goes to sleep. Then, I came across the article Keeping Your App Visible and the section "Update Content in Ambient Mode". However, it is not that easy to understand how it applies to watch faces. The solution described here is enabling a periodic update on the watch face, even when the Android Wear device goes to sleep.

Start by adding the following fields to your watch face:

/**
 * Action for the update in ambient mode, per our custom refresh cycle.
 */
private static final String UPDATE_ACTION = "your.package.action.UPDATE";
/**
 * Milliseconds between waking processor/screen for updates
 */
private static final long UPDATE_RATE = TimeUnit.MINUTES.toMillis(30);
private AlarmManager mUpdateAlarmManager;
private PendingIntent mUpdatePendingIntent;
private BroadcastReceiver mUpdateBroadcastReceiver;

In this example, the update is done every 30 minutes. In order to preserve battery power, most wear apps should not frequently update the screen while in ambient mode. Frequent updates have a significant impact on the battery power.

This is what the onCreateEngine() method looks like on my watch face:

@Override
public Engine onCreateEngine() {

    /* Set an AlarmManager. The AlarmManager calls itself again in the end for a periodic update. */
    mUpdateAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    Intent ambientUpdateIntent = new Intent(UPDATE_ACTION);

    mUpdatePendingIntent = PendingIntent.getBroadcast(
            getApplicationContext(), 0, ambientUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    mUpdateBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(this.getClass().getName(), "Broadcast received!");
            doMyUpdateAndScheduleNewUpdate();
        }
    };
    IntentFilter filter = new IntentFilter(UPDATE_ACTION);
    registerReceiver(mUpdateBroadcastReceiver, filter);

    doMyUpdateAndScheduleNewUpdate();

    return new Engine();
}

doMyUpdateAndScheduleNewUpdate() is the method that executes whatever you want to do periodically. Inside that method call also scheduleNewAlarm() - this is very important, as it is the method that will schedule your following alarm. It should be something like:

/**
 * Schedule the next alarm that will call onReceive of the BroadcastReceiver.
 */
private void scheduleNewAlarm() {
    // Calculate the next trigger time
    long triggerTimeMs = System.currentTimeMillis() + UPDATE_RATE;
    mUpdateAlarmManager.setExact(
            AlarmManager.RTC_WAKEUP,
            triggerTimeMs,
            mUpdatePendingIntent);
}

Finally, override the onDestroy method of your WatchFaceService, which is called right before the service is going away. There, we want to cancel the update Intent and unregister the broadcast receiver. Basically, add this code:

@Override
public void onDestroy() {
    // take care of the AlarmManager periodic update
    mUpdateAlarmManager.cancel(mUpdatePendingIntent);
    unregisterReceiver(mUpdateBroadcastReceiver);
    super.onDestroy();
}
DarkScrolls
  • 581
  • 5
  • 10
0

I'm looking for an example of code for an android watch that uses the AlarmManager class to update the face in ambient mode.

What you're looking for is the Update more frequently Android Wear guide.

Prepare the alarm manager The alarm manager launches a pending intent that updates the screen and schedules the next alarm. The following example shows how to declare the alarm manager and the pending intent in the onCreate() method of your activity:

private AlarmManager mAmbientStateAlarmManager;
private PendingIntent mAmbientStatePendingIntent;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setAmbientEnabled();

    mAmbientStateAlarmManager =
        (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent ambientStateIntent =
        new Intent(getApplicationContext(), MainActivity.class);

    mAmbientStatePendingIntent = PendingIntent.getActivity(
        getApplicationContext(),
        0,
        ambientStateIntent,
        PendingIntent.FLAG_UPDATE_CURRENT);
    ...
}

Update screen and schedule data updates In this example activity, the alarm manager triggers every 20 seconds in ambient mode. When the timer ticks, the alarm triggers the intent to update the screen and then sets the delay for the next update.

The following example shows how to update information on the screen and set the alarm for the next update:

// Milliseconds between waking processor/screen for updates
private static final long AMBIENT_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20);

private void refreshDisplayAndSetNextUpdate() {

    if (isAmbient()) {
        // Implement data retrieval and update the screen for ambient mode
    } else {
        // Implement data retrieval and update the screen for interactive mode
    }

    long timeMs = System.currentTimeMillis();

    // Schedule a new alarm
    if (isAmbient()) {
        // Calculate the next trigger time
        long delayMs = AMBIENT_INTERVAL_MS - (timeMs % AMBIENT_INTERVAL_MS);
        long triggerTimeMs = timeMs + delayMs;

        mAmbientStateAlarmManager.setExact(
            AlarmManager.RTC_WAKEUP,
            triggerTimeMs,
            mAmbientStatePendingIntent);

    } else {
        // Calculate the next trigger time for interactive mode
    }
}

Check the link for the full guide.

ReyAnthonyRenacia
  • 17,219
  • 5
  • 37
  • 56
  • This code seems to be for an android wear app rather than a watch. – kjl Jul 27 '16 at 04:20
  • android watch is android wear. Did you see the 'isAmbient()' part? that's for android watch. Read the links also – ReyAnthonyRenacia Jul 27 '16 at 04:22
  • as far as I can tell, the method to test ambient mode for the watch service is isInAmbientMode() – kjl Jul 27 '16 at 06:18
  • They both are. isAmbient() belongs to [WearableActivity](https://developer.android.com/reference/android/support/wearable/activity/WearableActivity.html#isAmbient()) class while isInAmbientMode() belongs to [WatchFaceService.Engine](https://developer.android.com/reference/android/support/wearable/watchface/WatchFaceService.Engine.html#isInAmbientMode()) class. – ReyAnthonyRenacia Jul 27 '16 at 06:28
  • exactly. I'm looking for code that shows how to apply AlarmManager to the WatchFaceServiceEngine class. I've come across examples for wearable apps. I'm looking for an example that pertains to code for the watchface. If you could tell me how to adjust the code to work on a watch face or show me a link to an example for code that works on a watch face, that would help me greatly. – kjl Jul 27 '16 at 06:48
  • I think you resolved your problem in this [SO thread](http://stackoverflow.com/questions/38288773/where-to-declair-the-alarm-manager-for-updating-a-watchface-in-ambient-mode) – ReyAnthonyRenacia Jul 28 '16 at 07:20
  • Half way there. I have yet to figure out how to setup and use the alarms. – kjl Jul 28 '16 at 19:59