【Android入门到项目实战-- 9.2】—— 传感器实战使用教程(靠近黑屏和计步器)

        上篇文章介绍了传感器的基础用法(如有需要,可先移步),下面将通过两个实战案例学习具体如何使用。

一、靠近黑屏

        这是距离传感器的简单应用。

        –检测手机是否贴在耳朵上正在打电话,以便自动熄灭屏幕达到省电的目的。也可用于皮套、口袋模式下自动实现解锁与锁屏动作。

        –用到电量管理器PowerManager来控制屏幕的亮灭,需要获取权限

        –我们并不需要获取距离传感器的值,而是让它和PowerManager的内建功能一起配合使用

新建项目SensorDemo3。

修改activity_main.xml文件,代码如下:

        下面定义了一个RelativeLayout布局,里面有一个TextView

<?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">

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="5dp"
        >

        <TextView
            android:textSize="20sp"
            android:layout_centerInParent="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="不要靠近我~~我会变黑的"/>
    </RelativeLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

修改AndroidManifest.xml文件,获取权限

        获取相关的系统唤醒锁定权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.WAKE_LOCK"/>

..............

修改MainAcitivity,代码如下:

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager sensorManager;

    /*使用电量管理器控制屏幕的熄灭和唤醒*/
    private PowerManager pm;
    private PowerManager.WakeLock wakeLock;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        pm = (PowerManager) getSystemService(POWER_SERVICE);
        closeOrClose();
    }


    /**
     * 初始化唤醒锁wakeLock,直接使用内置PROXIMITY_SCREEN_OFF_WAKE_LOCK,
     * 就可以直接实现靠近熄灭屏幕的功能
     *
     * 初始化完要调用acquire()方法启用
     */
    @SuppressLint("InvalidWakeLockTag")
    private void closeOrClose() {
        wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
                "w1");
        wakeLock.setReferenceCounted(false);
        wakeLock.acquire();
    }

    @Override
    protected void onResume() {
        /*注册距离传感器,只有注册了距离传感器唤醒锁才有效果*/
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
                SensorManager.SENSOR_DELAY_NORMAL);
        super.onResume();
    }

    @Override
    protected void onStop() {
        /*释放传感器和唤醒锁*/
        wakeLock.release();
        sensorManager.unregisterListener(this);
        super.onStop();
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
    }

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

PowerManager要点

•WakeLock级别:
–    PARTIAL_WAKE_LOCK       保持CPU运转,屏幕和键盘背光可能关闭
–    SCREEN_DIM_WAKE_LOCK    保持CPU运转,保持屏幕常亮(亮度低),键盘背光可能关闭
–    SCREEN_BRIGHT_WAKE_LOCK 保持CPU运转,保持屏幕和键盘背光高亮
–    FULL_WAKE_LOCK          保持CPU运转,保持屏幕和键盘背光高亮(亮度最高)
–    ACQUIRE_CAUSES_WAKEUP            强制亮屏,针对一些必须通知用户的操作
–    ON_AFTER_RELEASE                 当锁被释放时,保持亮屏一段时间(如果释放时屏幕没亮,则不会亮屏)
–    PROXIMITY_SCREEN_OFF_WAKE_LOCK   和接近传感器配合,当用户接近屏幕时黑屏,离开时亮屏(例如打电话)
•WakeLock方法:
–    void acquire()              获得WakeLock,除非显式释放,否则不会解锁(经测试,APP进程被杀死后,锁会失效)
–    void acquire(long timeOut)  当超过timeOut之后系统自动释放WakeLock
–    void release()              释放WakeLock
–    boolean isHeld()            是否已经获取WakeLock 
–    void setReferenceCounted(boolean value) 是否使用引用计数(默认ture): 一个WakeLock调用acquire()多次,也必须release()多次才能释放,    如果释放次数比acquire()多,则抛出异常: java.lang.RuntimeException: WakeLock under-locked MyTAG
可参考下面文章:
https://www.jianshu.com/p/2cfd179ef8dc
https://blog.csdn.net/fengyeNom1/article/details/121373158

二、计步器

最新记步模式 使用 Android4.4 Kitkat 新增的 STEP DETECTOR 以及 STEP COUNTER 传感器。

Step counter sensor
•    TYPE_STEP_COUNTER :计步器(记录历史步数累加值)
    这种类型的传感器返回用户自上次重新激活以来所采取的步骤数。 该值作为浮点数返回(小数部分设置为零),仅在系统重新引导时才将其重置为零。 事件的时间戳设置为采取该事件的最后一步的时间。 该传感器以硬件实现,预计功耗低。 如果要持续跟踪长时间的步数,请勿取消注册该传感器,以便即使 AP 处于挂起模式,也会在后台继续计数步骤,并且当 AP 处于挂起状态时报告聚合计数 苏醒。 应用程序需要保留该传感器的注册,因为如果没有激活步进计数器不计数步骤。 该传感器适用于健身跟踪应用。 它被定义为 REPORTING_MODE_ON_CHANGE 传感器。
Step detector sensor
•    TYPE_STEP_DETECTOR :检测器(检测每次步伐数据)
    这种类型的传感器每次用户触发一个事件。 唯一允许的返回值为 1.0 ,并为每个步骤生成一个事件。 与任何其他事件一样,时间戳表示事件(这里是步骤)何时发生,这对应于当脚撞到地面时,产生加速度的高变化。 该传感器仅用于检测每个单独的步骤,例如执行航位推算。 如果您只需要在一段时间内累积的步数,请注册 TYPE_STEP_COUNTER 。 它被定义为 REPORTING_MODE_SPECIAL_TRIGGER 传感器。
新建项目SensorDemo4
修改AndroidManifest.xml,申请权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-feature android:name="android.hardware.sensor.stepcounter" />
    <uses-feature android:name="android.hardware.sensor.stepdetector" />
    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>

..............

修改activity_main.xml代码,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/step_counter_txt"
        android:text="总步数"
        android:layout_gravity="center"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/step_counter"
        android:text="-1"
        android:layout_gravity="center"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/step_detector_txt"
        android:text="单次记步"
        android:layout_gravity="center" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/step_detector"
        android:text="0"
        android:layout_gravity="center" />

</LinearLayout>

修改MainActivity代码如下:

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager mSensorManager;
    private TextView mStepCounterTextView, mStepDetectorTextView; // Textview for showing steps counter of respective sensors
    private boolean isActivityRunning; // if true then activity is in foreground
    private int mStepDetectCounter = 0; // used in step detector sensor

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PackageManager packageManager = getPackageManager();
        if (packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER)
                && packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR)) {
            mStepCounterTextView = (TextView) findViewById(R.id.step_counter);
            mStepDetectorTextView = (TextView) findViewById(R.id.step_detector);
            mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        } else {
            Toast.makeText(this, "This phone does not supports required sensor", Toast.LENGTH_SHORT).show();
        }

        if(ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED){
            //ask for permission
            requestPermissions(new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, 1);
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        switch (event.sensor.getType()) {
            case Sensor.TYPE_STEP_COUNTER:
                if (isActivityRunning) {
                    mStepCounterTextView.setText(String.valueOf(event.values[0]));
                }
                break;
            case Sensor.TYPE_STEP_DETECTOR:
                if (isActivityRunning) {
                    mStepDetectCounter++;
                    mStepDetectorTextView.setText(String.valueOf(mStepDetectCounter));
                }
        }
    }

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

    }

    @Override
    protected void onResume() {
        super.onResume();

        isActivityRunning = true;
        Sensor countSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
        Sensor detectSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        if (countSensor != null) {
            mSensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_FASTEST);
        } else {
            Toast.makeText(this, "Count sensor not available!", Toast.LENGTH_LONG).show();
        }
        if (detectSensor != null) {
            mSensorManager.registerListener(this, detectSensor, SensorManager.SENSOR_DELAY_FASTEST);
        } else {
            Toast.makeText(this, "Count sensor not available!", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        isActivityRunning = false;
    }

    @Override
    protected void onStop() {
        super.onStop();
        mSensorManager.unregisterListener(this);
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天行健

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值