В этой заметке узнаем, как можно получить список установленных в устройстве датчиков(Sensors) и полную информацию о них. Сразу скажу, что метод работает только на Android устройствах. Я хотел использовать «кроссплатформенный» модуль «System.Sensors», но оказалось, что он не может решить данную задачу на Android, об этом я ещё немного напишу ниже.
И вопрос к разработчикам Embarcadero.
Написано на Delphi XE6 и Android 4.1.2.
Upd(2.10.14). Проверено на Delphi XE7 и Android 4.4.2
Для работы с датчиками в Android API есть класс «SensorManager(android.hardware.SensorManager)», он умеет много всего, но нам сегодня понадобится только один метод «getSensorList(int type)».
Метод возвращает список доступных датчиков указанного типа.
Типы (для Android API10), также можете найти их тут (Sensor(android.hardware.Sensor)):
- TYPE_ALL: 'Все типы'
- TYPE_ACCELEROMETER: 'Акселерометр'
- TYPE_GRAVITY: 'Датчик силы тяжести'
- TYPE_GYROSCOPE: 'Гироскоп'
- TYPE_LIGHT: 'Датчик света'
- TYPE_LINEAR_ACCELERATION: 'Датчик ускорения'
- TYPE_MAGNETIC_FIELD: 'Датчик магнитного поля'
- TYPE_ORIENTATION: 'Датчик ориентации'
- TYPE_PRESSURE: 'Датчик давления'
- TYPE_PROXIMITY: 'Датчик приближения'
- TYPE_ROTATION_VECTOR: 'Датчик вращения'
- TYPE_TEMPERATURE: 'Датчик температуры'
Методы (для Android API10):
- getMaximumRange() – Максимальное значение датчика
- getMinDelay() – Минимально допустимая задержка между двумя событиями (в микросекундах)
- getName() – Имя(название) датчика
- getPower() – Потребляемая мощность (в mA)
- getResolution() – Разрешающая способность датчика
- getType() – Тип датчика (число)
- getVendor() – Производитель датчика
- getVersion() – Версия датчика
Как видите информации достаточно, чтобы идентифицировать любой установленный на устройстве датчик.
Теперь напишем простейший код для вывода списка датчиков со всей информацией.
Примечание: Т.к. тип датчика возвращается в виде числа, то выглядит это совсем не информативно, я использовал оператор выбора для приведения типа к более информативному виду.
Код:
uses android.hardware.SensorManager, android.hardware.Sensor, Androidapi.JNI.JavaTypes, FMX.Helpers.android, Androidapi.JNIBridge, Androidapi.JNI.GraphicsContentViewText, Androidapi.Helpers; procedure TForm1.Button1Click(Sender: TObject); var SensorsManagerObj: JObject; SensorsManager: JSensorManager; Sensors: JList; Sensor: JSensor; i: Integer; StringType: String; begin Memo1.Lines.Clear; SensorsManagerObj := SharedActivityContext.getSystemService (TJContext.JavaClass.SENSOR_SERVICE); SensorsManager := TJSensorManager.Wrap((SensorsManagerObj as ILocalObject) .GetObjectID); Sensors := SensorsManager.getSensorList(TJSensor.JavaClass.TYPE_ALL); Label1.Text := 'Found: ' + IntToStr(Sensors.size) + ' sensors'; for i := 0 to Sensors.size - 1 do begin Sensor := TJSensor.Wrap((Sensors.get(i) as ILocalObject).GetObjectID); Memo1.Lines.Add('Name: ' + JStringToString(Sensor.getName)); case Sensor.getType of TJSensorTYPE_ACCELEROMETER: StringType := 'Акселерометр'; TJSensorTYPE_GRAVITY: StringType := 'Датчик силы тяжести'; TJSensorTYPE_GYROSCOPE: StringType := 'Гироскоп'; TJSensorTYPE_LIGHT: StringType := 'Датчик света'; TJSensorTYPE_LINEAR_ACCELERATION: StringType := 'Датчик ускорения'; TJSensorTYPE_MAGNETIC_FIELD: StringType := 'Датчик магнитного поля'; TJSensorTYPE_ORIENTATION: StringType := 'Датчик ориентации'; TJSensorTYPE_PRESSURE: StringType := 'Датчик давления'; TJSensorTYPE_PROXIMITY: StringType := 'Датчик приближения'; TJSensorTYPE_ROTATION_VECTOR: StringType := 'Датчик вращения'; TJSensorTYPE_TEMPERATURE: StringType := 'Датчик температуры'; else StringType := 'Undefined'; end; Memo1.Lines.Add('Type: ' + StringType); Memo1.Lines.Add('Vendor: ' + JStringToString(Sensor.getVendor)); Memo1.Lines.Add('Version: ' + IntToStr(Sensor.getVersion)); Memo1.Lines.Add('Resolution: ' + FloatToStr(Sensor.getResolution)); Memo1.Lines.Add('Max Range: ' + FloatToStr(Sensor.getMaximumRange)); Memo1.Lines.Add('Power: ' + FloatToStr(Sensor.getPower) + 'mA'); Memo1.Lines.Add('MinDelay: ' + IntToStr(Sensor.getMinDelay)); Memo1.Lines.Add('----------------'); end; end;
Результат:
Теперь про «System.Sensors».
После того как я написал код для Android API вспомнил, что в Delphi есть «кроссплатформенный» модуль для работы с всевозможными датчиками и решил (основная причина «кроссплатформенность») написать для вас второе решение. Написал код, запустил на устройстве и «увидел фигу», ни какой информации, кроме «Категории (типа)» и «Состояния датчика» у меня не получилось достать.
Код:
uses System.Sensors, System.TypInfo; procedure TForm1.Button2Click(Sender: TObject); var SensorsManager: TSensorManager; i: Integer; Sensor: TCustomSensor; begin SensorsManager := TSensorManager.Current; if SensorsManager.CanActivate then begin SensorsManager.Activate; Memo2.Lines.Clear; Label2.Text := 'Found: ' + IntToStr(SensorsManager.Count) + ' sensors'; for i := 0 to SensorsManager.Count - 1 do begin Sensor := SensorsManager.Sensors[i]; Memo2.Lines.Add('Name: ' + Sensor.Name); Memo2.Lines.Add('Category: ' + GetEnumName(TypeInfo(TSensorCategory), Ord(Sensor.Category))); Memo2.Lines.Add('Manufacturer: ' + Sensor.Manufacturer); Memo2.Lines.Add('Model: ' + Sensor.Model); Memo2.Lines.Add('State: ' + GetEnumName(TypeInfo(TSensorState), Ord(Sensor.State))); Memo2.Lines.Add('SerialNo: ' + Sensor.SerialNo); Memo2.Lines.Add('Description: ' + Sensor.Description); Memo2.Lines.Add('UniqueID: ' + Sensor.UniqueID); Memo2.Lines.Add('----------------'); end; end; SensorsManager.Current.Deactivate; end;
Результат:
Вопрос к разработчикам Embarcadero: Вы планируете «допилить» этот модуль до кроссплатформенного состояния?
На этом всё. Спасибо за внимание!
Исходный код: Скачать с Google Drive