نمای کلی سنسورها

اکثر دستگاه‌های مجهز به اندروید دارای حسگرهای داخلی هستند که حرکت، جهت‌گیری و شرایط محیطی مختلف را اندازه‌گیری می‌کنند. این سنسورها قادر به ارائه داده های خام با دقت و صحت بالا هستند و اگر می خواهید حرکت سه بعدی دستگاه یا موقعیت یابی را نظارت کنید یا می خواهید تغییرات محیط اطراف نزدیک دستگاه را نظارت کنید مفید هستند. برای مثال، یک بازی ممکن است خوانش‌های حسگر گرانش دستگاه را برای استنباط حرکات و حرکات پیچیده کاربر، مانند شیب، لرزش، چرخش یا چرخش، ردیابی کند. به همین ترتیب، یک برنامه آب و هوا ممکن است از حسگر دما و سنسور رطوبت دستگاه برای محاسبه و گزارش نقطه شبنم استفاده کند، یا یک برنامه سفر ممکن است از حسگر میدان ژئومغناطیسی و شتاب‌سنج برای گزارش یک قطب نما استفاده کند.

پلتفرم اندروید از سه دسته وسیع از سنسورها پشتیبانی می کند:

  • سنسورهای حرکت

    این سنسورها نیروهای شتاب و نیروهای دورانی را در سه محور اندازه گیری می کنند. این دسته شامل شتاب‌سنج‌ها، حسگرهای جاذبه، ژیروسکوپ‌ها و حسگرهای بردار چرخشی است.

  • سنسورهای محیطی

    این سنسورها پارامترهای مختلف محیطی مانند دما و فشار هوای محیط، روشنایی و رطوبت را اندازه گیری می کنند. این دسته شامل فشارسنج ها، نورسنج ها و دماسنج ها می شود.

  • سنسورهای موقعیت

    این حسگرها موقعیت فیزیکی دستگاه را اندازه گیری می کنند. این دسته شامل سنسورهای جهت یابی و مغناطیس سنج ها می شود.

با استفاده از چارچوب حسگر Android می‌توانید به حسگرهای موجود در دستگاه دسترسی داشته باشید و داده‌های خام حسگر را بدست آورید. چارچوب حسگر چندین کلاس و رابط را ارائه می دهد که به شما کمک می کند تا طیف گسترده ای از وظایف مرتبط با حسگر را انجام دهید. به عنوان مثال، می توانید از چارچوب سنسور برای انجام کارهای زیر استفاده کنید:

  • تعیین کنید که کدام حسگرها در دستگاه موجود هستند.
  • قابلیت‌های هر حسگر، مانند حداکثر برد، سازنده، توان مورد نیاز و وضوح آن را تعیین کنید.
  • داده های خام حسگر را به دست آورید و حداقل نرخی را که در آن داده های حسگر را به دست می آورید، تعریف کنید.
  • شنوندگان رویداد حسگر را که تغییرات حسگر را نظارت می کنند، ثبت و لغو ثبت کنید.

این مبحث نمای کلی از سنسورهای موجود در پلتفرم اندروید را ارائه می دهد. همچنین مقدمه ای بر چارچوب حسگر ارائه می دهد.

مقدمه ای بر حسگرها

چارچوب حسگر اندروید به شما امکان می دهد به انواع مختلفی از سنسورها دسترسی داشته باشید. برخی از این حسگرها مبتنی بر سخت افزار و برخی دیگر مبتنی بر نرم افزار هستند. حسگرهای مبتنی بر سخت افزار اجزای فیزیکی هستند که در یک گوشی یا تبلت تعبیه شده اند. آنها داده های خود را با اندازه گیری مستقیم ویژگی های محیطی خاص، مانند شتاب، قدرت میدان ژئومغناطیسی یا تغییر زاویه ای به دست می آورند. حسگرهای مبتنی بر نرم‌افزار دستگاه‌های فیزیکی نیستند، اگرچه حسگرهای مبتنی بر سخت‌افزار را تقلید می‌کنند. حسگرهای مبتنی بر نرم‌افزار داده‌های خود را از یک یا چند حسگر مبتنی بر سخت‌افزار استخراج می‌کنند و گاهی اوقات حسگرهای مجازی یا سنسورهای مصنوعی نامیده می‌شوند. سنسور شتاب خطی و سنسور گرانش نمونه هایی از حسگرهای مبتنی بر نرم افزار هستند. جدول 1 خلاصه ای از حسگرهایی است که توسط پلتفرم اندروید پشتیبانی می شوند.

تعداد کمی از دستگاه های مجهز به اندروید دارای هر نوع سنسور هستند. به عنوان مثال، اکثر دستگاه‌ها و تبلت‌های گوشی دارای شتاب‌سنج و مغناطیس‌سنج هستند، اما دستگاه‌های کمتری دارای فشارسنج یا دماسنج هستند. همچنین، یک دستگاه می تواند بیش از یک سنسور از یک نوع خاص داشته باشد. به عنوان مثال، یک دستگاه می تواند دو حسگر گرانش داشته باشد که هر کدام محدوده متفاوتی دارند.

جدول 1. انواع حسگرهای پشتیبانی شده توسط پلتفرم اندروید.

سنسور تایپ کنید توضیحات کاربردهای رایج
TYPE_ACCELEROMETER سخت افزار نیروی شتاب را بر حسب m/s 2 که روی هر سه محور فیزیکی (x، y، و z) به یک دستگاه اعمال می‌شود، از جمله نیروی گرانش اندازه‌گیری می‌کند. تشخیص حرکت (لرزش، شیب و غیره).
TYPE_AMBIENT_TEMPERATURE سخت افزار دمای محیط را بر حسب درجه سانتیگراد (درجه سانتیگراد) اندازه گیری می کند. به یادداشت زیر مراجعه کنید. نظارت بر دمای هوا
TYPE_GRAVITY نرم افزار یا سخت افزار نیروی گرانش را بر حسب m/s 2 اندازه گیری می کند که بر روی هر سه محور فیزیکی (x، y، z) به یک دستگاه اعمال می شود. تشخیص حرکت (لرزش، شیب و غیره).
TYPE_GYROSCOPE سخت افزار سرعت چرخش دستگاه را بر حسب راد بر ثانیه حول هر یک از سه محور فیزیکی (x، y، و z) اندازه گیری می کند. تشخیص چرخش (چرخش، چرخش و غیره).
TYPE_LIGHT سخت افزار سطح نور محیط (روشنایی) را بر حسب lx اندازه گیری می کند. کنترل روشنایی صفحه نمایش
TYPE_LINEAR_ACCELERATION نرم افزار یا سخت افزار نیروی شتاب را بر حسب m/s 2 اندازه گیری می کند که به یک دستگاه در هر سه محور فیزیکی (x، y، و z)، بدون احتساب نیروی گرانش، اعمال می شود. نظارت بر شتاب در امتداد یک محور.
TYPE_MAGNETIC_FIELD سخت افزار میدان ژئومغناطیسی محیط را برای هر سه محور فیزیکی (x، y، z) در μT اندازه گیری می کند. ایجاد قطب نما.
TYPE_ORIENTATION نرم افزار درجات چرخشی را که یک دستگاه حول هر سه محور فیزیکی (x، y، z) انجام می دهد، اندازه گیری می کند. از سطح 3 API، می‌توانید ماتریس شیب و ماتریس چرخش یک دستگاه را با استفاده از حسگر گرانش و حسگر میدان مغناطیسی در ارتباط با روش getRotationMatrix() بدست آورید. تعیین موقعیت دستگاه
TYPE_PRESSURE سخت افزار فشار هوای محیط را بر حسب hPa یا mbar اندازه گیری می کند. نظارت بر تغییرات فشار هوا
TYPE_PROXIMITY سخت افزار نزدیکی یک شی را نسبت به صفحه نمایش دستگاه بر حسب سانتی متر اندازه می گیرد. این سنسور معمولاً برای تعیین اینکه آیا یک گوشی در بالای گوش فرد قرار می گیرد یا خیر استفاده می شود. موقعیت تلفن در حین تماس
TYPE_RELATIVE_HUMIDITY سخت افزار رطوبت نسبی محیط را بر حسب درصد (%) اندازه گیری می کند. پایش نقطه شبنم، رطوبت مطلق و نسبی.
TYPE_ROTATION_VECTOR نرم افزار یا سخت افزار جهت گیری یک دستگاه را با ارائه سه عنصر بردار چرخش دستگاه اندازه گیری می کند. تشخیص حرکت و تشخیص چرخش.
TYPE_TEMPERATURE سخت افزار دمای دستگاه را بر حسب درجه سانتیگراد (درجه سانتیگراد) اندازه گیری می کند. اجرای این حسگر در دستگاه‌ها متفاوت است و این حسگر با حسگر TYPE_AMBIENT_TEMPERATURE در سطح 14 API جایگزین شد. نظارت بر دما

چارچوب سنسور

با استفاده از چارچوب حسگر اندروید می توانید به این سنسورها دسترسی داشته باشید و داده های خام حسگر را بدست آورید. چارچوب حسگر بخشی از بسته android.hardware است و شامل کلاس‌ها و رابط‌های زیر است:

SensorManager
می توانید از این کلاس برای ایجاد یک نمونه از سرویس سنسور استفاده کنید. این کلاس روش‌های مختلفی را برای دسترسی و فهرست‌بندی حسگرها، ثبت و لغو ثبت شنوندگان رویداد حسگر و کسب اطلاعات جهت‌گیری ارائه می‌کند. این کلاس همچنین چندین ثابت حسگر را ارائه می دهد که برای گزارش دقت سنسور، تنظیم نرخ اکتساب داده ها و کالیبره کردن سنسورها استفاده می شود.
Sensor
شما می توانید از این کلاس برای ایجاد یک نمونه از یک سنسور خاص استفاده کنید. این کلاس روش های مختلفی را ارائه می دهد که به شما امکان می دهد قابلیت های یک سنسور را تعیین کنید.
SensorEvent
سیستم از این کلاس برای ایجاد یک شی رویداد حسگر استفاده می کند که اطلاعاتی در مورد یک رویداد حسگر ارائه می دهد. یک شی رویداد حسگر شامل اطلاعات زیر است: داده‌های خام حسگر، نوع سنسوری که رویداد را ایجاد کرده است، دقت داده‌ها و مهر زمانی رویداد.
SensorEventListener
می توانید از این رابط برای ایجاد دو روش پاسخ به تماس استفاده کنید که اعلان ها (رویدادهای حسگر) را هنگام تغییر مقادیر سنسور یا زمانی که دقت حسگر تغییر می کند، دریافت می کنند.

در یک برنامه معمولی شما از این APIهای مرتبط با حسگر برای انجام دو کار اساسی استفاده می کنید:

  • شناسایی سنسورها و قابلیت های حسگر

    شناسایی سنسورها و قابلیت‌های حسگر در زمان اجرا مفید است اگر برنامه شما دارای ویژگی‌هایی باشد که به انواع یا قابلیت‌های حسگر خاصی متکی هستند. برای مثال، ممکن است بخواهید تمام حسگرهایی را که در یک دستگاه وجود دارند شناسایی کنید و هر ویژگی برنامه‌ای را که به حسگرهایی که وجود ندارند را غیرفعال کنید. به همین ترتیب، ممکن است بخواهید همه سنسورهای یک نوع معین را شناسایی کنید تا بتوانید اجرای سنسوری را انتخاب کنید که عملکرد بهینه را برای برنامه شما دارد.

  • نظارت بر رویدادهای حسگر

    نظارت بر رویدادهای حسگر نحوه به دست آوردن اطلاعات خام حسگر است. هر بار که حسگر تغییری را در پارامترهایی که اندازه‌گیری می‌کند، تشخیص می‌دهد، یک رویداد حسگر رخ می‌دهد. یک رویداد حسگر چهار اطلاعات را در اختیار شما قرار می دهد: نام سنسوری که رویداد را راه اندازی کرده است، مهر زمانی رویداد، دقت رویداد، و داده های حسگر خامی که رویداد را آغاز کرده است.

در دسترس بودن سنسور

در حالی که در دسترس بودن حسگر از دستگاهی به دستگاه دیگر متفاوت است، می تواند بین نسخه های اندروید نیز متفاوت باشد. این به این دلیل است که حسگرهای اندروید در طول چندین نسخه پلتفرم معرفی شده اند. به عنوان مثال، بسیاری از سنسورها در اندروید 1.5 (API Level 3) معرفی شدند، اما برخی از آنها پیاده سازی نشدند و تا اندروید 2.3 (API Level 9) برای استفاده در دسترس نبودند. به همین ترتیب، چندین حسگر در اندروید 2.3 (API Level 9) و Android 4.0 (API Level 14) معرفی شدند. دو سنسور منسوخ شده و با سنسورهای جدیدتر و بهتر جایگزین شده اند.

جدول 2 در دسترس بودن هر سنسور را بر اساس پلت فرم به پلتفرم خلاصه می کند. فقط چهار پلتفرم فهرست شده اند زیرا این پلتفرم ها شامل تغییرات سنسور می شوند. سنسورهایی که به‌عنوان منسوخ فهرست شده‌اند، همچنان در پلتفرم‌های بعدی در دسترس هستند (به شرطی که حسگر روی دستگاهی وجود داشته باشد)، که مطابق با خط‌مشی سازگاری آینده اندروید است.

جدول 2. در دسترس بودن سنسور بر اساس پلت فرم.

سنسور اندروید 4.0
(API سطح 14)
اندروید 2.3
(API سطح 9)
اندروید 2.2
(API سطح 8)
اندروید 1.5
(API سطح 3)
TYPE_ACCELEROMETER بله بله بله بله
TYPE_AMBIENT_TEMPERATURE بله n/a n/a n/a
TYPE_GRAVITY بله بله n/a n/a
TYPE_GYROSCOPE بله بله n/a 1 n/a 1
TYPE_LIGHT بله بله بله بله
TYPE_LINEAR_ACCELERATION بله بله n/a n/a
TYPE_MAGNETIC_FIELD بله بله بله بله
TYPE_ORIENTATION بله 2 بله 2 بله 2 بله
TYPE_PRESSURE بله بله n/a 1 n/a 1
TYPE_PROXIMITY بله بله بله بله
TYPE_RELATIVE_HUMIDITY بله n/a n/a n/a
TYPE_ROTATION_VECTOR بله بله n/a n/a
TYPE_TEMPERATURE بله 2 بله بله بله

1 این نوع حسگر در اندروید 1.5 (سطح API 3) اضافه شد، اما تا قبل از اندروید 2.3 (سطح API 9) برای استفاده در دسترس نبود.

2 این سنسور موجود است، اما منسوخ شده است.

شناسایی سنسورها و قابلیت های حسگر

چارچوب حسگر اندروید روش‌های مختلفی را ارائه می‌کند که تشخیص سنسورهای موجود در دستگاه را در زمان اجرا برای شما آسان می‌کند. API همچنین روش‌هایی را ارائه می‌کند که به شما امکان می‌دهد قابلیت‌های هر سنسور، مانند حداکثر برد، وضوح و نیازهای برق آن را تعیین کنید.

برای شناسایی حسگرهایی که روی یک دستگاه قرار دارند، ابتدا باید به خدمات حسگر مراجعه کنید. برای انجام این کار، با فراخوانی متد getSystemService() و ارسال آرگومان SENSOR_SERVICE یک نمونه از کلاس SensorManager ایجاد می کنید. به عنوان مثال:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

جاوا

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

در مرحله بعد، می‌توانید با فراخوانی متد getSensorList() و با استفاده از ثابت TYPE_ALL ، فهرستی از هر سنسور روی دستگاه را دریافت کنید. به عنوان مثال:

کاتلین

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

جاوا

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

اگر می‌خواهید همه حسگرهای یک نوع معین را فهرست کنید، می‌توانید به جای TYPE_ALL از یک ثابت دیگر مانند TYPE_GYROSCOPE ، TYPE_LINEAR_ACCELERATION ، یا TYPE_GRAVITY استفاده کنید.

همچنین می‌توانید با استفاده از متد getDefaultSensor() و تعیین نوع خاصی از سنسور برای یک سنسور خاص، تعیین کنید که آیا نوع خاصی از سنسور در دستگاه وجود دارد یا خیر. اگر دستگاهی بیش از یک سنسور از یک نوع خاص داشته باشد، یکی از سنسورها باید به عنوان سنسور پیش فرض تعیین شود. اگر یک حسگر پیش‌فرض برای نوع خاصی از سنسور وجود نداشته باشد، فراخوانی متد null را برمی‌گرداند، به این معنی که دستگاه آن نوع سنسور را ندارد. به عنوان مثال، کد زیر بررسی می کند که آیا مغناطیس سنج روی دستگاه وجود دارد یا خیر:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

توجه: اندروید از سازندگان دستگاه‌ها نمی‌خواهد که انواع خاصی از حسگرها را در دستگاه‌های مجهز به اندروید خود بسازند، بنابراین دستگاه‌ها می‌توانند طیف گسترده‌ای از تنظیمات حسگر را داشته باشند.

علاوه بر فهرست کردن سنسورهایی که روی یک دستگاه هستند، می‌توانید از روش‌های عمومی کلاس Sensor برای تعیین قابلیت‌ها و ویژگی‌های هر سنسور استفاده کنید. اگر می‌خواهید برنامه‌تان بر اساس حسگرها یا قابلیت‌های حسگر موجود در دستگاه، رفتار متفاوتی داشته باشد، مفید است. به عنوان مثال، می توانید از متدهای getResolution() و getMaximumRange() برای به دست آوردن وضوح سنسور و حداکثر محدوده اندازه گیری استفاده کنید. همچنین می توانید از متد getPower() برای به دست آوردن توان مورد نیاز سنسور استفاده کنید.

اگر می‌خواهید کاربرد خود را برای حسگرهای سازنده مختلف یا نسخه‌های مختلف سنسور بهینه کنید، دو روش عمومی به‌خصوص مفید هستند. به عنوان مثال، اگر برنامه شما نیاز به نظارت بر حرکات کاربر مانند شیب و لرزش دارد، می‌توانید مجموعه‌ای از قوانین فیلتر کردن داده‌ها و بهینه‌سازی‌ها را برای دستگاه‌های جدیدتر که دارای حسگر جاذبه فروشنده خاصی هستند، و مجموعه دیگری از قوانین فیلتر کردن داده‌ها و بهینه‌سازی‌ها برای دستگاه‌ها ایجاد کنید. که سنسور جاذبه ندارند و فقط شتاب سنج دارند. نمونه کد زیر به شما نشان می دهد که چگونه می توانید از متدهای getVendor() و getVersion() برای این کار استفاده کنید. در این نمونه، ما به دنبال سنسور گرانشی هستیم که Google LLC را به عنوان فروشنده فهرست می‌کند و شماره نسخه آن 3 است. اگر آن سنسور خاص روی دستگاه وجود ندارد، سعی می‌کنیم از شتاب‌سنج استفاده کنیم.

کاتلین

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

جاوا

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

روش مفید دیگر متد getMinDelay() است که حداقل بازه زمانی (در میکروثانیه) را که حسگر می تواند برای سنجش داده ها استفاده کند، برمی گرداند. هر حسگری که مقدار غیر صفر را برای متد getMinDelay() برمی گرداند، حسگر جریانی است. حسگرهای جریانی داده ها را در فواصل زمانی منظم حس می کنند و در اندروید 2.3 (سطح 9 API) معرفی شدند. اگر یک حسگر با فراخوانی متد 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 تعریف شده است.

کاتلین

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

جاوا

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

در این مثال، تاخیر پیش‌فرض داده ( SENSOR_DELAY_NORMAL ) زمانی که متد registerListener() فراخوانی می‌شود، مشخص می‌شود. تأخیر داده (یا نرخ نمونه‌برداری) بازه‌ای را کنترل می‌کند که در آن رویدادهای حسگر از طریق روش برگشت تماس onSensorChanged() به برنامه شما ارسال می‌شوند. تأخیر پیش‌فرض داده برای نظارت بر تغییرات معمولی جهت صفحه نمایش مناسب است و از تأخیر 200000 میکروثانیه استفاده می‌کند. می‌توانید تأخیرهای داده دیگری مانند SENSOR_DELAY_GAME (تأخیر 20000 میکروثانیه)، SENSOR_DELAY_UI (تأخیر 60000 میکروثانیه)، یا SENSOR_DELAY_FASTEST (تأخیر 0 میکروثانیه) را مشخص کنید. از Android 3.0 (API Level 11) همچنین می توانید تاخیر را به عنوان یک مقدار مطلق (در میکروثانیه) مشخص کنید.

تاخیری که شما مشخص می کنید فقط یک تاخیر پیشنهادی است. سیستم اندروید و سایر برنامه ها می توانند این تاخیر را تغییر دهند. به عنوان بهترین روش، باید بیشترین تاخیری را که می‌توانید مشخص کنید، زیرا سیستم معمولاً از تاخیر کمتری نسبت به آنچه که شما مشخص می‌کنید استفاده می‌کند (یعنی باید پایین‌ترین نرخ نمونه‌گیری را انتخاب کنید که همچنان نیازهای برنامه شما را برآورده می‌کند). استفاده از تاخیر بیشتر، بار کمتری را به پردازنده تحمیل می کند و در نتیجه انرژی کمتری مصرف می کند.

هیچ روش عمومی برای تعیین نرخی که چارچوب حسگر رویدادهای حسگر را به برنامه شما ارسال می کند وجود ندارد. با این حال، می توانید از مهرهای زمانی مرتبط با هر رویداد حسگر برای محاسبه نرخ نمونه برداری در چندین رویداد استفاده کنید. پس از تنظیم، مجبور نیستید نرخ نمونه برداری (تاخیر) را تغییر دهید. اگر به دلایلی نیاز به تغییر تأخیر دارید، باید شنونده حسگر را لغو ثبت و دوباره ثبت کنید.

همچنین مهم است که توجه داشته باشید که این مثال از متدهای برگشتی onResume() و onPause() برای ثبت و لغو ثبت شنونده رویداد سنسور استفاده می کند. به‌عنوان بهترین روش، همیشه باید حسگرهایی را که به آن‌ها نیاز ندارید، غیرفعال کنید، مخصوصاً زمانی که فعالیت شما متوقف شده است. عدم انجام این کار می تواند باتری را تنها در چند ساعت خالی کند زیرا برخی از سنسورها نیاز به انرژی قابل توجهی دارند و می توانند به سرعت باتری را مصرف کنند. هنگامی که صفحه نمایش خاموش می شود، سیستم به طور خودکار سنسورها را غیرفعال نمی کند.

مدیریت تنظیمات مختلف سنسور

اندروید پیکربندی استاندارد حسگر را برای دستگاه‌ها مشخص نمی‌کند، به این معنی که سازندگان دستگاه‌ها می‌توانند هر پیکربندی سنسوری را که می‌خواهند در دستگاه‌های مجهز به اندروید خود بگنجانند. در نتیجه، دستگاه ها می توانند انواع حسگرها را در طیف وسیعی از پیکربندی ها شامل شوند. اگر برنامه شما به نوع خاصی از سنسور متکی است، باید اطمینان حاصل کنید که حسگر در دستگاهی وجود دارد تا برنامه شما بتواند با موفقیت اجرا شود.

شما دو گزینه برای اطمینان از وجود حسگر معین در دستگاه دارید:

  • حسگرها را در زمان اجرا شناسایی کنید و ویژگی های برنامه را در صورت لزوم فعال یا غیرفعال کنید.
  • از فیلترهای Google Play برای هدف قرار دادن دستگاه‌هایی با تنظیمات حسگر خاص استفاده کنید.

هر گزینه در بخش های زیر مورد بحث قرار می گیرد.

تشخیص سنسورها در زمان اجرا

اگر برنامه شما از نوع خاصی از سنسور استفاده می کند، اما به آن متکی نیست، می توانید از چارچوب حسگر برای شناسایی حسگر در زمان اجرا استفاده کنید و سپس ویژگی های برنامه را در صورت لزوم غیرفعال یا فعال کنید. به عنوان مثال، یک برنامه ناوبری ممکن است از سنسور دما، سنسور فشار، سنسور GPS و حسگر میدان مغناطیسی برای نمایش دما، فشار هوا، مکان و یاتاقان قطب نما استفاده کند. اگر دستگاهی سنسور فشار ندارد، می توانید از چارچوب حسگر برای تشخیص عدم وجود سنسور فشار در زمان اجرا استفاده کنید و سپس بخشی از رابط کاربری برنامه خود را که فشار را نشان می دهد غیرفعال کنید. به عنوان مثال، کد زیر بررسی می کند که آیا سنسور فشار روی دستگاه وجود دارد یا خیر:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

استفاده از فیلترهای Google Play برای هدف قرار دادن تنظیمات حسگر خاص

اگر برنامه خود را در Google Play منتشر می کنید، می توانید از عنصر <uses-feature> در فایل مانیفست خود استفاده کنید تا برنامه خود را از دستگاه هایی که پیکربندی حسگر مناسب برای برنامه شما ندارند فیلتر کنید. عنصر <uses-feature> دارای چندین توصیفگر سخت افزاری است که به شما امکان می دهد برنامه ها را بر اساس وجود حسگرهای خاص فیلتر کنید. حسگرهایی که می توانید فهرست کنید عبارتند از: شتاب سنج، فشارسنج، قطب نما (میدان ژئومغناطیسی)، ژیروسکوپ، نور و مجاورت. در زیر نمونه ای از ورودی مانیفست است که برنامه هایی را که شتاب سنج ندارند فیلتر می کند:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

اگر این عنصر و توصیفگر را به مانیفست برنامه خود اضافه کنید، کاربران تنها در صورتی برنامه شما را در Google Play خواهند دید که دستگاه آنها شتاب سنج داشته باشد.

شما باید توصیفگر را روی android:required="true" تنظیم کنید فقط در صورتی که برنامه شما کاملاً به یک سنسور خاص متکی باشد. اگر برنامه شما از سنسور برای برخی عملکردها استفاده می کند، اما همچنان بدون حسگر اجرا می شود، باید حسگر را در عنصر <uses-feature> فهرست کنید، اما توصیفگر را روی android:required="false" تنظیم کنید. این کمک می کند تا مطمئن شوید که دستگاه ها می توانند برنامه شما را نصب کنند حتی اگر آن سنسور خاص را نداشته باشند. این نیز بهترین روش مدیریت پروژه است که به شما کمک می‌کند ویژگی‌هایی را که برنامه‌تان استفاده می‌کند پیگیری کنید. به خاطر داشته باشید، اگر برنامه شما از سنسور خاصی استفاده می‌کند، اما همچنان بدون سنسور اجرا می‌شود، باید حسگر را در زمان اجرا شناسایی کرده و ویژگی‌های برنامه را در صورت لزوم غیرفعال یا فعال کنید.

سیستم مختصات سنسور

به طور کلی، چارچوب حسگر از یک سیستم مختصات استاندارد 3 محوری برای بیان مقادیر داده استفاده می کند. برای اکثر سنسورها، سیستم مختصات نسبت به صفحه نمایش دستگاه تعریف می شود، زمانی که دستگاه در جهت پیش فرض خود نگه داشته شود (شکل 1 را ببینید). هنگامی که یک دستگاه در جهت پیش فرض خود نگه داشته می شود، محور X افقی است و به سمت راست اشاره می کند، محور Y عمودی است و به سمت بالا می رود، و محور Z به سمت خارج از صفحه نمایشگر قرار می گیرد. در این سیستم مختصات پشت صفحه دارای مقادیر Z منفی هستند. این سیستم مختصات توسط سنسورهای زیر استفاده می شود:

شکل 1. سیستم مختصات (نسبت به یک دستگاه) که توسط Sensor API استفاده می شود.

مهمترین نکته ای که باید در مورد این سیستم مختصات فهمید این است که وقتی جهت صفحه دستگاه تغییر می کند، محورها عوض نمی شوند - یعنی سیستم مختصات سنسور هرگز با حرکت دستگاه تغییر نمی کند. این رفتار همانند رفتار سیستم مختصات OpenGL است.

نکته دیگری که باید درک کنید این است که برنامه شما نباید جهت گیری طبیعی (پیش‌فرض) دستگاه را عمودی فرض کند. جهت گیری طبیعی بسیاری از دستگاه های تبلت منظره است. و سیستم مختصات حسگر همیشه بر اساس جهت گیری طبیعی یک دستگاه است.

در نهایت، اگر برنامه شما داده‌های حسگر را با نمایشگر روی صفحه مطابقت دهد، باید از متد getRotation() برای تعیین چرخش صفحه استفاده کنید و سپس از روش remapCoordinateSystem() برای ترسیم مختصات حسگر به مختصات صفحه استفاده کنید. باید این کار را انجام دهید حتی اگر مانیفست شما فقط نمایشگر پرتره را مشخص کند.

توجه: برخی از سنسورها و روش ها از سیستم مختصاتی استفاده می کنند که نسبت به چارچوب مرجع جهان (بر خلاف چارچوب مرجع دستگاه) است. این حسگرها و روش‌ها داده‌هایی را برمی‌گردانند که حرکت دستگاه یا موقعیت دستگاه را نسبت به زمین نشان می‌دهند. برای اطلاعات بیشتر، متد getOrientation() ، متد getRotationMatrix() ، سنسور جهت گیری و سنسور بردار چرخش را ببینید.

محدودیت سنسور

برای محافظت از اطلاعات بالقوه حساس در مورد کاربران، اگر برنامه شما Android 12 (سطح API 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 (سطح API 28) یا بالاتر، برنامه‌هایی که در پس‌زمینه اجرا می‌شوند دارای محدودیت‌های زیر هستند:

  • حسگرهایی که از حالت گزارش مداوم استفاده می کنند، مانند شتاب سنج و ژیروسکوپ، رویدادها را دریافت نمی کنند.
  • حسگرهایی که از حالت‌های گزارش لحظه‌ای یا یک‌شات استفاده می‌کنند، رویدادها را دریافت نمی‌کنند.

با توجه به این محدودیت‌ها، بهتر است رویدادهای حسگر را زمانی که برنامه شما در پیش‌زمینه است یا به عنوان بخشی از خدمات پیش‌زمینه شناسایی کنید.

لغو ثبت شنوندگان حسگر

پس از اتمام کار با سنسور یا زمانی که فعالیت حسگر متوقف می شود، مطمئن شوید که شنونده حسگر را لغو ثبت کنید. اگر شنونده حسگر ثبت شود و فعالیت آن متوقف شود، حسگر به دریافت داده ها و استفاده از منابع باتری ادامه می دهد، مگر اینکه سنسور را لغو ثبت کنید. کد زیر نحوه استفاده از متد onPause() برای لغو ثبت یک شنونده را نشان می دهد:

کاتلین

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

جاوا

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

برای اطلاعات بیشتر، به unregisterListener(SensorEventListener) مراجعه کنید.

با شبیه ساز اندروید تست کنید

شبیه ساز اندروید شامل مجموعه ای از کنترل های حسگر مجازی است که به شما امکان می دهد حسگرهایی مانند شتاب سنج، دمای محیط، مغناطیس سنج، مجاورت، نور و غیره را آزمایش کنید.

شبیه ساز از اتصال با دستگاه اندرویدی استفاده می کند که برنامه SdkControllerSensor را اجرا می کند. توجه داشته باشید که این برنامه فقط در دستگاه‌های دارای Android نسخه 4.0 (سطح API 14) یا بالاتر در دسترس است. (اگر دستگاه دارای اندروید 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 در دستگاه‌هایی که Android نسخه 4.0 دارند استفاده کنید.

قبل از استفاده از سنسورها را بررسی کنید

همیشه قبل از اینکه بخواهید اطلاعاتی از دستگاه دریافت کنید، وجود حسگر را در دستگاه بررسی کنید. تصور نکنید که یک سنسور صرفاً به این دلیل وجود دارد که یک سنسور پرکاربرد است. سازندگان دستگاه ملزم به ارائه سنسور خاصی در دستگاه خود نیستند.

تأخیرهای حسگر را با دقت انتخاب کنید

هنگامی که یک سنسور را با متد registerListener() ثبت می‌کنید، مطمئن شوید که نرخ تحویلی را انتخاب می‌کنید که برای برنامه یا مورد شما مناسب است. سنسورها می‌توانند داده‌ها را با نرخ بسیار بالا ارائه دهند. اجازه دادن به سیستم برای ارسال داده های اضافی که به آنها نیاز ندارید، منابع سیستم را هدر می دهد و از باتری استفاده می کند.

،

اکثر دستگاه‌های مجهز به اندروید دارای حسگرهای داخلی هستند که حرکت، جهت‌گیری و شرایط محیطی مختلف را اندازه‌گیری می‌کنند. این سنسورها قادر به ارائه داده های خام با دقت و صحت بالا هستند و اگر می خواهید حرکت سه بعدی دستگاه یا موقعیت یابی را نظارت کنید یا می خواهید تغییرات محیط اطراف نزدیک دستگاه را نظارت کنید مفید هستند. برای مثال، یک بازی ممکن است خوانش‌های حسگر گرانش دستگاه را برای استنباط حرکات و حرکات پیچیده کاربر، مانند شیب، لرزش، چرخش یا چرخش، ردیابی کند. به همین ترتیب، یک برنامه آب و هوا ممکن است از حسگر دما و سنسور رطوبت دستگاه برای محاسبه و گزارش نقطه شبنم استفاده کند، یا یک برنامه سفر ممکن است از حسگر میدان ژئومغناطیسی و شتاب‌سنج برای گزارش یک قطب نما استفاده کند.

پلتفرم اندروید از سه دسته وسیع از سنسورها پشتیبانی می کند:

  • سنسورهای حرکت

    این سنسورها نیروهای شتاب و نیروهای دورانی را در سه محور اندازه گیری می کنند. این دسته شامل شتاب‌سنج‌ها، حسگرهای جاذبه، ژیروسکوپ‌ها و حسگرهای بردار چرخشی است.

  • سنسورهای محیطی

    این سنسورها پارامترهای مختلف محیطی مانند دما و فشار هوای محیط، روشنایی و رطوبت را اندازه گیری می کنند. این دسته شامل فشارسنج ها، نورسنج ها و دماسنج ها می شود.

  • سنسورهای موقعیت

    این حسگرها موقعیت فیزیکی دستگاه را اندازه گیری می کنند. این دسته شامل سنسورهای جهت یابی و مغناطیس سنج ها می شود.

با استفاده از چارچوب حسگر Android می‌توانید به حسگرهای موجود در دستگاه دسترسی داشته باشید و داده‌های خام حسگر را بدست آورید. چارچوب حسگر چندین کلاس و رابط ارائه می دهد که به شما کمک می کند تا طیف گسترده ای از وظایف مرتبط با حسگر را انجام دهید. به عنوان مثال، می توانید از چارچوب سنسور برای انجام کارهای زیر استفاده کنید:

  • تعیین کنید که کدام حسگرها در دستگاه موجود هستند.
  • قابلیت‌های هر حسگر، مانند حداکثر برد، سازنده، توان مورد نیاز و وضوح آن را تعیین کنید.
  • داده های خام حسگر را به دست آورید و حداقل نرخی را که در آن داده های حسگر را به دست می آورید، تعریف کنید.
  • شنوندگان رویداد حسگر را که تغییرات حسگر را نظارت می کنند، ثبت و لغو ثبت کنید.

این مبحث نمای کلی از سنسورهای موجود در پلتفرم اندروید را ارائه می دهد. همچنین مقدمه ای بر چارچوب حسگر ارائه می دهد.

مقدمه ای بر حسگرها

چارچوب حسگر اندروید به شما امکان می دهد به انواع مختلفی از سنسورها دسترسی داشته باشید. برخی از این حسگرها مبتنی بر سخت افزار و برخی دیگر مبتنی بر نرم افزار هستند. حسگرهای مبتنی بر سخت افزار اجزای فیزیکی هستند که در یک گوشی یا تبلت تعبیه شده اند. آنها داده های خود را با اندازه گیری مستقیم ویژگی های محیطی خاص، مانند شتاب، قدرت میدان ژئومغناطیسی یا تغییر زاویه ای به دست می آورند. حسگرهای مبتنی بر نرم‌افزار دستگاه‌های فیزیکی نیستند، اگرچه حسگرهای مبتنی بر سخت‌افزار را تقلید می‌کنند. حسگرهای مبتنی بر نرم‌افزار داده‌های خود را از یک یا چند حسگر مبتنی بر سخت‌افزار استخراج می‌کنند و گاهی اوقات حسگرهای مجازی یا سنسورهای مصنوعی نامیده می‌شوند. سنسور شتاب خطی و سنسور گرانش نمونه هایی از حسگرهای مبتنی بر نرم افزار هستند. جدول 1 خلاصه ای از حسگرهایی است که توسط پلتفرم اندروید پشتیبانی می شوند.

تعداد کمی از دستگاه های مجهز به اندروید دارای هر نوع سنسور هستند. به عنوان مثال، اکثر دستگاه‌ها و تبلت‌های گوشی دارای شتاب‌سنج و مغناطیس‌سنج هستند، اما دستگاه‌های کمتری دارای فشارسنج یا دماسنج هستند. همچنین، یک دستگاه می تواند بیش از یک سنسور از یک نوع خاص داشته باشد. به عنوان مثال، یک دستگاه می تواند دو حسگر گرانش داشته باشد که هر کدام محدوده متفاوتی دارند.

جدول 1. انواع حسگرهای پشتیبانی شده توسط پلتفرم اندروید.

سنسور تایپ کنید توضیحات کاربردهای رایج
TYPE_ACCELEROMETER سخت افزار نیروی شتاب را بر حسب m/s 2 که روی هر سه محور فیزیکی (x، y، و z) به یک دستگاه اعمال می‌شود، از جمله نیروی گرانش اندازه‌گیری می‌کند. تشخیص حرکت (لرزش، شیب و غیره).
TYPE_AMBIENT_TEMPERATURE سخت افزار دمای محیط را بر حسب درجه سانتیگراد (درجه سانتیگراد) اندازه گیری می کند. به یادداشت زیر مراجعه کنید. نظارت بر دمای هوا
TYPE_GRAVITY نرم افزار یا سخت افزار نیروی گرانش را بر حسب m/s 2 اندازه گیری می کند که بر روی هر سه محور فیزیکی (x، y، z) به یک دستگاه اعمال می شود. تشخیص حرکت (لرزش، شیب و غیره).
TYPE_GYROSCOPE سخت افزار سرعت چرخش دستگاه را بر حسب راد بر ثانیه حول هر یک از سه محور فیزیکی (x، y، و z) اندازه گیری می کند. تشخیص چرخش (چرخش، چرخش و غیره).
TYPE_LIGHT سخت افزار سطح نور محیط (روشنایی) را بر حسب lx اندازه گیری می کند. کنترل روشنایی صفحه نمایش
TYPE_LINEAR_ACCELERATION نرم افزار یا سخت افزار نیروی شتاب را بر حسب m/s 2 اندازه گیری می کند که به یک دستگاه در هر سه محور فیزیکی (x، y، و z)، بدون احتساب نیروی گرانش، اعمال می شود. نظارت بر شتاب در امتداد یک محور.
TYPE_MAGNETIC_FIELD سخت افزار میدان ژئومغناطیسی محیط را برای هر سه محور فیزیکی (x ، y ، z) در μT اندازه گیری می کند. ایجاد قطب نما
TYPE_ORIENTATION نرم افزار درجه های چرخش را که یک دستگاه در حدود هر سه محور فیزیکی (x ، y ، z) ایجاد می کند ، اندازه گیری می کند. از API سطح 3 می توانید با استفاده از سنسور گرانش و سنسور میدان ژئومغناطیسی در رابطه با روش getRotationMatrix() ماتریس تمایل و ماتریس چرخش را برای یک دستگاه بدست آورید. تعیین موقعیت دستگاه
TYPE_PRESSURE سخت افزار فشار هوای محیط را در HPA یا MBAR اندازه گیری می کند. نظارت بر تغییرات فشار هوا.
TYPE_PROXIMITY سخت افزار نزدیکی یک شیء در CM نسبت به صفحه نمایش یک دستگاه را اندازه گیری می کند. این سنسور به طور معمول برای تعیین اینکه آیا یک گوشی تا گوش شخص نگه داشته می شود ، استفاده می شود. موقعیت تلفن در حین تماس
TYPE_RELATIVE_HUMIDITY سخت افزار رطوبت نسبی محیط را در درصد (٪) اندازه گیری می کند. نظارت بر نقطه شبنم ، رطوبت مطلق و نسبی.
TYPE_ROTATION_VECTOR نرم افزار یا سخت افزار جهت گیری یک دستگاه را با ارائه سه عنصر بردار چرخش دستگاه اندازه گیری می کند. تشخیص حرکت و تشخیص چرخش.
TYPE_TEMPERATURE سخت افزار دمای دستگاه را در درجه سانتیگراد (درجه سانتیگراد) اندازه گیری می کند. این اجرای سنسور در بین دستگاه ها متفاوت است و این سنسور با سنسور TYPE_AMBIENT_TEMPERATURE در سطح API 14 جایگزین شد نظارت بر دما.

چارچوب سنسور

شما می توانید به این سنسورها دسترسی پیدا کرده و با استفاده از چارچوب سنسور Android ، داده های حسگر خام را بدست آورید. چارچوب سنسور بخشی از بسته android.hardware است و کلاس ها و رابط های زیر را شامل می شود:

SensorManager
می توانید از این کلاس برای ایجاد نمونه ای از سرویس سنسور استفاده کنید. این کلاس روشهای مختلفی را برای دسترسی و لیست سنسورها ، ثبت نام و ثبت نام شنوندگان رویداد سنسور و دستیابی به اطلاعات جهت گیری فراهم می کند. این کلاس همچنین چندین ثابت سنسور را ارائه می دهد که برای گزارش دقت سنسور ، تعیین میزان دستیابی به داده ها و سنسورهای کالیبراسیون استفاده می شود.
Sensor
می توانید از این کلاس برای ایجاد نمونه ای از یک سنسور خاص استفاده کنید. این کلاس روشهای مختلفی را ارائه می دهد که به شما امکان می دهد قابلیت های یک سنسور را تعیین کنید.
SensorEvent
این سیستم از این کلاس برای ایجاد یک شیء رویداد سنسور استفاده می کند ، که اطلاعات مربوط به یک رویداد سنسور را ارائه می دهد. یک شیء رویداد سنسور شامل اطلاعات زیر است: داده های سنسور خام ، نوع سنسوری که باعث ایجاد رویداد ، صحت داده ها و زمان بندی برای این رویداد می شود.
SensorEventListener
شما می توانید از این رابط برای ایجاد دو روش پاسخ به تماس استفاده کنید که هنگام تغییر مقادیر سنسور یا هنگام تغییر دقت سنسور ، اعلان ها (حوادث سنسور) دریافت می کنند.

در یک برنامه معمولی از این API های مرتبط با سنسور برای انجام دو کار اساسی استفاده می کنید:

  • شناسایی سنسورها و قابلیت های سنسور

    شناسایی سنسورها و قابلیت های سنسور در زمان اجرا مفید است اگر برنامه شما دارای ویژگی هایی است که به انواع یا قابلیت های سنسور خاص متکی است. به عنوان مثال ، شما ممکن است بخواهید تمام سنسورهای موجود در یک دستگاه را شناسایی کرده و از ویژگی های کاربردی که به سنسورهای موجود متکی هستند ، غیرفعال کنید. به همین ترتیب ، ممکن است بخواهید تمام سنسورهای یک نوع معین را شناسایی کنید تا بتوانید اجرای سنسور را انتخاب کنید که عملکرد بهینه برای برنامه شما داشته باشد.

  • نظارت بر وقایع سنسور

    نظارت بر وقایع سنسور نحوه دستیابی به داده های سنسور خام است. یک رویداد سنسور هر بار که یک سنسور تغییر در پارامترهای اندازه گیری شده را تشخیص می دهد ، رخ می دهد. یک رویداد سنسور چهار قطعه اطلاعات را در اختیار شما قرار می دهد: نام سنسور که باعث ایجاد این رویداد ، زمان بندی برای رویداد ، صحت این رویداد و داده های حسگر خام که باعث ایجاد این رویداد شده است.

در دسترس بودن سنسور

در حالی که در دسترس بودن سنسور از دستگاه به دستگاه دیگر متفاوت است ، می تواند بین نسخه های اندرویدی نیز متفاوت باشد. این امر به این دلیل است که سنسورهای اندرویدی در طول چندین نسخه پلت فرم معرفی شده اند. به عنوان مثال ، بسیاری از سنسورها در Android 1.5 (API سطح 3) معرفی شدند ، اما برخی از آنها اجرا نشده و تا زمان Android 2.3 (سطح API 9) در دسترس نبودند. به همین ترتیب ، چندین سنسور در Android 2.3 (API سطح 9) و Android 4.0 (سطح API 14) معرفی شد. دو سنسور با سنسورهای جدیدتر و بهتر جایگزین شده و جایگزین شده اند.

جدول 2 در دسترس بودن هر سنسور بر اساس پلتفرم به پلتفرم است. فقط چهار سیستم عامل ذکر شده است زیرا این سیستم عامل هایی هستند که تغییرات سنسور را درگیر می کنند. سنسورهایی که به عنوان مستهلک ذکر شده اند ، هنوز در سیستم عامل های بعدی موجود هستند (به شرط آنکه سنسور در یک دستگاه موجود باشد) ، که مطابق با خط مشی سازگاری پیش رو اندروید است.

جدول 2. در دسترس بودن سنسور توسط سیستم عامل.

سنسور اندروید 4.0
(سطح 14 API)
Android 2.3
(API سطح 9)
Android 2.2
(API سطح 8)
Android 1.5
(API سطح 3)
TYPE_ACCELEROMETER بله بله بله بله
TYPE_AMBIENT_TEMPERATURE بله n/a n/a n/a
TYPE_GRAVITY بله بله n/a n/a
TYPE_GYROSCOPE بله بله n/a 1 n/a 1
TYPE_LIGHT بله بله بله بله
TYPE_LINEAR_ACCELERATION بله بله n/a n/a
TYPE_MAGNETIC_FIELD بله بله بله بله
TYPE_ORIENTATION بله 2 بله 2 بله 2 بله
TYPE_PRESSURE بله بله n/a 1 n/a 1
TYPE_PROXIMITY بله بله بله بله
TYPE_RELATIVE_HUMIDITY بله n/a n/a n/a
TYPE_ROTATION_VECTOR بله بله n/a n/a
TYPE_TEMPERATURE بله 2 بله بله بله

1 این نوع سنسور در Android 1.5 (API سطح 3) اضافه شد ، اما تا زمان Android 2.3 (سطح API 9) برای استفاده در دسترس نبود.

2 این سنسور در دسترس است ، اما کاهش یافته است.

شناسایی سنسورها و قابلیت های سنسور

چارچوب سنسور Android روش های مختلفی را ارائه می دهد که تعیین در زمان اجرا را برای شما آسان می کند که سنسورها در یک دستگاه هستند. API همچنین روش هایی را ارائه می دهد که به شما امکان می دهد قابلیت های هر سنسور را تعیین کنید ، مانند حداکثر دامنه آن ، وضوح آن و نیازهای قدرت آن.

برای شناسایی سنسورهای موجود در دستگاهی که ابتدا باید به سرویس سنسور مراجعه کنید. برای انجام این کار ، شما با فراخوانی روش getSystemService() و عبور در استدلال SENSOR_SERVICE ، نمونه ای از کلاس SensorManager را ایجاد می کنید. به عنوان مثال:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

جاوا

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

در مرحله بعد ، می توانید با فراخوانی روش getSensorList() و با استفاده از ثابت TYPE_ALL ، لیستی از هر سنسور را در دستگاه دریافت کنید. به عنوان مثال:

کاتلین

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

جاوا

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

اگر می خواهید تمام سنسورهای یک نوع معین را لیست کنید ، می توانید به جای TYPE_ALL مانند TYPE_GYROSCOPE ، TYPE_LINEAR_ACCELERATION یا TYPE_GRAVITY از ثابت دیگری استفاده کنید.

همچنین می توانید با استفاده از روش getDefaultSensor() و عبور از نوع ثابت برای یک سنسور خاص ، تعیین کنید که آیا نوع خاصی از سنسور در دستگاه وجود دارد. اگر دستگاه بیش از یک سنسور از یک نوع معین داشته باشد ، یکی از سنسورها باید به عنوان سنسور پیش فرض تعیین شود. اگر یک سنسور پیش فرض برای یک نوع سنسور معین وجود نداشته باشد ، روش تماس با روش بازگشت تهی می کند ، به این معنی که دستگاه آن نوع سنسور را ندارد. به عنوان مثال ، کد زیر بررسی می کند که آیا یک مغناطیس سنج در یک دستگاه وجود دارد:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

توجه: Android نیازی به تولید کنندگان دستگاه ندارد تا انواع خاصی از سنسورها را در دستگاه های اندرویدی خود بسازند ، بنابراین دستگاه ها می توانند طیف گسترده ای از تنظیمات سنسور را داشته باشند.

علاوه بر لیست سنسورهایی که در یک دستگاه قرار دارند ، می توانید از روشهای عمومی کلاس Sensor برای تعیین قابلیت ها و ویژگی های سنسورهای فردی استفاده کنید. این امر مفید است اگر می خواهید برنامه شما بر اساس اینکه سنسورها یا قابلیت سنسور در یک دستگاه در دسترس هستند ، متفاوت رفتار کند. به عنوان مثال ، می توانید از روشهای getResolution() و getMaximumRange() برای به دست آوردن وضوح سنسور و حداکثر دامنه اندازه گیری استفاده کنید. همچنین می توانید از روش getPower() برای به دست آوردن نیازهای قدرت سنسور استفاده کنید.

اگر می خواهید برنامه خود را برای سنسورهای مختلف تولید کننده یا نسخه های مختلف یک سنسور بهینه کنید ، دو روش عمومی به ویژه مفید هستند. به عنوان مثال ، اگر برنامه شما نیاز به نظارت بر حرکات کاربر مانند شیب و لرزش دارد ، می توانید یک مجموعه از قوانین فیلتر کردن داده ها و بهینه سازی برای دستگاه های جدیدتر که دارای سنسور گرانش فروشنده خاص هستند ، و مجموعه دیگری از قوانین فیلتر کردن داده ها و بهینه سازی برای دستگاه ها ایجاد کنید. که سنسور گرانشی ندارند و فقط شتاب سنج دارند. نمونه کد زیر به شما نشان می دهد که چگونه می توانید از روش های getVendor() و getVersion() برای انجام این کار استفاده کنید. در این نمونه ، ما به دنبال یک سنسور گرانش هستیم که Google LLC را به عنوان فروشنده لیست می کند و دارای شماره نسخه 3 است. اگر این سنسور خاص در دستگاه موجود نباشد ، سعی می کنیم از شتاب سنج استفاده کنیم.

کاتلین

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

جاوا

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

روش مفید دیگر روش getMinDelay() است که حداقل فاصله زمانی (در میکرو ثانیه) را برمی گرداند که یک سنسور می تواند برای حس کردن داده ها استفاده کند. هر سنسوری که مقدار غیر صفر را برای روش getMinDelay() برگرداند ، یک سنسور جریان است. سنسورهای جریان داده ها را در فواصل منظم حس می کنند و در Android 2.3 (سطح API 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 تعریف شده است ، نشان می دهد.

کاتلین

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

جاوا

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

در این مثال ، تأخیر داده پیش فرض ( SENSOR_DELAY_NORMAL ) با استفاده از روش registerListener() مشخص می شود. تأخیر داده (یا میزان نمونه برداری) فاصله ای را کنترل می کند که در آن رویدادهای سنسور از طریق روش پاسخ به تماس onSensorChanged() به برنامه شما ارسال می شود. تأخیر پیش فرض داده برای نظارت بر تغییرات معمولی در جهت گیری صفحه مناسب است و از تأخیر 200000 میکرو ثانیه استفاده می کند. می توانید تأخیر داده های دیگر مانند SENSOR_DELAY_GAME (20،000 تأخیر میکرو ثانیه) ، SENSOR_DELAY_UI (60،000 تأخیر میکرو ثانیه) یا SENSOR_DELAY_FASTEST (0 تأخیر میکرو ثانیه) را مشخص کنید. از Android 3.0 (API سطح 11) همچنین می توانید تأخیر را به عنوان یک مقدار مطلق (در میکرو ثانیه) مشخص کنید.

تأخیر که شما مشخص می کنید فقط یک تأخیر پیشنهادی است. سیستم Android و سایر برنامه ها می توانند این تأخیر را تغییر دهند. به عنوان بهترین روش ، شما باید بزرگترین تأخیر را که می توانید مشخص کنید زیرا سیستم به طور معمول از تأخیر کوچکتر از آنچه که مشخص می کنید استفاده می کند (یعنی ، باید کمترین نرخ نمونه برداری را انتخاب کنید که هنوز هم نیازهای برنامه شما را برآورده می کند). استفاده از یک تأخیر بزرگتر بار کمتری را به پردازنده وارد می کند و بنابراین از قدرت کمتری استفاده می کند.

هیچ روش عمومی برای تعیین میزان ارسال چارچوب سنسور ارسال رویدادهای سنسور به برنامه شما وجود ندارد. با این حال ، شما می توانید از زمانی استفاده کنید که با هر رویداد سنسور در ارتباط هستند تا میزان نمونه برداری را در چندین رویداد محاسبه کنید. پس از تنظیم ، نیازی به تغییر نرخ نمونه برداری (تأخیر) نیست. اگر به دلایلی نیاز به تغییر تأخیر دارید ، باید شنونده سنسور را مجدداً ثبت و مجدداً ثبت نام کنید.

همچنین توجه به این نکته حائز اهمیت است که این مثال از روشهای پاسخ به تماس onResume() و onPause() برای ثبت نام و ثبت نام شنونده رویداد سنسور استفاده می کند. به عنوان بهترین عمل ، شما همیشه باید سنسورهایی را که به آن احتیاج ندارید غیرفعال کنید ، به خصوص هنگامی که فعالیت شما متوقف می شود. عدم انجام این کار می تواند باتری را فقط در چند ساعت تخلیه کند زیرا برخی از سنسورها نیاز به انرژی قابل توجهی دارند و می توانند به سرعت از باتری استفاده کنند. هنگام خاموش شدن صفحه ، این سیستم به طور خودکار سنسورها را غیرفعال نمی کند.

رسیدگی به تنظیمات سنسور مختلف

Android پیکربندی سنسور استاندارد را برای دستگاه ها مشخص نمی کند ، به این معنی که تولید کنندگان دستگاه می توانند هر پیکربندی سنسوری را که می خواهند در دستگاه های اندرویدی خود داشته باشند ، درج کنند. در نتیجه ، دستگاه ها می توانند انواع سنسورها را در طیف گسترده ای از تنظیمات شامل شوند. اگر برنامه شما به نوع خاصی از سنسور متکی است ، باید اطمینان حاصل کنید که سنسور در یک دستگاه وجود دارد تا برنامه شما بتواند با موفقیت اجرا شود.

شما دو گزینه برای اطمینان از حضور یک سنسور معین در یک دستگاه دارید:

  • سنسورها را در زمان اجرا تشخیص داده و ویژگی های برنامه را در صورت لزوم فعال یا غیرفعال کنید.
  • از فیلترهای Google Play برای هدف قرار دادن دستگاه ها با تنظیمات سنسور خاص استفاده کنید.

هر گزینه در بخش های زیر مورد بحث قرار می گیرد.

تشخیص سنسورها در زمان اجرا

اگر برنامه شما از نوع خاصی از سنسور استفاده می کند ، اما به آن اعتماد نمی کند ، می توانید از چارچوب سنسور برای تشخیص سنسور در زمان اجرا استفاده کنید و سپس ویژگی های برنامه را در صورت لزوم غیرفعال یا فعال کنید. به عنوان مثال ، یک برنامه ناوبری ممکن است از سنسور دما ، سنسور فشار ، سنسور GPS و سنسور میدان ژئومغناطیسی برای نمایش دما ، فشار فشارسنج ، محل و یاتاقان قطب نما استفاده کند. اگر یک دستگاه سنسور فشار ندارد ، می توانید از چارچوب سنسور برای تشخیص عدم وجود سنسور فشار در زمان اجرا استفاده کنید و سپس بخشی از UI برنامه خود را که فشار را نشان می دهد غیرفعال کنید. به عنوان مثال ، کد زیر بررسی می کند که آیا سنسور فشار در دستگاه وجود دارد:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

استفاده از فیلترهای Google Play برای هدف قرار دادن تنظیمات سنسور خاص

اگر برنامه خود را در Google Play منتشر می کنید می توانید از عنصر <uses-feature> در پرونده مانیفست خود استفاده کنید تا برنامه خود را از دستگاه هایی که پیکربندی سنسور مناسب برای برنامه شما ندارند ، فیلتر کنید. عنصر <uses-feature> دارای چندین توصیف سخت افزار است که به شما امکان می دهد برنامه ها را بر اساس وجود سنسورهای خاص فیلتر کنید. سنسورهایی که می توانید لیست کنید عبارتند از: شتاب سنج ، فشارسنج ، قطب نما (میدان ژئومغناطیسی) ، ژیروسکوپ ، نور و مجاورت. موارد زیر به عنوان مثال آشکار است که برنامه هایی را که شتاب سنج ندارند ، فیلتر می کنند:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

اگر این عنصر و توصیف کننده را به مانیفست برنامه خود اضافه کنید ، کاربران برنامه شما را در Google Play تنها در صورتی که دستگاه آنها دارای شتاب سنج باشد ، مشاهده می کنند.

شما باید توصیف کننده را بر روی android:required="true" فقط در صورتی که برنامه شما کاملاً به یک سنسور خاص متکی باشد. اگر برنامه شما برای برخی از عملکردها از یک سنسور استفاده می کند ، اما هنوز هم بدون سنسور اجرا می شود ، باید سنسور را در عنصر <uses-feature> لیست کنید ، اما توصیف کننده را روی android:required="false" . این کمک می کند تا دستگاه ها بتوانند برنامه شما را نصب کنند حتی اگر آن سنسور خاص را نداشته باشند. این همچنین بهترین روش مدیریت پروژه است که به شما کمک می کند تا ویژگی هایی را که برنامه شما استفاده می کند ، پیگیری کنید. به خاطر داشته باشید ، اگر برنامه شما از یک سنسور خاص استفاده می کند ، اما هنوز هم بدون سنسور اجرا می شود ، باید سنسور را در زمان اجرا تشخیص دهید و ویژگی های برنامه را در صورت لزوم غیرفعال یا فعال کنید.

سیستم مختصات سنسور

به طور کلی ، چارچوب سنسور از یک سیستم مختصات استاندارد 3 محور برای بیان مقادیر داده استفاده می کند. برای اکثر سنسورها ، سیستم مختصات نسبت به صفحه نمایش دستگاه هنگام نگه داشتن دستگاه در جهت پیش فرض خود تعریف می شود (شکل 1 را ببینید). هنگامی که یک دستگاه در جهت پیش فرض خود نگه داشته می شود ، محور X افقی است و به سمت راست اشاره می کند ، محور Y عمودی است و به سمت بالا می رود و محور Z به سمت قسمت بیرونی صفحه نشان می دهد. در این سیستم ، مختصات پشت صفحه دارای مقادیر Z منفی هستند. این سیستم مختصات توسط سنسورهای زیر استفاده می شود:

شکل 1. سیستم مختصات (نسبت به دستگاه) که توسط API سنسور استفاده می شود.

مهمترین نکته برای درک این سیستم مختصات این است که محورها هنگام تغییر جهت گیری صفحه دستگاه تغییر نمی کنند - یعنی سیستم مختصات سنسور هرگز با حرکت دستگاه تغییر نمی کند. این رفتار همان رفتار سیستم مختصات OpenGL است.

نکته دیگر برای درک این است که برنامه شما نباید فرض کند که جهت گیری طبیعی (پیش فرض) یک دستگاه پرتره است. جهت گیری طبیعی برای بسیاری از دستگاه های لوح چشم انداز است. و سیستم مختصات سنسور همیشه مبتنی بر جهت گیری طبیعی یک دستگاه است.

سرانجام ، اگر برنامه شما با داده های سنسور با صفحه نمایش روی صفحه مطابقت دارد ، برای تعیین چرخش صفحه باید از روش getRotation() استفاده کنید و سپس از روش remapCoordinateSystem() برای نقشه برداری مختصات سنسور برای هماهنگی های صفحه استفاده کنید. شما باید این کار را انجام دهید حتی اگر مانیفست شما نمایشگر فقط پرتره را مشخص کند.

توجه: برخی از سنسورها و روشها از یک سیستم مختصات استفاده می کنند که نسبت به قاب مرجع جهان (بر خلاف قاب مرجع دستگاه) باشد. این سنسورها و روشها داده هایی را نشان می دهند که نشان دهنده حرکت دستگاه یا موقعیت دستگاه نسبت به زمین است. برای اطلاعات بیشتر ، به روش getOrientation() ، روش getRotationMatrix() ، سنسور جهت گیری و سنسور بردار چرخش مراجعه کنید.

محدود کننده نرخ سنسور

برای محافظت از اطلاعات حساس بالقوه در مورد کاربران ، اگر برنامه شما Android 12 (API سطح 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 (API سطح 28) یا بالاتر دارند ، برنامه هایی که در پس زمینه اجرا می شوند محدودیت های زیر را دارند:

  • سنسورهایی که از حالت گزارش مداوم استفاده می کنند ، مانند شتاب سنج و ژیروسکوپ ها ، رویدادهایی دریافت نمی کنند.
  • سنسورهایی که از حالت های گزارش دهی یا یک شات استفاده می کنند ، رویدادهایی دریافت نمی کنند.

با توجه به این محدودیت ها ، بهتر است وقتی برنامه شما در پیش زمینه یا به عنوان بخشی از یک سرویس پیش زمینه باشد ، رویدادهای سنسور را تشخیص دهید.

شنوندگان سنسور ثبت نام

هنگام استفاده از سنسور یا هنگام مکث فعالیت سنسور ، حتماً شنونده سنسور را ثبت نام کنید. اگر یک شنونده سنسور ثبت شده باشد و فعالیت آن متوقف شود ، سنسور به دست آوردن داده ها و استفاده از منابع باتری ادامه خواهد داد مگر اینکه سنسور را ثبت نام نکنید. کد زیر نحوه استفاده از روش onPause() برای ثبت نام شنونده نشان می دهد:

کاتلین

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

جاوا

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

برای اطلاعات بیشتر ، به unregisterListener(SensorEventListener) مراجعه کنید.

با شبیه ساز اندرویدی تست کنید

شبیه ساز Android شامل مجموعه ای از کنترل سنسور مجازی است که به شما امکان می دهد سنسورهایی مانند شتاب سنج ، دمای محیط ، مغناطیس سنج ، مجاورت ، نور و موارد دیگر را آزمایش کنید.

شبیه ساز از اتصال با دستگاه Android که برنامه SDKControllersEnsor را اجرا می کند ، استفاده می کند. توجه داشته باشید که این برنامه فقط در دستگاه هایی که Android 4.0 (API سطح 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 اجرا کنید.

برای اطلاعات بیشتر ، به راهنمای Emulator Android مراجعه کنید.

روش onsensorchanged () را مسدود نکنید

داده های سنسور می توانند با سرعت بالایی تغییر کنند ، به این معنی که سیستم ممکن است اغلب روش onSensorChanged(SensorEvent) را اغلب فراخوانی کند. به عنوان بهترین روش ، شما باید تا حد امکان در روش onSensorChanged(SensorEvent) انجام دهید تا آن را مسدود نکنید. اگر برنامه شما به شما نیاز دارد تا هرگونه فیلتر داده یا کاهش داده های سنسور را انجام دهید ، باید آن کار را در خارج از روش onSensorChanged(SensorEvent) انجام دهید.

از استفاده از روشهای مستهلک یا انواع سنسور خودداری کنید

چندین روش و ثابت کاهش یافته است. به طور خاص ، نوع سنسور TYPE_ORIENTATION مستهلک شده است. برای به دست آوردن داده های جهت گیری باید به جای آن از روش getOrientation() استفاده کنید. به همین ترتیب ، نوع سنسور TYPE_TEMPERATURE کاهش یافته است. شما باید به جای آن از نوع سنسور TYPE_AMBIENT_TEMPERATURE در دستگاه هایی که Android 4.0 را اجرا می کنند استفاده کنید.

قبل از استفاده از آنها سنسورها را تأیید کنید

همیشه تأیید کنید که یک سنسور قبل از تلاش برای به دست آوردن داده از آن در یک دستگاه وجود دارد. فرض نکنید که یک سنسور فقط به این دلیل که یک سنسور اغلب استفاده می شود وجود دارد. تولید کنندگان دستگاه ملزم به ارائه سنسور خاص در دستگاه های خود نیستند.

تأخیرهای سنسور را با دقت انتخاب کنید

هنگامی که یک سنسور را با روش registerListener() ثبت می کنید ، حتماً نرخ تحویل را انتخاب کنید که برای برنامه یا استفاده شما مناسب باشد. سنسورها می توانند داده ها را با نرخ بسیار بالا ارائه دهند. اجازه دادن به سیستم برای ارسال داده های اضافی که به منابع سیستم زباله نیاز ندارید و از باتری استفاده می کند.

،

بیشتر دستگاه های اندرویدی دارای سنسورهای داخلی هستند که حرکت ، جهت گیری و شرایط مختلف محیطی را اندازه گیری می کنند. این سنسورها قادر به ارائه داده های خام با دقت و دقت بالا هستند و اگر می خواهید حرکت یا موقعیت یابی دستگاه سه بعدی را کنترل کنید ، یا می خواهید تغییرات در محیط محیط را در نزدیکی یک دستگاه نظارت کنید. به عنوان مثال ، یک بازی ممکن است قرائت ها را از سنسور گرانش دستگاه ردیابی کند تا حرکات و حرکات کاربر پیچیده مانند شیب ، لرزش ، چرخش یا نوسان را استنباط کند. به همین ترتیب ، یک برنامه آب و هوایی ممکن است از سنسور دما و سنسور رطوبت دستگاه برای محاسبه و گزارش DewPoint استفاده کند ، یا یک برنامه سفر ممکن است از سنسور میدان ژئومغناطیسی و شتاب سنج برای گزارش یاتاقان قطب نما استفاده کند.

پلت فرم Android از سه دسته گسترده از سنسورها پشتیبانی می کند:

  • سنسورهای حرکت

    این سنسورها نیروهای شتاب و نیروهای چرخشی را در طول سه محور اندازه گیری می کنند. این گروه شامل شتاب سنج ، سنسورهای گرانشی ، ژیروسکوپ ها و سنسورهای بردار چرخشی است.

  • سنسورهای محیط زیست

    این سنسورها پارامترهای مختلف محیطی مانند دمای هوا و فشار ، روشنایی و رطوبت را اندازه گیری می کنند. این گروه شامل فشار سنج ، فوتومتر و دماسنج است.

  • سنسورهای موقعیت

    این سنسورها موقعیت فیزیکی یک دستگاه را اندازه گیری می کنند. این دسته شامل سنسورهای جهت گیری و مگنتومترها است.

شما می توانید به سنسورهای موجود در دستگاه دسترسی پیدا کنید و با استفاده از چارچوب سنسور Android ، داده های حسگر خام را بدست آورید. چارچوب سنسور کلاس ها و رابط های مختلفی را ارائه می دهد که به شما در انجام طیف گسترده ای از کارهای مرتبط با سنسور کمک می کند. به عنوان مثال ، می توانید از چارچوب سنسور برای انجام موارد زیر استفاده کنید:

  • تعیین کنید که سنسورها در یک دستگاه موجود هستند.
  • قابلیت های سنسور فردی ، مانند حداکثر دامنه آن ، تولید کننده ، نیازهای برق و وضوح را تعیین کنید.
  • داده های سنسور خام را بدست آورید و حداقل نرخ را که در آن داده های سنسور به دست می آورید تعریف کنید.
  • شنوندگان رویداد سنسور را ثبت نام و ثبت نام کنید که تغییرات سنسور را کنترل می کنند.

این موضوع مروری بر سنسورهای موجود در پلت فرم Android ارائه می دهد. همچنین مقدمه ای در چارچوب سنسور ارائه می دهد.

آشنایی با سنسورها

چارچوب سنسور Android به شما امکان می دهد به بسیاری از سنسورها دسترسی پیدا کنید. برخی از این سنسورها مبتنی بر سخت افزار هستند و برخی دیگر مبتنی بر نرم افزار هستند. حسگرهای مبتنی بر سخت افزار اجزای فیزیکی هستند که در یک گوشی یا تبلت تعبیه شده اند. آنها داده های خود را با اندازه گیری مستقیم ویژگی های محیطی خاص، مانند شتاب، قدرت میدان ژئومغناطیسی یا تغییر زاویه ای به دست می آورند. سنسورهای مبتنی بر نرم افزار دستگاه های فیزیکی نیستند ، اگرچه از سنسورهای مبتنی بر سخت افزار تقلید می کنند. سنسورهای مبتنی بر نرم افزار داده های خود را از یک یا چند سنسور مبتنی بر سخت افزار استخراج می کنند و گاهی اوقات سنسورهای مجازی یا سنسورهای مصنوعی نامیده می شوند. سنسور شتاب خطی و سنسور گرانش نمونه هایی از سنسورهای مبتنی بر نرم افزار هستند. جدول 1 سنسورهایی را که توسط پلت فرم Android پشتیبانی می شوند خلاصه می کند.

تعداد کمی از دستگاه های اندرویدی دارای هر نوع سنسور هستند. به عنوان مثال ، بیشتر دستگاه ها و قرص های گوشی دارای شتاب سنج و مغناطیس سنج هستند ، اما دستگاه های کمتری دارای فشار سنج یا دماسنج هستند. همچنین ، یک دستگاه می تواند بیش از یک سنسور از یک نوع خاص داشته باشد. به عنوان مثال ، یک دستگاه می تواند دو سنسور گرانش داشته باشد که هر کدام دارای دامنه متفاوتی هستند.

جدول 1. انواع سنسور پشتیبانی شده توسط پلت فرم Android.

سنسور تایپ کنید توضیحات کاربردهای مشترک
TYPE_ACCELEROMETER سخت افزار نیروی شتاب را در M/S 2 که برای یک دستگاه در هر سه محور فیزیکی (X ، Y و Z) اعمال می شود ، از جمله نیروی گرانش اندازه گیری می کند. تشخیص حرکت (لرزش ، شیب و غیره).
TYPE_AMBIENT_TEMPERATURE سخت افزار دمای اتاق محیط را در درجه سانتیگراد (درجه سانتیگراد) اندازه گیری می کند. به یادداشت زیر مراجعه کنید. نظارت بر دمای هوا.
TYPE_GRAVITY نرم افزار یا سخت افزار نیروی گرانش را در m/s 2 که برای یک دستگاه در هر سه محور فیزیکی (x ، y ، z) اعمال می شود ، اندازه گیری می کند. تشخیص حرکت (لرزش ، شیب و غیره).
TYPE_GYROSCOPE سخت افزار میزان چرخش دستگاه را در RAD/S در اطراف هر یک از سه محور فیزیکی (X ، Y و Z) اندازه گیری می کند. تشخیص چرخش (چرخش ، چرخش و غیره).
TYPE_LIGHT سخت افزار سطح نور محیط (روشنایی) را در LX اندازه گیری می کند. کنترل روشنایی صفحه.
TYPE_LINEAR_ACCELERATION نرم افزار یا سخت افزار نیروی شتاب را در m/s 2 که برای یک دستگاه در هر سه محور فیزیکی (x ، y و z) اعمال می شود ، به استثنای نیروی گرانش اندازه گیری می کند. نظارت بر شتاب در امتداد یک محور واحد.
TYPE_MAGNETIC_FIELD سخت افزار میدان ژئومغناطیسی محیط را برای هر سه محور فیزیکی (x ، y ، z) در μT اندازه گیری می کند. ایجاد قطب نما
TYPE_ORIENTATION نرم افزار درجه های چرخش را که یک دستگاه در حدود هر سه محور فیزیکی (x ، y ، z) ایجاد می کند ، اندازه گیری می کند. از API سطح 3 می توانید با استفاده از سنسور گرانش و سنسور میدان ژئومغناطیسی در رابطه با روش getRotationMatrix() ماتریس تمایل و ماتریس چرخش را برای یک دستگاه بدست آورید. تعیین موقعیت دستگاه
TYPE_PRESSURE سخت افزار فشار هوای محیط را در HPA یا MBAR اندازه گیری می کند. نظارت بر تغییرات فشار هوا.
TYPE_PROXIMITY سخت افزار نزدیکی یک شیء در CM نسبت به صفحه نمایش یک دستگاه را اندازه گیری می کند. این سنسور به طور معمول برای تعیین اینکه آیا یک گوشی تا گوش شخص نگه داشته می شود ، استفاده می شود. موقعیت تلفن در حین تماس
TYPE_RELATIVE_HUMIDITY سخت افزار رطوبت نسبی محیط را در درصد (٪) اندازه گیری می کند. نظارت بر نقطه شبنم ، رطوبت مطلق و نسبی.
TYPE_ROTATION_VECTOR نرم افزار یا سخت افزار جهت گیری یک دستگاه را با ارائه سه عنصر بردار چرخش دستگاه اندازه گیری می کند. تشخیص حرکت و تشخیص چرخش.
TYPE_TEMPERATURE سخت افزار دمای دستگاه را در درجه سانتیگراد (درجه سانتیگراد) اندازه گیری می کند. این اجرای سنسور در بین دستگاه ها متفاوت است و این سنسور با سنسور TYPE_AMBIENT_TEMPERATURE در سطح API 14 جایگزین شد نظارت بر دما.

چارچوب سنسور

شما می توانید به این سنسورها دسترسی پیدا کرده و با استفاده از چارچوب سنسور Android ، داده های حسگر خام را بدست آورید. چارچوب سنسور بخشی از بسته android.hardware است و کلاس ها و رابط های زیر را شامل می شود:

SensorManager
می توانید از این کلاس برای ایجاد نمونه ای از سرویس سنسور استفاده کنید. این کلاس روشهای مختلفی را برای دسترسی و لیست سنسورها ، ثبت نام و ثبت نام شنوندگان رویداد سنسور و دستیابی به اطلاعات جهت گیری فراهم می کند. این کلاس همچنین چندین ثابت سنسور را ارائه می دهد که برای گزارش دقت سنسور ، تعیین میزان دستیابی به داده ها و سنسورهای کالیبراسیون استفاده می شود.
Sensor
می توانید از این کلاس برای ایجاد نمونه ای از یک سنسور خاص استفاده کنید. این کلاس روشهای مختلفی را ارائه می دهد که به شما امکان می دهد قابلیت های یک سنسور را تعیین کنید.
SensorEvent
این سیستم از این کلاس برای ایجاد یک شیء رویداد سنسور استفاده می کند ، که اطلاعات مربوط به یک رویداد سنسور را ارائه می دهد. یک شیء رویداد سنسور شامل اطلاعات زیر است: داده های سنسور خام ، نوع سنسوری که باعث ایجاد رویداد ، صحت داده ها و زمان بندی برای این رویداد می شود.
SensorEventListener
شما می توانید از این رابط برای ایجاد دو روش پاسخ به تماس استفاده کنید که هنگام تغییر مقادیر سنسور یا هنگام تغییر دقت سنسور ، اعلان ها (حوادث سنسور) دریافت می کنند.

در یک برنامه معمولی از این API های مرتبط با سنسور برای انجام دو کار اساسی استفاده می کنید:

  • شناسایی سنسورها و قابلیت های سنسور

    شناسایی سنسورها و قابلیت های سنسور در زمان اجرا مفید است اگر برنامه شما دارای ویژگی هایی است که به انواع یا قابلیت های سنسور خاص متکی است. به عنوان مثال ، شما ممکن است بخواهید تمام سنسورهای موجود در یک دستگاه را شناسایی کرده و از ویژگی های کاربردی که به سنسورهای موجود متکی هستند ، غیرفعال کنید. به همین ترتیب ، ممکن است بخواهید تمام سنسورهای یک نوع معین را شناسایی کنید تا بتوانید اجرای سنسور را انتخاب کنید که عملکرد بهینه برای برنامه شما داشته باشد.

  • نظارت بر وقایع سنسور

    نظارت بر وقایع سنسور نحوه دستیابی به داده های سنسور خام است. یک رویداد سنسور هر بار که یک سنسور تغییر در پارامترهای اندازه گیری شده را تشخیص می دهد ، رخ می دهد. یک رویداد سنسور چهار قطعه اطلاعات را در اختیار شما قرار می دهد: نام سنسور که باعث ایجاد این رویداد ، زمان بندی برای رویداد ، صحت این رویداد و داده های حسگر خام که باعث ایجاد این رویداد شده است.

در دسترس بودن سنسور

در حالی که در دسترس بودن سنسور از دستگاه به دستگاه دیگر متفاوت است ، می تواند بین نسخه های اندرویدی نیز متفاوت باشد. این امر به این دلیل است که سنسورهای اندرویدی در طول چندین نسخه پلت فرم معرفی شده اند. به عنوان مثال ، بسیاری از سنسورها در Android 1.5 (API سطح 3) معرفی شدند ، اما برخی از آنها اجرا نشده و تا زمان Android 2.3 (سطح API 9) در دسترس نبودند. به همین ترتیب ، چندین سنسور در Android 2.3 (API سطح 9) و Android 4.0 (سطح API 14) معرفی شد. دو سنسور با سنسورهای جدیدتر و بهتر جایگزین شده و جایگزین شده اند.

جدول 2 در دسترس بودن هر سنسور بر اساس پلتفرم به پلتفرم است. فقط چهار سیستم عامل ذکر شده است زیرا این سیستم عامل هایی هستند که تغییرات سنسور را درگیر می کنند. Sensors that are listed as deprecated are still available on subsequent platforms (provided the sensor is present on a device), which is in line with Android's forward compatibility policy.

Table 2. Sensor availability by platform.

سنسور اندروید 4.0
(API Level 14)
Android 2.3
(API Level 9)
Android 2.2
(API Level 8)
Android 1.5
(API Level 3)
TYPE_ACCELEROMETER بله بله بله بله
TYPE_AMBIENT_TEMPERATURE بله n/a n/a n/a
TYPE_GRAVITY بله بله n/a n/a
TYPE_GYROSCOPE بله بله n/a 1 n/a 1
TYPE_LIGHT بله بله بله بله
TYPE_LINEAR_ACCELERATION بله بله n/a n/a
TYPE_MAGNETIC_FIELD بله بله بله بله
TYPE_ORIENTATION بله 2 بله 2 بله 2 بله
TYPE_PRESSURE بله بله n/a 1 n/a 1
TYPE_PROXIMITY بله بله بله بله
TYPE_RELATIVE_HUMIDITY بله n/a n/a n/a
TYPE_ROTATION_VECTOR بله بله n/a n/a
TYPE_TEMPERATURE بله 2 بله بله بله

1 This sensor type was added in Android 1.5 (API Level 3), but it was not available for use until Android 2.3 (API Level 9).

2 This sensor is available, but it has been deprecated.

Identifying Sensors and Sensor Capabilities

The Android sensor framework provides several methods that make it easy for you to determine at runtime which sensors are on a device. The API also provides methods that let you determine the capabilities of each sensor, such as its maximum range, its resolution, and its power requirements.

To identify the sensors that are on a device you first need to get a reference to the sensor service. To do this, you create an instance of the SensorManager class by calling the getSystemService() method and passing in the SENSOR_SERVICE argument. به عنوان مثال:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

جاوا

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

Next, you can get a listing of every sensor on a device by calling the getSensorList() method and using the TYPE_ALL constant. به عنوان مثال:

کاتلین

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

جاوا

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

If you want to list all of the sensors of a given type, you could use another constant instead of TYPE_ALL such as TYPE_GYROSCOPE , TYPE_LINEAR_ACCELERATION , or TYPE_GRAVITY .

You can also determine whether a specific type of sensor exists on a device by using the getDefaultSensor() method and passing in the type constant for a specific sensor. If a device has more than one sensor of a given type, one of the sensors must be designated as the default sensor. If a default sensor does not exist for a given type of sensor, the method call returns null, which means the device does not have that type of sensor. For example, the following code checks whether there's a magnetometer on a device:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Note: Android does not require device manufacturers to build any particular types of sensors into their Android-powered devices, so devices can have a wide range of sensor configurations.

In addition to listing the sensors that are on a device, you can use the public methods of the Sensor class to determine the capabilities and attributes of individual sensors. This is useful if you want your application to behave differently based on which sensors or sensor capabilities are available on a device. For example, you can use the getResolution() and getMaximumRange() methods to obtain a sensor's resolution and maximum range of measurement. You can also use the getPower() method to obtain a sensor's power requirements.

Two of the public methods are particularly useful if you want to optimize your application for different manufacturer's sensors or different versions of a sensor. For example, if your application needs to monitor user gestures such as tilt and shake, you could create one set of data filtering rules and optimizations for newer devices that have a specific vendor's gravity sensor, and another set of data filtering rules and optimizations for devices that do not have a gravity sensor and have only an accelerometer. The following code sample shows you how you can use the getVendor() and getVersion() methods to do this. In this sample, we're looking for a gravity sensor that lists Google LLC as the vendor and has a version number of 3. If that particular sensor is not present on the device, we try to use the accelerometer.

کاتلین

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

جاوا

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

Another useful method is the getMinDelay() method, which returns the minimum time interval (in microseconds) a sensor can use to sense data. Any sensor that returns a non-zero value for the getMinDelay() method is a streaming sensor. Streaming sensors sense data at regular intervals and were introduced in Android 2.3 (API Level 9). If a sensor returns zero when you call the getMinDelay() method, it means the sensor is not a streaming sensor because it reports data only when there is a change in the parameters it is sensing.

The getMinDelay() method is useful because it lets you determine the maximum rate at which a sensor can acquire data. If certain features in your application require high data acquisition rates or a streaming sensor, you can use this method to determine whether a sensor meets those requirements and then enable or disable the relevant features in your application accordingly.

Caution: A sensor's maximum data acquisition rate is not necessarily the rate at which the sensor framework delivers sensor data to your application. The sensor framework reports data through sensor events, and several factors influence the rate at which your application receives sensor events. For more information, see Monitoring Sensor Events .

Monitoring Sensor Events

To monitor raw sensor data you need to implement two callback methods that are exposed through the SensorEventListener interface: onAccuracyChanged() and onSensorChanged() . The Android system calls these methods whenever the following occurs:

The following code shows how to use the onSensorChanged() method to monitor data from the light sensor. This example displays the raw sensor data in a TextView that is defined in the main.xml file as sensor_data .

کاتلین

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

جاوا

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

In this example, the default data delay ( SENSOR_DELAY_NORMAL ) is specified when the registerListener() method is invoked. The data delay (or sampling rate) controls the interval at which sensor events are sent to your application via the onSensorChanged() callback method. The default data delay is suitable for monitoring typical screen orientation changes and uses a delay of 200,000 microseconds. You can specify other data delays, such as SENSOR_DELAY_GAME (20,000 microsecond delay), SENSOR_DELAY_UI (60,000 microsecond delay), or SENSOR_DELAY_FASTEST (0 microsecond delay). As of Android 3.0 (API Level 11) you can also specify the delay as an absolute value (in microseconds).

The delay that you specify is only a suggested delay. The Android system and other applications can alter this delay. As a best practice, you should specify the largest delay that you can because the system typically uses a smaller delay than the one you specify (that is, you should choose the slowest sampling rate that still meets the needs of your application). Using a larger delay imposes a lower load on the processor and therefore uses less power.

There is no public method for determining the rate at which the sensor framework is sending sensor events to your application; however, you can use the timestamps that are associated with each sensor event to calculate the sampling rate over several events. You should not have to change the sampling rate (delay) once you set it. If for some reason you do need to change the delay, you will have to unregister and reregister the sensor listener.

It's also important to note that this example uses the onResume() and onPause() callback methods to register and unregister the sensor event listener. As a best practice you should always disable sensors you don't need, especially when your activity is paused. Failing to do so can drain the battery in just a few hours because some sensors have substantial power requirements and can use up battery power quickly. The system will not disable sensors automatically when the screen turns off.

Handling Different Sensor Configurations

Android does not specify a standard sensor configuration for devices, which means device manufacturers can incorporate any sensor configuration that they want into their Android-powered devices. As a result, devices can include a variety of sensors in a wide range of configurations. If your application relies on a specific type of sensor, you have to ensure that the sensor is present on a device so your app can run successfully.

You have two options for ensuring that a given sensor is present on a device:

  • Detect sensors at runtime and enable or disable application features as appropriate.
  • Use Google Play filters to target devices with specific sensor configurations.

Each option is discussed in the following sections.

Detecting sensors at runtime

If your application uses a specific type of sensor, but doesn't rely on it, you can use the sensor framework to detect the sensor at runtime and then disable or enable application features as appropriate. For example, a navigation application might use the temperature sensor, pressure sensor, GPS sensor, and geomagnetic field sensor to display the temperature, barometric pressure, location, and compass bearing. If a device doesn't have a pressure sensor, you can use the sensor framework to detect the absence of the pressure sensor at runtime and then disable the portion of your application's UI that displays pressure. For example, the following code checks whether there's a pressure sensor on a device:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Using Google Play filters to target specific sensor configurations

If you are publishing your application on Google Play you can use the <uses-feature> element in your manifest file to filter your application from devices that do not have the appropriate sensor configuration for your application. The <uses-feature> element has several hardware descriptors that let you filter applications based on the presence of specific sensors. The sensors you can list include: accelerometer, barometer, compass (geomagnetic field), gyroscope, light, and proximity. The following is an example manifest entry that filters apps that do not have an accelerometer:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

If you add this element and descriptor to your application's manifest, users will see your application on Google Play only if their device has an accelerometer.

You should set the descriptor to android:required="true" only if your application relies entirely on a specific sensor. If your application uses a sensor for some functionality, but still runs without the sensor, you should list the sensor in the <uses-feature> element, but set the descriptor to android:required="false" . This helps ensure that devices can install your app even if they do not have that particular sensor. This is also a project management best practice that helps you keep track of the features your application uses. Keep in mind, if your application uses a particular sensor, but still runs without the sensor, then you should detect the sensor at runtime and disable or enable application features as appropriate.

Sensor Coordinate System

In general, the sensor framework uses a standard 3-axis coordinate system to express data values. For most sensors, the coordinate system is defined relative to the device's screen when the device is held in its default orientation (see figure 1). When a device is held in its default orientation, the X axis is horizontal and points to the right, the Y axis is vertical and points up, and the Z axis points toward the outside of the screen face. In this system, coordinates behind the screen have negative Z values. This coordinate system is used by the following sensors:

Figure 1. Coordinate system (relative to a device) that's used by the Sensor API.

The most important point to understand about this coordinate system is that the axes are not swapped when the device's screen orientation changes—that is, the sensor's coordinate system never changes as the device moves. This behavior is the same as the behavior of the OpenGL coordinate system.

Another point to understand is that your application must not assume that a device's natural (default) orientation is portrait. The natural orientation for many tablet devices is landscape. And the sensor coordinate system is always based on the natural orientation of a device.

Finally, if your application matches sensor data to the on-screen display, you need to use the getRotation() method to determine screen rotation, and then use the remapCoordinateSystem() method to map sensor coordinates to screen coordinates. You need to do this even if your manifest specifies portrait-only display.

Note: Some sensors and methods use a coordinate system that is relative to the world's frame of reference (as opposed to the device's frame of reference). These sensors and methods return data that represent device motion or device position relative to the earth. For more information, see the getOrientation() method, the getRotationMatrix() method, Orientation Sensor , and Rotation Vector Sensor .

Sensor Rate-Limiting

To protect potentially sensitive information about users, if your app targets Android 12 (API level 31) or higher, the system places a limit on the refresh rate of data from certain motion sensors and position sensors. This data includes values recorded by the device's accelerometer , gyroscope , and geomagnetic field sensor .

The refresh rate limit depends on how you access sensor data:

If your app needs to gather motion sensor data at a higher rate, you must declare the HIGH_SAMPLING_RATE_SENSORS permission, as shown in the following code snippet. Otherwise, if your app tries to gather motion sensor data at a higher rate without declaring this permission, a SecurityException occurs.

AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
    <application ...>
        ...
    </application>
</manifest>

Best Practices for Accessing and Using Sensors

As you design your sensor implementation, be sure to follow the guidelines that are discussed in this section. These guidelines are recommended best practices for anyone who is using the sensor framework to access sensors and acquire sensor data.

Only gather sensor data in the foreground

On devices running Android 9 (API level 28) or higher, apps running in the background have the following restrictions:

  • Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don't receive events.
  • Sensors that use the on-change or one-shot reporting modes don't receive events.

Given these restrictions, it's best to detect sensor events either when your app is in the foreground or as part of a foreground service .

Unregister sensor listeners

Be sure to unregister a sensor's listener when you are done using the sensor or when the sensor activity pauses. If a sensor listener is registered and its activity is paused, the sensor will continue to acquire data and use battery resources unless you unregister the sensor. The following code shows how to use the onPause() method to unregister a listener:

کاتلین

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

جاوا

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

For more information, see unregisterListener(SensorEventListener) .

Test with the Android Emulator

The Android Emulator includes a set of virtual sensor controls that allow you to test sensors such as accelerometer, ambient temperature, magnetometer, proximity, light, and more.

The emulator uses a connection with an Android device that is running the SdkControllerSensor app. Note that this app is available only on devices running Android 4.0 (API level 14) or higher. (If the device is running Android 4.0, it must have Revision 2 installed.) The SdkControllerSensor app monitors changes in the sensors on the device and transmits them to the emulator. The emulator is then transformed based on the new values that it receives from the sensors on your device.

You can view the source code for the SdkControllerSensor app in the following location:

$ your-android-sdk-directory/tools/apps/SdkController

To transfer data between your device and the emulator, follow these steps:

  1. Check that USB debugging is enabled on your device.
  2. Connect your device to your development machine using a USB cable.
  3. Start the SdkControllerSensor app on your device.
  4. In the app, select the sensors that you want to emulate.
  5. Run the following adb command:

  6. $ adb forward tcp:1968 tcp:1968
    
  7. Start the emulator. You should now be able to apply transformations to the emulator by moving your device.

Note: If the movements that you make to your physical device aren't transforming the emulator, try running the adb command from step 5 again.

For more information, see the Android Emulator guide .

Don't block the onSensorChanged() method

Sensor data can change at a high rate, which means the system may call the onSensorChanged(SensorEvent) method quite often. As a best practice, you should do as little as possible within the onSensorChanged(SensorEvent) method so you don't block it. If your application requires you to do any data filtering or reduction of sensor data, you should perform that work outside of the onSensorChanged(SensorEvent) method.

Avoid using deprecated methods or sensor types

Several methods and constants have been deprecated. In particular, the TYPE_ORIENTATION sensor type has been deprecated. To get orientation data you should use the getOrientation() method instead. Likewise, the TYPE_TEMPERATURE sensor type has been deprecated. You should use the TYPE_AMBIENT_TEMPERATURE sensor type instead on devices that are running Android 4.0.

Verify sensors before you use them

Always verify that a sensor exists on a device before you attempt to acquire data from it. Don't assume that a sensor exists simply because it's a frequently-used sensor. Device manufacturers are not required to provide any particular sensors in their devices.

Choose sensor delays carefully

When you register a sensor with the registerListener() method, be sure you choose a delivery rate that is suitable for your application or use-case. Sensors can provide data at very high rates. Allowing the system to send extra data that you don't need wastes system resources and uses battery power.

،

Most Android-powered devices have built-in sensors that measure motion, orientation, and various environmental conditions. These sensors are capable of providing raw data with high precision and accuracy, and are useful if you want to monitor three-dimensional device movement or positioning, or you want to monitor changes in the ambient environment near a device. For example, a game might track readings from a device's gravity sensor to infer complex user gestures and motions, such as tilt, shake, rotation, or swing. Likewise, a weather application might use a device's temperature sensor and humidity sensor to calculate and report the dewpoint, or a travel application might use the geomagnetic field sensor and accelerometer to report a compass bearing.

The Android platform supports three broad categories of sensors:

  • سنسورهای حرکت

    These sensors measure acceleration forces and rotational forces along three axes. This category includes accelerometers, gravity sensors, gyroscopes, and rotational vector sensors.

  • Environmental sensors

    These sensors measure various environmental parameters, such as ambient air temperature and pressure, illumination, and humidity. This category includes barometers, photometers, and thermometers.

  • Position sensors

    These sensors measure the physical position of a device. This category includes orientation sensors and magnetometers.

You can access sensors available on the device and acquire raw sensor data by using the Android sensor framework. The sensor framework provides several classes and interfaces that help you perform a wide variety of sensor-related tasks. For example, you can use the sensor framework to do the following:

  • Determine which sensors are available on a device.
  • Determine an individual sensor's capabilities, such as its maximum range, manufacturer, power requirements, and resolution.
  • Acquire raw sensor data and define the minimum rate at which you acquire sensor data.
  • Register and unregister sensor event listeners that monitor sensor changes.

This topic provides an overview of the sensors that are available on the Android platform. It also provides an introduction to the sensor framework.

Introduction to Sensors

The Android sensor framework lets you access many types of sensors. Some of these sensors are hardware-based and some are software-based. حسگرهای مبتنی بر سخت افزار اجزای فیزیکی هستند که در یک گوشی یا تبلت تعبیه شده اند. آنها داده های خود را با اندازه گیری مستقیم ویژگی های محیطی خاص، مانند شتاب، قدرت میدان ژئومغناطیسی یا تغییر زاویه ای به دست می آورند. Software-based sensors are not physical devices, although they mimic hardware-based sensors. Software-based sensors derive their data from one or more of the hardware-based sensors and are sometimes called virtual sensors or synthetic sensors. The linear acceleration sensor and the gravity sensor are examples of software-based sensors. Table 1 summarizes the sensors that are supported by the Android platform.

Few Android-powered devices have every type of sensor. For example, most handset devices and tablets have an accelerometer and a magnetometer, but fewer devices have barometers or thermometers. Also, a device can have more than one sensor of a given type. For example, a device can have two gravity sensors, each one having a different range.

Table 1. Sensor types supported by the Android platform.

سنسور تایپ کنید توضیحات Common Uses
TYPE_ACCELEROMETER سخت افزار Measures the acceleration force in m/s 2 that is applied to a device on all three physical axes (x, y, and z), including the force of gravity. Motion detection (shake, tilt, etc.).
TYPE_AMBIENT_TEMPERATURE سخت افزار Measures the ambient room temperature in degrees Celsius (°C). به یادداشت زیر مراجعه کنید. Monitoring air temperatures.
TYPE_GRAVITY Software or Hardware Measures the force of gravity in m/s 2 that is applied to a device on all three physical axes (x, y, z). Motion detection (shake, tilt, etc.).
TYPE_GYROSCOPE سخت افزار Measures a device's rate of rotation in rad/s around each of the three physical axes (x, y, and z). Rotation detection (spin, turn, etc.).
TYPE_LIGHT سخت افزار Measures the ambient light level (illumination) in lx. Controlling screen brightness.
TYPE_LINEAR_ACCELERATION Software or Hardware Measures the acceleration force in m/s 2 that is applied to a device on all three physical axes (x, y, and z), excluding the force of gravity. Monitoring acceleration along a single axis.
TYPE_MAGNETIC_FIELD سخت افزار Measures the ambient geomagnetic field for all three physical axes (x, y, z) in μT. Creating a compass.
TYPE_ORIENTATION نرم افزار Measures degrees of rotation that a device makes around all three physical axes (x, y, z). As of API level 3 you can obtain the inclination matrix and rotation matrix for a device by using the gravity sensor and the geomagnetic field sensor in conjunction with the getRotationMatrix() method. Determining device position.
TYPE_PRESSURE سخت افزار Measures the ambient air pressure in hPa or mbar. Monitoring air pressure changes.
TYPE_PROXIMITY سخت افزار Measures the proximity of an object in cm relative to the view screen of a device. This sensor is typically used to determine whether a handset is being held up to a person's ear. Phone position during a call.
TYPE_RELATIVE_HUMIDITY سخت افزار Measures the relative ambient humidity in percent (%). Monitoring dewpoint, absolute, and relative humidity.
TYPE_ROTATION_VECTOR Software or Hardware Measures the orientation of a device by providing the three elements of the device's rotation vector. Motion detection and rotation detection.
TYPE_TEMPERATURE سخت افزار Measures the temperature of the device in degrees Celsius (°C). This sensor implementation varies across devices and this sensor was replaced with the TYPE_AMBIENT_TEMPERATURE sensor in API Level 14 Monitoring temperatures.

Sensor Framework

You can access these sensors and acquire raw sensor data by using the Android sensor framework. The sensor framework is part of the android.hardware package and includes the following classes and interfaces:

SensorManager
You can use this class to create an instance of the sensor service. This class provides various methods for accessing and listing sensors, registering and unregistering sensor event listeners, and acquiring orientation information. This class also provides several sensor constants that are used to report sensor accuracy, set data acquisition rates, and calibrate sensors.
Sensor
You can use this class to create an instance of a specific sensor. This class provides various methods that let you determine a sensor's capabilities.
SensorEvent
The system uses this class to create a sensor event object, which provides information about a sensor event. A sensor event object includes the following information: the raw sensor data, the type of sensor that generated the event, the accuracy of the data, and the timestamp for the event.
SensorEventListener
You can use this interface to create two callback methods that receive notifications (sensor events) when sensor values change or when sensor accuracy changes.

In a typical application you use these sensor-related APIs to perform two basic tasks:

  • Identifying sensors and sensor capabilities

    Identifying sensors and sensor capabilities at runtime is useful if your application has features that rely on specific sensor types or capabilities. For example, you may want to identify all of the sensors that are present on a device and disable any application features that rely on sensors that are not present. Likewise, you may want to identify all of the sensors of a given type so you can choose the sensor implementation that has the optimum performance for your application.

  • Monitor sensor events

    Monitoring sensor events is how you acquire raw sensor data. A sensor event occurs every time a sensor detects a change in the parameters it is measuring. A sensor event provides you with four pieces of information: the name of the sensor that triggered the event, the timestamp for the event, the accuracy of the event, and the raw sensor data that triggered the event.

Sensor Availability

While sensor availability varies from device to device, it can also vary between Android versions. This is because the Android sensors have been introduced over the course of several platform releases. For example, many sensors were introduced in Android 1.5 (API Level 3), but some were not implemented and were not available for use until Android 2.3 (API Level 9). Likewise, several sensors were introduced in Android 2.3 (API Level 9) and Android 4.0 (API Level 14). Two sensors have been deprecated and replaced by newer, better sensors.

Table 2 summarizes the availability of each sensor on a platform-by-platform basis. Only four platforms are listed because those are the platforms that involved sensor changes. Sensors that are listed as deprecated are still available on subsequent platforms (provided the sensor is present on a device), which is in line with Android's forward compatibility policy.

Table 2. Sensor availability by platform.

سنسور اندروید 4.0
(API Level 14)
Android 2.3
(API Level 9)
Android 2.2
(API Level 8)
Android 1.5
(API Level 3)
TYPE_ACCELEROMETER بله بله بله بله
TYPE_AMBIENT_TEMPERATURE بله n/a n/a n/a
TYPE_GRAVITY بله بله n/a n/a
TYPE_GYROSCOPE بله بله n/a 1 n/a 1
TYPE_LIGHT بله بله بله بله
TYPE_LINEAR_ACCELERATION بله بله n/a n/a
TYPE_MAGNETIC_FIELD بله بله بله بله
TYPE_ORIENTATION بله 2 بله 2 بله 2 بله
TYPE_PRESSURE بله بله n/a 1 n/a 1
TYPE_PROXIMITY بله بله بله بله
TYPE_RELATIVE_HUMIDITY بله n/a n/a n/a
TYPE_ROTATION_VECTOR بله بله n/a n/a
TYPE_TEMPERATURE بله 2 بله بله بله

1 This sensor type was added in Android 1.5 (API Level 3), but it was not available for use until Android 2.3 (API Level 9).

2 This sensor is available, but it has been deprecated.

Identifying Sensors and Sensor Capabilities

The Android sensor framework provides several methods that make it easy for you to determine at runtime which sensors are on a device. The API also provides methods that let you determine the capabilities of each sensor, such as its maximum range, its resolution, and its power requirements.

To identify the sensors that are on a device you first need to get a reference to the sensor service. To do this, you create an instance of the SensorManager class by calling the getSystemService() method and passing in the SENSOR_SERVICE argument. به عنوان مثال:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

جاوا

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

Next, you can get a listing of every sensor on a device by calling the getSensorList() method and using the TYPE_ALL constant. به عنوان مثال:

کاتلین

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

جاوا

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

If you want to list all of the sensors of a given type, you could use another constant instead of TYPE_ALL such as TYPE_GYROSCOPE , TYPE_LINEAR_ACCELERATION , or TYPE_GRAVITY .

You can also determine whether a specific type of sensor exists on a device by using the getDefaultSensor() method and passing in the type constant for a specific sensor. If a device has more than one sensor of a given type, one of the sensors must be designated as the default sensor. If a default sensor does not exist for a given type of sensor, the method call returns null, which means the device does not have that type of sensor. For example, the following code checks whether there's a magnetometer on a device:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Note: Android does not require device manufacturers to build any particular types of sensors into their Android-powered devices, so devices can have a wide range of sensor configurations.

In addition to listing the sensors that are on a device, you can use the public methods of the Sensor class to determine the capabilities and attributes of individual sensors. This is useful if you want your application to behave differently based on which sensors or sensor capabilities are available on a device. For example, you can use the getResolution() and getMaximumRange() methods to obtain a sensor's resolution and maximum range of measurement. You can also use the getPower() method to obtain a sensor's power requirements.

Two of the public methods are particularly useful if you want to optimize your application for different manufacturer's sensors or different versions of a sensor. For example, if your application needs to monitor user gestures such as tilt and shake, you could create one set of data filtering rules and optimizations for newer devices that have a specific vendor's gravity sensor, and another set of data filtering rules and optimizations for devices that do not have a gravity sensor and have only an accelerometer. The following code sample shows you how you can use the getVendor() and getVersion() methods to do this. In this sample, we're looking for a gravity sensor that lists Google LLC as the vendor and has a version number of 3. If that particular sensor is not present on the device, we try to use the accelerometer.

کاتلین

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

جاوا

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

Another useful method is the getMinDelay() method, which returns the minimum time interval (in microseconds) a sensor can use to sense data. Any sensor that returns a non-zero value for the getMinDelay() method is a streaming sensor. Streaming sensors sense data at regular intervals and were introduced in Android 2.3 (API Level 9). If a sensor returns zero when you call the getMinDelay() method, it means the sensor is not a streaming sensor because it reports data only when there is a change in the parameters it is sensing.

The getMinDelay() method is useful because it lets you determine the maximum rate at which a sensor can acquire data. If certain features in your application require high data acquisition rates or a streaming sensor, you can use this method to determine whether a sensor meets those requirements and then enable or disable the relevant features in your application accordingly.

Caution: A sensor's maximum data acquisition rate is not necessarily the rate at which the sensor framework delivers sensor data to your application. The sensor framework reports data through sensor events, and several factors influence the rate at which your application receives sensor events. For more information, see Monitoring Sensor Events .

Monitoring Sensor Events

To monitor raw sensor data you need to implement two callback methods that are exposed through the SensorEventListener interface: onAccuracyChanged() and onSensorChanged() . The Android system calls these methods whenever the following occurs:

The following code shows how to use the onSensorChanged() method to monitor data from the light sensor. This example displays the raw sensor data in a TextView that is defined in the main.xml file as sensor_data .

کاتلین

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

جاوا

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

In this example, the default data delay ( SENSOR_DELAY_NORMAL ) is specified when the registerListener() method is invoked. The data delay (or sampling rate) controls the interval at which sensor events are sent to your application via the onSensorChanged() callback method. The default data delay is suitable for monitoring typical screen orientation changes and uses a delay of 200,000 microseconds. You can specify other data delays, such as SENSOR_DELAY_GAME (20,000 microsecond delay), SENSOR_DELAY_UI (60,000 microsecond delay), or SENSOR_DELAY_FASTEST (0 microsecond delay). As of Android 3.0 (API Level 11) you can also specify the delay as an absolute value (in microseconds).

The delay that you specify is only a suggested delay. The Android system and other applications can alter this delay. As a best practice, you should specify the largest delay that you can because the system typically uses a smaller delay than the one you specify (that is, you should choose the slowest sampling rate that still meets the needs of your application). Using a larger delay imposes a lower load on the processor and therefore uses less power.

There is no public method for determining the rate at which the sensor framework is sending sensor events to your application; however, you can use the timestamps that are associated with each sensor event to calculate the sampling rate over several events. You should not have to change the sampling rate (delay) once you set it. If for some reason you do need to change the delay, you will have to unregister and reregister the sensor listener.

It's also important to note that this example uses the onResume() and onPause() callback methods to register and unregister the sensor event listener. As a best practice you should always disable sensors you don't need, especially when your activity is paused. Failing to do so can drain the battery in just a few hours because some sensors have substantial power requirements and can use up battery power quickly. The system will not disable sensors automatically when the screen turns off.

Handling Different Sensor Configurations

Android does not specify a standard sensor configuration for devices, which means device manufacturers can incorporate any sensor configuration that they want into their Android-powered devices. As a result, devices can include a variety of sensors in a wide range of configurations. If your application relies on a specific type of sensor, you have to ensure that the sensor is present on a device so your app can run successfully.

You have two options for ensuring that a given sensor is present on a device:

  • Detect sensors at runtime and enable or disable application features as appropriate.
  • Use Google Play filters to target devices with specific sensor configurations.

Each option is discussed in the following sections.

Detecting sensors at runtime

If your application uses a specific type of sensor, but doesn't rely on it, you can use the sensor framework to detect the sensor at runtime and then disable or enable application features as appropriate. For example, a navigation application might use the temperature sensor, pressure sensor, GPS sensor, and geomagnetic field sensor to display the temperature, barometric pressure, location, and compass bearing. If a device doesn't have a pressure sensor, you can use the sensor framework to detect the absence of the pressure sensor at runtime and then disable the portion of your application's UI that displays pressure. For example, the following code checks whether there's a pressure sensor on a device:

کاتلین

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

جاوا

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Using Google Play filters to target specific sensor configurations

If you are publishing your application on Google Play you can use the <uses-feature> element in your manifest file to filter your application from devices that do not have the appropriate sensor configuration for your application. The <uses-feature> element has several hardware descriptors that let you filter applications based on the presence of specific sensors. The sensors you can list include: accelerometer, barometer, compass (geomagnetic field), gyroscope, light, and proximity. The following is an example manifest entry that filters apps that do not have an accelerometer:

<uses-feature android:name="android.hardware.sensor.accelerometer"
              android:required="true" />

If you add this element and descriptor to your application's manifest, users will see your application on Google Play only if their device has an accelerometer.

You should set the descriptor to android:required="true" only if your application relies entirely on a specific sensor. If your application uses a sensor for some functionality, but still runs without the sensor, you should list the sensor in the <uses-feature> element, but set the descriptor to android:required="false" . This helps ensure that devices can install your app even if they do not have that particular sensor. This is also a project management best practice that helps you keep track of the features your application uses. Keep in mind, if your application uses a particular sensor, but still runs without the sensor, then you should detect the sensor at runtime and disable or enable application features as appropriate.

Sensor Coordinate System

In general, the sensor framework uses a standard 3-axis coordinate system to express data values. For most sensors, the coordinate system is defined relative to the device's screen when the device is held in its default orientation (see figure 1). When a device is held in its default orientation, the X axis is horizontal and points to the right, the Y axis is vertical and points up, and the Z axis points toward the outside of the screen face. In this system, coordinates behind the screen have negative Z values. This coordinate system is used by the following sensors:

Figure 1. Coordinate system (relative to a device) that's used by the Sensor API.

The most important point to understand about this coordinate system is that the axes are not swapped when the device's screen orientation changes—that is, the sensor's coordinate system never changes as the device moves. This behavior is the same as the behavior of the OpenGL coordinate system.

Another point to understand is that your application must not assume that a device's natural (default) orientation is portrait. The natural orientation for many tablet devices is landscape. And the sensor coordinate system is always based on the natural orientation of a device.

Finally, if your application matches sensor data to the on-screen display, you need to use the getRotation() method to determine screen rotation, and then use the remapCoordinateSystem() method to map sensor coordinates to screen coordinates. You need to do this even if your manifest specifies portrait-only display.

Note: Some sensors and methods use a coordinate system that is relative to the world's frame of reference (as opposed to the device's frame of reference). These sensors and methods return data that represent device motion or device position relative to the earth. For more information, see the getOrientation() method, the getRotationMatrix() method, Orientation Sensor , and Rotation Vector Sensor .

Sensor Rate-Limiting

To protect potentially sensitive information about users, if your app targets Android 12 (API level 31) or higher, the system places a limit on the refresh rate of data from certain motion sensors and position sensors. This data includes values recorded by the device's accelerometer , gyroscope , and geomagnetic field sensor .

The refresh rate limit depends on how you access sensor data:

If your app needs to gather motion sensor data at a higher rate, you must declare the HIGH_SAMPLING_RATE_SENSORS permission, as shown in the following code snippet. Otherwise, if your app tries to gather motion sensor data at a higher rate without declaring this permission, a SecurityException occurs.

AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
    <application ...>
        ...
    </application>
</manifest>

Best Practices for Accessing and Using Sensors

As you design your sensor implementation, be sure to follow the guidelines that are discussed in this section. These guidelines are recommended best practices for anyone who is using the sensor framework to access sensors and acquire sensor data.

Only gather sensor data in the foreground

On devices running Android 9 (API level 28) or higher, apps running in the background have the following restrictions:

  • Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don't receive events.
  • Sensors that use the on-change or one-shot reporting modes don't receive events.

Given these restrictions, it's best to detect sensor events either when your app is in the foreground or as part of a foreground service .

Unregister sensor listeners

Be sure to unregister a sensor's listener when you are done using the sensor or when the sensor activity pauses. If a sensor listener is registered and its activity is paused, the sensor will continue to acquire data and use battery resources unless you unregister the sensor. The following code shows how to use the onPause() method to unregister a listener:

کاتلین

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

جاوا

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

For more information, see unregisterListener(SensorEventListener) .

Test with the Android Emulator

The Android Emulator includes a set of virtual sensor controls that allow you to test sensors such as accelerometer, ambient temperature, magnetometer, proximity, light, and more.

The emulator uses a connection with an Android device that is running the SdkControllerSensor app. Note that this app is available only on devices running Android 4.0 (API level 14) or higher. (If the device is running Android 4.0, it must have Revision 2 installed.) The SdkControllerSensor app monitors changes in the sensors on the device and transmits them to the emulator. The emulator is then transformed based on the new values that it receives from the sensors on your device.

You can view the source code for the SdkControllerSensor app in the following location:

$ your-android-sdk-directory/tools/apps/SdkController

To transfer data between your device and the emulator, follow these steps:

  1. Check that USB debugging is enabled on your device.
  2. Connect your device to your development machine using a USB cable.
  3. Start the SdkControllerSensor app on your device.
  4. In the app, select the sensors that you want to emulate.
  5. Run the following adb command:

  6. $ adb forward tcp:1968 tcp:1968
    
  7. Start the emulator. You should now be able to apply transformations to the emulator by moving your device.

Note: If the movements that you make to your physical device aren't transforming the emulator, try running the adb command from step 5 again.

For more information, see the Android Emulator guide .

Don't block the onSensorChanged() method

Sensor data can change at a high rate, which means the system may call the onSensorChanged(SensorEvent) method quite often. As a best practice, you should do as little as possible within the onSensorChanged(SensorEvent) method so you don't block it. If your application requires you to do any data filtering or reduction of sensor data, you should perform that work outside of the onSensorChanged(SensorEvent) method.

Avoid using deprecated methods or sensor types

Several methods and constants have been deprecated. In particular, the TYPE_ORIENTATION sensor type has been deprecated. To get orientation data you should use the getOrientation() method instead. Likewise, the TYPE_TEMPERATURE sensor type has been deprecated. You should use the TYPE_AMBIENT_TEMPERATURE sensor type instead on devices that are running Android 4.0.

Verify sensors before you use them

Always verify that a sensor exists on a device before you attempt to acquire data from it. Don't assume that a sensor exists simply because it's a frequently-used sensor. Device manufacturers are not required to provide any particular sensors in their devices.

Choose sensor delays carefully

When you register a sensor with the registerListener() method, be sure you choose a delivery rate that is suitable for your application or use-case. Sensors can provide data at very high rates. Allowing the system to send extra data that you don't need wastes system resources and uses battery power.