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

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

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

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 التي تم تحديدها في ملف رئيسي.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 ميكرو ثانية). بدءًا من 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.
}

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>

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

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

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

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

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

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

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

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

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

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

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

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

اختَر بعناية التأخيرات المتعلقة بأداة الاستشعار

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