/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.wearable.watchface; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.os.Bundle; import android.support.wearable.watchface.CanvasWatchFaceService; import android.support.wearable.watchface.WatchFaceStyle; import android.util.Log; import android.view.SurfaceHolder; import android.view.WindowInsets; /** * Demonstrates interactive watch face capabilities, i.e., touching the display and registering * three different events: touch, touch-cancel and tap. The watch face UI will show the count of * these events as they occur. See the {@code onTapCommand} below. */ public class InteractiveWatchFaceService extends CanvasWatchFaceService { private static final String TAG = "InteractiveWatchFace"; 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); @Override public Engine onCreateEngine() { return new Engine(); } private class Engine extends CanvasWatchFaceService.Engine { private Paint mTextPaint; private final Paint mPeekCardBackgroundPaint = new Paint(); private float mXOffset; private float mYOffset; private float mTextSpacingHeight; private int mScreenTextColor = Color.WHITE; private int mTouchCommandTotal; private int mTouchCancelCommandTotal; private int mTapCommandTotal; private int mTouchCoordinateX; private int mTouchCoordinateY; private final Rect mCardBounds = new Rect(); /** * Whether the display supports fewer bits for each color in ambient mode. When true, we * disable anti-aliasing in ambient mode. */ private boolean mLowBitAmbient; @Override public void onCreate(SurfaceHolder holder) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "onCreate"); } super.onCreate(holder); /** Accepts tap events via WatchFaceStyle (setAcceptsTapEvents(true)). */ setWatchFaceStyle(new WatchFaceStyle.Builder(InteractiveWatchFaceService.this) .setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE) .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE) .setShowSystemUiTime(false) .setAcceptsTapEvents(true) .build()); Resources resources = InteractiveWatchFaceService.this.getResources(); mTextSpacingHeight = resources.getDimension(R.dimen.interactive_text_size); mTextPaint = new Paint(); mTextPaint.setColor(mScreenTextColor); mTextPaint.setTypeface(BOLD_TYPEFACE); mTextPaint.setAntiAlias(true); mTouchCommandTotal = 0; mTouchCancelCommandTotal = 0; mTapCommandTotal = 0; mTouchCoordinateX = 0; mTouchCoordinateX = 0; } @Override public void onApplyWindowInsets(WindowInsets insets) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "onApplyWindowInsets: " + (insets.isRound() ? "round" : "square")); } super.onApplyWindowInsets(insets); /** Loads offsets / text size based on device type (square vs. round). */ Resources resources = InteractiveWatchFaceService.this.getResources(); boolean isRound = insets.isRound(); mXOffset = resources.getDimension( isRound ? R.dimen.interactive_x_offset_round : R.dimen.interactive_x_offset); mYOffset = resources.getDimension( isRound ? R.dimen.interactive_y_offset_round : R.dimen.interactive_y_offset); float textSize = resources.getDimension( isRound ? R.dimen.interactive_text_size_round : R.dimen.interactive_text_size); mTextPaint.setTextSize(textSize); } @Override public void onPeekCardPositionUpdate(Rect bounds) { super.onPeekCardPositionUpdate(bounds); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "onPeekCardPositionUpdate: " + bounds); } super.onPeekCardPositionUpdate(bounds); if (!bounds.equals(mCardBounds)) { mCardBounds.set(bounds); invalidate(); } } @Override public void onPropertiesChanged(Bundle properties) { super.onPropertiesChanged(properties); boolean burnInProtection = properties.getBoolean(PROPERTY_BURN_IN_PROTECTION, false); mTextPaint.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 onAmbientModeChanged(boolean inAmbientMode) { super.onAmbientModeChanged(inAmbientMode); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "onAmbientModeChanged: " + inAmbientMode); } if (mLowBitAmbient) { boolean antiAlias = !inAmbientMode; mTextPaint.setAntiAlias(antiAlias); } invalidate(); } /* * Captures tap event (and tap type) and increments correct tap type total. */ @Override public void onTapCommand(int tapType, int x, int y, long eventTime) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Tap Command: " + tapType); } mTouchCoordinateX = x; mTouchCoordinateY = y; switch(tapType) { case TAP_TYPE_TOUCH: mTouchCommandTotal++; break; case TAP_TYPE_TOUCH_CANCEL: mTouchCancelCommandTotal++; break; case TAP_TYPE_TAP: mTapCommandTotal++; break; } invalidate(); } @Override public void onDraw(Canvas canvas, Rect bounds) { /** Draws background */ canvas.drawColor(Color.BLACK); canvas.drawText( "TAP: " + String.valueOf(mTapCommandTotal), mXOffset, mYOffset, mTextPaint); canvas.drawText( "CANCEL: " + String.valueOf(mTouchCancelCommandTotal), mXOffset, mYOffset + mTextSpacingHeight, mTextPaint); canvas.drawText( "TOUCH: " + String.valueOf(mTouchCommandTotal), mXOffset, mYOffset + (mTextSpacingHeight * 2), mTextPaint); canvas.drawText( "X, Y: " + mTouchCoordinateX + ", " + mTouchCoordinateY, mXOffset, mYOffset + (mTextSpacingHeight * 3), mTextPaint ); /** Covers area under peek card */ if (isInAmbientMode()) { canvas.drawRect(mCardBounds, mPeekCardBackgroundPaint); } } } }