Android指南针应用编写

news/2024/10/22 19:22:43/

目录

概述

一、运行环境:

二、编码

三、结果

四、总结


概述

        由于最近有个地磁项目的需要,重温多年Android知识,通过手机地磁传感器数据,编写了一个指南针App,同时支持,获取手机端各个传感器数据,如:陀螺仪、地磁、加速度、方位/向传感器。

一、运行环境:

1、vivo手机 MIUI版本 12.5.4

2、Android Studio Arctic Fox | 2020.3.1
 

二、编码

1、创建MiCompass.java文件(自定义view)

package com.example.mycompass;import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.Matrix;
import android.graphics.Camera;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Color;
import android.graphics.RadialGradient;
import android.view.MotionEvent;
import android.view.View;import androidx.annotation.Nullable;
import android.util.AttributeSet;public class MiCompass extends View{private Canvas mCanvas;private Context mContext;//View矩形的宽度private int width;//指南针圆心点坐标private int mCenterX;private int mCenterY;//外圆半径private int mOutSideRadius;//外接圆半径private int mCircumRadius;//指南针文字大小空间高度private int mTextHeight;//暗红色 外圈笔private Paint mDarkRedPaint;//深灰 外圈笔private Paint mDeepGrayPaint;//外三角笔private Paint mOutSideCircumPaint;//浅灰 外圈笔private Paint mLightGrayPaint;//指南针上面 文字笔private Paint mTextPaint;//外接圆,三角形笔private Paint mCircumPaint;//指南针上面文字的外接矩形,用来测文字大小让文字居中private Rect mTextRect;//外圈小三角形的Pathprivate Path mOutsideTriangle;//外接圆小三角形的Pathprivate Path mCircumTriangle;//NESW 文字笔 和文字外接矩形private Paint mNorthPaint;private Paint mOthersPaint;private Rect  mPositionRect;//小刻度文字大小矩形和画笔private Paint mSamllDegreePaint;//两位数的private Rect mSencondRect;//三位数的private Rect mThirdRect;//圆心数字矩形private Rect mCenterTextRect;//中心文字笔private Paint mCenterPaint;//内心圆是一个颜色辐射渐变的圆private Shader mInnerShader;private Paint mInnerPaint;//定义个点击属性动画private ValueAnimator mValueAnimator;// camera绕X轴旋转的角度private float mCameraRotateX;// camera绕Y轴旋转的角度private float mCameraRotateY;//camera最大旋转角度private float mMaxCameraRotate = 10;// camera绕X轴旋转的角度private float mCameraTranslateX;// camera绕Y轴旋转的角度private float mCameraTranslateY;//camera最大旋转角度private float mMaxCameraTranslate;//camera矩阵private Matrix mCameraMatrix;//设置cameraprivate Camera mCamera;private float val=0f;private float valCompare;//偏转角度红线笔private Paint mAnglePaint;//方位文字private String text="北";public float getVal() {return val;}public void setVal(float val) {this.val = val;invalidate();}public MiCompass(Context context) {this(context,null);}public MiCompass(Context context, @Nullable AttributeSet attrs) {this(context, attrs,0);}public MiCompass(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mContext = context;mDarkRedPaint = new Paint();mDarkRedPaint.setStyle(Paint.Style.STROKE);mDarkRedPaint.setAntiAlias(true);mDarkRedPaint.setColor(context.getResources().getColor(R.color.darkRed));mDeepGrayPaint = new Paint();mDeepGrayPaint.setStyle(Paint.Style.STROKE);mDeepGrayPaint.setAntiAlias(true);mDeepGrayPaint.setColor(context.getResources().getColor(R.color.deepGray));mLightGrayPaint = new Paint();mLightGrayPaint.setStyle(Paint.Style.FILL);mLightGrayPaint.setAntiAlias(true);mLightGrayPaint.setColor(context.getResources().getColor(R.color.lightGray));mTextPaint = new Paint();mTextPaint.setStyle(Paint.Style.STROKE);mTextPaint.setAntiAlias(true);mTextPaint.setTextSize(80);mTextPaint.setColor(context.getResources().getColor(R.color.white));mCircumPaint = new Paint();mCircumPaint.setStyle(Paint.Style.FILL);mCircumPaint.setAntiAlias(true);mCircumPaint.setColor(context.getResources().getColor(R.color.red));mOutSideCircumPaint = new Paint();mOutSideCircumPaint.setStyle(Paint.Style.FILL);mOutSideCircumPaint.setAntiAlias(true);mOutSideCircumPaint.setColor(context.getResources().getColor(R.color.lightGray));mTextRect = new Rect();mOutsideTriangle = new Path();mCircumTriangle = new Path();mNorthPaint = new Paint();mNorthPaint.setStyle(Paint.Style.STROKE);mNorthPaint.setAntiAlias(true);mNorthPaint.setTextSize(40);mNorthPaint.setColor(context.getResources().getColor(R.color.red));mOthersPaint = new Paint();mOthersPaint.setStyle(Paint.Style.STROKE);mOthersPaint.setAntiAlias(true);mOthersPaint.setTextSize(40);mOthersPaint.setColor(context.getResources().getColor(R.color.white));mPositionRect = new Rect();mCenterTextRect = new Rect();mCenterPaint = new Paint();mCenterPaint.setStyle(Paint.Style.STROKE);mCenterPaint.setAntiAlias(true);mCenterPaint.setTextSize(120);mCenterPaint.setColor(context.getResources().getColor(R.color.white));mSamllDegreePaint = new Paint();mSamllDegreePaint.setStyle(Paint.Style.STROKE);mSamllDegreePaint.setAntiAlias(true);mSamllDegreePaint.setTextSize(30);mSamllDegreePaint.setColor(context.getResources().getColor(R.color.lightGray));mSencondRect = new Rect();mThirdRect = new Rect();mInnerPaint = new Paint();mInnerPaint.setStyle(Paint.Style.FILL);mInnerPaint.setAntiAlias(true);mAnglePaint = new Paint();mAnglePaint.setStyle(Paint.Style.STROKE);mAnglePaint.setAntiAlias(true);mAnglePaint.setColor(context.getResources().getColor(R.color.red));mCameraMatrix = new Matrix();mCamera = new Camera();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mCanvas = canvas;//设置Camera矩阵 实现3D效果set3DMetrix();//画文字drawText();//画指南针外圈drawCompassOutSide();//画指南针外接圆drawCompassCircum();//画内部渐变颜色圆drawInnerCricle();//画指南针内部刻度drawCompassDegreeScale();//画圆心数字drawCenterText();}/*** 设置camera相关*/private void set3DMetrix() {mCameraMatrix.reset();mCamera.save();mCamera.rotateX(mCameraRotateX);mCamera.rotateY(mCameraRotateY);mCamera.getMatrix(mCameraMatrix);mCamera.restore();//camera默认旋转是View左上角为旋转中心//所以动作之前要,设置矩阵位置 -mTextHeight-mOutSideRadiusmCameraMatrix.preTranslate(-getWidth()/2,-getHeight()/2);//动作之后恢复位置mCameraMatrix.postTranslate(getWidth()/2,getHeight()/2);mCanvas.concat(mCameraMatrix);}private void drawInnerCricle() {mInnerShader = new RadialGradient(width/2,mOutSideRadius+mTextHeight,mCircumRadius-40, Color.parseColor("#323232"),Color.parseColor("#000000"),Shader.TileMode.CLAMP);mInnerPaint.setShader(mInnerShader);mCanvas.drawCircle(width/2,mOutSideRadius+mTextHeight,mCircumRadius-40,mInnerPaint);}private void drawCenterText() {String centerText=String.valueOf((int) val+"°");mCenterPaint.getTextBounds(centerText,0,centerText.length(),mCenterTextRect);int centerTextWidth = mCenterTextRect.width();int centerTextHeight = mCenterTextRect.height();mCanvas.drawText(centerText,width/2-centerTextWidth/2,mTextHeight+mOutSideRadius+centerTextHeight/5,mCenterPaint);}private void drawCompassDegreeScale() {mCanvas.save();//获取N文字的宽度mNorthPaint.getTextBounds("N",0,1,mPositionRect);int mPositionTextWidth = mPositionRect.width();int mPositionTextHeight = mPositionRect.height();//获取W文字宽度,因为W比较宽 所以要单独获取mNorthPaint.getTextBounds("W",0,1,mPositionRect);int mWPositionTextWidth = mPositionRect.width();int mWPositionTextHeight = mPositionRect.height();//获取小刻度,两位数的宽度mSamllDegreePaint.getTextBounds("30",0,1,mSencondRect);int mSencondTextWidth = mSencondRect.width();int mSencondTextHeight = mSencondRect.height();//获取小刻度,3位数的宽度mSamllDegreePaint.getTextBounds("30",0,1,mThirdRect);int mThirdTextWidth = mThirdRect.width();int mThirdTextHeight = mThirdRect.height();mCanvas.rotate(-val,width/2,mOutSideRadius+mTextHeight);//画刻度线for (int i = 0; i < 240; i++) {if (i==0||i==60||i==120||i==180){mCanvas.drawLine(getWidth() / 2, mTextHeight+mOutSideRadius-mCircumRadius+10,getWidth() / 2,  mTextHeight+mOutSideRadius-mCircumRadius+30, mDeepGrayPaint);}else{mCanvas.drawLine(getWidth() / 2, mTextHeight+mOutSideRadius-mCircumRadius+10,getWidth() / 2,  mTextHeight+mOutSideRadius-mCircumRadius+30, mLightGrayPaint);}if (i==0){mCanvas.drawText("N", this.width /2-mPositionTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mPositionTextHeight,mNorthPaint);}else if (i==60){mCanvas.drawText("E", this.width /2-mPositionTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mPositionTextHeight,mOthersPaint);}else if (i==120){mCanvas.drawText("S", this.width /2-mPositionTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mPositionTextHeight,mOthersPaint);}else if (i==180){mCanvas.drawText("W", this.width /2-mWPositionTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mWPositionTextHeight,mOthersPaint);}else if (i==20){mCanvas.drawText("30", this.width /2-mSencondTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mSencondTextHeight,mSamllDegreePaint);}else if (i==40){mCanvas.drawText("60", this.width /2-mSencondTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mSencondTextHeight,mSamllDegreePaint);}else if (i==80){mCanvas.drawText("120", this.width /2-mThirdTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mThirdTextHeight,mSamllDegreePaint);}else if (i==100){mCanvas.drawText("150", this.width /2-mThirdTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mThirdTextHeight,mSamllDegreePaint);}else if (i==140){mCanvas.drawText("210", this.width /2-mThirdTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mThirdTextHeight,mSamllDegreePaint);}else if (i==160){mCanvas.drawText("240", this.width /2-mThirdTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mThirdTextHeight,mSamllDegreePaint);}else if (i==200){mCanvas.drawText("300", this.width /2-mThirdTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mThirdTextHeight,mSamllDegreePaint);}else if (i==220){mCanvas.drawText("330", this.width /2-mThirdTextWidth/2,mTextHeight+mOutSideRadius-mCircumRadius+40+mThirdTextHeight,mSamllDegreePaint);}mCanvas.rotate(1.5f, mCenterX, mOutSideRadius+mTextHeight);}mCanvas.restore();}/*** 指南针外接圆,和外部圆换道理差不多*/private void drawCompassCircum() {mCanvas.save();//外接圆小三角形的高度int mTriangleHeight=(mOutSideRadius-mCircumRadius)/2;mCanvas.rotate(-val,width/2,mOutSideRadius+mTextHeight);mCircumTriangle.moveTo(width/2,mTriangleHeight+mTextHeight);//内接三角形的边长,简单数学运算float mTriangleSide = (float) ((mTriangleHeight/(Math.sqrt(3)))*2);mCircumTriangle.lineTo(width/2-mTriangleSide/2,mTextHeight+mTriangleHeight*2);mCircumTriangle.lineTo(width/2+mTriangleSide/2,mTextHeight+mTriangleHeight*2);mCircumTriangle.close();mCanvas.drawPath(mCircumTriangle,mCircumPaint);mCanvas.drawArc(width/2-mCircumRadius,mTextHeight+mOutSideRadius-mCircumRadius,width/2+mCircumRadius,mTextHeight+mOutSideRadius+mCircumRadius,-85,350,false,mDeepGrayPaint);mAnglePaint.setStrokeWidth(5f);if (val<=180){valCompare = val;mCanvas.drawArc(width/2-mCircumRadius,mTextHeight+mOutSideRadius-mCircumRadius,width/2+mCircumRadius,mTextHeight+mOutSideRadius+mCircumRadius,-85,valCompare,false,mAnglePaint);}else{valCompare = 360-val;mCanvas.drawArc(width/2-mCircumRadius,mTextHeight+mOutSideRadius-mCircumRadius,width/2+mCircumRadius,mTextHeight+mOutSideRadius+mCircumRadius,-95,-valCompare,false,mAnglePaint);}mCanvas.restore();}/*** 指南针外部可简单分为两部分* 1、用Path实现小三角形* 2、两个圆弧*/private void drawCompassOutSide() {mCanvas.save();//小三角形的高度int mTriangleHeight=40;//定义Path画小三角形mOutsideTriangle.moveTo(width/2,mTextHeight-mTriangleHeight);//小三角形的边长float mTriangleSide = 46.18f;//画出小三角形mOutsideTriangle.lineTo(width/2-mTriangleSide/2,mTextHeight);mOutsideTriangle.lineTo(width/2+mTriangleSide/2,mTextHeight);mOutsideTriangle.close();mCanvas.drawPath(mOutsideTriangle,mOutSideCircumPaint);//画圆弧mDarkRedPaint.setStrokeWidth((float) 5);mLightGrayPaint.setStrokeWidth((float)5);mDeepGrayPaint.setStrokeWidth((float)3);mLightGrayPaint.setStyle(Paint.Style.STROKE);mCanvas.drawArc(width/2-mOutSideRadius,mTextHeight,width/2+mOutSideRadius,mTextHeight+mOutSideRadius*2,-80,120,false,mLightGrayPaint);mCanvas.drawArc(width/2-mOutSideRadius,mTextHeight,width/2+mOutSideRadius,mTextHeight+mOutSideRadius*2,40,20,false,mDeepGrayPaint);mCanvas.drawArc(width/2-mOutSideRadius,mTextHeight,width/2+mOutSideRadius,mTextHeight+mOutSideRadius*2,-100,-20,false,mLightGrayPaint);mCanvas.drawArc(width/2-mOutSideRadius,mTextHeight,width/2+mOutSideRadius,mTextHeight+mOutSideRadius*2,-120,-120,false,mDarkRedPaint);mCanvas.restore();}private void drawText() {if (val<=15||val>=345){text = "北";}else if (val>15&&val<=75){text= "东北";}else if (val>75&&val<=105){text= "东";}else if (val>105&&val<=165){text="东南";}else if (val>165&&val<=195){text = "南";}else if (val>195&&val<=255){text = "西南";}else if (val>255&&val<=285){text = "西";}else if (val>285&&val<345){text="西北";}mTextPaint.getTextBounds(text,0,text.length(),mTextRect);//文字宽度int mTextWidth = mTextRect.width();//让文字水平居中显示mCanvas.drawText(text,width/2-mTextWidth/2,mTextHeight/2,mTextPaint);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);width = Math.min(widthSize, heightSize);if (widthMode == MeasureSpec.UNSPECIFIED) {width = heightSize;} else if (heightMode == MeasureSpec.UNSPECIFIED) {width = widthSize;}//为指南针上面的文字预留空间,定为1/3边张mTextHeight = width/3;//设置圆心点坐标mCenterX = width/2;mCenterY = width/2+mTextHeight;//外部圆的外径mOutSideRadius = width*3/8;//外接圆的半径mCircumRadius = mOutSideRadius*4/5;//camera最大平移距离mMaxCameraTranslate = 0.02f*mOutSideRadius;setMeasuredDimension(width, width+width/3 );}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:if (mValueAnimator!=null&&mValueAnimator.isRunning()){mValueAnimator.cancel();}//3D 效果让Camera旋转,获取旋转偏移大小getCameraRotate(event);//获取平移大小getCameraTranslate(event);break;case MotionEvent.ACTION_MOVE://3D 效果让Camera旋转,获取旋转偏移大小getCameraRotate(event);//获取平移大小getCameraTranslate(event);break;case MotionEvent.ACTION_UP://松开手 复原动画startRestore();break;}return true;}private void startRestore() {final String cameraRotateXName = "cameraRotateX";final String cameraRotateYName = "cameraRotateY";final String canvasTranslateXName = "canvasTranslateX";final String canvasTranslateYName = "canvasTranslateY";PropertyValuesHolder cameraRotateXHolder =PropertyValuesHolder.ofFloat(cameraRotateXName, mCameraRotateX, 0);PropertyValuesHolder cameraRotateYHolder =PropertyValuesHolder.ofFloat(cameraRotateYName, mCameraRotateY, 0);PropertyValuesHolder canvasTranslateXHolder =PropertyValuesHolder.ofFloat(canvasTranslateXName, mCameraTranslateX, 0);PropertyValuesHolder canvasTranslateYHolder =PropertyValuesHolder.ofFloat(canvasTranslateYName, mCameraTranslateY, 0);mValueAnimator = ValueAnimator.ofPropertyValuesHolder(cameraRotateXHolder,cameraRotateYHolder, canvasTranslateXHolder, canvasTranslateYHolder);mValueAnimator.setInterpolator(new TimeInterpolator() {@Overridepublic float getInterpolation(float input) {float f = 0.571429f;return (float) (Math.pow(2, -2 * input) * Math.sin((input - f / 4) * (2 * Math.PI) / f) + 1);}});mValueAnimator.setDuration(1000);mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mCameraRotateX = (float) animation.getAnimatedValue(cameraRotateXName);mCameraRotateY = (float) animation.getAnimatedValue(cameraRotateYName);mCameraTranslateX = (float) animation.getAnimatedValue(canvasTranslateXName);mCameraTranslateX = (float) animation.getAnimatedValue(canvasTranslateYName);}});mValueAnimator.start();}/*** 获取Camera,平移大小* @param event*/private void getCameraTranslate(MotionEvent event) {float translateX = (event.getX() - getWidth() / 2);float translateY = (event.getY() - getHeight()/2);//求出此时位移的大小与半径之比float[] percentArr = getPercent(translateX, translateY);//最终位移的大小按比例匀称改变mCameraTranslateX = percentArr[0] * mMaxCameraTranslate;mCameraTranslateY = percentArr[1] * mMaxCameraTranslate;}/*** 让Camera旋转,获取旋转偏移大小* @param event*/private void getCameraRotate(MotionEvent event) {float mRotateX = -(event.getY()-(getHeight())/2);float mRotateY = (event.getX()-getWidth()/2);//求出旋转大小与半径之比float[] percentArr = getPercent(mRotateX,mRotateY);mCameraRotateX = percentArr[0]*mMaxCameraRotate;mCameraRotateY = percentArr[1]*mMaxCameraRotate;}/*** 获取比例* @param mCameraRotateX* @param mCameraRotateY* @return*/private float[] getPercent(float mCameraRotateX, float mCameraRotateY) {float[] percentArr = new float[2];float percentX = mCameraRotateX/width;float percentY = mCameraRotateY/width;//处理一下比例值if (percentX > 1) {percentX = 1;} else if (percentX < -1) {percentX = -1;}if (percentY > 1) {percentY = 1;} else if (percentY < -1) {percentY = -1;}percentArr[0] = percentX;percentArr[1] = percentY;return percentArr;}}

2、colors.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="colorPrimary">#3F51B5</color><color name="colorPrimaryDark">#303F9F</color><color name="colorAccent">#FF4081</color><color name="black">#000</color><color name="darkRed">#702216</color><color name="lightGray">#323232</color><color name="deepGray">#8B8B8B</color><color name="white">#fff</color><color name="red">#f00</color><color name="ocbg">#237EAD</color>
</resources>

3、value\themes.xml、value-nigth\themes.xml文件

  此时有两个报错,不用怕,挨个解决,挨个创建即可。

 

报错的地方,按照以上方法,挨个创建即可,创建好之后如下所示: 

 4、activity_main.xml文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/black"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/accSensor_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/white"android:text="加速度传感器"/><TextViewandroid:id="@+id/mangeticSensor_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/white"android:text="地磁传感器"/><TextViewandroid:id="@+id/gyroscopeSensor_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/white"android:text="陀螺仪感应器"/><TextViewandroid:id="@+id/orientationSensor_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="@color/white"android:text="方向传感器"/><TextViewandroid:id="@+id/adjust_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:textAlignment="center"android:textColor="@color/red"android:text="compass"/><com.example.mycompass.MiCompassandroid:id="@+id/miui"android:layout_centerInParent="true"android:layout_gravity="center"android:background="@color/black"android:layout_width="match_parent"android:layout_height="wrap_content"tools:ignore="MissingConstraints" /></LinearLayout><!--<com.example.mycompass.MiCompassandroid:id="@+id/miui"android:layout_centerInParent="true"android:layout_gravity="center"android:background="@color/black"android:layout_width="match_parent"android:layout_height="wrap_content"tools:ignore="MissingConstraints" />--></androidx.constraintlayout.widget.ConstraintLayout>

5、MainActivity.java文件

package com.example.mycompass;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.widget.TextView;import java.util.List;public class MainActivity extends AppCompatActivity {public static final int SENSOR_STATUS_NO_CONTACT = -1;public static final int SENSOR_STATUS_UNRELIABLE = 0;public static final int SENSOR_STATUS_ACCURACY_LOW = 1;/*** This sensor is reporting data with an average level of accuracy,* calibration with the environment may improve the readings*/public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;/** This sensor is reporting data with maximum accuracy */public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;private SensorManager mSensorManager;private MySensorEventListener mMySensorEventListener;private MiCompass miui;private  float val;private float[] mAccelerometerReading = new float[3];private float[] mMagneticFieldReading = new float[3];private TextView mAccelerometerSensorTextView;private TextView mMagneticSensorTextView;private TextView mGyroscopeSensorTextView;private TextView mOrientationSensorTextView;private TextView mAdjustTextView;private String Tag = "Tag:";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mAccelerometerSensorTextView = findViewById(R.id.accSensor_tv);mMagneticSensorTextView = findViewById(R.id.mangeticSensor_tv);mGyroscopeSensorTextView = findViewById(R.id.gyroscopeSensor_tv);mOrientationSensorTextView = findViewById(R.id.orientationSensor_tv);mAdjustTextView = findViewById(R.id.adjust_tv);miui = findViewById(R.id.miui);mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);this.mMySensorEventListener = new MySensorEventListener();Sensor accelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);Sensor magneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);Sensor gyroscopeSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);if (accelerometerSensor != null) {System.out.println("传感器存在");Log.d(Tag, "传感器存在");} else {System.out.println("传感器不存在");Log.d(Tag, "传感器不存在");}mSensorManager.registerListener(mMySensorEventListener,mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),SensorManager.SENSOR_DELAY_GAME);mSensorManager.registerListener(mMySensorEventListener,accelerometerSensor,SensorManager.SENSOR_DELAY_UI);mSensorManager.registerListener(mMySensorEventListener,magneticSensor,SensorManager.SENSOR_DELAY_UI);mSensorManager.registerListener(mMySensorEventListener,gyroscopeSensor,SensorManager.SENSOR_DELAY_UI);}@Overrideprotected void onDestroy() {super.onDestroy();mSensorManager.unregisterListener(mMySensorEventListener);}private void calculateOrientation() {final float[] rotationMatrix = new float[9];SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometerReading, mMagneticFieldReading);final float[] orientationAngles = new float[3];SensorManager.getOrientation(rotationMatrix, orientationAngles);System.out.println("orientation data[x:" + orientationAngles[0] + ", y:" + orientationAngles[1] + ", z:" + orientationAngles[2] + "]");mOrientationSensorTextView.setText("orientation [x:" + orientationAngles[0] + ", y:" + orientationAngles[1] + ", z:" + orientationAngles[2] + "]");}private class MySensorEventListener implements SensorEventListener {@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {val = event.values[0];System.out.println(val);miui.setVal(val);} else if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {mAccelerometerReading = event.values;System.out.println("accelerometer data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
//                Log.d(Tag, "accelerometer data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");mAccelerometerSensorTextView.setText("accelerometer [x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {mMagneticFieldReading = event.values;System.out.println("magnetic data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
//                Log.d(Tag, "magnetic data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");mMagneticSensorTextView.setText("magnetic [x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");} else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {System.out.println("gyroscope data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
//                Log.d(Tag, "gyroscope data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");mGyroscopeSensorTextView.setText("gyroscope [x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");}calculateOrientation();}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {System.out.println("onAccuracyChanged:" + sensor.getType() + "->" + accuracy);if (accuracy >= SensorManager.SENSOR_STATUS_ACCURACY_HIGH ) {System.out.println("Compass, 不需要校验");
//                Log.e("Compass", " 不需要校验");mAdjustTextView.setText("Compass, 不需要校验");} else {System.out.println("Compass, 需要校准 ");
//                Log.e("Compass", " 需要校准 ");mAdjustTextView.setText("Compass, 需要校验, 拿手机画8");}}}}

6、AndroidManifest.xml 文件
 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.mycompass"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.MyCompass"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application><!-- 添加下面这句话 --><uses-featureandroid:name="android.hardware.sensor.accelerometer"android:required="true" />
</manifest>

三、结果

四、总结

       在此,做个笔录,没想到多年没碰Android,现在还是初恋的感觉 哈哈^_^。在这希望能帮到各个技术攻城狮。基本多部分都是参考以下文章编写而成,在此非常感谢!这位大佬无私贡献。

源码(csdn代码仓库):Ch_champion / MyCompass · CODE CHINA

参考文章:

android学习笔记之磁场传感器制做指南针_晓晓的博客-CSDN博客


http://www.ppmy.cn/news/707127.html

相关文章

制作简单的指南针

/**** 指南针简单制作**/ public class CompassActivity extends BaseActivity {private SensorManager sensorManager;Bind(R.id.compass_img)ImageView compassImg;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setCont…

指南针的实现

1、在/res/drawable/目录下放入指南针的图片 2、main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:l…

指南针和陀螺仪

http://www.code4app.com/thread-9058-1-1.html

司空见惯 - 车载指南针拆解

我网上买了个车载指南针&#xff0c;贴在了车前挡风玻璃附近。开始贴在中间&#xff0c;结果指针不准&#xff0c;应该是车机的音响喇叭在中间有一个&#xff0c;喇叭里面有磁铁&#xff0c;所以影响了这个指南针。 然后就贴在了前挡风玻璃最左边&#xff0c;方向盘左边。 最近…

Android开发之指南针

Android开发之指南针 一、基于方向传感器1.效果图2.布局文件(activity_main)3.java文件(MainActivity) 二、基于加速度传感器和磁场传感器1.效果图2.布局文件(compass01)3.java文件(TypeTwoActivity) 三、资源下载 Android基于多种手机传感器开发指南针的项目 一、基于方向传感…

HTML5指南针

deviceOrientation & deviceMotion 以上为HTML5的提供的两种接口 摇一摇功能&#xff08;DeviceMotion&#xff09;重力感应方向控制/指南针&#xff08;DeviceOrientation&#xff09; 重力感应与罗盘 DeviceOrientation 当浏览器的Orientation发生变化时&#xff0c;触发…

指南针安卓demo

2016/05/12// ///by xbw/ /eclipse api21/ 指南针小demo&#xff0c;整理一下&#xff0c; package com.example.compass;import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import and…

一个好看的指南针制作

成品演示&#xff1a; 教程开始 1.首先先创建一个23*23厘米的正方形画布&#xff0c;并填充#ffb1b1颜色。 2.在中心位置创建一个圆角矩形大小为444*444像素&#xff0c;半径为85像素&#xff0c;颜色为eed4d3。 3.给这个圆角矩形添加一些图层样式。 &#xff08;1&#xff…