android studio for android learning (二十三 )Android Orientation Sensor(方向传感器)与指南针实战(新方法替代orientation)

这篇博客介绍了如何使用Android手机的传感器开发一个指南针应用。作者首先讲解了利用SensorManager获取传感器服务,然后通过方向传感器获取设备位置,但由于Sensor.TYPE_ORIENTATION已弃用,故提出使用加速度传感器和地磁传感器结合的方式来计算方向角,提供了一种新的实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
//        List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
//        Log.e("dragon",deviceSensors+"");
//        实例化加速度传感器
        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的在移动端的实现,如果你还有问题没解决,你可以加入我们一起交流。或是关注我们的技术公众号,这是提供技术干货的地方,你有干货可以向我们推荐。

这里写图片描述

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


github源码地址下载

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值