2014-12-12 21 views
6

Sto cercando di utilizzare la nuova API di orologio sull'emulatore di usura e quando estendo CanvasWatchFaceService i metodi onTimeTick non sono mai stati attivati ​​in modo che l'orologio non sia mai stato aggiornato.Android Wear WatchFace API onTimeTick non attivato

sto usando il campionamento analogico e cercare di rimuovere seconda mano (basta disabilitare il timer per ora):

/* 
* 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, 200); 
      mHourPaint.setStrokeWidth(5.f); 
      mHourPaint.setAntiAlias(true); 
      mHourPaint.setStrokeCap(Paint.Cap.ROUND); 

      mMinutePaint = new Paint(); 
      mMinutePaint.setARGB(255, 200, 200, 200); 
      mMinutePaint.setStrokeWidth(3.f); 
      mMinutePaint.setAntiAlias(true); 
      mMinutePaint.setStrokeCap(Paint.Cap.ROUND); 

      mSecondPaint = new Paint(); 
      mSecondPaint.setARGB(255, 255, 0, 0); 
      mSecondPaint.setStrokeWidth(2.f); 
      mSecondPaint.setAntiAlias(true); 
      mSecondPaint.setStrokeCap(Paint.Cap.ROUND); 

      mTickPaint = new Paint(); 
      mTickPaint.setARGB(100, 255, 255, 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, Log.DEBUG)) { 
       Log.d(TAG, "onPropertiesChanged: 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 (Log.isLoggable(TAG, Log.DEBUG)) { 
       Log.d(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, 0, 0, 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, centerY, centerX + minX, centerY + minY, mMinutePaint); 

      float hrX = (float) Math.sin(hrRot) * hrLength; 
      float hrY = (float) -Math.cos(hrRot) * hrLength; 
      canvas.drawLine(centerX, centerY, centerX + hrX, centerY + hrY, mHourPaint); 
     } 

     @Override 
     public void onVisibilityChanged(boolean visible) { 
      super.onVisibilityChanged(visible); 
      if (Log.isLoggable(TAG, Log.DEBUG)) { 
       Log.d(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, 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() && !isInAmbientMode() && false; 
     } 

    } 
} 

risposta

8

onTimeTick saranno consegnati a voi in modalità ambiente. Guardate il riferimento di WatchFaceService:

 Called periodically in ambient mode to update the time shown by the watch face. This 
    method is called at least once per minute. 

In modalità interattiva è necessario implementare il proprio meccanismo.

+0

Grazie !! Mi manca quello! – jaumard

+2

Grazie - questo potrebbe essere molto più chiaro nei documenti. Nel documento di visualizzazione di Disegni di disegno, si dice semplicemente "Il sistema chiama il metodo Engine.onTimeTick() ogni minuto." Non si fa cenno che ciò avvenga solo in modalità ambiente. – String

+4

Lo aggiusteremo nella prossima versione e lo faremo sparare in modo più affidabile. – gruszczy