Android Open Source - Wake-Me-At Compass






From Project

Back to project page Wake-Me-At.

License

The source code is released under:

GNU General Public License

If you think the Android project Wake-Me-At listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package uk.co.spookypeanut.wake_me_at;
/*//  w  w  w  . j av  a 2  s. c o m
    This file is part of Wake Me At. Wake Me At is the legal property
    of its developer, Henry Bush (spookypeanut).

    Wake Me At is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Wake Me At is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Wake Me At, in the file "COPYING".  If not, see
    <http://www.gnu.org/licenses/>.
 */

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

//REF#0010
/**
 * Class for the compass which appears on the alarm / tracking screen
 * @author spookypeanut
 */
class Compass extends SurfaceView implements SurfaceHolder.Callback {
    private final String LOG_NAME;
    private final String BROADCAST_UPDATE;

    private final float RADTODEGREES = (float) (180.0 / 3.14159265);

    private Paint mPaint = new Paint();
    private Path mNeedlePath = new Path();

    private CompassThread mThread = null;
    private Context mContext;

    private final int mBkgColor = getResources().getColor(R.color.mainbg);
    private final int mDialColor = getResources().getColor(R.color.compassdials);
    private final int mNeedleColor = getResources().getColor(R.color.compassneedle);

    private SensorManager mSensorManager;
    private int mLayoutWidth, mLayoutHeight;
    private SurfaceView mSurfaceView;

    private float[] mOriValues = {(float)10.0, (float)10.0, (float)10.0};

    private float[] mGravity = new float[3];
    private float[] mGeoMag = new float[3];
    private float[] mRotMatrix = new float[16];
    private float[] mInclMatrix = new float[16];

    private double mCurrLat, mCurrLong;
    private Location mCurrLoc;
    private Location mDestLoc;
    private long mRowId;

    public Compass(Context context) {
        super(context);
        LOG_NAME = (String) context.getText(R.string.app_name_nospaces);
        BROADCAST_UPDATE = (String) context.getText(R.string.serviceBroadcastName);
    }

    public Compass(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LOG_NAME = (String) context.getText(R.string.app_name_nospaces);
        BROADCAST_UPDATE = (String) context.getText(R.string.serviceBroadcastName);

        Log.d(LOG_NAME, "Compass constructor");
        mContext = context;
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
        preparePaths();

        mCurrLoc = new Location("");
        mDestLoc = new Location("");
    }


    private void drawDials(Canvas canvas) {
        Paint paint = mPaint;
        Path outer = new Path();
        Path inner = new Path();
        Path northMark = new Path();
        Path eastMark = new Path();
        final int drawColor = mDialColor;
        final int bkgColor = mBkgColor;
        final int radius = 80;
        final int lineWidth = 3;
        final int fontSize = 35;

        paint.setColor(drawColor);
        outer.addCircle(0, 0, radius + lineWidth, Path.Direction.CW);
        canvas.drawPath(outer, paint);

        paint.setColor(bkgColor);
        inner.addCircle(0, 0, radius - lineWidth, Path.Direction.CW);
        canvas.drawPath(inner, paint);

        paint.setColor(drawColor);
        paint.setTextSize(fontSize);
        paint.setTextAlign(Paint.Align.CENTER);
        // Up is negative. Which seems strange.
        canvas.drawText ("N", (float) 0.0, (float) -1.4 * radius, paint);

        northMark.moveTo((float) lineWidth, (float) (radius));
        northMark.lineTo((float) -lineWidth, (float) (radius));
        northMark.lineTo((float) -lineWidth, (float) (-radius * 1.2));
        northMark.lineTo((float) lineWidth, (float) (-radius * 1.2));
        northMark.close();
        canvas.drawPath(northMark, paint);

        eastMark.moveTo((float) (-radius), (float) lineWidth);
        eastMark.lineTo((float) (-radius), (float) -lineWidth);
        eastMark.lineTo((float) (radius), (float) -lineWidth);
        eastMark.lineTo((float) (radius), (float) lineWidth);
        eastMark.close();
        canvas.drawPath(eastMark, paint);
    }

    private void preparePaths() {
        // Construct a wedge-shaped path
        int needleWidth = 15;
        int needleLength = 60;

        mNeedlePath.moveTo(0, -needleLength);
        mNeedlePath.lineTo(-needleWidth, needleLength);
        mNeedlePath.lineTo(0, (float) (needleLength * 0.75));
        mNeedlePath.lineTo(needleWidth, needleLength);
        mNeedlePath.close();
    }

    private final SensorEventListener mListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {
            boolean sensorReady = false;
            //Log.d(LOG_NAME, "Compass.onSensorChanged, " + event.sensor.getType());

            switch (event.sensor.getType()) {
            case Sensor.TYPE_MAGNETIC_FIELD:
                mGeoMag = event.values.clone();
                sensorReady = true;
                break;
            case Sensor.TYPE_ACCELEROMETER:
                mGravity = event.values.clone();
                sensorReady = true;
                break;
            }

            if (sensorReady && mGeoMag != null && mGravity != null) {
                //Log.d(LOG_NAME, "All values present");
                sensorReady = false;

                SensorManager.getRotationMatrix(mRotMatrix, mInclMatrix, mGravity, mGeoMag);
                SensorManager.getOrientation(mRotMatrix, mOriValues);
            }

        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // TODO Auto-generated method stub
        }
    };

    //REF#0011, REF#0012
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (canvas == null) {
            return;
        }
        Paint paint = mPaint;

        canvas.drawColor(mBkgColor);

        int cx = mLayoutWidth / 2;
        int cy = mLayoutHeight / 2;

        canvas.setMatrix(null);
        canvas.translate(cx, cy);

        float northRotation = 0;
        if (mOriValues != null) {
            northRotation = -mOriValues[0] * RADTODEGREES;
            canvas.rotate(northRotation);
        }

        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);

        drawDials(canvas);

        float bearing = mCurrLoc.bearingTo(mDestLoc);
        canvas.rotate(bearing);
        paint.setColor(mNeedleColor);
        canvas.drawPath(mNeedlePath, mPaint);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (mThread == null) {
            mThread = new CompassThread(holder, mContext, new Handler() {
                @Override
                public void handleMessage(Message m) {
                    Log.d(LOG_NAME, "CompassThread.handleMessage");
                }
            });
        }

        mThread.setRunning(true);
        Log.d(LOG_NAME, "Before start, mThread.getState(): " + mThread.getState());
        mThread.start();
        Log.d(LOG_NAME, "After start, mThread.getState(): " + mThread.getState());

        mSurfaceView = (SurfaceView) findViewById(R.id.compassSurface);
        mLayoutWidth = mSurfaceView.getWidth();
        mLayoutHeight = mSurfaceView.getHeight();
        Log.d(LOG_NAME, "SurfaceView is " + mLayoutWidth + "x" + mLayoutHeight);

        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mSensorManager.registerListener(mListener, sensor, SensorManager.SENSOR_DELAY_UI);
        sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(mListener, sensor, SensorManager.SENSOR_DELAY_UI);

        IntentFilter filter = new IntentFilter(BROADCAST_UPDATE);
        mContext.registerReceiver(this.mReceiver, filter);
        Log.d(LOG_NAME, "Registered receiver");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mContext.unregisterReceiver(this.mReceiver);
        Log.d(LOG_NAME, "Unregistered receiver");
        mSensorManager.unregisterListener(mListener);
        boolean retry = true;
        Log.d(LOG_NAME, "Before setRunning(false), mThread.getState(): " + mThread.getState());

        mThread.setRunning(false);
        Log.d(LOG_NAME, "After setRunning(false), mThread.getState(): " + mThread.getState());

        while (retry) {
            try {
                mThread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
        Log.d(LOG_NAME, "After mThread.join(), mThread.getState(): " + mThread.getState());
        CompassThread limbo = mThread;
        mThread = null;
        limbo.interrupt();
    }

    /**
     * Thread class for the compass surface
     * @author spookypeanut
     */
    class CompassThread extends Thread {
        private SurfaceHolder mSurfaceHolder;
        private boolean mRun = false;

        public CompassThread(SurfaceHolder surfaceHolder, Context context,
                Handler handler) {
            mSurfaceHolder = surfaceHolder;
        }

        /**
         * Set the running flag of the thread
         * @param run True if thread should be set to running
         */
        public void setRunning(boolean run) {
            mRun = run;
        }

        @Override
        public void run() {
            Canvas c;
            while (mRun) {
                c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        onDraw(c);
                    }
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }
    }

    /**
     * Method called when the location on the service has changed
     * @param rowId
     */
    private void locationChanged(long rowId) {
        if (rowId >= 0) {
            DatabaseManager db = new DatabaseManager(mContext);
            mDestLoc.setLatitude(db.getLatitude(rowId));
            mDestLoc.setLongitude(db.getLongitude(rowId));
            db.close();
        }
    }

    public BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(LOG_NAME, "Received broadcast");
            Bundle extras = intent.getExtras();
            mCurrLat = extras.getDouble("currLat");
            mCurrLong = extras.getDouble("currLong");
            Log.d(LOG_NAME, "currently " + mCurrLat + ", " + mCurrLong);
            mCurrLoc.setLatitude(mCurrLat);
            mCurrLoc.setLongitude(mCurrLong);
            if (mRowId != extras.getLong("rowId")) {
                mRowId = extras.getLong("rowId");
                locationChanged(mRowId);
            }

        }
   };
}




Java Source Code List

uk.co.spookypeanut.wake_me_at.Alarm.java
uk.co.spookypeanut.wake_me_at.Compass.java
uk.co.spookypeanut.wake_me_at.DatabaseManager.java
uk.co.spookypeanut.wake_me_at.EditLocation.java
uk.co.spookypeanut.wake_me_at.GetLocationMap.java
uk.co.spookypeanut.wake_me_at.Presets.java
uk.co.spookypeanut.wake_me_at.Shortcuts.java
uk.co.spookypeanut.wake_me_at.UnitConverter.java
uk.co.spookypeanut.wake_me_at.WakeMeAtService.java
uk.co.spookypeanut.wake_me_at.WakeMeAt.java