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

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

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

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

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

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

أداة استشعار بيانات أحداث أداة الاستشعار الوصف وحدات القياس
TYPE_GAME_ROTATION_VECTOR SensorEvent.values[0] مكوّن متجه التدوير على طول المحور x (x * sin(الوارد/2)). بلا وحدة
SensorEvent.values[1] مكوّن متجه الدوران على طول المحور ص (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 * 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] درجة الصوت (الزاوية حول المحور x).
SensorEvent.values[2] اللفة (الزاوية حول المحور y).
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 درجة.
  • درجة الدوران (درجات الدوران حول المحور x) هذه هي الزاوية بين مستوى موازٍ لشاشة الجهاز وطائرة موازية للأرض. عند تثبيت الجهاز بشكل موازٍ للأرض مع الحرص على إضافة الحافة السفلية إليك بإمالة الجهاز نحو الأرض، تصبح زاوية النبرة موجبة. أما إمالة الجهاز في الاتجاه المعاكس، أي تحريك الحافة العلوية للجهاز بعيدًا عن الأرض، فيؤدي إلى أن تصبح زاوية درجة الصوت سالبة. ويتراوح نطاق القيم بين -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().

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