-1

I have created a watch face using CanvasWatchFaceService. I have created the watch face. And created the configuration app for phone.

The problem is, my watch face is taking too much battery, and when watch go to sleep it wakes in 1-2 minutes. And lagging the watch too much, I want it to run smoothly. And it is restarting my watch too.

I am testing the Watch Face on Moto 360.

public class DigitalWatchFaceService extends CanvasWatchFaceService {

String[] days = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
String[] months = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG",
        "SEP", "OCT", "NOV", "DEC" };

Prefs prefs;

@Override
public Engine onCreateEngine() {
    /* provide your watch face implementation */
    return new Engine();
}

/* implement service callback methods */
private class Engine extends CanvasWatchFaceService.Engine {

    boolean hr24Format = false;
    int hourColor = -1, minuteColor = -16742014, secondColor = -16723470,
            backgroundColor = -16761271;
    int width, centerX, centerY;

    Canvas canvas;

    Typeface typeFace;
    Paint hourPaint;
    Paint minutePaint;
    Paint datePaint;
    Paint hourCircle, minuteCircle, secondCircle;
    RectF ovalHour, ovalMinute, ovalSecond;
    Calendar cal;

    int day, month, date;
    Rect hourBounds, minuteBounds, dateBounds;
    String mHour = "00", mMinutes, mDate;
    int hh, mm, ss;

    boolean inAmbientMode;

    @Override
    public void onCreate(SurfaceHolder holder) {
        super.onCreate(holder);
        /* initialize your watch face */
        setWatchFaceStyle(new WatchFaceStyle.Builder(
                DigitalWatchFaceService.this)
                .setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE)
                .setBackgroundVisibility(
                        WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
                .setShowSystemUiTime(false).build());
        prefs = new Prefs(DigitalWatchFaceService.this);
        typeFace = Typeface.createFromAsset(getAssets(), "roboto.ttf");

        initAssets();
        setAssets();

    }

    private void setAssets() {
        // TODO Auto-generated method stub
        hourPaint.setColor(hourColor);
        hourPaint.setTextSize(70);
        hourPaint.setTypeface(typeFace);
        hourPaint.setAntiAlias(true);

        minutePaint.setColor(minuteColor);
        minutePaint.setTextSize(70);
        minutePaint.setTypeface(typeFace);
        minutePaint.setAntiAlias(true);

        datePaint.setColor(hourColor);
        datePaint.setTextSize(20);
        datePaint.setTypeface(typeFace);
        datePaint.setAntiAlias(true);

        hourCircle.setColor(hourColor);
        hourCircle.setStyle(Paint.Style.FILL);
        hourCircle.setStyle(Paint.Style.STROKE);
        hourCircle.setStrokeWidth(7);
        hourCircle.setAntiAlias(true);

        minuteCircle.setColor(minuteColor);
        minuteCircle.setStyle(Paint.Style.FILL);
        minuteCircle.setStyle(Paint.Style.STROKE);
        minuteCircle.setStrokeWidth(5);
        minuteCircle.setAntiAlias(true);

        secondCircle.setColor(secondColor);
        secondCircle.setStyle(Paint.Style.FILL);
        secondCircle.setStyle(Paint.Style.STROKE);
        secondCircle.setStrokeWidth(2);
        secondCircle.setAntiAlias(true);

        ovalHour.set(32, 32, width - 32, width - 32);
        ovalMinute = new RectF();
        ovalMinute.set(22, 22, width - 22, width - 22);
        ovalSecond = new RectF();
        ovalSecond.set(15, 15, width - 15, width - 15);
    }

    private void initAssets() {
        // TODO Auto-generated method stub
        hourPaint = new Paint();
        minutePaint = new Paint();
        datePaint = new Paint();

        hourCircle = new Paint();

        minuteCircle = new Paint();

        secondCircle = new Paint();

        ovalHour = new RectF();

        hourBounds = new Rect();
        minuteBounds = new Rect();
        dateBounds = new Rect();
    }

    @Override
    public void onPropertiesChanged(Bundle properties) {
        super.onPropertiesChanged(properties);
        /* get device features (burn-in, low-bit ambient) */
    }

    @Override
    public void onTimeTick() {
        super.onTimeTick();
        /* the time changed */
    }

    @Override
    public void onAmbientModeChanged(boolean inAmbientMode) {
        super.onAmbientModeChanged(inAmbientMode);
        /* the wearable switched between modes */
        this.inAmbientMode = inAmbientMode;
        if (inAmbientMode) {
            backgroundColor = -16777216;
            hourColor = -1;
            minuteColor = -1;
        } else {
            hourColor = prefs.getPrefs(Prefs.hourColor, -1);
            minuteColor = prefs.getPrefs(Prefs.minuteColor, -16742014);
            backgroundColor = prefs.getPrefs(Prefs.backgroundColor,
                    -16761271);
        }
        setAssets();
    }

    private final String HOUR_FORMAT = "hh";
    private final String HOUR_FORMAT_24 = "kk";
    private final String MINUTE_FORMAT = "mm";

    @Override
    public void onDraw(Canvas canvas, Rect bounds) {
        /* draw your watch face */
        this.canvas = canvas;
        width = bounds.width();
        centerX = bounds.centerX();
        centerY = bounds.centerY();
        backgroundColor = prefs.getPrefs(Prefs.backgroundColor, -16761271);
        canvas.drawColor(backgroundColor);
        drawForNormalMode();
    }

    public void drawForNormalMode() {
        hr24Format = prefs.getPrefs(Prefs.format24Key, false);
        if (!inAmbientMode) {
            hourColor = prefs.getPrefs(Prefs.hourColor, -1);
            minuteColor = prefs.getPrefs(Prefs.minuteColor, -16742014);
            secondColor = prefs.getPrefs(Prefs.secondColor, -16723470);
            backgroundColor = prefs.getPrefs(Prefs.backgroundColor,
                    -16761271);
        }
        setTimeNormal();
    }

    public void setTimeNormal() {
        cal = Calendar.getInstance();
        day = cal.get(Calendar.DAY_OF_WEEK);
        month = cal.get(Calendar.MONTH);
        date = cal.get(Calendar.DATE);

        // draw hour
        if (hr24Format == false)
            mHour = new SimpleDateFormat(HOUR_FORMAT).format(cal.getTime());
        else
            mHour = new SimpleDateFormat(HOUR_FORMAT_24).format(cal
                    .getTime());

        hourPaint.getTextBounds(mHour, 0, mHour.length(), hourBounds);
        canvas.drawText(mHour, centerX - hourBounds.width() - 15, centerY
                - hourBounds.centerY(), hourPaint);

        // draw minute
        mMinutes = new SimpleDateFormat(MINUTE_FORMAT)
                .format(cal.getTime());
        minutePaint.getTextBounds(mMinutes, 0, mMinutes.length(),
                minuteBounds);
        canvas.drawText(mMinutes, centerX,
                centerY - minuteBounds.centerY(), minutePaint);

        // draw date
        if (!inAmbientMode) {
            mDate = days[day - 1] + ", " + months[month] + " " + date;
            datePaint.getTextBounds(mDate, 0, mDate.length(), dateBounds);
            canvas.drawText(mDate, centerX - dateBounds.centerX(), centerY
                    + hourBounds.height() + 10, datePaint);
        }

        // draw minute circle
        mm = cal.get(Calendar.MINUTE);
        circularMinute(mm, 60);

        // draw hour circle
        hh = cal.get(Calendar.HOUR);
        circularHour((hh * 60) + mm, 720);

        // draw second circle
        if (!inAmbientMode)
            ss = cal.get(Calendar.SECOND);
        circularSecond(ss, 60);

        invalidate();
    }

    private void circularHour(int number, int max) {
        canvas.drawArc(ovalHour, 270, ((number * 360) / max), false,
                hourCircle);
    }

    private void circularMinute(int number, int max) {
        canvas.drawArc(ovalMinute, 270, ((number * 360) / max), false,
                minuteCircle);
    }

    private void circularSecond(int number, int max) {
        canvas.drawArc(ovalSecond, 270, ((number * 360) / max), false,
                secondCircle);
    }

    @Override
    public void onVisibilityChanged(boolean visible) {
        super.onVisibilityChanged(visible);
        /* the watch face became visible or invisible */
    }
}
   }
halfer
  • 19,824
  • 17
  • 99
  • 186
Ayush
  • 1
  • 1
  • 2
  • how often onDraw is called? – pskink Mar 07 '15 at 16:33
  • I think 3 times in 1 milisecond – Ayush Mar 07 '15 at 16:35
  • what ??? so your frame rate is 3000 fps ??? – pskink Mar 07 '15 at 16:36
  • i don't know. when i used log in onDraw method. It was printing 2 or 3 logs per milliseconds, so i updated the time in onDraw Function – Ayush Mar 07 '15 at 16:37
  • And it is restarting my watch too. again and again – Ayush Mar 07 '15 at 16:44
  • You're doing way too much in your onDraw method. Getting preferences, creating new paints, etc. are expensive calls. – myanimal Mar 07 '15 at 17:00
  • so, what should i do. i think i can update time only in ondraw. But can getting preferences make a significant difference? And i try optimising my code, then test. Thanks for this. – Ayush Mar 07 '15 at 17:06
  • I have optimised my code. Not i initialized all variables in onCreate. I am only fetching SharedPrefs and drawing objects in onDraw. Will it run smoothly to fetch SharedPrefs in onDraw – Ayush Mar 07 '15 at 17:28
  • I have changed my code in question. Please see it, now i have changed many things but it is lagging.:( – Ayush Mar 07 '15 at 18:10
  • Sorry for wrong answer. onDraw was called 2-3 times per second not millisecond. And that was recursion as answered below. Thanks for your help buddy. – Ayush Mar 07 '15 at 18:43

1 Answers1

2

You are calling "invalidate" within "onDraw" (last line of "setTimeNormal"), so your watchface will be continuously repainted over and over again.

Update:

Follow the documentation here: http://developer.android.com/training/wearables/watch-faces/drawing.html

The WatchFace is automatically drawn once a minute so you shouldn't ever call "invalidate" unless you're doing a custom animation or need updates faster than 1 per minute.

Ander Webbs
  • 1,158
  • 1
  • 8
  • 11