在Android内置传感器(方向传感器、加速度传感器、地磁传感器等。)可用于实现指南针功能,并编写能够识别手机方向的指南针app。本文将讲述两种编写指南针的方法app方法是使用方向传感器,将加速度传感器与地磁传感器相结合。
文章目录
- 一、方向传感器
- 二、基于加速度传感器和地磁传感器
- 三、页面布局
- 总结
一、方向传感器
方向传感器是Android通过三维坐标确定基本传感器之一(X,Y,Z)进一步实现指南针功能的三个方向,Sensor.TYPE_ORIENTATION在目前的Android不再推荐在系统中使用,但仍然可以通过它获取数据。
实现代码(Activity):
///方向传感器指南针页面 public class CompassActivity1 extends AppCompatActivity implements SensorEventListener {
private ImageView iv_arrow; private TextView tv_orientation; private Context context; private SensorManager sensorManager;// private int currentSensorType;///方向角度 @Override protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout_compactivity); iv_arrow = findViewById(R.id.iv_arrow); tv_orientation = findViewById(R.id.tv_orientation); context = CompassActivity1.this; sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE); } @Override protected void onResume() {
super.onResume(); //为方向传感器注册监听器 List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION); for (Sensor s : sensors) {
sensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_FASTEST); } } @Override protected void onPause() {
super.onPause(); sensorManager.unregisterListener(this); } //1、北,2东北,3东,4东南,5南,6西南,7西,8西北 public void showLocationWithSensor(int type){
if(type==currentSensorType){
return; } currentSensorType = type; Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.iv_arrow), dip2px(context,40), dip2px(context,40), true); int degrees=0;//旋转角度 if(currentSensorType==1){
degrees=0; tv_orientation.setText("北"); }else if(currentSensorType==2){
degrees=45; tv_orientation.setText("东北"); }else if(currentSensorType==3){
degrees=90; tv_orientation.setText("东"); }else if(currentSensorType==4){
degrees=135; tv_orientation.setText("东南"); }else if(currentSensorType==5){
degrees=180; tv_orientation.setText("南"); }else if(currentSensorType==6){
degrees=-135; tv_orientation.setText("西南"); }else if(currentSensorType==7){
degrees=-90; tv_orientation.setText("西"); }else if(currentSensorType==8){
degrees=-45; tv_orientation.setText("西北"); } Matrix matrix = new Matrix(); matrix.postRotate(degrees); Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); iv_arrow.setImageBitmap(newBmp); } @Override public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType()==Sensor.TYPE_ORIENTATION){
float degree = event.values[0]; //取围绕z轴转过的角度 float azimuth = (degree + 360) % 360; if (azimuth <= 15 || azimuth >= 345) {
showLocationWithSensor(1); } else if (15 < azimuth && azimuth < 75) {
showLocationWithSensor(2); } else if (75 <= azimuth && azimuth <= 105) {
showLocationWithSensor(3); } else if (105 < azimuth && azimuth < 165) {
showLocationWithSensor(4); } else if (165 <= azimuth && azimuth <= 195) {
showLocationWithSensor(5); } else if (195 < azimuth && azimuth < 255) {
showLocationWithSensor(6); } else if (255 <= azimuth && azimuth <= 285) {
showLocationWithSensor(7); } else if (285 < azimuth && azimuth < 345) {
showLocationWithSensor(8); } } } @Override public void onAccuracyChanged(Sensor sensor, int i) {
} /** * dip转换px */ public static int dip2px(Context context, float dip) {
final float scale = context.getResources().getDisplayMetrics().density; return (int) (dip * scale + 0.5f); } }
二、基于加速度传感器和地磁传感器
实现代码(Activity):
//基于加速度传感器和地磁传感器
public class CompassActivity2 extends AppCompatActivity implements SensorEventListener {
private ImageView iv_arrow;
private TextView tv_orientation;
private Context context;
private SensorManager sensorManager;//
private int currentSensorType;//方向角度
private float[] mGravity = new float[3];
private float[] mGeomagnetic = new float[3];
@Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout_compactivity);
iv_arrow = findViewById(R.id.iv_arrow);
tv_orientation = findViewById(R.id.tv_orientation);
context = CompassActivity2.this;
sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); //加速度感应器
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //地磁感应器
sensorManager.registerListener(this, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}
//1、北,2东北,3东,4东南,5南,6西南,7西,8西北
public void showLocationWithSensor(int type){
if(type==currentSensorType){
return;
}
currentSensorType = type;
Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.iv_arrow), dip2px(context,40), dip2px(context,40), true);
int degrees=0;//旋转角度
if(currentSensorType==1){
degrees=0;
tv_orientation.setText("北");
}else if(currentSensorType==2){
degrees=45;
tv_orientation.setText("东北");
}else if(currentSensorType==3){
degrees=90;
tv_orientation.setText("东");
}else if(currentSensorType==4){
degrees=135;
tv_orientation.setText("东南");
}else if(currentSensorType==5){
degrees=180;
tv_orientation.setText("南");
}else if(currentSensorType==6){
degrees=-135;
tv_orientation.setText("西南");
}else if(currentSensorType==7){
degrees=-90;
tv_orientation.setText("西");
}else if(currentSensorType==8){
degrees=-45;
tv_orientation.setText("西北");
}
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
iv_arrow.setImageBitmap(newBmp);
}
@Override
public void onSensorChanged(SensorEvent event) {
final float alpha = 0.97f;
synchronized (this) {
//指南针转动角度算法
//判断当前是加速度感应器还是地磁感应器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity[0] = alpha * mGravity[0] + (1 - alpha) * event.values[0];
mGravity[1] = alpha * mGravity[1] + (1 - alpha) * event.values[1];
mGravity[2] = alpha * mGravity[2] + (1 - alpha) * event.values[2];
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
float[] values = event.values;
mGeomagnetic[0] = alpha * mGeomagnetic[0] + (1 - alpha) * event.values[0];
mGeomagnetic[1] = alpha * mGeomagnetic[1] + (1 - alpha) * event.values[1];
mGeomagnetic[2] = alpha * mGeomagnetic[2] + (1 - alpha) * event.values[2];
}
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
float azimuth = (float) Math.toDegrees(orientation[0]); // orientation
azimuth = (azimuth + 360) % 360;
if (azimuth <= 15 || azimuth >= 345) {
showLocationWithSensor(1);
} else if (15 < azimuth && azimuth < 75) {
showLocationWithSensor(2);
} else if (75 <= azimuth && azimuth <= 105) {
showLocationWithSensor(3);
} else if (105 < azimuth && azimuth < 165) {
showLocationWithSensor(4);
} else if (165 <= azimuth && azimuth <= 195) {
showLocationWithSensor(5);
} else if (195 < azimuth && azimuth < 255) {
showLocationWithSensor(6);
} else if (255 <= azimuth && azimuth <= 285) {
showLocationWithSensor(7);
} else if (285 < azimuth && azimuth < 345) {
showLocationWithSensor(8);
}
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
/** * dip转换px */
public static int dip2px(Context context, float dip) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dip * scale + 0.5f);
}
}
三、页面布局
这两个页面使用的同一个xml布局文件。
实现代码(xml):
标签:
sp2880角度传感器sp2801角度传感器