تحتوي معظم أجهزة Android على مستشعرات مدمجة تقيس الحركة والاتجاه والظروف البيئية المختلفة. يمكن لهذه المستشعرات تقديم بيانات أولية بدقة عالية، وهي مفيدة إذا كنت تريد تتبُّع حركة الجهاز أو تحديد موقعه الثلاثي الأبعاد، أو إذا كنت تريد تتبُّع التغييرات في البيئة المحيطة بالجهاز. على سبيل المثال، قد تتتبّع إحدى الألعاب القراءات من مستشعر الجاذبية في الجهاز لاستنتاج إيماءات وحركات معقّدة للمستخدم، مثل الإمالة أو الرجّ أو الدوران أو التأرجح. وبالمثل، قد يستخدم تطبيق الطقس جهاز استشعار درجة الحرارة وجهاز استشعار الرطوبة في الجهاز لحساب نقطة الندى والإبلاغ عنها، أو قد يستخدم تطبيق السفر جهاز استشعار المجال المغناطيسي الأرضي ومقياس التسارع للإبلاغ عن اتجاه البوصلة.
يُرجى الرجوع إلى المراجع ذات الصلة التالية:
تتيح منصة Android ثلاث فئات واسعة من أجهزة الاستشعار:
- أجهزة استشعار الحركة
تقيس أجهزة الاستشعار هذه قوى التسارع وقوى الدوران على طول ثلاثة محاور. وتشمل هذه الفئة مقاييس التسارع وأدوات استشعار الجاذبية والجيروسكوبات وأدوات استشعار متجهات الدوران.
- أدوات الاستشعار البيئية
وتقيس هذه المستشعرات معلَمات بيئية مختلفة، مثل درجة حرارة الهواء المحيط والضغط والإضاءة والرطوبة. تشمل هذه الفئة مقاييس الضغط الجوي ومقاييس الضوء ومقاييس الحرارة.
- أجهزة استشعار الموضع
تقيس أدوات الاستشعار هذه الموقع الجغرافي للجهاز. تشمل هذه الفئة مستشعرات الاتجاه ومقاييس المغناطيسية.
يمكنك الوصول إلى أدوات الاستشعار المتوفّرة على الجهاز والحصول على بيانات الاستشعار الأولية باستخدام إطار عمل أدوات الاستشعار في Android. يوفّر إطار عمل أجهزة الاستشعار العديد من الفئات والواجهات التي تساعدك في تنفيذ مجموعة متنوعة من المهام المتعلقة بأجهزة الاستشعار. على سبيل المثال، يمكنك استخدام إطار عمل أجهزة الاستشعار لإجراء ما يلي:
- تحديد المستشعرات المتوفّرة على الجهاز
- تحديد إمكانات جهاز استشعار فردي، مثل الحد الأقصى للنطاق والشركة المصنّعة ومتطلبات الطاقة والدقة
- الحصول على بيانات أجهزة الاستشعار الأولية وتحديد الحدّ الأدنى لمعدّل الحصول على بيانات أجهزة الاستشعار
- تسجيل أدوات معالجة أحداث أجهزة الاستشعار وإلغاء تسجيلها، وهي الأدوات التي تراقب التغييرات في أجهزة الاستشعار
يقدّم هذا الموضوع نظرة عامة على أجهزة الاستشعار المتوفّرة على منصة Android. ويقدّم أيضًا مقدمة عن إطار عمل أداة الاستشعار.
مقدمة حول أجهزة الاستشعار
يتيح لك إطار عمل أجهزة الاستشعار في Android الوصول إلى العديد من أنواع أجهزة الاستشعار. بعض هذه المستشعرات يعتمد على الأجهزة وبعضها الآخر على البرامج. أدوات الاستشعار المستندة إلى الأجهزة هي مكونات مادية مدمجة في هاتف جوّال أو جهاز لوحي. وتستمد هذه الأجهزة بياناتها من خلال قياس خصائص بيئية معيّنة بشكل مباشر، مثل التسارع أو قوة المجال المغناطيسي الأرضي أو التغيير الزاوي. أدوات الاستشعار المستندة إلى البرامج ليست أجهزة مادية، على الرغم من أنّها تحاكي أدوات الاستشعار المستندة إلى الأجهزة. تستمد أجهزة الاستشعار المستندة إلى البرامج بياناتها من جهاز استشعار واحد أو أكثر من أجهزة الاستشعار المستندة إلى الأجهزة، ويُطلق عليها أحيانًا اسم أجهزة الاستشعار الافتراضية أو أجهزة الاستشعار الاصطناعية. جهاز استشعار التسارع الخطي وجهاز استشعار الجاذبية هما مثالان على أجهزة الاستشعار المستندة إلى البرامج. يلخّص الجدول 1 أجهزة الاستشعار المتوافقة مع نظام Android الأساسي.
لا تتضمّن سوى أجهزة Android القليلة كل أنواع أدوات الاستشعار. على سبيل المثال، تتضمّن معظم الهواتف والأجهزة اللوحية مقياس تسارع ومقياس مغناطيسية، ولكن عددًا أقل من الأجهزة يتضمّن مقياس ضغط جوي أو مقياس حرارة. يمكن أن يتضمّن الجهاز أيضًا أكثر من مستشعر واحد من نوع معيّن. على سبيل المثال، يمكن أن يحتوي الجهاز على جهازَي استشعار للجاذبية، ولكل منهما نطاق مختلف.
الجدول 1. أنواع أجهزة الاستشعار المتوافقة مع نظام التشغيل Android
| أداة استشعار | النوع | الوصف | الاستخدامات الشائعة |
|---|---|---|---|
TYPE_ACCELEROMETER |
الأجهزة | يقيس هذا المستشعر قوة التسارع بوحدة القياس متر/ثانية2 التي يتم تطبيقها على الجهاز على جميع المحاور الفيزيائية الثلاثة (س، ص، ع)، بما في ذلك قوة الجاذبية. | رصد الحركة (الاهتزاز والإمالة وما إلى ذلك) |
TYPE_AMBIENT_TEMPERATURE |
الأجهزة | يقيس درجة حرارة الغرفة المحيطة بالدرجة المئوية (°C). راجِع الملاحظة أدناه. | مراقبة درجات حرارة الهواء |
TYPE_GRAVITY |
البرامج أو الأجهزة | يقيس هذا النوع قوة الجاذبية بوحدة متر/ثانية2 التي يتم تطبيقها على الجهاز على جميع المحاور الفيزيائية الثلاثة (س، ص، ع). | رصد الحركة (الاهتزاز والإمالة وما إلى ذلك) |
TYPE_GYROSCOPE |
الأجهزة | يقيس هذا المستشعر معدّل دوران الجهاز بالراديان في الثانية حول كل محور من المحاور الفيزيائية الثلاثة (س، ص، ع). | رصد الدوران (الدوران السريع، الدوران العادي، إلخ) |
TYPE_LIGHT |
الأجهزة | تقيس هذه السمة مستوى الإضاءة المحيطة (الإنارة) بوحدة اللوكس. | التحكّم في سطوع الشاشة |
TYPE_LINEAR_ACCELERATION |
البرامج أو الأجهزة | يقيس هذا المستشعر قوة التسارع بوحدة متر/ثانية2 التي يتم تطبيقها على جهاز على جميع المحاور المادية الثلاثة (س، ص، ع)، باستثناء قوة الجاذبية. | تتبُّع التسارع على طول محور واحد |
TYPE_MAGNETIC_FIELD |
الأجهزة | يقيس هذا النوع المجال المغناطيسي الأرضي المحيط لجميع المحاور الفيزيائية الثلاثة (س، ص، ع) بوحدة الميكروتيسلا (μT). | إنشاء بوصلة |
TYPE_ORIENTATION |
البرامج | يقيس هذا المستشعر درجات الدوران التي يحدثها الجهاز حول جميع المحاور المادية الثلاثة (س، ص، ع).
بدءًا من مستوى واجهة برمجة التطبيقات 3، يمكنك الحصول على مصفوفة الميل ومصفوفة الدوران لجهاز باستخدام مستشعر الجاذبية ومستشعر المجال المغناطيسي الأرضي معًا باستخدام الطريقة getRotationMatrix(). |
تحديد موضع الجهاز |
TYPE_PRESSURE |
الأجهزة | تقيس هذه السمة ضغط الهواء المحيط بوحدة الهكتوباسكال أو الميليبار. | مراقبة التغيّرات في ضغط الهواء |
TYPE_PROXIMITY |
الأجهزة | يقيس هذا المقياس مدى قرب جسم ما بالسنتيمتر مقارنةً بشاشة العرض على الجهاز. يُستخدم هذا المستشعر عادةً لتحديد ما إذا كان الهاتف المحمول موضوعًا بالقرب من أذن المستخدم. | وضع الهاتف أثناء المكالمة |
TYPE_RELATIVE_HUMIDITY |
الأجهزة | تقيس هذه السمة الرطوبة النسبية المحيطة كنسبة مئوية (%). | مراقبة نقطة الندى والرطوبة المطلقة والنسبية |
TYPE_ROTATION_VECTOR |
البرامج أو الأجهزة | تقيس هذه السمة اتجاه الجهاز من خلال توفير العناصر الثلاثة لمتجه دوران الجهاز. | رصد الحركة ورصد الدوران |
TYPE_TEMPERATURE |
الأجهزة | تقيس درجة حرارة الجهاز بالدرجة المئوية (°C). يختلف تنفيذ هذا المستشعر باختلاف الأجهزة، وتم استبداله بالمستشعر TYPE_AMBIENT_TEMPERATURE في المستوى 14 لواجهة برمجة التطبيقات. |
مراقبة درجات الحرارة |
إطار عمل المستشعرات
يمكنك الوصول إلى أدوات الاستشعار هذه والحصول على بيانات الاستشعار الأولية باستخدام إطار عمل أدوات الاستشعار في Android.
يشكّل إطار عمل المستشعر جزءًا من حزمة android.hardware ويتضمّن الفئات والواجهات التالية:
SensorManager- يمكنك استخدام هذه الفئة لإنشاء مثيل لخدمة المستشعر. يوفر هذا الصف طرقًا مختلفة للوصول إلى أدوات الاستشعار وإدراجها، وتسجيل أدوات معالجة أحداث أدوات الاستشعار وإلغاء تسجيلها، والحصول على معلومات الاتجاه. يوفر هذا الصف أيضًا العديد من الثوابت الخاصة بأدوات الاستشعار التي تُستخدَم لتحديد دقة أدوات الاستشعار، وضبط معدّلات جمع البيانات، ومعايرة أدوات الاستشعار.
Sensor- يمكنك استخدام هذه الفئة لإنشاء مثيل لجهاز استشعار معيّن. يوفر هذا الصف طرقًا مختلفة تتيح لك تحديد إمكانات جهاز الاستشعار.
SensorEvent- يستخدم النظام هذه الفئة لإنشاء عنصر حدث مستشعر، يوفّر معلومات حول حدث مستشعر. يتضمّن عنصر حدث جهاز الاستشعار المعلومات التالية: بيانات جهاز الاستشعار الأولية ونوع جهاز الاستشعار الذي أنشأ الحدث ودقة البيانات والطابع الزمني للحدث.
SensorEventListener- يمكنك استخدام هذه الواجهة لإنشاء طريقتَي ردّ اتصال تتلقّيان الإشعارات (أحداث المستشعر) عند تغيُّر قيم المستشعر أو دقته.
في التطبيق العادي، يمكنك استخدام واجهات برمجة التطبيقات المرتبطة بأجهزة الاستشعار لتنفيذ مهمتَين أساسيتَين:
- تحديد أدوات الاستشعار وإمكانياتها
تكون عملية تحديد أدوات الاستشعار وإمكانياتها في وقت التشغيل مفيدة إذا كان تطبيقك يتضمّن ميزات تعتمد على أنواع أو إمكانيات معيّنة لأدوات الاستشعار. على سبيل المثال، قد تحتاج إلى تحديد جميع أجهزة الاستشعار المتوفّرة على جهاز وإيقاف أي ميزات في التطبيق تعتمد على أجهزة استشعار غير متوفّرة. وبالمثل، قد تحتاج إلى تحديد جميع أدوات الاستشعار من نوع معيّن حتى تتمكّن من اختيار تنفيذ أداة الاستشعار الذي يحقّق أفضل أداء لتطبيقك.
- مراقبة أحداث المستشعر
تتيح لك مراقبة أحداث أجهزة الاستشعار الحصول على بيانات أجهزة الاستشعار الأولية. يحدث حدث المستشعر كلما رصد المستشعر تغييرًا في المَعلمات التي يقيسها. يوفّر لك حدث المستشعر أربع معلومات: اسم المستشعر الذي أدّى إلى تشغيل الحدث، والطابع الزمني للحدث، ودقة الحدث، وبيانات المستشعر الأولية التي أدّت إلى تشغيل الحدث.
توفُّر أداة الاستشعار
مع أنّ مدى توفّر المستشعر يختلف من جهاز إلى آخر، يمكن أن يختلف أيضًا بين إصدارات Android. ويرجع ذلك إلى أنّ مستشعرات Android تم طرحها على مدار عدة إصدارات من النظام الأساسي. على سبيل المثال، تم طرح العديد من أدوات الاستشعار في الإصدار 1.5 من نظام التشغيل Android (المستوى 3 من واجهة برمجة التطبيقات)، ولكن لم يتم تنفيذ بعضها ولم تكن متاحة للاستخدام إلا في الإصدار 2.3 من نظام التشغيل Android (المستوى 9 من واجهة برمجة التطبيقات). وبالمثل، تم طرح العديد من أدوات الاستشعار في الإصدار 2.3 من نظام التشغيل Android (المستوى 9 من واجهة برمجة التطبيقات) والإصدار 4.0 من نظام التشغيل Android (المستوى 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 |
نعم | نعم | n/a1 | n/a1 |
TYPE_LIGHT |
نعم | نعم | نعم | نعم |
TYPE_LINEAR_ACCELERATION |
نعم | نعم | لا تنطبق | لا تنطبق |
TYPE_MAGNETIC_FIELD |
نعم | نعم | نعم | نعم |
TYPE_ORIENTATION |
نعم2 | نعم2 | نعم2 | نعم |
TYPE_PRESSURE |
نعم | نعم | n/a1 | n/a1 |
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() وتمرير الثابت الخاص بالنوع
لأداة استشعار معيّنة. إذا كان الجهاز يتضمّن أكثر من مستشعر واحد من نوع معيّن، يجب تحديد أحد المستشعرات كمستشعر تلقائي. إذا لم يكن هناك جهاز استشعار تلقائي لنوع معيّن من أجهزة الاستشعار، سيعرض طلب الطريقة القيمة null، ما يعني أنّ الجهاز لا يتضمّن هذا النوع من أجهزة الاستشعار. على سبيل المثال، يتحقّق الرمز التالي مما إذا كان هناك مقياس مغناطيسي على الجهاز:
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 ميكروثانية. يمكنك تحديد تأخيرات أخرى في البيانات، مثل SENSOR_DELAY_GAME (تأخير بمقدار 20,000 ميكروثانية) أو SENSOR_DELAY_UI (تأخير بمقدار 60,000 ميكروثانية) أو SENSOR_DELAY_FASTEST (تأخير بمقدار 0 ميكروثانية). بدءًا من الإصدار 3.0 من نظام التشغيل Android (المستوى 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. }
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". يساعد ذلك في ضمان إمكانية تثبيت تطبيقك على الأجهزة حتى إذا لم تتضمّن جهاز الاستشعار المحدّد. وهذه أيضًا إحدى أفضل ممارسات إدارة المشروعات التي تساعدك في تتبُّع الميزات التي يستخدمها تطبيقك.
يُرجى العِلم أنّه إذا كان تطبيقك يستخدم جهاز استشعار معيّنًا، ولكنّه يظل يعمل بدون هذا الجهاز، عليك رصد جهاز الاستشعار في وقت التشغيل وإيقاف ميزات التطبيق أو تفعيلها حسب الاقتضاء.
نظام إحداثيات أداة الاستشعار
بشكل عام، يستخدم إطار عمل المستشعر نظام إحداثيات ثلاثي المحاور قياسيًا للتعبير عن قيم البيانات. بالنسبة إلى معظم أجهزة الاستشعار، يتم تحديد نظام الإحداثيات بالنسبة إلى شاشة الجهاز عندما يكون الجهاز في وضعه التلقائي (راجِع الشكل 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>
أفضل الممارسات المتعلّقة بالوصول إلى أجهزة الاستشعار واستخدامها
أثناء تصميم عملية تنفيذ المستشعر، احرص على اتّباع الإرشادات الموضّحة في هذا القسم. هذه الإرشادات هي أفضل الممارسات المقترَحة لأي شخص يستخدم إطار عمل أدوات الاستشعار للوصول إلى أدوات الاستشعار والحصول على بياناتها.
جمع بيانات أجهزة الاستشعار في المقدّمة فقط
على الأجهزة التي تعمل بالإصدار 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 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث. (إذا كان الجهاز يعمل بالإصدار 4.0 من نظام التشغيل Android، يجب أن يكون الإصدار 2 مثبّتًا عليه). يراقب تطبيق SdkControllerSensor التغييرات في أجهزة الاستشعار على الجهاز وينقلها إلى المحاكي. يتم بعد ذلك تحويل المحاكي استنادًا إلى القيم الجديدة التي يتلقّاها من المستشعرات على جهازك.
يمكنك الاطّلاع على رمز المصدر لتطبيق SdkControllerSensor في الموقع الجغرافي التالي:
$ your-android-sdk-directory/tools/apps/SdkController
لنقل البيانات بين جهازك والمحاكي، اتّبِع الخطوات التالية:
- تأكَّد من تفعيل تصحيح الأخطاء عبر USB على جهازك.
- وصِّل جهازك بجهاز التطوير باستخدام كابل USB.
- ابدأ تشغيل تطبيق SdkControllerSensor على جهازك.
- في التطبيق، اختَر أجهزة الاستشعار التي تريد محاكاتها.
نفِّذ أمر
adbالتالي:- ابدأ تشغيل المحاكي. من المفترض أن تتمكّن الآن من تطبيق عمليات تحويل على المحاكي من خلال تحريك جهازك.
$ adb forward tcp:1968 tcp:1968
ملاحظة: إذا لم تؤدِّ الحركات التي تجريها على جهازك الفعلي إلى تحويل المحاكي، حاوِل تنفيذ الأمر adb من الخطوة 5 مرة أخرى.
لمزيد من المعلومات، يمكنك الاطّلاع على دليل محاكي Android.
عدم حظر طريقة onSensorChanged()
يمكن أن تتغيّر بيانات أجهزة الاستشعار بمعدّل مرتفع، ما يعني أنّ النظام قد يستدعي طريقة onSensorChanged(SensorEvent) بشكل متكرّر. كأفضل ممارسة، يجب تنفيذ أقل قدر ممكن من العمليات داخل طريقة onSensorChanged(SensorEvent) لتجنُّب حظرها. إذا كان تطبيقك يتطلّب منك فلترة البيانات أو تقليل بيانات أجهزة الاستشعار، عليك تنفيذ هذه العملية خارج طريقة onSensorChanged(SensorEvent).
تجنُّب استخدام الطرق أو أنواع أجهزة الاستشعار المتوقّفة نهائيًا
تم إيقاف استخدام العديد من الطرق والثوابت.
على وجه الخصوص، تم إيقاف TYPE_ORIENTATION
نوع أداة الاستشعار نهائيًا. للحصول على بيانات الاتجاه، عليك استخدام طريقة getOrientation() بدلاً من ذلك. وبالمثل، تم إيقاف نوع جهاز الاستشعار
TYPE_TEMPERATURE نهائيًا. يجب استخدام نوع المستشعر TYPE_AMBIENT_TEMPERATURE بدلاً من ذلك على الأجهزة التي تعمل بالإصدار 4.0 من نظام التشغيل Android.
التحقّق من المستشعرات قبل استخدامها
احرص دائمًا على التأكّد من توفّر مستشعر على الجهاز قبل محاولة الحصول على بيانات منه. لا تفترض توفُّر جهاز استشعار لمجرّد أنّه جهاز استشعار يُستخدَم بشكل متكرر. ولا يُشترط على الشركات المصنّعة للأجهزة توفير أي أجهزة استشعار معيّنة في أجهزتها.
اختيار تأخيرات أجهزة الاستشعار بعناية
عند تسجيل جهاز استشعار باستخدام طريقة registerListener()، احرص على اختيار معدّل تسليم مناسب لتطبيقك أو حالة الاستخدام. يمكن أن توفّر أجهزة الاستشعار البيانات بمعدّلات عالية جدًا. يؤدي السماح للنظام بإرسال بيانات إضافية لا تحتاج إليها إلى إهدار موارد النظام واستخدام طاقة البطارية.