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

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

يدعم نظام Android الأساسي ثلاث فئات واسعة من المستشعرات:

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

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

  • أدوات الاستشعار البيئية

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

  • أدوات استشعار الموضع

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

مدى توفُّر أجهزة الاستشعار

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

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

الجدول 2. مدى توفُّر أدوات الاستشعار حسب النظام الأساسي

أداة استشعار Android 4.0
(مستوى واجهة برمجة التطبيقات 14)
Android 2.3
(مستوى واجهة برمجة التطبيقات 9)
Android 2.2
(مستوى واجهة برمجة التطبيقات 8)
Android 1.5
(مستوى واجهة برمجة التطبيقات 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

جافا

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

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

لغة Kotlin

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

جافا

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

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

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

لغة 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.
}

جافا

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
    }
}

جافا

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 المحددة في ملف sitemap.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)
    }
}

جافا

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 ميكرو ثانية. ويمكنك تحديد تأخيرات أخرى في البيانات، مثل SENSOR_DELAY_GAME (تأخير يصل إلى 20,000 ميكرو ثانية) أو SENSOR_DELAY_UI (مهلة 60,000 ميكرو ثانية) أو SENSOR_DELAY_FASTEST (تأخير 0 ميكرو ثانية). بدءًا من Android 3.0 (المستوى 11 من واجهة برمجة التطبيقات)، يمكنك أيضًا تحديد التأخير كقيمة مطلقة (بالميكرو ثانية).

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

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

يُرجى العِلم أيضًا أنّ هذا المثال يستخدم طريقتَي معاودة الاتصال 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.
}

جافا

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". يساعد ذلك في ضمان إمكانية تثبيت الأجهزة لتطبيقك حتى إذا لم تتضمن أداة الاستشعار هذه. هذه أيضًا من أفضل ممارسات إدارة المشروعات التي تساعدك في تتبع الميزات التي يستخدمها تطبيقك. تجدر الإشارة إلى أنه إذا كان تطبيقك يستخدم أداة استشعار معيّنة، ولكن لا يزال يعمل بدون أداة الاستشعار، عليك رصد أداة الاستشعار في وقت التشغيل وإيقاف ميزات التطبيق أو تفعيلها حسب المناسبة.

نظام تنسيق المستشعر

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

الشكل 1. نظام التنسيق (المتعلق بالجهاز) الذي تستخدمه واجهة برمجة تطبيقات Sensor.

إن أهم نقطة يجب فهمها حول نظام الإحداثيات هذا هي أن المحاور لا يتم تبديلها عند تغير اتجاه شاشة الجهاز - أي أن نظام إحداثيات أداة الاستشعار لا يتغير أبدًا مع تحرك الجهاز. وهذا السلوك هو نفسه سلوك نظام إحداثي 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>

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

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

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

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

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

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

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

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

لغة Kotlin

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

جافا

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. شغِّل المحاكي. من المفترض أن تتمكّن الآن من تطبيق عمليات التحويل على المحاكي عن طريق نقل جهازك.

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

لمزيد من المعلومات، راجع دليل محاكي Android.

عدم حظر طريقة onSensorChanged()

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

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

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

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

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

اختيار تأخيرات أجهزة الاستشعار بعناية

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