前言:
十年前传感器在智能设备上早已大行其道,迄今为止无论iOS亦或Android设备没有搭载传感器的屈指可数。今天依赖于完善的开发工具以及成熟的传感器技术的应用,我们得以展开一场完全依靠自己的双手开发一款金属探测仪的机会。
一:构思
传感器种类很多,包括温度、亮度、湿度以及磁场等。它们统称为Sensor
,由其特有的管理者SensorManager
来进行管理使用。当我们想要使用某种传感器,只需将SensorManager
获取具体传感器的方法内传入特定参数即可。我们获得磁场传感器的实例应用后,会得到设备在三维空间中面向x
、y
、z
三个坐标轴的地磁场强度(单位:微特斯拉)。如果说我们的设备处于一个三维环境中,只要任意一轴方向上磁感应强度发生了变化,那么我们就可以判定附近有磁场上的变化,无论x
、y
、z
三个坐标轴的地磁场强度是否相等。事实上,磁场变化并不是在同一时刻围绕一个物体发生360°的变化,那么我们就可以以任意一轴上的磁感应变化来判断设备附件是否有金属(金属引起物体附近磁场变化)。
二:布局
我们就只创建一个活动,里面放入显示x
、y
、z
三个坐标轴的地磁场强度 的控件。这里有TextView
、ProgressBar
、CircleProgress
(第三方控件)。布局结构也非常简单,一个方向向下的线性布局。
<?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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Tesla Sensor"
android:gravity="center"
android:textSize="24sp"
android:textStyle="bold"
android:paddingTop="25dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text_view_x"
android:gravity="center"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress_bar_x"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text_view_y"
android:gravity="center"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress_bar_y"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text_view_z"
android:gravity="center"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress_bar_z"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>
<com.ihat.pihat.circleprogress.CircleProgress
android:id="@+id/circle_progress_x"
android:layout_width="100dp"
android:layout_height="100dp"
app:despText="X Detective"
app:valueText="None"
app:valueTextSize="13sp"
app:despTextSize="07sp"
app:roundProgressColor="@color/colorPrimaryDark"
app:valueTextColor="@color/colorAccent"
app:circleStrokeWidth="2dp"
android:layout_gravity="center"/>
<com.ihat.pihat.circleprogress.CircleProgress
android:id="@+id/circle_progress_y"
android:layout_width="100dp"
android:layout_height="100dp"
app:despText="Y Detective"
app:valueText="None"
app:valueTextSize="13sp"
app:despTextSize="07sp"
app:roundProgressColor="@color/colorPrimaryDark"
app:valueTextColor="@color/colorAccent"
app:circleStrokeWidth="2dp"
android:layout_gravity="center"
/>
<com.ihat.pihat.circleprogress.CircleProgress
android:id="@+id/circle_progress_z"
android:layout_width="100dp"
android:layout_height="100dp"
app:despText="Z Detective"
app:valueText="None"
app:valueTextSize="13sp"
app:despTextSize="07sp"
app:roundProgressColor="@color/colorPrimaryDark"
app:valueTextColor="@color/colorAccent"
app:circleStrokeWidth="2dp"
android:layout_gravity="center"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
预览如下:
三:代码:
这里也没什么特别难以理解的地方。onSensorChanged()
内是磁场传感器数值发生改变时回调的方法,里面传入我们想要更新的控件的逻辑即可。另外不要忘了注册SensorManager()
的监听器,以及及时卸载即可。
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.media.Ringtone;
import android.media.RingtoneManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.ayst.dashboardview.DashboardView;
import com.ihat.pihat.circleprogress.CircleProgress;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor sensor;
private TextView textViewX;
private TextView textViewY;
private TextView textViewZ;
private ProgressBar progressBarX;
private ProgressBar progressBarY;
private ProgressBar progressBarZ;
private SoundPool soundPool;
// Third widget to show a progress information.
private CircleProgress circleProgressX;
private CircleProgress circleProgressY;
private CircleProgress circleProgressZ;
private void initView(){
textViewX = (TextView) findViewById(R.id.text_view_x);
textViewY = (TextView) findViewById(R.id.text_view_y);
textViewZ = (TextView) findViewById(R.id.text_view_z);
progressBarX = (ProgressBar) findViewById(R.id.progress_bar_x);
progressBarY = (ProgressBar) findViewById(R.id.progress_bar_y);
progressBarZ = (ProgressBar) findViewById(R.id.progress_bar_z);
circleProgressX = (CircleProgress) findViewById(R.id.circle_progress_x);
circleProgressY = (CircleProgress) findViewById(R.id.circle_progress_y);
circleProgressZ = (CircleProgress) findViewById(R.id.circle_progress_z);
}
// Init the Sensor and SensorManager, notice the parameter of (Sensor.TYPE_MAGNETIC_FIELD),
// we get magnetic sensor to use.
private void initSensor(){
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initSensor();
}
@Override
protected void onResume() {
super.onResume();
// Register SensorManager listener.
sensorManager.registerListener(MainActivity.this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
// Unregister SensorManager listener when callback onPause().
sensorManager.unregisterListener(this);
}
/**
* Notice event is an array to store float values.
* @param event event[0] for x axis, event[1] for y axis, event[2] for z axis.
*/
@Override
public void onSensorChanged(SensorEvent event) {
textViewX.setText(String.valueOf(event.values[0]));
progressBarX.setProgress(0 - (int) event.values[0]);
circleProgressX.setValueText(String.valueOf(event.values[0]));
circleProgressX.setSweepValue(-event.values[0]);
textViewY.setText(String.valueOf(event.values[1]));
progressBarY.setProgress((int) event.values[1]);
circleProgressY.setValueText(String.valueOf(event.values[1]));
circleProgressY.setSweepValue(event.values[1]);
textViewZ.setText(String.valueOf(event.values[2]));
progressBarZ.setProgress(0 - (int) event.values[2]);
circleProgressZ.setValueText(String.valueOf(event.values[2]));
circleProgressZ.setSweepValue(event.values[2]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
**附:**github 地址 :https://github.com/mcry416/metal_detective