资讯详情

Andoird开发--指南针(基于手机传感器)

在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):


        标签: sp2880角度传感器sp2801角度传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台