[Android Getting Started to Project Actual Combat -- 9.2] —— センサー実戦チュートリアル (黒画面と歩数計に近い)

        前回の記事ではセンサーの基本的な使い方を紹介しました(必要に応じて先に移動することもできます)。次に、2つの実際のケースを通してセンサーの使い方を学びます。

1. 黒い画面に近づく

        これは距離センサーの単純なアプリケーションです。

        – 電話機が耳に装着されて通話中かどうかを検出し、画面を自動的にオフにして電力を節約します。レザーケースモードやポケットモードでも使用して、画面のロックを自動的に解除およびロックすることができます。

        – 電源マネージャー PowerManager を使用して画面のオンとオフを制御します。これには許可が必要です

        – 距離センサーの値を取得する必要はありませんが、PowerManager の組み込み関数で機能させます。

新しいプロジェクト SensorDemo3 を作成します。

activity_main.xml ファイルを変更します。コードは次のとおりです。

        以下は、TextView を内部に持つ RelativeLayout レイアウトを定義します。

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

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

MainActivity を変更します。コードは次のとおりです。

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 の必需品

• ウェイクロックレベル:
– 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 は近接センサーと連携し、ユーザーが画面に近づくと画面が黒くなり、ユーザーが画面から離れると (電話をかけるなど)
• ウェイクロック方式:
– voidacquire() を使用して WakeLock を取得します。明示的に解放しない限り、ロックは解除されません (テスト済み、APP プロセスが強制終了された後、ロックは無効になります)
– voidacquire(long timeOut) timeOut後にシステムが自動的にWakeLockを解放します。
– void release() WakeLock をリリースする
– boolean isHeld() WakeLockが取得されているかどうか 
– void setReferenceCounted(boolean value) 参照カウントを使用するかどうか (デフォルト): WakeLock は、acquire() を複数回呼び出し、解放される前に release() を複数回呼び出す必要があります。 、例外がスローされます: java .lang.RuntimeException: WakeLock under-locked MyTAG
次の記事を参照できます。
https://www.jianshu.com/p/2cfd179ef8dc
https://blog.csdn.net/fengyeNom1/article/details/121373158

2.歩数計

最新の歩数計測モードは、 Android4.4 Kitkatの新しいSTEP DETECTORおよびSTEP COUNTERセンサー を使用します

ステップカウンターセンサー
•    TYPE_STEP_COUNTER : 歩数計 (歩数の累積値を記録します)
    このタイプのセンサーは、最後に再アクティブ化してからユーザーが歩いた歩数を返します。値は浮動小数点数 (小数部はゼロに設定) として返され、システムの再起動時にのみゼロにリセットされます。イベントのタイムスタンプは、そのイベントの最後のステップが実行された時刻に設定されます。センサーはハードウェアに実装されており、低消費電力が期待されます。長期間の歩数を継続的に追跡する場合は、センサーの登録を解除しないでください。これにより、AP がサスペンド モードであってもバックグラウンドで歩数のカウントが継続され、AP がサスペンド モードになって復帰したときに集計されたカウントがレポート ます 。上。歩数カウンターはアクティブ化されていない場合は歩数をカウントしないため、アプリケーションはセンサーを登録しておく必要があります。このセンサーはフィットネス追跡アプリケーションに適しています。 REPORTING_MODE_ON_CHANGEセンサー として定義されます
段差検知センサー
•    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);
    }
}

Supongo que te gusta

Origin blog.csdn.net/Tir_zhang/article/details/130536824
Recomendado
Clasificación