当前位置:网站首页>Andoird开发--指南针(基于手机传感器)
Andoird开发--指南针(基于手机传感器)
2022-07-31 08:36:00 【程@@程】
在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):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout android:id="@+id/layout_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:orientation="horizontal" android:gravity="center" android:layout_centerVertical="true">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="西" android:textStyle="bold" android:textSize="22sp" />
<ImageView android:id="@+id/iv_arrow" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginTop="10dp" android:src="@color/purple_500" android:layout_marginRight="10dp" android:layout_marginLeft="10dp"/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="东" android:textStyle="bold" android:textSize="22sp"/>
</LinearLayout>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="南" android:textStyle="bold" android:textSize="22sp" android:layout_centerHorizontal="true" android:layout_below="@id/layout_arrow" android:layout_marginTop="10dp"/>
<TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="北" android:textStyle="bold" android:textSize="22sp" android:layout_above="@id/layout_arrow" android:layout_centerHorizontal="true"/>
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/layout_arrow" android:layout_marginTop="100dp">
<TextView android:id="@+id/tv_orientation" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="方位:东" android:textStyle="bold" android:textSize="22sp" android:layout_centerHorizontal="true"/>
</RelativeLayout>
</RelativeLayout>

总结
这两种方式都可以实现,不过方向传感器相对简单但是不提倡了。
指针实现用了Bitmap的偏移(旋转)操作。
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
边栏推荐
猜你喜欢

SSM框架讲解(史上最详细的文章)

[What is the role of auto_increment in MySQL?】

skynet中一条消息从取出到处理完整流程(源码刨析)
![[转载] Virtual Studio 让系统找到需要的头文件和库](/img/85/909c2ef52bbecb3faf7ed683fee65b.png)
[转载] Virtual Studio 让系统找到需要的头文件和库

Feign介绍

51单片机-----外部中断

【Unity】编辑器扩展-01-拓展Project视图

PowerCLi 通过自建PXE Server一键esxi7下批量部署常规New-VM

Small application project development, jingdong mall 】 【 uni - app custom search component (below) - search history

2019 NeurIPS | Graph Convolutional Policy Network for Goal-Directed Molecular Graph Generation
随机推荐
[Yellow ah code] Introduction to MySQL - 3. I use select, the boss directly drives me to take the train home, and I still buy a station ticket
MySQL (2)
Golang-based swagger super intimate and super detailed usage guide [there are many pits]
skynet中一条消息从取出到处理完整流程(源码刨析)
Ubuntu22.04安装mysql
深度理解递归,手撕经典递归问题(汉诺塔,青蛙跳台阶),保姆级教学。
jupyter notebook初使用
【小程序专栏】总结uniapp开发小程序的开发规范
SQL 入门之第一讲——MySQL 8.0.29安装教程(windows 64位)
免安装版的Mysql安装与配置——详细教程
Spark 在 Yarn 上运行 Spark 应用程序
MySQL 视图(详解)
How to restore data using mysql binlog
How to upgrade nodejs version
SQL join table (inner join, left join, right join, cross join, full outer join)
Splunk Workflow action 给我们带来的好处
科目三:左转弯
蚂蚁核心科技产品亮相数字中国建设峰会 持续助力企业数字化转型
SQL 嵌套 N 层太长太难写怎么办?
高并发-高可用-高性能