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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

أداة استشعار Type الوصف الاستخدامات الشائعة
TYPE_ACCELEROMETER الأجهزة يقيس قوة التسارع بوحدة م/ث2 التي يتم تطبيقها على جهاز في المحاور المادية الثلاثة (س و ص وع)، بما في ذلك قوة الجاذبية. كشف الحركة (الاهتزاز والإمالة وما إلى ذلك)
TYPE_AMBIENT_TEMPERATURE الأجهزة تقيس درجة حرارة الغرفة المحيطة بدرجة مئوية (°م). انظر الملاحظة أدناه. يتم رصد درجات حرارة الهواء.
TYPE_GRAVITY البرامج أو الأجهزة تقيس قوة الجاذبية بوحدة م/ث2 التي يتم تطبيقها على جهاز في جميع المحاور الفعلية الثلاثة (س، ص، ع). كشف الحركة (الاهتزاز والإمالة وما إلى ذلك)
TYPE_GYROSCOPE الأجهزة تقيس معدل دوران الجهاز بالراد/الثانية حول كل من المحاور المادية الثلاثة (س، وص، ع). اكتشاف التدوير (التدوير، الدوران، إلخ.).
TYPE_LIGHT الأجهزة يقيس مستوى الإضاءة المحيطة (الإضاءة) بالوحدة. التحكّم في سطوع الشاشة
TYPE_LINEAR_ACCELERATION البرامج أو الأجهزة يقيس قوة التسارع بوحدة م/ث2 التي يتم تطبيقها على جهاز في جميع المحاور المادية الثلاثة (س وص وع)، باستثناء قوة الجاذبية. رصد التسارع على محور واحد.
TYPE_MAGNETIC_FIELD الأجهزة يقيس المجال المغناطيسي المحيطي لجميع المحاور المادية الثلاثة (س، ص، ع) بالميكرومتر. إنشاء بوصلة.
TYPE_ORIENTATION البرامج يقيس درجات الدوران التي يقوم بها الجهاز حول جميع المحاور المادية الثلاثة (س، ص، ع). ومع المستوى 3 من واجهة برمجة التطبيقات، يمكنك الحصول على مصفوفة الميل ومصفوفة التدوير لأحد الأجهزة باستخدام أداة استشعار الجاذبية وأجهزة استشعار المجال المغناطيسي جنبًا إلى جنب مع الطريقة getRotationMatrix(). جارٍ تحديد موضع الجهاز.
TYPE_PRESSURE الأجهزة يقيس ضغط الهواء المحيط بوحدة hPa أو mbar. يتم رصد التغيّرات في ضغط الهواء.
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 تم تعريفه في ملف 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(). يتناسب تأخير البيانات الافتراضي مع مراقبة التغييرات النموذجية في اتجاه الشاشة ويستخدم تأخيرًا قدره 200000 ميكرو ثانية. يمكنك تحديد تأخير آخر للبيانات، مثل 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. نظام التنسيق (بالنسبة إلى الجهاز) الذي تستخدمه واجهة برمجة تطبيقات أداة الاستشعار

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

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

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

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

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