1

我正在关注如何制作自定义表盘的本教程。在复制代码并正确设置项目后(除了为每只手表制作动态坐标),我不知道如何实际运行该应用程序。我将在此处发布项目和代码:

和代码:

public class ZCycleWatchFaceService extends CanvasWatchFaceService{//Made specifically for moto 360

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

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

        static final int MSG_UPDATE_TIME = 0;
        static final int INTERACTIVE_UPDATE_RATE_MS = 1000;

        RectF smallCircleRect;
        RectF bigCircleRect;

        /* a time object */
        Time mTime;

        /* device features */
        boolean mLowBitAmbient;
        boolean mBurnInProtection;

        float textY = 135;
        float textSize = 20;

        /* graphic objects */
        Paint mHourPaint;
        Paint mMinutePaint;
        Paint mTextPaint;

        /* 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:
                        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;
                }
            }
        };

        /* receiver to update the time zone */
        final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                mTime.clear(intent.getStringExtra("time-zone"));
                mTime.setToNow();
            }
        };

        private void updateTimer() {
            mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME);
            if (shouldTimerBeRunning()) {
                mUpdateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME);
            }
        }

        private boolean shouldTimerBeRunning() {
            return isVisible() && !isInAmbientMode();
        }

        @Override
        public void onCreate(SurfaceHolder holder) {
            super.onCreate(holder);
            /* initialize your watch face */

            bigCircleRect = new RectF(5 , 5 , 315 , 280);
            smallCircleRect = new RectF(15 , 15 , 305 , 270);

            /* create graphic styles */
            mHourPaint = new Paint();
            mHourPaint.setARGB(255, 77 , 175 , 240);
            mHourPaint.setStrokeWidth(5.0f);
            mHourPaint.setAntiAlias(true);
            mHourPaint.setStrokeCap(Paint.Cap.ROUND);
            mHourPaint.setTextSize(textSize);

            mMinutePaint = new Paint();
            mMinutePaint.setARGB(225 , 240 , 150 , 77);
            mMinutePaint.setStrokeWidth(3.5f);
            mMinutePaint.setAntiAlias(true);
            mMinutePaint.setStrokeCap(Paint.Cap.ROUND);


            /* allocate an object to hold the time */
            mTime = new Time();

            /* configure the system UI */
            setWatchFaceStyle(new WatchFaceStyle.Builder(ZCycleWatchFaceService.this)
                    .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
                    .setBackgroundVisibility(WatchFaceStyle
                            .BACKGROUND_VISIBILITY_INTERRUPTIVE)
                    .setShowSystemUiTime(false)
                    .build());

        }

        @Override
        public void onPropertiesChanged(Bundle properties) {
            /* get device features (burn-in, low-bit ambient) */
            super.onPropertiesChanged(properties);
            mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false);
            mBurnInProtection = properties.getBoolean(PROPERTY_BURN_IN_PROTECTION,
                    false);
        }

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

            invalidate();
        }

        @Override
        public void onAmbientModeChanged(boolean inAmbientMode) {
            /* the wearable switched between modes */
            boolean wasInAmbientMode = isInAmbientMode();
            super.onAmbientModeChanged(inAmbientMode);

            if (inAmbientMode != wasInAmbientMode) {
                if (mLowBitAmbient) {
                    boolean antiAlias = !inAmbientMode;
                    mHourPaint.setAntiAlias(antiAlias);
                    mMinutePaint.setAntiAlias(antiAlias);

                    //mSecondPaint.setAntiAlias(antiAlias);
                    //mTickPaint.setAntiAlias(antiAlias);
                }
                invalidate();
                updateTimer();
            }
        }

        @Override
        public void onDraw(Canvas canvas, Rect bounds) {
            /* draw your watch face */
            // Update the time
            mTime.setToNow();

            //int width = bounds.width();
            //int height = bounds.height();

            // 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;
            //float circleCenter = centerY + FLAT_TIRE_OFFSET;

            float minsPassed = mTime.minute;
            float hoursPassed = mTime.hour;
            float secsPassed = mTime.second;

            float timePassedForBigCircle = minsPassed + hoursPassed * 60;
            double radsForBigCircle = 0.87222222292 * timePassedForBigCircle;
            double radsForSmallCircle = 10.4666667 * minsPassed;

            double degForBigCircle = Math.toDegrees(radsForBigCircle);
            double degForSmallCircle = Math.toDegrees(radsForSmallCircle);

            canvas.drawArc(bigCircleRect , 0 , (float) degForBigCircle , false , mHourPaint);
            canvas.drawArc(smallCircleRect , 0 , (float) degForSmallCircle , false , mMinutePaint);

            float textX = 0;

            if(hoursPassed >= 10){
                textX = 320 - textSize * 4;
            }else{
                textX = textSize * 5;
            }

            canvas.drawText(hoursPassed + ":" + minsPassed , textX , textY , mHourPaint);
            /*// Compute rotations and lengths for the clock hands.
            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;

            // Only draw the second hand in interactive mode.
            /*if (!mAmbient) {
                float secX = (float) Math.sin(secRot) * secLength;
                float secY = (float) -Math.cos(secRot) * secLength;
                canvas.drawLine(centerX, centerY, centerX + secX, centerY +
                        secY, mSecondPaint);
            }*/

            /*// Draw the minute and hour hands.
            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) {
            /* the watch face became visible or invisible */
            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 and
            // 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);
            ZCycleWatchFaceService.this.registerReceiver(mTimeZoneReceiver, filter);
        }

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

    }

}

大部分还没有做太多,我只是想测试一下我的绘图机制

清单文件: 穿戴清单文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.rfsdev.zarkopafilis.zcycle">
    <uses-feature android:name="android.hardware.type.watch" />
    <application android:allowBackup="true" android:label="@string/app_name"
        android:icon="@drawable/ic_launcher" android:theme="@android:style/Theme.DeviceDefault">

    </application>

    <uses-permission
        android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
    <uses-permission
        android:name="android.permission.WAKE_LOCK" />

</manifest>

手机/电话清单文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.rfsdev.zarkopafilis.zcycle">

    <application android:allowBackup="true" android:label="@string/app_name"
        android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme">


        <service
            android:name=".ZCycleWatchFaceService"
            android:label="@string/analog_name"
            android:allowEmbedded="true"
            android:taskAffinity=""
            android:permission="android.permission.BIND_WALLPAPER" >
            <intent-filter>
                <action android:name="android.service.wallpaper.WallpaperService" />
                <category
                    android:name=
                        "com.google.android.wearable.watchface.category.WATCH_FACE" />
            </intent-filter>
        </service>


    </application>

    <uses-permission
        android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
    <uses-permission
        android:name="android.permission.WAKE_LOCK" />



</manifest>

我不知道如何测试运行这个东西。消息显示“未找到活动”,但我正确地遵循了教程。我已经制作了android应用程序,这让我很困惑。

(我不想要我的绘图代码的提示和东西,我只想知道我需要做什么才能运行它)

编辑:我不想从“开始...”开始应用程序

4

3 回答 3

4

请记住,您不是使用 Activity 来制作 Android 应用程序,您可以启动,而是仅使用 Service 制作 Android 应用程序。在你的情况下 - 你应该只使用选项 - 部署 apk,而不启动任何活动在此处输入图像描述

于 2014-12-14T20:40:19.310 回答
0
  1. 需要在磨损清单中,而不是在手机清单中
  2. 必须有一个

    <meta-data
        android:name="com.google.android.wearable.watchface.preview"
        android:resource="@drawable/preview_my_clock" />
    

    输入,否则表盘将不会显示在表盘选择器上。

完成这两项更改后,上传应用后长按主屏幕,它应该会显示在表盘选择器中。

于 2014-12-15T00:35:29.847 回答
0
  1. 如果您只想部署和测试表盘,则暂时不需要移动/应用模块。只需在穿戴设备或模拟器上选择并运行您的“穿戴”配置,并确保在其设置中选择“不启动活动”。
  2. 对我来说,定义预览图像很重要,否则表盘将不会显示在选择器中。
  3. 看起来你已经打乱了你的清单文件。

您穿戴的清单文件应如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="net.rfsdev.zarkopafilis.zcycle">

    <uses-feature android:name="android.hardware.type.watch"/>

    <uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <application android:allowBackup="true"
                 android:label="@string/app_name"
                 android:icon="@drawable/ic_launcher"
                 android:theme="@android:style/Theme.DeviceDefault">

        <service
                android:name=".ZCycleWatchFaceService"
                android:label="@string/analog_name"
                android:allowEmbedded="true"
                android:taskAffinity=""
                android:permission="android.permission.BIND_WALLPAPER">
            <meta-data
                    android:name="android.service.wallpaper"
                    android:resource="@xml/watch_face"/>
            <meta-data
                android:name="com.google.android.wearable.watchface.preview"
                android:resource="@drawable/preview" />
            <intent-filter>
                <action android:name="android.service.wallpaper.WallpaperService"/>
                <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
            </intent-filter>
        </service>

    </application>

</manifest>

您应用的清单文件可能如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="net.rfsdev.zarkopafilis.zcycle">

    <uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <application android:allowBackup="true"
                 android:label="@string/app_name"
                 android:icon="@mipmap/ic_launcher"
                 android:theme="@style/AppTheme">

    </application>

</manifest>
于 2015-04-28T08:07:26.100 回答