-
Notifications
You must be signed in to change notification settings - Fork 5.3k
/
Copy pathCompassActivity.java
215 lines (148 loc) · 5.01 KB
/
CompassActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package course.examples.compass;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
public class CompassActivity extends Activity implements SensorEventListener {
@SuppressWarnings("unused")
private String TAG = "SensorCompass";
// Main View
private RelativeLayout mFrame;
// Sensors & SensorManager
private Sensor accelerometer;
private Sensor magnetometer;
private SensorManager mSensorManager;
// Storage for Sensor readings
private float[] mGravity = null;
private float[] mGeomagnetic = null;
// Rotation around the Z axis
private double mRotationInDegress;
// View showing the compass arrow
private CompassArrowView mCompassArrow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFrame = (RelativeLayout) findViewById(R.id.frame);
mCompassArrow = new CompassArrowView(getApplicationContext());
mFrame.addView(mCompassArrow);
// Get a reference to the SensorManager
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// Get a reference to the accelerometer
accelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// Get a reference to the magnetometer
magnetometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// Exit unless both sensors are available
if (null == accelerometer || null == magnetometer)
finish();
}
@Override
protected void onResume() {
super.onResume();
// Register for sensor updates
mSensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, magnetometer,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
// Unregister all sensors
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// Acquire accelerometer event data
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity = new float[3];
System.arraycopy(event.values, 0, mGravity, 0, 3);
}
// Acquire magnetometer event data
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mGeomagnetic = new float[3];
System.arraycopy(event.values, 0, mGeomagnetic, 0, 3);
}
// If we have readings from both sensors then
// use the readings to compute the device's orientation
// and then update the display.
if (mGravity != null && mGeomagnetic != null) {
float rotationMatrix[] = new float[9];
// Users the accelerometer and magnetometer readings
// to compute the device's rotation with respect to
// a real world coordinate system
boolean success = SensorManager.getRotationMatrix(rotationMatrix,
null, mGravity, mGeomagnetic);
if (success) {
float orientationMatrix[] = new float[3];
// Returns the device's orientation given
// the rotationMatrix
SensorManager.getOrientation(rotationMatrix, orientationMatrix);
// Get the rotation, measured in radians, around the Z-axis
// Note: This assumes the device is held flat and parallel
// to the ground
float rotationInRadians = orientationMatrix[0];
// Convert from radians to degrees
mRotationInDegress = Math.toDegrees(rotationInRadians);
// Request redraw
mCompassArrow.invalidate();
// Reset sensor event data arrays
mGravity = mGeomagnetic = null;
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// N/A
}
public class CompassArrowView extends View {
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.arrow);
int mBitmapWidth = mBitmap.getWidth();
// Height and Width of Main View
int mParentWidth;
int mParentHeight;
// Center of Main View
int mParentCenterX;
int mParentCenterY;
// Top left position of this View
int mViewTopX;
int mViewLeftY;
public CompassArrowView(Context context) {
super(context);
};
// Compute location of compass arrow
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mParentWidth = mFrame.getWidth();
mParentHeight = mFrame.getHeight();
mParentCenterX = mParentWidth / 2;
mParentCenterY = mParentHeight / 2;
mViewLeftY = mParentCenterX - mBitmapWidth / 2;
mViewTopX = mParentCenterY - mBitmapWidth / 2;
}
// Redraw the compass arrow
@Override
protected void onDraw(Canvas canvas) {
// Save the canvas
canvas.save();
// Rotate this View
canvas.rotate((float) -mRotationInDegress, mParentCenterX,
mParentCenterY);
// Redraw this View
canvas.drawBitmap(mBitmap, mViewLeftY, mViewTopX, null);
// Restore the canvas
canvas.restore();
}
}
}