Create our Android Compass

Base on last post "Detect Orientation using Accelerometer and Magnetic Field sensors", a Android compass is implemented here. In the implementation, the final result (base on Accelerometer and Magnetic Field sensors) is show in RED, point to the north.

our Android Compass

Create a custom View, Compass, extends View. The method update() is called from onSensorChanged() of main activity, with the updated direction.
package com.AndroidDetOrientation;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class Compass extends View {

private float direction;

public Compass(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

public Compass(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

public Compass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}

@Override
protected void onDraw(Canvas canvas) {

int w = getMeasuredWidth();
int h = getMeasuredHeight();
int r;
if(w > h){
r = h/2;
}else{
r = w/2;
}

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint.setColor(Color.WHITE);

canvas.drawCircle(w/2, h/2, r, paint);

paint.setColor(Color.RED);
canvas.drawLine(
w/2,
h/2,
(float)(w/2 + r * Math.sin(-direction)),
(float)(h/2 - r * Math.cos(-direction)),
paint);

}

public void update(float dir){
direction = dir;
invalidate();
}

}


Modify main activity, AndroidDetOrientationActivity, to update Compass.
package com.AndroidDetOrientation;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidDetOrientationActivity extends Activity
implements SensorEventListener{

SensorManager sensorManager;
private Sensor sensorAccelerometer;
private Sensor sensorMagneticField;

private float[] valuesAccelerometer;
private float[] valuesMagneticField;

private float[] matrixR;
private float[] matrixI;
private float[] matrixValues;

TextView readingAzimuth, readingPitch, readingRoll;
Compass myCompass;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
readingAzimuth = (TextView)findViewById(R.id.azimuth);
readingPitch = (TextView)findViewById(R.id.pitch);
readingRoll = (TextView)findViewById(R.id.roll);

myCompass = (Compass)findViewById(R.id.mycompass);

sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

valuesAccelerometer = new float[3];
valuesMagneticField = new float[3];

matrixR = new float[9];
matrixI = new float[9];
matrixValues = new float[3];
}

@Override
protected void onResume() {

sensorManager.registerListener(this,
sensorAccelerometer,
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this,
sensorMagneticField,
SensorManager.SENSOR_DELAY_NORMAL);
super.onResume();
}

@Override
protected void onPause() {

sensorManager.unregisterListener(this,
sensorAccelerometer);
sensorManager.unregisterListener(this,
sensorMagneticField);
super.onPause();
}

@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub

}

@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub

switch(event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
for(int i =0; i < 3; i++){
valuesAccelerometer[i] = event.values[i];
}
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for(int i =0; i < 3; i++){
valuesMagneticField[i] = event.values[i];
}
break;
}

boolean success = SensorManager.getRotationMatrix(
matrixR,
matrixI,
valuesAccelerometer,
valuesMagneticField);

if(success){
SensorManager.getOrientation(matrixR, matrixValues);

double azimuth = Math.toDegrees(matrixValues[0]);
double pitch = Math.toDegrees(matrixValues[1]);
double roll = Math.toDegrees(matrixValues[2]);

readingAzimuth.setText("Azimuth: " + String.valueOf(azimuth));
readingPitch.setText("Pitch: " + String.valueOf(pitch));
readingRoll.setText("Roll: " + String.valueOf(roll));

myCompass.update(matrixValues[0]);
}

}
}


Modify main.xml to add a View of Compass.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<TextView
android:id="@+id/azimuth"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/pitch"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/roll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<view
class="com.AndroidDetOrientation.Compass"
android:id="@+id/mycompass"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>

</LinearLayout>

0 Response to "Create our Android Compass"

Posting Komentar