-1

我正在尝试编码的表盘无法正常工作。这是代码:

package mnx.watch;

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.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.wearable.watchface.CanvasWatchFaceService;
import android.support.wearable.watchface.WatchFaceStyle;
import android.text.format.Time;
import android.view.SurfaceHolder;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

/**
 * 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.
 */
public class WatchFace extends CanvasWatchFaceService  {
/**
 * 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 implements SensorEventListener{
    static final int MSG_UPDATE_TIME = 0;

    Bitmap mBackgroundBitmap;
    Bitmap mBackgroundScaledBitmap;
    Bitmap mBackgroundBitmapamb;
    Bitmap mBackgroundScaledBitmapamb;

    Bitmap minMap;
    Bitmap minSMap;
    Matrix minMatrix;
    Bitmap hrMap;
    Bitmap hrSMap;
    Matrix hrMatrix;
    Bitmap secMap;
    Bitmap secSMap;
    Matrix secMatrix;
    Bitmap ziMap;
    Bitmap ziSMap;
    Matrix ziMatrix;
    Matrix lunaMatrix;

    Bitmap minMapamb;
    Bitmap minSMapamb;

    Bitmap hrMapamb;
    Bitmap hrSMapamb;


    Bitmap busola;
    Bitmap busolaMap;
    Matrix busolaMatrix;

    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
    private Sensor mMagnetometer;
    private float[] mLastAccelerometer = new float[3];
    private float[] mLastMagnetometer = new float[3];
    private boolean mLastAccelerometerSet = false;
    private boolean mLastMagnetometerSet = false;
    private float[] mR = new float[9];
    private float[] mOrientation = new float[3];
    private float mCurrentDegree = 0f;





    boolean mAmbient;
    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:
                    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;


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

        setWatchFaceStyle(new WatchFaceStyle.Builder(WatchFace.this)
                .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
                .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
                .setShowSystemUiTime(false)
                .build());

        Resources resources = WatchFace.this.getResources();

        Drawable backgroundDrawable = resources.getDrawable(R.drawable.fata, null);
        mBackgroundBitmap = ((BitmapDrawable) backgroundDrawable).getBitmap();

        Drawable backgroundambDrawable = resources.getDrawable(R.drawable.background_amb1, null);
        mBackgroundBitmapamb = ((BitmapDrawable) backgroundambDrawable).getBitmap();

        Drawable minuteDrawable = resources.getDrawable(R.drawable.minute,null);
        minMap = ((BitmapDrawable) minuteDrawable).getBitmap();
        minMatrix = new Matrix();

        Drawable hourDrawable = resources.getDrawable(R.drawable.hour,null);
        hrMap = ((BitmapDrawable)hourDrawable).getBitmap();
        hrMatrix = new Matrix();

        Drawable secDrawable = resources.getDrawable(R.drawable.second,null);
        secMap = ((BitmapDrawable)secDrawable).getBitmap();
        secMatrix = new Matrix();

        Drawable minuteambDrawable = resources.getDrawable(R.drawable.minute_amb,null);
        minMapamb = ((BitmapDrawable) minuteambDrawable).getBitmap();


        Drawable hourambDrawable = resources.getDrawable(R.drawable.hour_amb,null);
        hrMapamb = ((BitmapDrawable)hourambDrawable).getBitmap();


        Drawable ziDrawable = resources.getDrawable(R.drawable.zi,null);
        ziMap = ((BitmapDrawable)ziDrawable).getBitmap();
        ziMatrix = new Matrix();
        lunaMatrix = new Matrix();

        Drawable busolaDrawable = resources.getDrawable(R.drawable.busola,null);
        busola = ((BitmapDrawable)busolaDrawable).getBitmap();
        busolaMatrix = new Matrix();



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

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

    @Override
    public void onAmbientModeChanged(boolean inAmbientMode) {
        super.onAmbientModeChanged(inAmbientMode);
        if (mAmbient != inAmbientMode) {
            mAmbient = 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();
    }


    @Override
    public void onDraw(Canvas canvas, Rect bounds) {
        mTime.setToNow();


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

        if(mBackgroundScaledBitmap == null
                || mBackgroundScaledBitmap.getWidth() != width
                || mBackgroundScaledBitmap.getHeight() != height){
            mBackgroundScaledBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap,width,height,true);

        }

            mBackgroundScaledBitmapamb = Bitmap.createScaledBitmap(mBackgroundBitmapamb,width,height,false);



        // Draw the background.



        minSMap = Bitmap.createScaledBitmap(minMap,width,height,true);
        hrSMap = Bitmap.createScaledBitmap(hrMap,width,height,true);
        secSMap = Bitmap.createScaledBitmap(secMap,width,height,true);
        minSMapamb = Bitmap.createScaledBitmap(minMapamb,width,height,true);
        hrSMapamb = Bitmap.createScaledBitmap(hrMapamb,width,height,true);
        ziSMap = Bitmap.createScaledBitmap(ziMap,ziMap.getWidth()-23,ziMap.getHeight()-23,true);
        busolaMap = Bitmap.createScaledBitmap(busola,busola.getWidth()/3 - 10,busola.getHeight()/3 - 10,true);

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

        int day = mTime.weekDay;
        int month = mTime.month ;

        SimpleDateFormat dfDate = new SimpleDateFormat("dd");
        String date = "";
        Calendar c = Calendar.getInstance();
        date=dfDate.format(c.getTime());



        float ziRot = (day-1) * (360/7);
        int lunaRot = (month) * (360/12) + 15;
        float centerX = width / 2f;
        float centerY = height / 2f;
        float widthp;

        float secRot = mTime.second * 6;
        int minutes = mTime.minute;
        float minRot = minutes * 6;
        float hrRot = (float) (mTime.hour*30+mTime.minute*0.5);


        Paint mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setTextSize(20);
        mPaint.setTypeface(Typeface.SANS_SERIF);
        widthp=mPaint.measureText(date);


        ziMatrix.setRotate(ziRot, ziSMap.getWidth() / 2, ziSMap.getHeight() / 2);
        ziMatrix.postTranslate(centerX - 129, centerY - 114);

        lunaMatrix.setRotate(lunaRot,ziSMap.getWidth() / 2, ziSMap.getHeight() / 2);
        lunaMatrix.postTranslate(centerX - 13 , centerY -114);

        secMatrix.setRotate(secRot, secSMap.getWidth() / 2, secSMap.getHeight() / 2);
        secMatrix.postTranslate(centerX - secSMap.getWidth() / 2, centerY - secSMap.getHeight() / 2);

        minMatrix.setRotate(minRot, minSMap.getWidth() / 2, minSMap.getHeight() / 2);
        minMatrix.postTranslate(centerX - minSMap.getWidth() / 2, centerY - minSMap.getHeight() / 2);

        hrMatrix.setRotate(hrRot, hrSMap.getWidth() / 2, hrSMap.getHeight() / 2);
        hrMatrix.postTranslate(centerX - hrSMap.getWidth() / 2, centerY - hrSMap.getHeight() / 2);

        busolaMatrix.setRotate(mCurrentDegree , busolaMap.getWidth()/2,busolaMap.getHeight()/2);
        busolaMatrix.postTranslate(centerX - busolaMap.getWidth()/2 ,centerY +25);



        if (!mAmbient) {
            canvas.drawBitmap(mBackgroundScaledBitmap,0,0, null);
            canvas.drawBitmap(ziSMap,ziMatrix,null);
            canvas.drawBitmap(ziSMap,lunaMatrix,null);
            canvas.drawText(date,centerX - widthp/2,centerY - 80 ,mPaint);
            canvas.drawBitmap(busolaMap,busolaMatrix,null);

            canvas.drawBitmap(minSMap, minMatrix,null);
            canvas.drawBitmap(hrSMap, hrMatrix,null);
            canvas.drawBitmap(secSMap, secMatrix, null);

        }
        else {
            canvas.drawBitmap(mBackgroundScaledBitmapamb, 0, 0, null);
            canvas.drawBitmap(hrSMapamb, hrMatrix, null);
            canvas.drawBitmap(minSMapamb, minMatrix, null);
        }


    }

    @Override
    public void onVisibilityChanged(boolean visible) {
        super.onVisibilityChanged(visible);

        if (visible) {
            registerReceiver();
            registerSensor();

            // Update time zone in case it changed while we weren't visible.
            mTime.clear(TimeZone.getDefault().getID());
            mTime.setToNow();
        } else {
            unregisterReceiver();
            unregisterSensor();
        }

        // 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);
        WatchFace.this.registerReceiver(mTimeZoneReceiver, filter);
    }

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

    private void registerSensor(){
        mSensorManager.registerListener(this,mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
    }
    private void unregisterSensor(){
        mSensorManager.unregisterListener(this, mAccelerometer);
        mSensorManager.unregisterListener(this, mMagnetometer);
    }

    /**
     * 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();
    }
    @Override
    public void onSensorChanged(SensorEvent event){
        if (event.sensor == mAccelerometer){
            System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
            mLastAccelerometerSet = true;
        }
        else if (event.sensor ==mMagnetometer){
            System.arraycopy(event.values,0,mLastMagnetometer,0,event.values.length);
            mLastMagnetometerSet = true;
        }
        if (mLastAccelerometerSet && mLastMagnetometerSet) {
            SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
            SensorManager.getOrientation(mR, mOrientation);

            float degree = (float) Math.floor(Math.toDegrees(mOrientation[0]));

            if (degree < 0) {
                degree = 360 + degree;
            }
            if (mCurrentDegree < -300 && -degree > -60) {
                mCurrentDegree = mCurrentDegree + 360;
            } else if (mCurrentDegree > -60 && -degree < -300) {
                mCurrentDegree = mCurrentDegree - 360;
            }

            mCurrentDegree = (0.9f *mCurrentDegree) + (0.1f*-degree);

            invalidate();
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy){}
}
}

我做了一个测试并在没有指南针的情况下运行代码,它可以工作,手表指针似乎有点粗糙,但没关系,它有效。在我在程序中引入代码后,它没有显示任何错误,但在我点击运行后,我的智能手表需要一段时间,但它显示了一条错误消息:

不幸的是,Watch 已停止。

这是调试:

06-26 21:18:49.864 18676-18676/mnx.watch E/AndroidRuntime:致命异常:主进程:mnx.watch,PID:18676 java.lang.NullPointerException:尝试调用虚拟方法'boolean android.hardware.SensorManager .registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int)' 在 mnx.watch.WatchFace$Engine.registerSensor(WatchFace.java:374) 的 mnx.watch.WatchFace$Engine.onVisibilityChanged 的​​空对象引用上(WatchFace.java:341) 在 android.service.service.wallpaper.WallpaperService$Engine.updateSurface(WallpaperService.java:809) 在 android.service.wallpaper.WallpaperService$Engine.attach(WallpaperService.java:860) 在 android.service。壁纸.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:1147) 在 com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java :135) 在 android.app.ActivityThread.main(ActivityThread.java:5254) 在 java.lang.reflect.Method.invoke(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:372) 在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)app.ActivityThread.main(ActivityThread.java:5254) 在 java.lang.reflect.Method.invoke(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal。 os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)app.ActivityThread.main(ActivityThread.java:5254) 在 java.lang.reflect.Method.invoke(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal。 os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

4

1 回答 1

0

我知道我做错了什么,我忘了写这个:

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

至少如果有人想在表盘中集成指南针,他不必像我一样搜索

于 2015-06-27T15:07:07.740 回答