Получить в Delphi всю информацию о датчиках мобильного устройства — достаточно популярная задача. Довольно часто, при разработке приложений в Delphi для мобильных операционных систем, например Android, нам приходится иметь дело с датчиками, например, датчиком местоположения или ускорения. Вместе с этим, различные Android-устройства могут иметь в своем составе различные наборы датчиков и разработчику необходимо знать с какими датчиками его приложение может взаимодействовать при запуске на определенном устройстве, чтобы исходя из имеющейся информации выстраивать логику работы приложения.
В представленном ниже примере рассматривается вопрос о том, как в Delphi получить информацию обо всех установленных датчиках в мобильном устройстве.
| Основная информация по компоненту | ||
| Исходник официального примера и документация | DocWiki | |
На главной форме демонстрационного приложения расположены следующие компоненты:
- TListBox — для вывода информации о датчиках
- TTimer — при срабатывании таймера выводится информация с текущего датчика устройства
- TLabel
- TButton — кнопка возврата к выбору датчика из списка
Внешний вид демонстрационного приложения представлен на рисунке ниже:
Демонстрационный пример
Демонстрационное приложение выводит список датчиков, установленных в мобильном устройстве и, при выборе определенного датчика, показывает его свойства.
Приложение использует следующие модули в дополнительной секции uses, части из которых используется при работе приложения в Android:
uses System.Permissions, {$IFDEF ANDROID} Androidapi.JNI.Os, Androidapi.JNI.JavaTypes, Androidapi.Helpers, {$ENDIF} FMX.DialogService;
В секции private формы приложения определены следующие поля:
type TfrmAboutSensors = class(TForm) [...] private { Private declarations } FShowInfo: Boolean; //True, если выбран какой-либо датчик в списке FActiveSensor: TCustomSensor; //содержит объект выбранного датчика [...]
Обработчик события OnCreate главной формы:
var LSensorCat: TSensorCategory; begin FActiveSensor := nil; FShowInfo := False; ReAlignComponents; //выравниваем компоненты на форме {получаем доступ к общему менеджеру датчиков} TSensorManager.Current.Activate(); {перебираем все возможные категории датчиков и формируем их список} for LSensorCat in AllCat do CreateIfExists(LSensorCat); end;
TSensorManager используется для идентификации датчиков, подключенных к устройству и предоставления их для использования в приложениях. В приведенном выше коде AllCat представляет собой константу, описанную в модуле приложения:
const AllCat: TSensorCategories = [TSensorCategory.Location, TSensorCategory.Environmental, TSensorCategory.Motion, TSensorCategory.Orientation, TSensorCategory.Mechanical, TSensorCategory.Electrical, TSensorCategory.Biometric, TSensorCategory.Light, TSensorCategory.Scanner];
Метод CreateIfExists заполняет список TListBox информацией о датчиках выбранной категории и выглядит следующим образом:
procedure TfrmAboutSensors.CreateIfExists(ASensorCategory: TSensorCategory); var LSensorArray: TSensorArray; LSensor: TCustomSensor; LHeader: TListBoxGroupHeader; LItem: TListBoxItem; begin //получаем массив датчиков устройства, относящихся к заданной категории LSensorArray := TSensorManager.Current.GetSensorsByCategory(ASensorCategory); //создаем элемент списка - заголовок (TListBoxGroupHeader) LHeader := TListBoxGroupHeader.Create(Owner); LHeader.Parent := lbMain; LHeader.Text := GetSensorCategoryName(ASensorCategory); //метод представлен ниже LHeader.Height := LHeader.Height * 2; //проходим по каждому датчику в массиве и создаем для него отдельную строку списка for LSensor in LSensorArray do begin LItem := TListBoxItem.Create(Owner); LItem.Parent := lbMain; LItem.Text := GetSensorType(LSensor); //определяем тип датчика LItem.ItemData.Accessory := TListBoxItemData.TAccessory.aDetail; LItem.Data := LSensor; LItem.OnClick := ListBoxItemClick; LItem.Height := LItem.Height * 2; LItem.Font.Size := LItem.Font.Size * 2; end; end; function TfrmAboutSensors.GetSensorCategoryName(ASensorCategory: TSensorCategory): string; begin Result := cND; case ASensorCategory of TSensorCategory.Location: Result := 'Location'; TSensorCategory.Environmental: Result := 'Environmental'; TSensorCategory.Motion: Result := 'Motion'; TSensorCategory.Orientation: Result := 'Orientation'; TSensorCategory.Mechanical: Result := 'Mechanical'; TSensorCategory.Electrical: Result := 'Electrical'; TSensorCategory.Biometric: Result := 'Biometric'; TSensorCategory.Light: Result := 'Light'; TSensorCategory.Scanner: Result := 'Scanner'; end; end;
Для определения типа датчика используется следующий метод:
function TfrmAboutSensors.GetSensorType(ASensor: TCustomSensor): string; begin Result := cND; case ASensor.Category of TSensorCategory.Location: Result := GetTypeNameLocation(TCustomLocationSensor(ASensor).SensorType); TSensorCategory.Environmental: Result := GetTypeNameEnv(TCustomEnvironmentalSensor(ASensor).SensorType); TSensorCategory.Motion: Result := GetTypeNameMotion(TCustomMotionSensor(ASensor).SensorType); TSensorCategory.Orientation: Result := GetTypeNameOrientation(TCustomOrientationSensor(ASensor).SensorType); TSensorCategory.Mechanical: Result := GetTypeNameMech(TCustomMechanicalSensor(ASensor).SensorType); TSensorCategory.Electrical: Result := GetTypeNameElectro(TCustomElectricalSensor(ASensor).SensorType); TSensorCategory.Biometric: Result := GetTypeNameBio(TCustomBiometricSensor(ASensor).SensorType); TSensorCategory.Light: Result := GetTypeNameLight(TCustomLightSensor(ASensor).SensorType); TSensorCategory.Scanner: Result := GetTypeNameScanner(TCustomScannerSensor(ASensor).SensorType); end; end;
В этом методе в зависимости от категории к которой относится датчик выполняется одна из функций: GetTypeNameLocation, GetTypeNameEnv, GetTypeNameMotion, GetTypeNameOrientation и так далее, которые служат для вывода информации и типе датчик в человекопонятной форме. Все эти методы выглядят идентично, например, так выглядит метод определения типа датчика движения:
function TfrmAboutSensors.GetTypeNameMotion(AType: TMotionSensorType): string; begin case AType of TMotionSensorType.Accelerometer1D: Result := 'Accelerometer1D'; TMotionSensorType.Accelerometer2D: Result := 'Accelerometer2D'; TMotionSensorType.Accelerometer3D: Result := 'Accelerometer3D'; TMotionSensorType.MotionDetector: Result := 'MotionDetector'; TMotionSensorType.Gyrometer1D: Result := 'Gyrometer1D'; TMotionSensorType.Gyrometer2D: Result := 'Gyrometer2D'; TMotionSensorType.Gyrometer3D: Result := 'Gyrometer3D'; TMotionSensorType.Speedometer: Result := 'Speedometer'; TMotionSensorType.LinearAccelerometer3D: Result := 'LinearAccelerometer3D'; TMotionSensorType.GravityAccelerometer3D: Result := 'GravityAccelerometer3D'; else Result := cND; end; end;
После того, как список всех датчиков устройства создан, можно кликнуть по названию датчика в списке и приложение покажет по этому датчику подробную информацию. Обработчик OnClick элемента списка выглядит следующим образом:
procedure TfrmAboutSensors.ListBoxItemClick(Sender: TObject); begin if Sender is TListBoxItem then begin FActiveSensor := TCustomSensor(TListBoxItem(Sender).Data); if (FActiveSensor <> nil) and (not FActiveSensor.Started) then begin {$IFDEF ANDROID} if FActiveSensor.Category = TSensorCategory.Location then begin PermissionsService.RequestPermissions([JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION)], procedure(const APermissions: TArray; const AGrantResults: TArray) begin if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then FActiveSensor.Start else TDialogService.ShowMessage('Location permission not granted'); end) end; {$ELSE} FActiveSensor.Start; {$ENDIF} end; end; FShowInfo := True; end;
Здесь опять же использована условная компиляция в Delphi для того, чтобы в случае, если приложение запущено под Android и выбран датчик местоположения, то можно было запросить разрешение на использование этого датчика. Если выбран датчик, то он запускается и пользователь видит информацию полученную с него. Для этого, в обработчике таймера OnTimer используется следующий код:
procedure TfrmAboutSensors.Timer1Timer(Sender: TObject); var ResultText: string; LStep: Single; begin { SysDebug( 'Assigned(FActiveSensor) = ' + BoolToStr(Assigned(FActiveSensor)) + '| FShowInfo = ' + BoolToStr(FShowInfo) ); } if Assigned(FActiveSensor) then begin case FActiveSensor.Category of TSensorCategory.Location: ResultText := GetInfoAboutLocation(FActiveSensor); TSensorCategory.Environmental: ResultText := GetInfoAboutEnv(FActiveSensor); TSensorCategory.Motion: ResultText := GetInfoAboutMotion(FActiveSensor); TSensorCategory.Orientation: ResultText := GetInfoAboutOrientation(FActiveSensor); TSensorCategory.Mechanical: ResultText := GetInfoAboutMechanical(FActiveSensor); TSensorCategory.Electrical: ResultText := GetInfoAboutElectro(FActiveSensor); TSensorCategory.Biometric: ResultText := GetInfoAboutBiometric(FActiveSensor); TSensorCategory.Light: ResultText := GetInfoAboutLight(FActiveSensor); TSensorCategory.Scanner: ResultText := GetInfoAboutScanner(FActiveSensor); end; lInfo.Text := ResultText; end; if not FOnOneScreen then begin if FShowInfo then begin if lInfo.Position.Point.X > (cBorder*2) then begin LStep := Width / 5; lInfo.Position.Point := PointF(lInfo.Position.Point.X - LStep, cBorder); lbMain.Position.Point := PointF(lbMain.Position.Point.X - LStep, cBorder); end; end else begin if lbMain.Position.Point.X < cBorder then begin LStep := Width / 5; lInfo.Position.Point := PointF(lInfo.Position.Point.X + LStep, cBorder); lbMain.Position.Point := PointF(lbMain.Position.Point.X + LStep, cBorder); end; end; end; end;
Опять же, в зависимости от выбранного датчика используются различные методы: GetInfoAboutLocation, GetInfoAboutEnv, GetInfoAboutMotion, GetInfoAboutLight и так далее. Ниже представлен метод вывода информации в Delphi датчика освещенности в зависимости от свойств самого датчика:
function TfrmAboutSensors.GetInfoAboutLight(ASensor: TCustomSensor): string; var ls: TCustomLightSensor; LValues: string; LProp: TCustomLightSensor.TProperty; begin LValues := ''; ls := TCustomLightSensor(ASensor); for LProp in ls.AvailableProperties do begin case LProp of TCustomLightSensor.TProperty.Lux: LValues := LValues + ToFormStr('Lux', ls.Lux); TCustomLightSensor.TProperty.Temperature: LValues := LValues + ToFormStr('Temperature', ls.Temperature); TCustomLightSensor.TProperty.Chromacity: LValues := LValues + ToFormStr('Chromacity', ls.Chromacity); end; end; Result := GetFullInfo( GetSensorCategoryName(ASensor.Category), GetTypeNameLight(ls.SensorType), ls.ClassName, LValues ); end;
На рисунке ниже представлен пример работающего демонстрационного приложения кратко, что показано:
Таким образом, используя менеджер датчиков (TSensorManager) в Delphi можно получить информацию по всем датчикам мобильного устройства.
При подготовке статьи использовалась информация со следующих ресурсов:
- Официальный репозиторий демонстрационных примеров Delphi на SourceForge


