title: Start Android Wear Watchface from Activity
body: <p>I am wondering if it's possible to start the Watchface Service from an activity?</p>
  
  <p>I tried to start the service in the onCreate method of my activity but it does not show the Watchface:</p>
  
  <pre><code>    Intent serviceIntent = new Intent(this, CustomWatchFaceService);
      startService(serviceIntent);
  </code></pre>
  
  <p><em>update</em>
  Here is the code for the WatchfaceService</p>
  
  <pre><code>public class CustomWatchFaceService extends CanvasWatchFaceService {
      private static final String TAG = "DigitalWatchFaceService";
  
      private static final Typeface BOLD_TYPEFACE =
              Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
      private static final Typeface NORMAL_TYPEFACE =
              Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
  
      private static final long NORMAL_UPDATE_RATE_MS = 500;
      private static final long MUTE_UPDATE_RATE_MS = TimeUnit.MINUTES.toMillis(1);
  
      @Override
      public Engine onCreateEngine() {
          return new Engine();
      }
  
      private class Engine extends CanvasWatchFaceService.Engine {
  
          static final String COLON_STRING = ":";
          static final int MUTE_ALPHA = 100;
          static final int NORMAL_ALPHA = 255;
          static final int MSG_UPDATE_TIME = 0;
          long mInteractiveUpdateRateMs = NORMAL_UPDATE_RATE_MS;
  
          final Handler mUpdateTimeHandler = new Handler() {
              @Override
              public void handleMessage(Message message) {
                  switch (message.what) {
                      case MSG_UPDATE_TIME:
                          if (Log.isLoggable(TAG, Log.VERBOSE)) {
                              Log.v(TAG, "updating time");
                          }
                          invalidate();
                          if (shouldTimerBeRunning()) {
                              long timeMs = System.currentTimeMillis();
                              long delayMs =
                                      mInteractiveUpdateRateMs - (timeMs % mInteractiveUpdateRateMs);
                              mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
                          }
                          break;
                  }
              }
          };
  
  
          Paint mBackgroundPaint;
          Bitmap mBackgroundBitmap;
          Bitmap wifiIconOn;
          Bitmap wifiIconOff;
          Paint mDatePaint;
          Paint mNotificationPaint;
          Paint mNotificationMax;
          Paint mNotificationHigh;
          Paint mHourPaint;
          Paint mMinutePaint;
          Paint mSecondPaint;
          Paint mAmPmPaint;
          Paint mColonPaint;
          float mColonWidth;
          boolean mMute;
  
          Calendar mCalendar;
          Date mDate;
          SimpleDateFormat mDayOfWeekFormat;
          java.text.DateFormat mDateFormat;
  
          boolean mShouldDrawColons;
          float mXOffset;
          float mYOffset;
          float mLineHeight;
  
          int mInteractiveBackgroundColor =
                  R.color.interactive_bg;
          int mInteractiveNotificationMax =
                  R.color.notification_max;
          int mInteractiveNotificationHigh =
                  R.color.notification_high;
          int mInteractiveNotificationColor =
                  R.color.notification;
          int mInteractiveHourDigitsColor =
                  R.color.interactive_time;
          int mInteractiveMinuteDigitsColor =
                  R.color.interactive_time;
          int mInteractiveSecondDigitsColor =
                  R.color.interactive_time;
  
          boolean mLowBitAmbient;
  
          @Override
          public void onCreate(SurfaceHolder holder) {
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "onCreate");
              }
              super.onCreate(holder);
              Locale locale = new Locale("de");
              Locale.setDefault(locale);
              Configuration config = getResources().getConfiguration();
              getBaseContext().getResources().updateConfiguration(config,
                      getBaseContext().getResources().getDisplayMetrics());
  
  
              setWatchFaceStyle(new WatchFaceStyle.Builder(CustomWatchFaceService.this)
                      .setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE)
                      .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
                      .setShowSystemUiTime(false)
                      .build());
              Resources resources = CustomWatchFaceService.this.getResources();
              mYOffset = resources.getDimension(R.dimen.digital_y_offset);
              mLineHeight = resources.getDimension(R.dimen.digital_line_height);
  
  
              setInteractiveColors();
  
              // Not sure why the text color needs to be set here again ... it should be set in setDefaultColors()!
              mDatePaint.setColor(getColor(R.color.digital_date));
              mNotificationPaint.setColor(getColor(R.color.notification));
              mNotificationMax.setColor(getColor(R.color.notification_max));
              mNotificationHigh.setColor(getColor(R.color.notification_high));
  
              mHourPaint.setColor(getColor(R.color.interactive_time));
              mMinutePaint.setColor(getColor(R.color.interactive_time));
              mSecondPaint.setColor(getColor(R.color.interactive_time));
              mColonPaint.setColor(getColor(R.color.interactive_time));
  
              //Images should be loaded here so they can be called during the Draw Method
              wifiIconOn = BitmapFactory.decodeResource(CustomWatchFaceService.this.getResources(), R.drawable.wifi_on_small);
              wifiIconOff = BitmapFactory.decodeResource(CustomWatchFaceService.this.getResources(), R.drawable.wifi_off_small);
              mBackgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.customcart_logo_240_alpha);
  
  
  
              mCalendar = Calendar.getInstance();
              mDate = new Date();
              initFormats();
          }
  
          public void setInteractiveColors() {
              mBackgroundPaint = new Paint();
              mBackgroundPaint.setColor(getColor(mInteractiveBackgroundColor));
              mNotificationPaint = createTextPaint(mInteractiveNotificationColor);
              mNotificationMax = createTextPaint(mInteractiveNotificationMax);
              mNotificationHigh = createTextPaint(mInteractiveNotificationHigh);
              mDatePaint = createTextPaint(R.color.digital_date);
              mHourPaint = createTextPaint(mInteractiveHourDigitsColor, BOLD_TYPEFACE);
              mMinutePaint = createTextPaint(mInteractiveMinuteDigitsColor);
              mSecondPaint = createTextPaint(mInteractiveSecondDigitsColor);
              mColonPaint = createTextPaint(R.color.digital_colons);
          }
          @Override
          public void onDestroy() {
              mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
              super.onDestroy();
          }
  
          private Paint createTextPaint(int defaultInteractiveColor) {
              return createTextPaint(defaultInteractiveColor, NORMAL_TYPEFACE);
          }
  
          private Paint createTextPaint(int defaultInteractiveColor, Typeface typeface) {
              Paint paint = new Paint();
              paint.setColor(defaultInteractiveColor);
              paint.setTypeface(typeface);
              paint.setAntiAlias(true);
              return paint;
          }
  
          @Override
          public void onVisibilityChanged(boolean visible) {
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "onVisibilityChanged: " + visible);
              }
              super.onVisibilityChanged(visible);
              updateTimer();
          }
  
          private void initFormats() {
              mDayOfWeekFormat = new SimpleDateFormat("EEEE", Locale.getDefault());
              mDayOfWeekFormat.setCalendar(mCalendar);
              mDateFormat = DateFormat.getDateFormat(CustomWatchFaceService.this);
              mDateFormat.setCalendar(mCalendar);
          }
  
  
          @Override
          public void onApplyWindowInsets(WindowInsets insets) {
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "onApplyWindowInsets: " + (insets.isRound() ? "round" : "square"));
              }
              super.onApplyWindowInsets(insets);
  
              // Load resources that have alternate values for round watches.
              Resources resources = CustomWatchFaceService.this.getResources();
              boolean isRound = insets.isRound();
              mXOffset = resources.getDimension(isRound
                      ? R.dimen.digital_x_offset_round : R.dimen.digital_x_offset);
              float textSize = resources.getDimension(isRound
                      ? R.dimen.digital_text_size_round : R.dimen.digital_text_size);
              float notificationTextSize = resources.getDimension(isRound
                      ? R.dimen.notification_text_size : R.dimen.notification_text_size);
  
              mDatePaint.setTextSize(resources.getDimension(R.dimen.digital_date_text_size));
  
              mHourPaint.setTextSize(textSize);
              mMinutePaint.setTextSize(textSize);
              mSecondPaint.setTextSize(textSize);
              mColonPaint.setTextSize(textSize);
              mNotificationPaint.setTextSize(notificationTextSize);
  
              mColonWidth = mColonPaint.measureText(COLON_STRING);
  
          }
  
          @Override
          public void onPropertiesChanged(Bundle properties) {
              super.onPropertiesChanged(properties);
  
              boolean burnInProtection = properties.getBoolean(PROPERTY_BURN_IN_PROTECTION, false);
              mHourPaint.setTypeface(burnInProtection ? NORMAL_TYPEFACE : BOLD_TYPEFACE);
  
              mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false);
  
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "onPropertiesChanged: burn-in protection = " + burnInProtection
                          + ", low-bit ambient = " + mLowBitAmbient);
              }
          }
  
          @Override
          public void onTimeTick() {
              super.onTimeTick();
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "onTimeTick: ambient = " + isInAmbientMode());
              }
              invalidate();
          }
  
          @Override
          public void onAmbientModeChanged(boolean inAmbientMode) {
              super.onAmbientModeChanged(inAmbientMode);
              if (!isInAmbientMode()) {
                  mBackgroundPaint = new Paint();
                  mBackgroundPaint.setColor(getColor(R.color.interactive_bg));
                  mDatePaint.setColor(getColor(R.color.digital_date));
                  mHourPaint.setColor(getColor(R.color.interactive_time));
                  mMinutePaint.setColor(getColor(R.color.interactive_time));
                  mSecondPaint.setColor(getColor(R.color.interactive_time));
                  mColonPaint.setColor(getColor(R.color.interactive_time));
              }
              else {
                  mBackgroundPaint = new Paint();
                  mBackgroundPaint.setColor(getColor(R.color.ambient_bg));
                  mDatePaint.setColor(getColor(R.color.digital_date));
                  mHourPaint.setColor(getColor(R.color.ambient_time));
                  mMinutePaint.setColor(getColor(R.color.ambient_time));
                  mSecondPaint.setColor(getColor(R.color.ambient_time));
                  mColonPaint.setColor(getColor(R.color.ambient_time));
              }
  
              //Log.d("XXX", "onAmbientModeChanged: " + inAmbientMode);
  
  
              if (mLowBitAmbient) {
                  boolean antiAlias = !inAmbientMode;
                  mDatePaint.setAntiAlias(antiAlias);
                  mHourPaint.setAntiAlias(antiAlias);
                  mMinutePaint.setAntiAlias(antiAlias);
                  mSecondPaint.setAntiAlias(antiAlias);
                  mAmPmPaint.setAntiAlias(antiAlias);
                  mColonPaint.setAntiAlias(antiAlias);
              }
              invalidate();
  
              // Whether the timer should be running depends on whether we're in ambient mode (as well
              // as whether we're visible), so we may need to start or stop the timer.
              updateTimer();
          }
  
          @Override
          public void onInterruptionFilterChanged(int interruptionFilter) {
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "onInterruptionFilterChanged: " + interruptionFilter);
              }
              super.onInterruptionFilterChanged(interruptionFilter);
  
              boolean inMuteMode = interruptionFilter == WatchFaceService.INTERRUPTION_FILTER_NONE;
              // We only need to update once a minute in mute mode.
              setInteractiveUpdateRateMs(inMuteMode ? MUTE_UPDATE_RATE_MS : NORMAL_UPDATE_RATE_MS);
  
              if (mMute != inMuteMode) {
                  mMute = inMuteMode;
                  int alpha = inMuteMode ? MUTE_ALPHA : NORMAL_ALPHA;
                  mDatePaint.setAlpha(alpha);
                  mHourPaint.setAlpha(alpha);
                  mMinutePaint.setAlpha(alpha);
                  mColonPaint.setAlpha(alpha);
                  mAmPmPaint.setAlpha(alpha);
                  invalidate();
              }
          }
  
          public void setInteractiveUpdateRateMs(long updateRateMs) {
              if (updateRateMs == mInteractiveUpdateRateMs) {
                  return;
              }
              mInteractiveUpdateRateMs = updateRateMs;
  
              // Stop and restart the timer so the new update rate takes effect immediately.
              if (shouldTimerBeRunning()) {
                  updateTimer();
              }
          }
  
          private String formatTwoDigitNumber(int hour) {
              return String.format("%02d", hour);
          }
  
          @Override
          public void onDraw(Canvas canvas, Rect bounds) {
              long now = System.currentTimeMillis();
  
  
              int width = bounds.width();
              int height = bounds.height();
              mCalendar.setTimeInMillis(now);
              mDate.setTime(now);
              boolean is24Hour = DateFormat.is24HourFormat(CustomWatchFaceService.this);
  
              // Draw the background.
              canvas.drawRect(0, 0, bounds.width(), bounds.height(), mBackgroundPaint);
  
              //Draw the background Image
              if (mBackgroundBitmap == null
                      || mBackgroundBitmap.getWidth() != width
                      || mBackgroundBitmap.getHeight() != height) {
                  mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap,
                          width, height, true /* filter */);
  
              }
              //Log.d("XXX", "Width: "+ mBackgroundBitmap.getWidth() + "Height: "+mBackgroundBitmap.getHeight() );
  
  
              if (isInAmbientMode() &amp;&amp; (mLowBitAmbient)) {
                  canvas.drawColor(Color.BLACK);
              } else if (isInAmbientMode()) {
                  canvas.drawColor(Color.BLACK);
              } else {
                  canvas.drawBitmap(mBackgroundBitmap, 0, 0, mBackgroundPaint);
              }
  
  
  
              // Show colons for the first half of each second so the colons blink on when the time updates.
              mShouldDrawColons = (System.currentTimeMillis() % 1000) &lt; 500;
  
  
  
              // Draw the hours.
              float x = mXOffset;
              String hourString;
              if (is24Hour) {
                  hourString = formatTwoDigitNumber(mCalendar.get(Calendar.HOUR_OF_DAY));
              } else {
                  int hour = mCalendar.get(Calendar.HOUR);
                  if (hour == 0) {
                      hour = 12;
                  }
                  hourString = String.valueOf(hour);
              }
              canvas.drawText(hourString, x, mYOffset, mHourPaint);
              x += mHourPaint.measureText(hourString);
  
              // In ambient and mute modes, always draw the first colon. Otherwise, draw the
              // first colon for the first half of each second.
              if (isInAmbientMode() || mMute || mShouldDrawColons) {
                  canvas.drawText(COLON_STRING, x, mYOffset, mColonPaint);
              }
              x += mColonWidth;
  
              // Draw the minutes.
              String minuteString = formatTwoDigitNumber(mCalendar.get(Calendar.MINUTE));
              canvas.drawText(minuteString, x, mYOffset, mMinutePaint);
              x += mMinutePaint.measureText(minuteString);
  
              // In unmuted interactive mode, draw a second blinking colon followed by the seconds.
              // Otherwise, if we're in 12-hour mode, draw AM/PM
              if (!isInAmbientMode() &amp;&amp; !mMute) {
                  if (mShouldDrawColons) {
                      canvas.drawText(COLON_STRING, x, mYOffset, mColonPaint);
                  }
                  x += mColonWidth;
                  canvas.drawText(formatTwoDigitNumber(
                          mCalendar.get(Calendar.SECOND)), x, mYOffset, mSecondPaint);
              } else if (!is24Hour) {
                  x += mColonWidth;
  
              }
  
              // Only render the day of week and date if there is no peek card, so they do not bleed
              // into each other in ambient mode.
              if (getPeekCardPosition().isEmpty()) {
                  // Day of week
                  canvas.drawText(
                          mDayOfWeekFormat.format(mDate),
                          mXOffset, mYOffset + mLineHeight, mDatePaint);
                  // Date
                  canvas.drawText(
                          mDateFormat.format(mDate),
                          mXOffset, mYOffset + mLineHeight * 2, mDatePaint);
              }
  
          }
  
          /**
           * Starts the {@link #mUpdateTimeHandler} timer if it should be running and isn't currently
           * or stops it if it shouldn't be running but currently is.
           */
          private void updateTimer() {
              if (Log.isLoggable(TAG, Log.DEBUG)) {
                  Log.d(TAG, "updateTimer");
              }
              mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
              if (shouldTimerBeRunning()) {
                  mUpdateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME);
              }
          }
  
          /**
           * Returns whether the {@link #mUpdateTimeHandler} timer should be running. The timer should
           * only run when we're visible and in interactive mode.
           */
          private boolean shouldTimerBeRunning() {
              return isVisible() &amp;&amp; !isInAmbientMode();
          }
      }
  }
  </code></pre>