我正在尝试在Wear模拟器上使用新的watch face API,当我扩展CanvasWatchFaceService时
onTimeTick方法从未被触发,因此时钟永远不会更新.
onTimeTick方法从未被触发,因此时钟永远不会更新.
我正在使用模拟样本并尝试删除秒针(暂时禁用计时器):
/* * Copyright (C) 2014 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.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.wearable.watchface.CanvasWatchFaceService; import android.support.wearable.watchface.WatchFaceService; import android.support.wearable.watchface.WatchFaceStyle; import android.text.format.Time; import android.util.Log; import android.view.SurfaceHolder; import java.util.TimeZone; import java.util.concurrent.TimeUnit; /** * Sample analog watch face with a ticking second hand. In ambient mode,the second hand isn't * shown. On devices with low-bit ambient mode,the hands are drawn without anti-aliasing in ambient * mode. The watch face is drawn with less contrast in mute mode. * * {@link SweepWatchFaceService} is similar but has a sweep second hand. */ public class AnalogWatchFaceService extends CanvasWatchFaceService { private static final String TAG = "AnalogWatchFaceService"; /** * Update rate in milliseconds for interactive mode. We update once a second to advance the * second hand. */ private static final long INTERACTIVE_UPDATE_RATE_MS = TimeUnit.SECONDS.toMillis(1); @Override public Engine onCreateEngine() { return new Engine(); } private class Engine extends CanvasWatchFaceService.Engine { static final int MSG_UPDATE_TIME = 0; Paint mHourPaint; Paint mMinutePaint; Paint mSecondPaint; Paint mTickPaint; boolean mMute; Time mTime; /** Handler to update the time once a second in interactive mode. */ 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 = INTERACTIVE_UPDATE_RATE_MS - (timeMs % INTERACTIVE_UPDATE_RATE_MS); mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME,delayMs); } break; } } }; final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context,Intent intent) { mTime.clear(intent.getStringExtra("time-zone")); mTime.setToNow(); } }; boolean mRegisteredTimeZoneReceiver = false; /** * Whether the display supports fewer bits for each color in ambient mode. When true,we * disable anti-aliasing in ambient mode. */ boolean mLowBitAmbient; Bitmap mBackgroundBitmap; Bitmap mBackgroundScaledBitmap; @Override public void onCreate(SurfaceHolder holder) { if (Log.isLoggable(TAG,Log.DEBUG)) { Log.d(TAG,"onCreate"); } super.onCreate(holder); setWatchFaceStyle(new WatchFaceStyle.Builder(AnalogWatchFaceService.this) .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT) .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE) .setShowsystemUITime(false) .build()); Resources resources = AnalogWatchFaceService.this.getResources(); Drawable backgroundDrawable = resources.getDrawable(R.drawable.bg); mBackgroundBitmap = ((BitmapDrawable) backgroundDrawable).getBitmap(); mHourPaint = new Paint(); mHourPaint.setARGB(255,200,200); mHourPaint.setStrokeWidth(5.f); mHourPaint.setAntiAlias(true); mHourPaint.setStrokeCap(Paint.Cap.ROUND); mMinutePaint = new Paint(); mMinutePaint.setARGB(255,200); mMinutePaint.setStrokeWidth(3.f); mMinutePaint.setAntiAlias(true); mMinutePaint.setStrokeCap(Paint.Cap.ROUND); mSecondPaint = new Paint(); mSecondPaint.setARGB(255,255,0); mSecondPaint.setStrokeWidth(2.f); mSecondPaint.setAntiAlias(true); mSecondPaint.setStrokeCap(Paint.Cap.ROUND); mTickPaint = new Paint(); mTickPaint.setARGB(100,255); mTickPaint.setStrokeWidth(2.f); mTickPaint.setAntiAlias(true); mTime = new Time(); } @Override public void onDestroy() { mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME); super.onDestroy(); } @Override public void onPropertiesChanged(Bundle properties) { super.onPropertiesChanged(properties); mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT,false); if (Log.isLoggable(TAG,"onPropertiesChanged: low-bit ambient = " + mLowBitAmbient); } } @Override public void onTimeTick() { super.onTimeTick(); if (Log.isLoggable(TAG,"onTimeTick: ambient = " + isInAmbientMode()); } invalidate(); } @Override public void onAmbientModeChanged(boolean inAmbientMode) { super.onAmbientModeChanged(inAmbientMode); if (Log.isLoggable(TAG,"onAmbientModeChanged: " + inAmbientMode); } if (mLowBitAmbient) { boolean antiAlias = !inAmbientMode; mHourPaint.setAntiAlias(antiAlias); mMinutePaint.setAntiAlias(antiAlias); mSecondPaint.setAntiAlias(antiAlias); mTickPaint.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) { super.onInterruptionFilterChanged(interruptionFilter); boolean inMuteMode = (interruptionFilter == WatchFaceService.INTERRUPTION_FILTER_NONE); if (mMute != inMuteMode) { mMute = inMuteMode; mHourPaint.setAlpha(inMuteMode ? 100 : 255); mMinutePaint.setAlpha(inMuteMode ? 100 : 255); mSecondPaint.setAlpha(inMuteMode ? 80 : 255); invalidate(); } } @Override public void onDraw(Canvas canvas,Rect bounds) { mTime.setToNow(); int width = bounds.width(); int height = bounds.height(); // Draw the background,scaled to fit. if (mBackgroundScaledBitmap == null || mBackgroundScaledBitmap.getWidth() != width || mBackgroundScaledBitmap.getHeight() != height) { mBackgroundScaledBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap,width,height,true /* filter */); } canvas.drawBitmap(mBackgroundScaledBitmap,null); // Find the center. Ignore the window insets so that,on round watches with a // "chin",the watch face is centered on the entire screen,not just the usable // portion. float centerX = width / 2f; float centerY = height / 2f; // Draw the ticks. float innerTickRadius = centerX - 10; float outerTickRadius = centerX; for (int tickIndex = 0; tickIndex < 12; tickIndex++) { float tickRot = (float) (tickIndex * Math.PI * 2 / 12); float innerX = (float) Math.sin(tickRot) * innerTickRadius; float innerY = (float) -Math.cos(tickRot) * innerTickRadius; float outerX = (float) Math.sin(tickRot) * outerTickRadius; float outerY = (float) -Math.cos(tickRot) * outerTickRadius; canvas.drawLine(centerX + innerX,centerY + innerY,centerX + outerX,centerY + outerY,mTickPaint); } float secRot = mTime.second / 30f * (float) Math.PI; int minutes = mTime.minute; float minRot = minutes / 30f * (float) Math.PI; float hrRot = ((mTime.hour + (minutes / 60f)) / 6f ) * (float) Math.PI; float secLength = centerX - 20; float minLength = centerX - 40; float hrLength = centerX - 80; if (!isInAmbientMode()) { float secX = (float) Math.sin(secRot) * secLength; float secY = (float) -Math.cos(secRot) * secLength; canvas.drawLine(centerX,centerY,centerX + secX,centerY + secY,mSecondPaint); } float minX = (float) Math.sin(minRot) * minLength; float minY = (float) -Math.cos(minRot) * minLength; canvas.drawLine(centerX,centerX + minX,centerY + minY,mMinutePaint); float hrX = (float) Math.sin(hrRot) * hrLength; float hrY = (float) -Math.cos(hrRot) * hrLength; canvas.drawLine(centerX,centerX + hrX,centerY + hrY,mHourPaint); } @Override public void onVisibilityChanged(boolean visible) { super.onVisibilityChanged(visible); if (Log.isLoggable(TAG,"onVisibilityChanged: " + visible); } if (visible) { registerReceiver(); // Update time zone in case it changed while we weren't visible. mTime.clear(TimeZone.getDefault().getID()); mTime.setToNow(); } else { unregisterReceiver(); } // Whether the timer should be running depends on whether we're visible (as well as // whether we're in ambient mode),so we may need to start or stop the timer. updateTimer(); } private void registerReceiver() { if (mRegisteredTimeZoneReceiver) { return; } mRegisteredTimeZoneReceiver = true; IntentFilter filter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED); AnalogWatchFaceService.this.registerReceiver(mTimeZoneReceiver,filter); } private void unregisterReceiver() { if (!mRegisteredTimeZoneReceiver) { return; } mRegisteredTimeZoneReceiver = false; AnalogWatchFaceService.this.unregisterReceiver(mTimeZoneReceiver); } /** * 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,"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() && !isInAmbientMode() && false; } } }
解决方法
onTimeTick将以环境模式发送给您.看看WatchFaceService的参考:
Called periodically in ambient mode to update the time shown by the watch face. This method is called at least once per minute.
在交互模式下,您需要实现自己的机制.