نظرة عامة على أجهزة الاستشعار

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

تتيح منصة Android ثلاث فئات عامة من أجهزة الاستشعار:

  • أجهزة استشعار الحركة

    تقيس هذه الحساسات قوى التسارع وقوى الدوران على طول ثلاثة محاور. تشمل هذه الفئة مقاييس التسارع وأدوات استشعار الجاذبية والجيروسكوبات وأدوات استشعار المتّجهات الدوّارة.

  • أجهزة الاستشعار البيئية

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

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

    تقيس هذه الأدوات الموقع الجغرافي للجهاز. تشمل هذه الفئة أدوات قياس الاتجاهات وأدوات قياس المجال المغناطيسي.

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

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

يوفّر هذا الموضوع نظرة عامة على أجهزة الاستشعار المتوفّرة على نظام Android الأساسي. ويقدّم أيضًا مقدّمة عن إطار عمل أداة الاستشعار.

مقدمة عن أجهزة الاستشعار

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

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

الجدول 1: أنواع الحساسات المتوافقة مع نظام Android الأساسي

أداة استشعار النوع الوصف الاستخدامات الشائعة
TYPE_ACCELEROMETER الأجهزة يقيس هذا المقياس قوة التسارع بوحدة متر في الثانية2 التي يتم تطبيقها على جهاز على جميع المحاور الثلاثة (x وy وz)، بما في ذلك قوة الجاذبية. رصد الحركة (الاهتزاز أو الميل أو غير ذلك)
TYPE_AMBIENT_TEMPERATURE الأجهزة يقيس درجة الحرارة المحيطة في الغرفة بالدرجة المئوية (°C). يُرجى الاطّلاع على الملاحظة أدناه. مراقبة درجات حرارة الهواء
TYPE_GRAVITY البرامج أو الأجهزة تقيس قوة الجاذبية بوحدة m/s2 التي يتم تطبيقها على جهاز على كل المحاور الثلاثة (x وy وz). رصد الحركة (الاهتزاز أو الميل أو غير ذلك)
TYPE_GYROSCOPE الأجهزة تقيس هذه السمة معدّل دوران الجهاز بالراديان في الثانية حول كلّ من السواطير الثلاثة (x وy وz). رصد التدوير (الدوران أو الالتفاف أو غير ذلك)
TYPE_LIGHT الأجهزة تقيس هذه الميزة مستوى الإضاءة المحيطة (الإضاءة) بالوحدة lx. التحكّم في سطوع الشاشة
TYPE_LINEAR_ACCELERATION البرامج أو الأجهزة يقيس هذا المقياس قوة التسارع بوحدة متر في الثانية2 التي يتم تطبيقها على جهاز على جميع المحاور الثلاثة (x وy وz)، باستثناء قوة الجاذبية. رصد التسارع على طول محور واحد
TYPE_MAGNETIC_FIELD الأجهزة يقيس المجال المغناطيسي الأرضي المحيط لجميع المحاور الثلاثة (x وy وz) بالملي تسلا (μT). إنشاء بوصلة
TYPE_ORIENTATION البرامج تقيس درجات الدوران التي يجريها الجهاز حول جميع المحاور الثلاثة (x وy وz). اعتبارًا من المستوى 3 من واجهة برمجة التطبيقات، يمكنك الحصول على مصفوفة الميل ومصفوفة الدوران لجهاز باستخدام جهاز استشعار الجاذبية وجهاز استشعار الحقل المغناطيسي الأرضي مع استخدام getRotationMatrix() الطريقة. تحديد موضع الجهاز
TYPE_PRESSURE الأجهزة تقيس هذه القيمة ضغط الهواء المحيط بالوحدة hPa أو mbar. مراقبة التغيُّرات في ضغط الهواء
TYPE_PROXIMITY الأجهزة تقيس هذه السمة مدى قرب جسم معيّن بالسنتيمترات من شاشة العرض في الجهاز. يُستخدَم هذا المستشعر عادةً لتحديد ما إذا كان الهاتف الجوّال مُمسكًا به عند أذن المستخدم. موضع الهاتف أثناء المكالمة
TYPE_RELATIVE_HUMIDITY الأجهزة يقيس الرطوبة النسبية للبيئة المحيطة بالمقياس المئوي (%). مراقبة نقطة الندى والرطوبة المطلقة والنسبية
TYPE_ROTATION_VECTOR البرامج أو الأجهزة تقيس اتجاه الجهاز من خلال توفير العناصر الثلاثة لمتجه دوران الجهاز. رصد الحركة ورصد الالتفاف
TYPE_TEMPERATURE الأجهزة يقيس درجة حرارة الجهاز بالدرجة المئوية. يختلف تنفيذ هذا المستشعر باختلاف الأجهزة، وقد تم استبدال هذا المستشعر بمستشعر TYPE_AMBIENT_TEMPERATURE في المستوى 14 لواجهة برمجة التطبيقات. مراقبة درجات الحرارة

إطار عمل الاستشعار

يمكنك الوصول إلى أدوات الاستشعار هذه والحصول على بياناتها الأولية باستخدام إطار عمل أدوات الاستشعار في Android. تشكّل إطار عمل الاستشعار جزءًا من حزمة android.hardware وتتضمّن الklassen والواجهات التالية:

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

في التطبيق العادي، يتم استخدام واجهات برمجة التطبيقات هذه ذات الصلة بأجهزة الاستشعار لتنفيذ مهمتَين أساسيتَين:

  • تحديد أدوات الاستشعار وإمكاناتها

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

  • مراقبة أحداث أجهزة الاستشعار

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

مدى توفّر أداة الاستشعار

يختلف مدى توفّر أداة الاستشعار من جهاز إلى آخر، وقد يختلف أيضًا بين إصدارات Android. ويرجع ذلك إلى أنّ أدوات استشعار Android تم طرحها على مدار عدة إصدارات من النظام الأساسي. على سبيل المثال، تم طرح العديد من أجهزة الاستشعار في الإصدار 1.5 من نظام التشغيل Android (المستوى 3 لواجهة برمجة التطبيقات)، ولكن لم يتم تنفيذ بعض هذه الأجهزة ولم تكن متاحة للاستخدام حتى الإصدار 2.3 من نظام التشغيل Android (المستوى 9 لواجهة برمجة التطبيقات). وبالمثل، تم طرح العديد من أجهزة الاستشعار في الإصدار 2.3 من نظام التشغيل Android (المستوى 9 لواجهة برمجة التطبيقات) والإصدار 4.0 من نظام التشغيل Android (المستوى 14 لواجهة برمجة التطبيقات). تم إيقاف جهازَي قياس درجة الحرارة نهائيًا واستبدالهما بأجهزة قياس أحدث وأفضل.

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

الجدول 2: مدى توفّر أجهزة الاستشعار حسب المنصة

أداة استشعار الإصدار 4.0 من نظام التشغيل Android
(المستوى 14 لواجهة برمجة التطبيقات)
الإصدار 2.3 من نظام التشغيل Android
(المستوى 9 من واجهة برمجة التطبيقات)
الإصدار 2.2 من نظام التشغيل Android
(المستوى 8 لواجهة برمجة التطبيقات)
الإصدار 1.5 من نظام التشغيل Android
(المستوى 3 لواجهة برمجة التطبيقات)
TYPE_ACCELEROMETER نعم نعم نعم نعم
TYPE_AMBIENT_TEMPERATURE نعم لا تنطبق لا تنطبق لا تنطبق
TYPE_GRAVITY نعم نعم لا تنطبق لا تنطبق
TYPE_GYROSCOPE نعم نعم لا تنطبق1 لا تنطبق1
TYPE_LIGHT نعم نعم نعم نعم
TYPE_LINEAR_ACCELERATION نعم نعم لا تنطبق لا تنطبق
TYPE_MAGNETIC_FIELD نعم نعم نعم نعم
TYPE_ORIENTATION نعم2 نعم2 نعم2 نعم
TYPE_PRESSURE نعم نعم لا تنطبق1 لا تنطبق1
TYPE_PROXIMITY نعم نعم نعم نعم
TYPE_RELATIVE_HUMIDITY نعم لا تنطبق لا تنطبق لا تنطبق
TYPE_ROTATION_VECTOR نعم نعم لا تنطبق لا تنطبق
TYPE_TEMPERATURE نعم2 نعم نعم نعم

1 تمت إضافة نوع أداة الاستشعار هذا في Android 1.5 (المستوى 3 لواجهة برمجة التطبيقات)، ولكنه لم يكن متاحًا للاستخدام حتى Android 2.3 (المستوى 9 لواجهة برمجة التطبيقات).

2 أداة الاستشعار هذه متاحة، ولكن تم إيقافها نهائيًا.

تحديد أدوات الاستشعار وإمكاناتها

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

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

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

بعد ذلك، يمكنك الحصول على قائمة بكل أجهزة الاستشعار على الجهاز من خلال استدعاء الطريقة getSensorList() واستخدام الثابت TYPE_ALL. مثلاً:

Kotlin

val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)

Java

List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

إذا كنت تريد إدراج جميع أجهزة الاستشعار من نوع معيّن، يمكنك استخدام ثابت آخر بدلاً من TYPE_ALL مثل TYPE_GYROSCOPE أو TYPE_LINEAR_ACCELERATION أو TYPE_GRAVITY.

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

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

ملاحظة: لا يطلب نظام التشغيل Android من المصنّعين تضمين أي نوع معيّن من أجهزة الاستشعار في أجهزتهم التي تعمل بنظام التشغيل Android، لذا يمكن أن تتضمّن الأجهزة مجموعة كبيرة من إعدادات أجهزة الاستشعار.

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

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

Kotlin

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

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

Java

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

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

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

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

مراقبة أحداث أجهزة الاستشعار

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

  • تغيُّر دقة أحد أجهزة الاستشعار

    في هذه الحالة، يستدعي النظام طريقة onAccuracyChanged()، ما يمنحك مرجعًا إلى عنصر Sensor الذي تغيّر و الدقة الجديدة لجهاز الاستشعار. يتم تمثيل الدقة بأحد الثوابت الأربعة للحالة: SENSOR_STATUS_ACCURACY_LOW، SENSOR_STATUS_ACCURACY_MEDIUM، SENSOR_STATUS_ACCURACY_HIGH، أو SENSOR_STATUS_UNRELIABLE.

  • يُبلِغ أحد أجهزة الاستشعار عن قيمة جديدة.

    في هذه الحالة، يستدعي النظام الطريقة onSensorChanged()، ما يوفّر لك عنصر SensorEvent. يحتوي عنصر SensorEvent على معلومات عن بيانات أداة الاستشعار الجديدة، بما في ذلك دقة البيانات، و أداة الاستشعار التي أنشأت البيانات، والطابع الزمني الذي تم إنشاء البيانات فيه، والبيانات الجديدة التي سجّلتها أداة الاستشعار.

يوضّح الرمز البرمجي التالي كيفية استخدام الطريقة onSensorChanged() لمراقبة البيانات الواردة من جهاز استشعار الإضاءة. يعرض هذا المثال بيانات المستشعر الأوّلية في TextView يتم تعريفها في ملف main.xml على أنّها sensor_data.

Kotlin

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

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

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

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

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

Java

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

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

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

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

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

في هذا المثال، يتم تحديد مهلة البيانات التلقائية (SENSOR_DELAY_NORMAL) عند استدعاء الطريقة registerListener(). يتحكّم تأخُّر تسجيل البيانات (أو معدّل أخذ العينات) في الفاصل الزمني الذي يتم فيه إرسال أحداث أداة الاستشعار إلى تطبيقك من خلال طريقة الاستدعاء onSensorChanged(). إنّ القيمة التلقائية لتأخُّر البيانات مناسبة لرصد التغييرات المعتادة في اتجاه الشاشة، وتستخدم تأخُّرًا يبلغ 200,000 ميكرو ثانية. يمكنك تحديد تأخُّرات data أخرى، مثل SENSOR_DELAY_GAME (تأخُّر 20,000 ميكرو ثانية) أو SENSOR_DELAY_UI (تأخُّر 60,000 ميكرو ثانية) أو SENSOR_DELAY_FASTEST (تأخُّر 0 ميكرو ثانية). اعتبارًا من Android 3.0 (المستوى 11 من واجهة برمجة التطبيقات)، يمكنك أيضًا تحديد المدة الزمنية المتأخرة كقيمة مطلقة (بالميكرو ثانية).

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

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

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

التعامل مع إعدادات أجهزة الاستشعار المختلفة

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

لديك خياران للتأكّد من توفّر أداة استشعار معيّنة على الجهاز:

  • رصد أجهزة الاستشعار أثناء التشغيل وتفعيل ميزات التطبيق أو إيقافها حسب الاقتضاء
  • استخدِم فلاتر Google Play لاستهداف الأجهزة التي تتضمّن إعدادات محدّدة لأجهزة الاستشعار.

يتمّ مناقشة كلّ خيار في الأقسام التالية.

رصد أجهزة الاستشعار أثناء التشغيل

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

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

استخدام فلاتر Google Play لاستهداف إعدادات محدّدة لأجهزة الاستشعار

إذا كنت بصدد نشر تطبيقك على Google Play، يمكنك استخدام العنصر <uses-feature> في ملف البيان لفلترة تطبيقك من الأجهزة التي لا تملك إعدادات أداة الاستشعار المناسبة لتطبيقك. يحتوي عنصر <uses-feature> على العديد من أوصاف الأجهزة التي تتيح لك فلترة التطبيقات استنادًا إلى توفّر أدوات استشعار معيّنة. تشمل أدوات الاستشعار التي يمكنك إدراجها ما يلي: مقياس التسارع ومقياس الضغط الجوي والبوصلة (المجال المغناطيسي الأرضي) والجيروسكوب والضوء والقرب. في ما يلي مثال على إدخال ملف البيان الذي لفلترة التطبيقات التي لا تحتوي على مقياس تسارع:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

في حال إضافة هذا العنصر والوصف إلى بيان تطبيقك، لن يظهر تطبيقك للمستخدمين على Google Play إلا إذا كان جهازهم مزوّدًا بمقياس تسارع.

يجب ضبط الوصف على android:required="true" فقط إذا كان تطبيقك يعتمد بالكامل على أداة استشعار معيّنة. إذا كان تطبيقك يستخدم أداة استشعار لبعض الوظائف، ولكنه يظل يعمل بدون أداة الاستشعار، يجب إدراج أداة الاستشعار في العنصر <uses-feature> ، ولكن يجب ضبط العنصر الوصفي على android:required="false". يساعد ذلك في ضمان أنّه يمكن للأجهزة تثبيت تطبيقك حتى إذا لم تكن مزوّدة بجهاز الاستشعار هذا. يُعدّ ذلك أيضًا أحد أفضل الممارسات لإدارة المشاريع التي تساعدك في تتبُّع الميزات التي يستخدمها تطبيقك. يُرجى العِلم أنّه إذا كان تطبيقك يستخدم أداة استشعار معيّنة، ولكنه لا يزال يعمل بدونها، عليك رصد أداة الاستشعار أثناء التشغيل وإيقاف ميزات التطبيق أو تفعيلها حسب الحاجة.

نظام إحداثيات أداة الاستشعار

بشكل عام، يستخدم إطار عمل أداة الاستشعار نظام إحداثيات عاديًا من 3 محاور للتعبير عن قيم البيانات. بالنسبة إلى معظم أجهزة الاستشعار، يتم تحديد نظام الإحداثيات بالنسبة إلى شاشة الجهاز عند حمل الجهاز باتجاهه التلقائي (راجِع الشكل 1). عند حمل الجهاز في الاتجاه التلقائي، يكون محور X عموديًا ويشير إلى اليمين، ويكون محور Y رأسيًا ويشير إلى الأعلى، ويشير محور Z إلى الجهة الخارجية من شاشة الجهاز. في هذا النظام، تكون الإحداثيات التي تقع خلف الشاشة لها قيم سلبية لسمة Z. يستخدم نظام الإحداثيات هذا المستشعرات التالية:

الشكل 1: نظام الإحداثيات (بالنسبة إلى جهاز) الذي تستخدمه واجهة برمجة تطبيقات أدوات الاستخدام.

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

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

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

ملاحظة: تستخدِم بعض الحساسات والأساليب نظام إحداثيات نسبيًا إلى إطار مرجعي عالمي (على عكس إطار مرجعي الجهاز). تعرض هذه الأدوات وطرق الاستشعار بيانات تمثّل حركة الجهاز أو موقعه بالنسبة إلى الأرض. لمزيد من المعلومات، اطّلِع على طريقة getOrientation() وطريقة getRotationMatrix() ومستشعر اتجاه الشاشة ومستشعر متجه الدوران.

الحدّ من معدّل إرسال البيانات من أجهزة الاستشعار

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

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

  • في حال استدعاء الأسلوب registerListener() لمراقبة أحداث أجهزة الاستشعار، يكون معدّل أخذ العينات من أجهزة الاستشعار محدودًا بـ 200 هرتز. وينطبق ذلك على جميع الصيغ المُحمَّلة من الأسلوب registerListener().
  • في حال استخدام فئة SensorDirectChannel، يقتصر معدّل أخذ العينات من المستشعر على RATE_NORMAL، وهو عادةً ما يقارب 50 هرتز.

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

AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
    <application ...>
        ...
    </application>
</manifest>

أفضل الممارسات للوصول إلى أجهزة الاستشعار واستخدامها

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

جمع بيانات أجهزة الاستشعار في المقدّمة فقط

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

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

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

إلغاء تسجيل أدوات الاستماع إلى أجهزة الاستشعار

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

Kotlin

private lateinit var sensorManager: SensorManager
...
override fun onPause() {
    super.onPause()
    sensorManager.unregisterListener(this)
}

Java

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

لمزيد من المعلومات، يُرجى الاطّلاع على unregisterListener(SensorEventListener).

الاختبار باستخدام "محاكي Android"

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

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

يمكنك الاطّلاع على رمز المصدر لتطبيق SdkControllerSensor في الموقع التالي:

$ your-android-sdk-directory/tools/apps/SdkController

لنقل البيانات بين جهازك والمحاكي، اتّبِع الخطوات التالية:

  1. تأكَّد من أنّ ميزة تصحيح أخطاء الجهاز عبر USB مفعَّلة على جهازك.
  2. وصِّل جهازك بجهاز التطوير باستخدام كابل USB.
  3. ابدأ تطبيق SdkControllerSensor على جهازك.
  4. في التطبيق، اختَر أجهزة الاستشعار التي تريد محاكاتها.
  5. شغِّل الأمر adb التالي:

  6. $ adb forward tcp:1968 tcp:1968
    
  7. ابدأ تشغيل المحاكي. من المفترض أن تتمكّن الآن من تطبيق عمليات التحويل على الemualtor عن طريق تحريك جهازك.

ملاحظة: إذا لم تؤدِ الحركات التي تجريها على الجهاز الفعلي إلى تحويل المحاكي، حاوِل تنفيذ الأمر adb من الخطوة 5 مرة أخرى.

لمزيد من المعلومات، يمكنك الاطّلاع على دليل محاكي Android.

لا تحظر الطريقة onSensorChanged()‎.

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

تجنَّب استخدام الطرق أو أنواع أجهزة الاستشعار المتوقّفة نهائيًا.

تم إيقاف استخدام العديد من الطرق والثوابت. وعلى وجه التحديد، تم إيقاف نوع أداة الاستشعار TYPE_ORIENTATION نهائيًا. للحصول على بيانات الاتجاه، يجب استخدام الطريقة getOrientation() بدلاً من ذلك. وبالمثل، تم إيقاف نوع أداة استشعار TYPE_TEMPERATURE نهائيًا. يجب استخدام نوع المستشعر TYPE_AMBIENT_TEMPERATURE بدلاً من ذلك على الأجهزة التي تعمل بالإصدار 4.0 من Android.

التحقّق من صحة بيانات أجهزة الاستشعار قبل استخدامها

تأكَّد دائمًا من توفُّر أداة استشعار على الجهاز قبل محاولة الحصول على بيانات منه. لاتفترض أنّ هناك جهاز استشعار متوفّرًا لمجرد أنّه جهاز استشعار يتم استخدامه بشكل متكرر. ليس على الشركات المصنّعة للأجهزة توفير أي أدوات استشعار معيّنة في أجهزتها.

اختيار تأخيرات أدوات الاستشعار بعناية

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