1.只要android手机硬件提供了相关的传感器支持,就可以用来做个简单的指南针玩玩。
2.步骤简单如下:a.调用Context的getSystemService()方法获取sensorManager,它代表传感器的管理服务;b.指定所用传感器类型,sensor:可以创建一个特定的传感器实例,c.注册相应的监听事件sensorEvent事件对象,d.当传感器数据发生变化时回调。
3.传感器的API不复杂,包含3个类和一个接口,分别是:SensorManager,Sensor,SensorEvent,SensorEventListener,共4个API。
4.基本使用方法:
实例化SensorManager
SensorManager mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
当你不知道设备支持的Sensor时,可以先获取设备支持的传感器列表。
List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL)
安卓平台提供了2个传感器用于让我们判断设备的位置,分别是地磁场传感器(the geomagnetic field sensor)和方向传感器(the orientation sensor),本文中用方向传感器,方向传感器是基于软件的,并且它的数据是通过加速度传感器和磁场传感器共同获得的。
5.传感器坐标系统,z是指向地心的方位角,x轴是仰俯角(由静止状态开始前后反转),y轴是翻转角(由静止状态开始左右反转),如下图中所示,系统会给我们返回一个长度为三的float数组,包含三个方向值,按顺序分别是ZXY轴。

6.介绍差不多了,上源码。
package com.dragon.compass;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import java.util.List;
public class Main extends AppCompatActivity implements SensorEventListener {
ImageView znzImage;
float currentDegree = 0f;
SensorManager mSensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
znzImage = (ImageView)findViewById(R.id.znzImage);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
Log.e("dragon",deviceSensors+"");
}
@Override
protected void onResume(){
super.onResume();
mSensorManager.registerListener(this,mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onPause(){
mSensorManager.unregisterListener(this);
super.onPause();
}
@Override
protected void onStop(){
mSensorManager.unregisterListener(this);
super.onStop();
}
@Override
public void onSensorChanged(SensorEvent event){
int sensorType = event.sensor.getType();
switch(sensorType){
case Sensor.TYPE_ORIENTATION:
float degree = event.values[0];
RotateAnimation ra = new RotateAnimation(currentDegree,-degree, Animation.RELATIVE_TO_PARENT,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
ra.setDuration(200);
znzImage.startAnimation(ra);
currentDegree = -degree;
break;
}
}
@Override
public void onAccuracyChanged(Sensor sensor,int accuracy){
}
}
布局文件main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
>
<ImageView
android:id="@+id/znzImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:src="@drawable/znz" />
</LinearLayout>
7.成功了但发现,方向传感器已经弃用了,Sensor.TYPE_ORIENTATION这上面会有一横线。为了后面学习者的连续性,将它进行改进,利用加速度传感器和地磁传感器来计算方向角。
新的替代方法,这里只用到了Z轴,用到了加速度传感器和地磁传感器
package com.dragon.compass;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
public class Main extends AppCompatActivity implements SensorEventListener {
ImageView znzImage;
float currentDegree = 0f;
SensorManager mSensorManager;
private Sensor accelerometer;
private Sensor magnetic;
private float[] accelerometerValues = new float[3];
private float[] magneticFieldValues = new float[3];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
znzImage = (ImageView)findViewById(R.id.znzImage);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetic = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
calculateOrientation();
}
@Override
protected void onResume(){
mSensorManager.registerListener(this,accelerometer,SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this,magnetic,SensorManager.SENSOR_DELAY_GAME);
super.onResume();
}
@Override
protected void onPause(){
mSensorManager.unregisterListener(this);
super.onPause();
}
@Override
protected void onStop(){
mSensorManager.unregisterListener(this);
super.onStop();
}
private float calculateOrientation(){
float[] values = new float[3];
float[] R = new float[9];
SensorManager.getRotationMatrix(R, null, accelerometerValues,
magneticFieldValues);
SensorManager.getOrientation(R, values);
values[0] = (float) Math.toDegrees(values[0]);
return values[0];
}
@Override
public void onSensorChanged(SensorEvent event){
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accelerometerValues = event.values;
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magneticFieldValues = event.values;
}
float degree = calculateOrientation();
RotateAnimation ra = new RotateAnimation(currentDegree,-degree, Animation.RELATIVE_TO_PARENT,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
ra.setDuration(200);
znzImage.startAnimation(ra);
currentDegree=-degree;
}
@Override
public void onAccuracyChanged(Sensor sensor,int accuracy){
}
}
效果图

专注于AR的在移动端的实现,如果你还有问题没解决,你可以加入我们一起交流。或是关注我们的技术公众号,这是提供技术干货的地方,你有干货可以向我们推荐。

如果你觉得写的不错,对你有用,请在下面点个 顶 支持一下嘛,有问题可以在下面留言评论。