Android项目开发:指南针(两种方法实现)

在Android中可以使用内置传感器(方向传感器、加速度传感器和地磁传感器等)实现指南针功能,编写出能够辨别手机方位的app。本文将讲述两种方法编写指南针app的方法,一是使用方向传感器,二是将加速度传感器和地磁传感器结合。

1.基于方向传感器

方向传感器是Android的基本传感器之一,通过三维坐标来确定(X,Y,Z)的三个方向,以进一步实现指南针功能。
ps:Sensor.TYPE_ORIENTATION在目前的Android系统中已经不再推荐使用,但是仍然可以通过其来获取数据。

activity_main.xml

简单一点,在layout中只设计了一个imageview来放置指南针的图片,以通过动画转动图片实现指南针功能。

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" 
  android:gravity="center"> 
  <ImageView
    android:id="@+id/imageview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/compass" /> 
</LinearLayout>

MainActivity.java

思路比较简单,通过SensorEventListener监听传感器事件,获取方向传感器Z轴采集到的数据,转动指南针图片。

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    //使用方向传感器编写指南针
    private ImageView imageView;
    private float currentDegree;
    private SensorManager sensorManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView=(ImageView) findViewById(R.id.imageview);
        currentDegree=0f;
        sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);  //获取传感器服务
    }

    @Override
    protected void onResume() {
        //为方向传感器注册监听器
        super.onResume();
        sensorManager.registerListener(this,sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),sensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onPause() {
        //取消监听器
        super.onPause();
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        //保持设备水平,使用水平传感器
        if(event.sensor.getType()==Sensor.TYPE_ORIENTATION){
            //取围绕Z轴转过的角度
            float degree=event.values[0];
            RotateAnimation rotateAnimation=new RotateAnimation(currentDegree,-degree, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);  //动画转动角度
            rotateAnimation.setDuration(200); //设置动画持续时间
            rotateAnimation.setFillAfter(true); //设置动画结束后的保留状态
            imageView.setAnimation(rotateAnimation);
            currentDegree=-degree;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

2.基于加速度传感器和地磁传感器

布局和上面的方法一致,因此可以直接复制上面的activity_main.xml代码,详细介绍一下java代码部分。
在onCreate方法中分别获取了加速度传感器和地磁传感器实例,并给他们都注册了监听器。然后在onSensorChanged()方法中进行判断,如果当前是加速度传感器,就将values数组赋给accelerometerValues数组,如果当前是地磁传感器,就将values数组赋给magneticValues数组。在赋值的时候一定要调用values的clone()方法,不然accelerometerValues和magneticValues将指向同一块引用。
接下来,分别创建一个长度为9的R数组和一个长度为3的values数组,然后调用getRotationMatrix()方法给R数组赋值,再调用getOrientation()方法为values数组赋值,这是values数组中含有手机在所有方向上旋转的弧度了。(可以将弧度转换为度)
最后,在回调方法中利用RotateAnimation和当前旋转过的角度值values[0],可以将图片旋转。

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {
	//通过加速度传感器和地磁传感器编写指南针
    private SensorManager sensorManager;
    private ImageView imageView;
    private float lastRotateDegree;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = (ImageView) findViewById(R.id.imageview);
        sensorManager = (SensorManager) getSystemService(Context.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);
        }
    }

    float[] accelerometerValues = new float[3];

    float[] magneticValues = new float[3];

    @Override
    public void onSensorChanged(SensorEvent event) {
        // 判断当前是加速度感应器还是地磁感应器
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            //赋值调用clone方法
            accelerometerValues = event.values.clone();
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            //赋值调用clone方法
            magneticValues = event.values.clone();
        }
        float[] R = new float[9];
        float[] values = new float[3];
        SensorManager.getRotationMatrix(R,null,accelerometerValues,magneticValues);
        sensorManager.getOrientation(R, values);
        Log.d("Main","values[0] :"+Math.toDegrees(values[0]));
        //values[0]的取值范围是-180到180度。
        //+-180表示正南方向,0度表示正北,-90表示正西,+90表示正东

        //将计算出的旋转角度取反,用于旋转指南针背景图
        float rotateDegree = -(float) Math.toDegrees(values[0]);
        if (Math.abs(rotateDegree - lastRotateDegree) > 1) {
            RotateAnimation animation = new RotateAnimation(lastRotateDegree,rotateDegree, Animation.RELATIVE_TO_SELF,0.5f,
                    Animation.RELATIVE_TO_SELF,0.5f);
            animation.setFillAfter(true);
            imageView.startAnimation(animation); //动画效果转动传感器
            lastRotateDegree = rotateDegree;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

最后,附上项目链接

  • 1
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 华为USG6000防火墙支持DDNS功能,可以配置为域名映射或动态DNS。要设置DDNS,可以通过以下步骤进行:1、进入DDNS页面,点击“新建”;2、填写服务器地址,用户名,密码;3、填写域名;4、点击“确定”。 ### 回答2: 华为防火墙USG6000是一款优秀的网络安全设备,可以通过设置DDNS来实现动态域名解析,下面是如何设置DDNS的步骤: 1. 首先,登录到USG6000的web管理界面。 2. 在管理界面中,点击左侧导航栏中的“网络管理”。 3. 在网络管理页面中,找到“DDNS”设置选项,并点击进入。 4. 在DDNS设置界面中,首先选择一个DDNS服务提供商,比如“DynDNS”。 5. 接下来,填写相关的DDNS账号信息,包括账号名称、账号密码以及要更新的域名。 6. 在设置界面中,可以选择是否启用DDNS功能,以及设置更新时间间隔。 7. 填写完相关信息后,点击“应用”按钮,保存设置。 8. 设置完成后,可以通过点击“状态”标签页,查看DDNS的状态,是否已成功更新。 需要注意的是,在设置DDNS之前,确保USG6000已经连接到可联网的网络中,并且已经获得了有效的IP地址。 设置DDNS后,USG6000会自动将动态IP地址与域名进行绑定,当动态IP地址发生变化时,DDNS服务会自动将最新的IP地址更新到指定的域名上,从而实现域名的动态解析。 通过以上步骤,您可以轻松地在华为防火墙USG6000上设置DDNS功能。如有问题,建议参考华为官方文档或咨询华为技术支持团队。 ### 回答3: 华为防火墙USG6000可以通过以下步骤设置DDNS: 1. 登录到防火墙的Web界面。在浏览器地址栏中输入防火墙的IP地址,并输入管理员账号和密码登录。 2. 在导航栏中找到“网络”选项,并点击“DDNS”子选项。 3. 在DDNS页面中,点击“新建”按钮。 4. 在弹出的“新建DDNS”对话框中,填写以下信息: - DDNS名称:填写一个有意义的名称来标识这个DDNS设置。 - DDNS服务器:选择所使用的DDNS服务器。根据需要选择合适的DDNS服务提供商。 - Hostname/域名:填写您注册DDNS服务时获得的域名。例如,example.ddnsprovider.com。 - 使用接口IP:选择防火墙上的一个接口IP地址作为DDNS的工作IP地址。 5. 点击“确定”按钮保存设置。 6. 返回DDNS页面,点击“应用”按钮使配置生效。 完成上述步骤后,华为防火墙USG6000将会定期向DDNS服务器发送请求,将防火墙当前的公网IP地址更新到DDNS服务器绑定的域名上。这样,您就可以通过使用域名来访问防火墙,而不必担心公网IP地址的变化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值