java - 在哪里声明用于在环境模式下更新表盘的闹钟管理器?

标签 java android-studio alarmmanager wear-os watch-face-api

我正在尝试添加一个 AlarmManager 以每半分钟更新一次表盘。 这是用于三态时钟的。 这是我第一次使用 Java 或 android studio 进行编程。

我正在遵循 https://developer.android.com/training/wearables/apps/always-on.html 上的指南

指南说“在 Activity 的 onCreate() 方法中声明警报管理器和待处理的意图”

我应该使用

@Override
public Engine onCreateEngine() {
    return new Engine();
}

@Override
public Engine onCreateEngine() {
    return new Engine();
}

或者我应该开始一个新方法或在其他地方声明它?

目前我正在使用

private class Engine extends CanvasWatchFaceService.Engine {
    final Handler mUpdateTimeHandler = new EngineHandler(this);

对于我的大部分初始化。

这是我的代码,没有警报管理器。问题是它必须在半分钟内更新,因为作为平衡三元,时间应该是最接近的分钟。

public class ternary extends CanvasWatchFaceService {
private static final Typeface NORMAL_TYPEFACE =
        Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);

private static final int MSG_UPDATE_TIME = 0;

@Override
public Engine onCreateEngine() {
    return new Engine();
}

private static class EngineHandler extends Handler {
    private final WeakReference<ternary.Engine> mWeakReference;

    public EngineHandler(ternary.Engine reference) {
        mWeakReference = new WeakReference<>(reference);
    }

    @Override
    public void handleMessage(Message msg) {
        ternary.Engine engine = mWeakReference.get();
        if (engine != null) {
            switch (msg.what) {
                case MSG_UPDATE_TIME:
                    engine.handleUpdateTimeMessage();
                    break;
            }
        }
    }
}

private class Engine extends CanvasWatchFaceService.Engine {
    final Handler mUpdateTimeHandler = new EngineHandler(this);
    boolean mRegisteredTimeZoneReceiver = false;
    Paint mBackgroundPaint;
    Paint mTextPaint;
    boolean mAmbient;
    Time mTime;
    final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mTime.clear(intent.getStringExtra("time-zone"));
            mTime.setToNow();
        }
    };
    int mTapCount;

    float mXOffset;
    float mYOffset;

    // adjust text size
    float textRatio = (float)1;  // 2/3;

    // make adjusted offset for hours
    float hrsIndent;
    float hrsIndentAdjust = textRatio * 55;

    // vertical offset for multiple lines
    float ySpacer = textRatio * 65;

    // first run.
    boolean yesFirstRun = true;
    // flag for seconds
    boolean yesSecs;
    // prior state of yesSecs
    boolean wasSecs = true;
    // flag for conservation mode (no seconds in ambient)
    boolean yesConcerve = false;
    // flag for allowing seconds
    boolean allowSecs = true;
    // for execution control
    boolean openGate = false;

    // counter for next draw
    int c = 0;
    // counter for time loops
    int k;
    boolean drawNow = true;
    // strings for draw
    String hrs = "";
    String mns = "";
    String sks = "";
    // register for milliseconds
    long millis = 0;
    // float for calculating trits from time.
    float tim = 0;
    // ints for minute and hour offsets.
    int minInt = 0;
    int hourInt = 0;

    // lists for time to trit for loop conversions.
    int [] trits3 = {9, 3, 1};
    int [] trits4 = {27, 9, 3, 1};

    // absolute count for trouble shooting
    // long x = 0;

    /**
     * Whether the display supports fewer bits for each color in ambient mode. When true, we
     * disable anti-aliasing in ambient mode.
     */
    boolean mLowBitAmbient;

    @Override
    public void onCreate(SurfaceHolder holder) {
        super.onCreate(holder);

        setWatchFaceStyle(new WatchFaceStyle.Builder(ternary.this)
                .setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE)
                .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
                .setShowSystemUiTime(false)
                .setAcceptsTapEvents(true)
                .build());
        Resources resources = ternary.this.getResources();

        // shift y offset up
        mYOffset = -30 + resources.getDimension(R.dimen.digital_y_offset);

        mBackgroundPaint = new Paint();
        mBackgroundPaint.setColor(resources.getColor(R.color.background));

        mTextPaint = new Paint();
        mTextPaint = createTextPaint(resources.getColor(R.color.digital_text));

        mTime = new Time();
    }

    @Override
    public void onDestroy() {
        mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
        super.onDestroy();
    }

    private Paint createTextPaint(int textColor) {
        Paint paint = new Paint();
        paint.setColor(textColor);
        paint.setTypeface(NORMAL_TYPEFACE);
        paint.setAntiAlias(true);
        return paint;
    }

    @Override
    public void onVisibilityChanged(boolean visible) {
        super.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);
        ternary.this.registerReceiver(mTimeZoneReceiver, filter);
    }

    private void unregisterReceiver() {
        if (!mRegisteredTimeZoneReceiver) {
            return;
        }
        mRegisteredTimeZoneReceiver = false;
        ternary.this.unregisterReceiver(mTimeZoneReceiver);
    }

    @Override
    public void onApplyWindowInsets(WindowInsets insets) {
        super.onApplyWindowInsets(insets);

        // Load resources that have alternate values for round watches.
        Resources resources = ternary.this.getResources();
        boolean isRound = insets.isRound();

        // shift offset 75 to the right
        mXOffset = 75 + 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);

        // adjust hrs Indent to MXOffset
        hrsIndent = hrsIndentAdjust + mXOffset;

        // adjust size to textRatio
        mTextPaint.setTextSize(textSize * textRatio );
    }

    @Override
    public void onPropertiesChanged(Bundle properties) {
        super.onPropertiesChanged(properties);
        mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false);
    }

    @Override
    public void onTimeTick() {
        super.onTimeTick();
        invalidate();
    }

    @Override
    public void onAmbientModeChanged(boolean inAmbientMode) {
        super.onAmbientModeChanged(inAmbientMode);
        if (mAmbient != inAmbientMode) {
            mAmbient = inAmbientMode;
            if (mLowBitAmbient) {
                mTextPaint.setAntiAlias(!inAmbientMode);
            }
            invalidate();
        }

        // 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();
    }

    /**
     * Captures tap event (and tap type) and toggles the background color if the user finishes
     * a tap.
     */
    @Override
    public void onTapCommand(int tapType, int x, int y, long eventTime) {
        Resources resources = ternary.this.getResources();
        switch (tapType) {
            case TAP_TYPE_TOUCH:
                // The user has started touching the screen.
                break;
            case TAP_TYPE_TOUCH_CANCEL:
                // The user has started a different gesture or otherwise cancelled the tap.
                break;
            case TAP_TYPE_TAP:
                // The user has completed the tap gesture.
                mTapCount++;
                mBackgroundPaint.setColor(resources.getColor(mTapCount % 2 == 0 ?
                        R.color.background : R.color.background2));
                break;
        }
        invalidate();
    }

    @Override
    public void onDraw(Canvas canvas, Rect bounds) {
        // Greebo counter
        // x += 1;

        // seconds handling
        wasSecs = yesSecs;
        yesSecs = allowSecs && !isInAmbientMode();
        // for clearing seconds
        if (!yesSecs && wasSecs) { sks = ""; }

        // Draw at mid second
        if (c == 0 && yesSecs) {
            drawNow = true;
        } else {
            c = 0;
            // mid minute
            if (mTime.second == 30 || isInAmbientMode()) {
                drawNow = true;
            } else {
                // mid hour
                if (mTime.second == 0) {
                    if (mTime.minute == 30) {
                        drawNow = true;
                    } else {
                        // mid night
                        if (mTime.minute == 0) {
                            if (mTime.hour == 0) {
                                drawNow = true;
                            }
                        }
                    }
                }
            }
        }

        if (drawNow) {
            drawNow = false;

            mTime.setToNow();
            millis = System.currentTimeMillis() % 1000;

            // mid seconds
            if (yesSecs) { if (millis > 499) { c = 1; } }

            tim = (float)((mTime.minute * 60 + mTime.second) * 1000 + millis)/ 3600000;
            // hours past noon
            tim += mTime.hour - 12;

            // find hrs 9s, 3s, 1s.
            openGate = false;
            if (yesFirstRun || mTime.minute == 30){ openGate = true; }
            else { openGate = mTime.second == 0 && mTime.minute == 0 && mTime.hour == 0;}
            if (openGate) {
                hrs = "";
                hourInt = 0;
                // i is for item.
                for (int i : trits3) {
                    if (tim > ((float) i / 2)) {
                        tim -= i;
                        hourInt -= i;
                        hrs = hrs + "1";
                    } else {
                        if (tim < ((float) i / -2)) {
                            tim += i;
                            hourInt += i;
                            hrs = hrs + "¬";
                        } else {
                            hrs = hrs + "0";
                        }
                    }
                    // add space
                    if (i > 1) {hrs += " "; }
                }
            } else { tim += hourInt; }

            // minutes 27s, 9s, 3s, 1s
            openGate = false;
            if (yesFirstRun || mTime.second == 30 || isInAmbientMode()) {openGate = true; }
            else { openGate = mTime.second == 0 && (mTime.minute == 30
                    || (mTime.minute == 0 && mTime.hour == 0));}
            if (openGate) {
                mns = "";
                tim *= 60;
                minInt = 0;
                // i is for item.
                for (int i : trits4) {
                    if (tim > ((float) i / 2)) {
                        tim -= i;
                        if (yesSecs) {minInt -= i;}
                        mns = mns + "1";
                    } else {
                        if (tim < ((float) i / -2)) {
                            tim += i;
                            if (yesSecs) {minInt += i;}
                            mns = mns + "¬";
                        } else {
                            mns = mns + "0";
                        }
                    }
                    // add space
                    if (i > 1) {mns += " "; }
                }
            } else { if (yesSecs) { tim += minInt; tim *= 60; } }

            // seconds 27s, 9s, 3s, 1s
            if (yesSecs) {
                sks = "";
                tim *= 60;
                for (int i : trits4) {
                    if (tim > ((float) i / 2)) {
                        tim -= i;
                        sks = sks + "1";
                    } else {
                        if (tim < ((float) i / -2)) {
                            tim += i;
                            sks = sks + "¬";
                        } else {
                            sks = sks + "0";
                        }
                    }
                    // add space
                    if (i > 1) {sks += " "; }
                }
            }
        }

        // Draw the background.
        if (isInAmbientMode()) {
            canvas.drawColor(Color.BLACK);
        } else {
            canvas.drawRect(0, 0, bounds.width(), bounds.height(), mBackgroundPaint);
        }

        // draw hours
        canvas.drawText(hrs, hrsIndent, mYOffset - ySpacer, mTextPaint);
        // draw minutes
        canvas.drawText(mns, mXOffset, mYOffset, mTextPaint);
        // draw or clear seconds
        if (yesSecs || wasSecs) {canvas.drawText(sks, mXOffset, mYOffset + ySpacer , mTextPaint);}

        // show count and millis for greebo reduction.
        // canvas.drawText(String.format("%1$03d,%2$02d,%3$d", x % 1000, millis / 10, 0), mXOffset, mYOffset + 100, mTextPaint);
        //canvas.drawText(String.format("%$02d:%2$02d:%3$02d", mTime.hour, mTime.minute,
        //        mTime.second), mXOffset, mYOffset + 100, mTextPaint);

    }


    /**
     * 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() {
        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();
    }

    /**
     * Handle updating the time periodically in interactive mode.
     */
    private void handleUpdateTimeMessage() {
        invalidate();
        if (shouldTimerBeRunning()) {
            long timeMs = System.currentTimeMillis();
            long delayMs = INTERACTIVE_UPDATE_RATE_MS
                    - (timeMs % INTERACTIVE_UPDATE_RATE_MS);
            mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs);
        }
    }
}

}

最佳答案

“onCreate()”方法似乎与以下内容相关:

公共(public)类三元扩展CanvasWatchFaceService

您的声明应如下所示:

public class ternary extends CanvasWatchFaceService {
    private AlarmManager mAmbientStateAlarmManager;
    private PendingIntent mAmbientStatePendingIntent;

并且一定要导入 android.app.AlarmManager 和 android.app.PendingIntent .

关于java - 在哪里声明用于在环境模式下更新表盘的闹钟管理器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38288773/

相关文章:

java - 异构Java EE集群

java - FlowLayout占用垂直空间过多,改变高度

java - 如何在流式传输时删除 HashMap 的元素(lambda)

java - tagForChildDirectedTreatment(boolean) 弃用

java - Android 通知应用程序无法正常工作

java - 如何正确配置网络应用程序,以便 axis2 找到所需的模块?

android - Google Material Design 图标 - 为什么文件名不以实际大小命名。如何在Android Studio中使用它们而无需重命名?

android-studio - 安卓工作室 : Cannot get DialogFragment's inflated layout to match_parent

android - 使用警报管理器在主线程外每隔 X 分钟启动一次服务?

Android:保持后台服务活着(防止进程死亡)