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

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

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

  • مستشعرات الحركة

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

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

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

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

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

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

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

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

مقدّمة حول أدوات الاستشعار

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

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

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

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

إطار عمل أدوات الاستشعار

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

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

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

  • التعرّف على أدوات الاستشعار وإمكاناتها

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

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

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

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

While sensor availability varies from device to device, it can also vary between Android versions. ويرجع ذلك إلى أنّ أدوات الاستشعار في Android تم طرحها على مدار عدة إصدارات من النظام الأساسي. على سبيل المثال، تم تقديم العديد من أدوات الاستشعار في الإصدار 1.5 من Android (المستوى 3 من واجهة برمجة التطبيقات)، ولكن لم يتم تنفيذ بعضها ولم تكن متاحة للاستخدام حتى الإصدار 2.3 من Android (المستوى 9 من واجهة برمجة التطبيقات). وبالمثل، تم تقديم العديد من أدوات الاستشعار في Android 2.3 (المستوى 9 من واجهة برمجة التطبيقات) وAndroid 4.0 (المستوى 14 من واجهة برمجة التطبيقات). تم إيقاف أداتَي استشعار واستبدالهما بأدوات استشعار أحدث وأفضل.

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

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

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

‫1 تمت إضافة نوع أداة الاستشعار هذا في الإصدار 1.5 من نظام التشغيل Android (المستوى 3 لواجهة برمجة التطبيقات)، ولكنه لم يكن متاحًا للاستخدام حتى الإصدار 2.3 من نظام التشغيل Android (المستوى 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 ميكروثانية). اعتبارًا من الإصدار 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). عند حمل الجهاز في اتجاهه التلقائي، يكون المحور X أفقيًا ويشير إلى اليمين، والمحور Y عموديًا ويشير إلى الأعلى، والمحور Z يشير إلى خارج وجه الشاشة. في هذا النظام، الإحداثيات خلف الشاشة لها قيم Z سالبة. يستخدم نظام الإحداثيات هذا أدوات الاستشعار التالية:

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

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

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

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

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

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

لحماية المعلومات الحساسة عن المستخدمين التي يُحتمل أن تكون حساسة، إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 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 Emulator

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

يستخدم المحاكي اتصالاً بجهاز Android يعمل عليه تطبيق SdkControllerSensor. يُرجى العِلم أنّ هذا التطبيق متاح فقط على الأجهزة التي تعمل بنظام التشغيل Android 4.0 (مستوى واجهة برمجة التطبيقات 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 Emulator.

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

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

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

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

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

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

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

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