如何部署和运行监视面部服务

时间:2014-12-14 19:16:06

标签: java android android-studio structure android-wear-data-api

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

代码:

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应用程序,这让我很困惑。

(我不想要我的绘图代码的提示和内容,我只是想知道我需要做什么 为了运行这个)

编辑:我不想从“开始...”

启动应用程序

3 个答案:

答案 0 :(得分:4)

请记住,您没有使用Activity创建Android应用程序,您可以启动,但只使用Service制作Android应用程序。在您的情况下 - 您应该只使用选项 - 部署apk,而无需启动任何活动enter image description here

答案 1 :(得分:0)

  1. 需要在磨损清单中,而不是在电话清单中
  2. 必须有

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

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

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

答案 2 :(得分:0)

  1. 如果您只想部署和测试您的表盘,那么您现在不需要移动/应用模块。只需在磨损设备或仿真器上选择并运行“磨损”配置,并确保在其设置中选择“不启动活动”。
  2. 对我而言,定义预览图像非常重要,否则表盘将不会显示在选择器中。
  3. 好像你已经把你的清单文件弄乱了。
  4. 你的服装清单文件应如下所示:

    <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>