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

يقدّم نظام 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] مكوّن متجه الالتفاف على طول محور ص (ص * sin(θ/2))
SensorEvent.values[2] مكوّن متجه الالتفاف على محور z (z * sin(θ/2))
TYPE_GEOMAGNETIC_ROTATION_VECTOR SensorEvent.values[0] مكوّن متجّه الدوران على محور x (x * sin(θ/2)) بدون وحدة
SensorEvent.values[1] مكوّن متجه الالتفاف على طول محور ص (ص * sin(θ/2))
SensorEvent.values[2] مكوّن متجه الالتفاف على محور z (z * sin(θ/2))
TYPE_MAGNETIC_FIELD SensorEvent.values[0] قوة المجال المغناطيسي الأرضي على طول محور x μT
SensorEvent.values[1] شدة المجال المغناطيسي الأرضي على طول محور y
SensorEvent.values[2] شدة المجال المغناطيسي الأرضي على طول محور z
TYPE_MAGNETIC_FIELD_UNCALIBRATED SensorEvent.values[0] شدة المجال المغناطيسي الأرضي (بدون معايرة الحديد الصلب) على طول محور x μT
SensorEvent.values[1] شدة المجال المغناطيسي الأرضي (بدون معايرة الحديد الصلب) على طول محور y
SensorEvent.values[2] شدة المجال المغناطيسي الأرضي (بدون معايرة الحديد الصلب) على طول محور z
SensorEvent.values[3] تقدير الانحياز الحديدي على طول المحور السيني
SensorEvent.values[4] تقدير الانحياز الحديدي على طول المحور y
SensorEvent.values[5] تقدير الانحياز الحديدي على طول محور z
TYPE_ORIENTATION1 SensorEvent.values[0] السمت (الزاوية حول محور z) الدرجات
SensorEvent.values[1] انحناء الطائرة (الزاوية حول المحور x)
SensorEvent.values[2] الدوران (الزاوية حول المحور الصادي)
TYPE_PROXIMITY SensorEvent.values[0] المسافة من الجسم2 سم

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

2 لا تقدّم بعض أدوات استشعار التقارب سوى قيم ثنائية تشير إلى "قريب" و"بعيد".

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

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

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

يوضّح لك الرمز التالي كيفية الحصول على مثيل لمتجه اتجاه الدوران التلقائي في اللعبة sensor:

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. ونتيجةً لذلك، تم إيقاف أداة استشعار الاتجاه نهائيًا في الإصدار 2.2 من نظام التشغيل Android (المستوى 8 لواجهة برمجة التطبيقات)، وتم إيقاف نوع أداة استشعار الاتجاه نهائيًا في الإصدار 4.4W من نظام التشغيل Android (المستوى 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);

ملاحظة: إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android (المستوى 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().

ننصحك أيضًا بقراءة