当前位置:网站首页>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);
边栏推荐
- 2022杭电杯超级联赛3
- 云服务器部署 Web 项目
- 【Unity】编辑器扩展-03-拓展Inspector视图
- 《如何戒掉坏习惯》读书笔记
- [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
- 0730~Mysql optimization
- mysql 数据去重的三种方式[实战]
- A brief introduction to the SSM framework
- 服务器上解压文件时提示“gzip: stdin: not in gzip format,tar: Child returned status 1,tar: Error is not recovera“
- SSM framework explanation (the most detailed article in history)
猜你喜欢
随机推荐
科目三:右转弯
文件管理:目录管理
mysql 数据去重的三种方式[实战]
2022/7/30 考试总结
SQL连接表(内连接、左连接、右连接、交叉连接、全外连接)
【小程序项目开发-- 京东商城】uni-app之商品列表页面 (上)
Cloud server deployment web project
Pytorch学习记录(七):自定义模型 & Auto-Encoders
怎样修改MySQL数据库的密码
MySQL 的几种碎片整理方案总结(解决delete大量数据后空间不释放的问题)
功能强大的国产Api管理工具
A, MySQL principle of master-slave replication
模块化规范
【pytorch记录】pytorch的分布式 torch.distributed.launch 命令在做什么呢
如何在 Linux 上安装 MySQL
ScheduledExecutorService - 定时周期执行任务
Golang-based swagger super intimate and super detailed usage guide [there are many pits]
UML图及在drawio中的绘制
【MySQL中auto_increment有什么作用?】
PowerCLi 通过自建PXE Server一键esxi7下批量部署常规New-VM