أجهزة استشعار الموضع

ويوفّر نظام Android الأساسي مستشعرَين يسمحان لك بتحديد موضع الجهاز، وهما: مستشعر المجال المغناطيسي الجغرافي ومقياس التسارع. ويوفّر نظام Android الأساسي أيضًا أداة استشعار تتيح لك تحديد مدى قرب الجهاز من الجسم (المعروفة باسم أداة استشعار التقارب). يعتمد كل من مستشعر المجال المغناطيسي وأداة استشعار التقارب على الأجهزة. وتتضمّن معظم الشركات المصنّعة للهواتف والأجهزة اللوحية أداة استشعار للمجال المغناطيسي الأرضي. وبالمثل، تتضمّن الشركات المصنّعة للهاتف عادةً أداة استشعار التقارب لتحديد الأوقات التي يتم فيها إبقاء الهاتف بالقرب من وجه المستخدم (أثناء مكالمة هاتفية مثلاً). ولتحديد اتجاه الجهاز، يمكنك استخدام القراءات من مقياس التسارع وجهاز استشعار المجال المغناطيسي الأرضي.

ملاحظة: تم إيقاف أداة استشعار الاتجاه نهائيًا في Android 2.2 (المستوى 8 لواجهة برمجة التطبيقات)، وتم إيقاف نوع أداة استشعار الاتجاه نهائيًا في Android 4.4W (المستوى 20 لواجهة برمجة التطبيقات).

تساعد أدوات استشعار الموضع في تحديد الموضع الفعلي للجهاز في الإطار المرجعي حول العالم. على سبيل المثال، يمكنك استخدام أداة استشعار المجال المغناطيسي الأرضي مع مقياس التسارع لتحديد موضع الجهاز بالنسبة إلى القطب الشمالي المغناطيسي. ويمكنك أيضًا استخدام أدوات الاستشعار هذه لتحديد اتجاه الجهاز في الإطار المرجعي لتطبيقك. لا تُستخدَم أجهزة استشعار الموضع عادةً لمراقبة حركة الجهاز أو الحركة، مثل الاهتزاز أو الإمالة أو الدفع (لمزيد من المعلومات، يُرجى الاطّلاع على أجهزة استشعار الحركة).

يعرض مستشعر المجال المغناطيسي ومقياس التسارع صفائف متعددة الأبعاد لقيم أداة الاستشعار لكل SensorEvent. على سبيل المثال، يوفّر جهاز استشعار المجال المغناطيسي الأرضي قيم قوة المجال المغناطيسي الأرضي لكل من محور الإحداثيات الثلاثة خلال عملية استشعار واحدة. وبالمثل، تقيس أداة استشعار مقياس التسارع التسارع المطبَّق على الجهاز أثناء وقوع حدث صادر عن أداة الاستشعار. لمزيد من المعلومات عن أنظمة الإحداثيات التي تستخدمها أدوات الاستشعار، راجِع أنظمة إحداثيات جهاز الاستشعار. توفِّر أداة استشعار التقارب قيمة واحدة لكل حدث من أحداث أداة الاستشعار. يلخّص الجدول 1 أجهزة استشعار الموضع المتوافقة مع نظام Android الأساسي.

الجدول 1. أدوات استشعار الموضع المتوافقة مع نظام Android الأساسي

أداة استشعار بيانات أحداث أدوات الاستشعار الوصف وحدات القياس
TYPE_GAME_ROTATION_VECTOR SensorEvent.values[0] مكوّن متّجه التدوير على طول المحور x (x * sin(التحديد/2)) بلا وحدة
SensorEvent.values[1] مكوّن متجه التدوير على طول المحور y (y * sin(التحديد/2))
SensorEvent.values[2] مكوّن متجه التدوير على طول المحور z (z * sin(عقد/2))
TYPE_GEOMAGNETIC_ROTATION_VECTOR SensorEvent.values[0] مكوّن متّجه التدوير على طول المحور x (x * sin(التحديد/2)) بلا وحدة
SensorEvent.values[1] مكوّن متجه التدوير على طول المحور y (y * sin(التحديد/2))
SensorEvent.values[2] مكوّن متجه التدوير على طول المحور z (z * sin(عقد/2))
TYPE_MAGNETIC_FIELD SensorEvent.values[0] قوة المجال المغناطيسي الأرضي على طول المحور س. ميكرومتر
SensorEvent.values[1] قوة المجال المغناطيسي الأرضي على طول المحور ص.
SensorEvent.values[2] قوة المجال المغناطيسي الأرضي على طول المحور z.
TYPE_MAGNETIC_FIELD_UNCALIBRATED SensorEvent.values[0] قوة المجال المغناطيسي الأرضي (بدون معايرة الحديد الصلب) على طول المحور س. ميكرومتر
SensorEvent.values[1] قوة المجال المغناطيسي الأرضي (بدون معايرة الحديد الصلب) على طول المحور ص.
SensorEvent.values[2] قوة المجال المغناطيسي الأرضي (بدون معايرة الحديد الصلب) على طول المحور z.
SensorEvent.values[3] تقدير التحيز الحدي على طول المحور س.
SensorEvent.values[4] تقدير التحيز الحدي على طول المحور ص.
SensorEvent.values[5] تقدير التحيز الحدي على طول المحور z.
TYPE_ORIENTATION1 SensorEvent.values[0] السمت (الزاوية حول المحور z). الدرجات
SensorEvent.values[1] درجة الميل (زاوية حول المحور س).
SensorEvent.values[2] لفة (الزاوية حول المحور ص).
TYPE_PROXIMITY SensorEvent.values[0] المسافة من الكائن2 سم

1تم إيقاف أداة الاستشعار هذه نهائيًا في الإصدار Android 2.2 (المستوى 8 من واجهة برمجة التطبيقات)، وتم إيقاف نوع أداة الاستشعار هذا نهائيًا في الإصدار Android 4.4W (المستوى 20 من واجهة برمجة التطبيقات). يوفر إطار عمل أداة الاستشعار طرقًا بديلة للحصول على اتجاه الجهاز، وقد تمت مناقشتها في مقالة حساب اتجاه الجهاز.

2 توفّر بعض أدوات استشعار التقارب قيمًا ثنائية تمثّل فقط القيم القريبة والبعيدة.

استخدام أداة استشعار متجه تدوير اللعبة

يتطابق مستشعر متجه دوران اللعبة مع أداة استشعار متجه التدوير، باستثناء أنه لا يستخدم المجال المغناطيسي الأرضي. لذلك لا يشير المحور ص إلى الشمال ولكن بدلاً من ذلك إلى مرجع آخر. يُسمح لهذا المرجع بالانحراف بنفس ترتيب المقدار الذي ينحرف فيه الجيروسكوب حول المحور Z.

نظرًا لأن أداة استشعار متجه دوران الألعاب لا تستخدم المجال المغناطيسي، فإن الدوران النسبي تكون أكثر دقة ولا تتأثر بتغيرات المجال المغناطيسي. استخدم هذا المستشعر في اللعبة إذا كنت لا تهتم بمكان الشمال، ولا يناسب متجه الدوران العادي احتياجاتك بسبب اعتماده على المجال المغناطيسي.

يوضح لك الرمز التالي كيفية الحصول على مثيل للمستشعر الافتراضي لمتجه دوران اللعبة:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);

استخدام مستشعر متجه الدوران الأرضي المغناطيسي

يشبه مستشعر متجه الدوران الأرضي مُستشعر متجه الدوران، ولكنه لا يستخدم الجيروسكوب. وتكون دقة هذا المستشعر أقل من مستشعر الدوران العادي، لكن يتم تقليل استهلاك الطاقة. لا تستخدم أداة الاستشعار هذه إلا إذا كنت تريد جمع معلومات التدوير في الخلفية بدون استهلاك الكثير من طاقة البطارية. تكون أداة الاستشعار هذه مفيدة للغاية عند استخدامها مع التجميع.

توضح لك التعليمة البرمجية التالية كيفية الحصول على مثيل للمستشعر الافتراضي متجه الدوران الأرضي:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);

احتساب اتجاه الجهاز

ومن خلال حساب اتجاه الجهاز، يمكنك مراقبة موضع الجهاز بالنسبة إلى الإطار المرجعي للأرض (على وجه التحديد، القطب الشمالي المغناطيسي). ويوضّح لك الرمز التالي كيفية احتساب اتجاه جهاز:

Kotlin

private lateinit var sensorManager: SensorManager
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
val rotationMatrix = FloatArray(9)
SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading)

// Express the updated rotation matrix as three orientation angles.
val orientationAngles = FloatArray(3)
SensorManager.getOrientation(rotationMatrix, orientationAngles)

Java

private SensorManager sensorManager;
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
final float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrix(rotationMatrix, null,
    accelerometerReading, magnetometerReading);

// Express the updated rotation matrix as three orientation angles.
final float[] orientationAngles = new float[3];
SensorManager.getOrientation(rotationMatrix, orientationAngles);

يحسب النظام زوايا الاتجاه عن طريق استخدام أداة استشعار المجال المغناطيسي الأرضي للجهاز مع مقياس التسارع في الجهاز. باستخدام مستشعرَي الجهاز هاتين، يوفر النظام بيانات لزوايا الاتجاه الثلاث التالية:

  • السمت (درجات الدوران حول المحور -z). هذه هي الزاوية بين اتجاه بوصلة الجهاز الحالي والشمال المغناطيسي. وإذا كانت الحافة العلوية من الجهاز مواجهة للشمال المغناطيسي، تكون السمت 0 درجة، أما إذا كانت الحافة العلوية من الجهاز مواجهة للجنوب، تكون السمت 180 درجة. وبالمثل، إذا كانت الحافة العليا مواجهة للشرق، يكون السمت 90 درجة، وإذا كانت الحافة العلوية مواجهة للغرب، تكون السمت 270 درجة.
  • درجة الصوت (درجات الدوران حول المحور س). هذه هي الزاوية بين سطح موازي لشاشة الجهاز وسطح موازي للأرض. إذا تمسك الجهاز بشكل موازٍ للأرض مع الحافة السفلية للجهاز وإمالة الحافة العلوية من الجهاز نحو الأرض، تصبح زاوية درجة الصوت موجبة. والإمالة في الاتجاه المعاكس، أو تحريك الحافة العلوية من الجهاز بعيدًا عن الأرض، تؤدي إلى أن تصبح زاوية الانحدار سالبة. ويتراوح نطاق القيم بين -90 درجة إلى 90 درجة.
  • اللف (درجات الدوران حول المحور ص). هذه هي الزاوية بين مستوى مسطّح على شاشة الجهاز وسطح عمودي على الأرض. إذا تمسك الجهاز بشكل موازٍ للأرض مع الحافة السفلية للجهاز وإمالة الحافة اليسرى للجهاز نحو الأرض، تصبح زاوية اللفة موجبة. والإمالة في الاتجاه المعاكس، أي تحريك الحافة اليمنى من الجهاز نحو الأرض، تؤدي إلى أن تصبح زاوية اللفة سالبة. ويتراوح نطاق القيم بين -180 درجة و180 درجة.

ملاحظة: تم تغيير تعريف لفة أداة الاستشعار ليعكس الغالبية العظمى من عمليات التنفيذ في المنظومة المتكاملة للمستشعرات الجغرافية.

يُرجى العلم أنّ هذه الزوايا تعمل بنظام إحداثيات مختلف عن تلك الزوايا المستخدمة في الطيران (للانعطاف والنحو واللف). وفي نظام الطيران، يقع المحور x على طول الجانب الطويل من الطائرة، من الذيل إلى الأنف.

يستمد جهاز استشعار الاتجاه بياناته من خلال معالجة بيانات أداة الاستشعار الأولية من مقياس التسارع وأداة استشعار المجال المغناطيسي الجغرافي. وبسبب المعالجة الثقيلة التي تتطلبها هذه الأداة، تتضاءل دقة ودقة جهاز استشعار الاتجاه. وعلى وجه التحديد، لا يمكن الاعتماد على هذا المستشعر إلا عندما تكون زاوية الدوران 0. ونتيجةً لذلك، تم إيقاف أداة استشعار الاتجاه نهائيًا في الإصدار Android 2.2 (المستوى 8 لواجهة برمجة التطبيقات)، كما تم إيقاف نوع أداة استشعار الاتجاه في Android 4.4W (المستوى 20 لواجهة برمجة التطبيقات). وبدلاً من استخدام البيانات الأولية من أداة استشعار الاتجاه، ننصحك باستخدام طريقة getRotationMatrix() وgetOrientation() لاحتساب قيم الاتجاه، كما هو موضّح في نموذج الرمز التالي. وكجزء من هذه العملية، يمكنك استخدام طريقة remapCoordinateSystem() لترجمة قيم الاتجاه إلى الإطار المرجعي لتطبيقك.

Kotlin

class SensorActivity : Activity(), SensorEventListener {

    private lateinit var sensorManager: SensorManager
    private val accelerometerReading = FloatArray(3)
    private val magnetometerReading = FloatArray(3)

    private val rotationMatrix = FloatArray(9)
    private val orientationAngles = FloatArray(3)

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
        // You must implement this callback in your code.
    }

    override fun onResume() {
        super.onResume()

        // Get updates from the accelerometer and magnetometer at a constant rate.
        // To make batch operations more efficient and reduce power consumption,
        // provide support for delaying updates to the application.
        //
        // In this example, the sensor reporting delay is small enough such that
        // the application receives an update before the system checks the sensor
        // readings again.
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer ->
            sensorManager.registerListener(
                    this,
                    accelerometer,
                    SensorManager.SENSOR_DELAY_NORMAL,
                    SensorManager.SENSOR_DELAY_UI
            )
        }
        sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField ->
            sensorManager.registerListener(
                    this,
                    magneticField,
                    SensorManager.SENSOR_DELAY_NORMAL,
                    SensorManager.SENSOR_DELAY_UI
            )
        }
    }

    override fun onPause() {
        super.onPause()

        // Don't receive any more updates from either sensor.
        sensorManager.unregisterListener(this)
    }

    // Get readings from accelerometer and magnetometer. To simplify calculations,
    // consider storing these readings as unit vectors.
    override fun onSensorChanged(event: SensorEvent) {
        if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
            System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size)
        } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
            System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size)
        }
    }

    // Compute the three orientation angles based on the most recent readings from
    // the device's accelerometer and magnetometer.
    fun updateOrientationAngles() {
        // Update rotation matrix, which is needed to update orientation angles.
        SensorManager.getRotationMatrix(
                rotationMatrix,
                null,
                accelerometerReading,
                magnetometerReading
        )

        // "rotationMatrix" now has up-to-date information.

        SensorManager.getOrientation(rotationMatrix, orientationAngles)

        // "orientationAngles" now has up-to-date information.
    }
}

Java

public class SensorActivity extends Activity implements SensorEventListener {

    private SensorManager sensorManager;
    private final float[] accelerometerReading = new float[3];
    private final float[] magnetometerReading = new float[3];

    private final float[] rotationMatrix = new float[9];
    private final float[] orientationAngles = new float[3];

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
        // You must implement this callback in your code.
    }

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

        // Get updates from the accelerometer and magnetometer at a constant rate.
        // To make batch operations more efficient and reduce power consumption,
        // provide support for delaying updates to the application.
        //
        // In this example, the sensor reporting delay is small enough such that
        // the application receives an update before the system checks the sensor
        // readings again.
        Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (accelerometer != null) {
            sensorManager.registerListener(this, accelerometer,
                SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
        }
        Sensor magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        if (magneticField != null) {
            sensorManager.registerListener(this, magneticField,
                SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
        }
    }

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

        // Don't receive any more updates from either sensor.
        sensorManager.unregisterListener(this);
    }

    // Get readings from accelerometer and magnetometer. To simplify calculations,
    // consider storing these readings as unit vectors.
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
          System.arraycopy(event.values, 0, accelerometerReading,
              0, accelerometerReading.length);
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            System.arraycopy(event.values, 0, magnetometerReading,
                0, magnetometerReading.length);
        }
    }

    // Compute the three orientation angles based on the most recent readings from
    // the device's accelerometer and magnetometer.
    public void updateOrientationAngles() {
        // Update rotation matrix, which is needed to update orientation angles.
        SensorManager.getRotationMatrix(rotationMatrix, null,
            accelerometerReading, magnetometerReading);

        // "rotationMatrix" now has up-to-date information.

        SensorManager.getOrientation(rotationMatrix, orientationAngles);

        // "orientationAngles" now has up-to-date information.
    }
}

لن تحتاج عادةً إلى إجراء أي معالجة للبيانات أو فلترة لزوايا الاتجاه الأولية للجهاز، ولكن لن تحتاج عادةً إلى نقل نظام إحداثيات أداة الاستشعار إلى الإطار المرجعي للتطبيق.

استخدام مستشعر المجال المغناطيسي الأرضي

يتيح لك مستشعر المجال المغناطيسي الأرضي مراقبة التغيرات في المجال المغناطيسي للأرض. يوضح الرمز التالي كيفية الحصول على مثيل للمستشعر الافتراضي للمجال المغناطيسي الجغرافي:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

ملاحظة: إذا كان تطبيقك يستهدف نظام Android 12 (المستوى 31 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، تكون أداة الاستشعار هذه محدودة المعدّل.

يقدم هذا المستشعر بيانات أولية لقوة المجال (بالميكرومتر) لكل محور من المحاور الإحداثية الثلاثة. لن تحتاج عادةً إلى استخدام أداة الاستشعار هذه مباشرةً. بدلاً من ذلك، يمكنك استخدام مستشعر متجه الدوران لتحديد حركة الدوران الأولية أو يمكنك استخدام مقياس التسارع ومستشعر المجال المغناطيسي إلى جانب طريقة getRotationMatrix() للحصول على مصفوفة الدوران ومصفوفة الميل. يمكنك بعد ذلك استخدام هذه المصفوفات مع طريقتي getOrientation() وgetInclination() للحصول على بيانات السمت والميل المغناطيسي الأرضي.

ملاحظة: عند اختبار تطبيقك، يمكنك تحسين دقة أداة الاستشعار من خلال التلويح بالجهاز بنمط على شكل 8.

استخدام مقياس المغناطيسية الذي لم تتم معايرته

يشبه مقياس المغناطيسية الذي لم تتم معايرته جهاز استشعار المجال المغناطيسي، باستثناء أنه لا يتم تطبيق معايرة حديد صلب على المجال المغناطيسي. لا تزال معايرة المصنع وتعويض درجة الحرارة مطبقة على المجال المغناطيسي. يُعد مقياس المغناطيسية الذي لم تتم معايرته مفيدًا للتعامل مع تقديرات الحديد الصلب السيئة. بشكل عام، سيكون geomagneticsensor_event.values[0] بالقرب من uncalibrated_magnetometer_event.values[0] - uncalibrated_magnetometer_event.values[3]. أي

calibrated_x ~= uncalibrated_x - bias_estimate_x

ملاحظة: تقدّم أدوات الاستشعار التي لم تتم معايرتها نتائج أولية أكثر وقد تتضمّن بعض الانحياز، إلا أنّ قياساتها تتضمّن قفزات أقل بين التصحيحات التي تم تطبيقها من خلال المعايرة. قد تفضل بعض التطبيقات هذه النتائج التي لم تتم معايرتها باعتبارها أكثر سلاسة وموثوقية. على سبيل المثال، إذا كان أحد التطبيقات يحاول إجراء اندماج مستشعر خاص به، فإن تقديم عمليات معايرة يمكن أن تشوّه النتائج بالفعل.

بالإضافة إلى المجال المغناطيسي، يوفر مقياس المغناطيسية الذي لم تتم معايرته أيضًا تقدير تحيز الحديد الصلب في كل محور. يوضح الرمز التالي كيفية الحصول على مثيل لمقياس المغناطيسية التلقائي الذي لم تتم معايرته:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);

استخدام أداة استشعار التقارب

تتيح لك أداة استشعار التقارب تحديد مدى بُعد الجسم عن الجهاز. يوضح لك الكود التالي كيفية الحصول على مثيل لأداة استشعار التقارب الافتراضية:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

يتم استخدام أداة استشعار التقارب عادةً لتحديد مدى بُعد رأس الشخص عن وجه جهاز الهاتف (على سبيل المثال، عندما يُجري المستخدم مكالمة هاتفية أو يتلقاها). تعرض معظم أجهزة استشعار التقارب المسافة المطلقة بالسم، ولكن البعض لا يعرض سوى القيم القريبة والبعيدة فقط.

ملاحظة: في بعض طُرز الأجهزة، توجد أداة استشعار التقارب أسفل الشاشة، ما قد يتسبب في ظهور نقطة وامضة على الشاشة إذا تم تفعيلها أثناء تشغيل الشاشة.

يوضح لك الرمز التالي كيفية استخدام أداة استشعار التقارب:

Kotlin

class SensorActivity : Activity(), SensorEventListener {

    private lateinit var sensorManager: SensorManager
    private var proximity: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        // Get an instance of the sensor service, and use that to get an instance of
        // a particular sensor.
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        val distance = event.values[0]
        // Do something with this sensor data.
    }

    override fun onResume() {
        // Register a listener for the sensor.
        super.onResume()

        proximity?.also { proximity ->
            sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        // Be sure to unregister the sensor when the activity pauses.
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

Java

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor proximity;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Get an instance of the sensor service, and use that to get an instance of
        // a particular sensor.
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        float distance = event.values[0];
        // Do something with this sensor data.
    }

    @Override
    protected void onResume() {
        // Register a listener for the sensor.
        super.onResume();
        sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL);
      }

    @Override
    protected void onPause() {
        // Be sure to unregister the sensor when the activity pauses.
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

ملاحظة: تعرض بعض أدوات استشعار التقارب قيمًا ثنائية تمثل "قريب" أو "بعيد". في هذه الحالة، يُبلغ المستشعر عادةً عن قيمة الحد الأقصى للنطاق في الحالة البعيدة وقيمة أقل في الحالة القريبة. عادةً ما تكون القيمة البعيدة أكبر من 5 سم، ولكن هذا قد يختلف من أداة استشعار إلى أخرى. يمكنك تحديد الحد الأقصى لنطاق المستشعر باستخدام طريقة getMaximumRange().

يجب عليك أيضًا قراءة