Skip to content Skip to sidebar Skip to footer

Delphi Androidapi Motion Detection

I want to code a motion detector (Accelerometer) using the AndroidApi directly. I currently have tested implementations (per Embarcadero examples) using TMotionSensor as well as TS

Solution 1:

Here is my (almost completed) answer for those of you who are trying to do the same (or similar) things, especially with Listeners, in Delphi Android 10.x.

Note:

  1. SensorListener has been deprecated in Android. Use SensorEventListener instead.

  2. Java2pas coded the JSensorEventListener in android.hardware.SensorEventListener.pas incorrectly. It was JSensorEventListener = interface(JObject). It must be corrected to JSensorEventListener = interface(IJavaInstance).

  3. In android.hardware.SensorEvent, the values property and the _Getvalues function, was missing from the JSensorEvent declaration. Just copy them from the JSensorEventClass.

Here is the code:

unit Unit2;

interfaceuses    
 System.SysUtils, System.Types, System.UITypes, System.Classes,
 System.Variants,
 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
 FMX.Controls.Presentation, FMX.StdCtrls
 , Androidapi.JNIBridge
 , Androidapi.JNI.Embarcadero
 , Androidapi.JNI.GraphicsContentViewText
 , androidapi.JNI.JavaTypes
 , AndroidApi.JNI.Location
 , Androidapi.JNI.Os
 // java2pas gen'd units (modified as noted above)
 , android.hardware.SensorManager
 , android.hardware.Sensor
 , android.hardware.SensorEventListener
 , android.hardware.SensorEvent
 , FMX.ScrollBox, FMX.Memo
 ;

typeTSensorEventListener= class;

  TForm2 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FSensorManager: JSensorManager;
    FDefaultSensor: JSensor;
    SensorEventListener: TSensorEventListener;
    FStarted: Boolean;
    procedure StartApi;
    procedure StopApi;
  public
    { Public declarations }
  end;

  TSensorEventListener = class(TJavaLocal, JSensorEventListener)
  private
    [weak]
    FParent: TForm2;
  public
    constructor Create(AParent: TForm2);
    procedure onAccuracyChanged(JSensorparam0 : JSensor; Integerparam1 : Integer) ; cdecl;
    procedure onSensorChanged(JSensorEventparam0 : JSensorEvent) ; cdecl;
  end;

var
  Form2: TForm2;

implementation

uses
  Androidapi.Helpers
  , Androidapi.JNI.Net
  , FMX.Helpers.Android
  ;

procedure TForm2.Button1Click(Sender: TObject);
begin
  if Fstarted then
    StopApi
  else
    StartApi;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  FStarted := False;
end;

procedure TForm2.StartApi;
var
  SensorManagerService: JObject;
begin
  if not Assigned(FSensorManager) then
  begin
    SensorManagerService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.SENSOR_SERVICE);
    FSensorManager := TJSensorManager.Wrap((SensorManagerService as ILocalObject).GetObjectID);
    if not Assigned(SensorEventListener) then
      SensorEventListener := TSensorEventListener.Create(Self);
    FDefaultSensor := FSensorManager.getDefaultSensor(TJSensorManager.JavaClass.SENSOR_ACCELEROMETER);
  end;
  FSensorManager.registerListener(SensorEventListener, FDefaultSensor, TJSensorManager.JavaClass.SENSOR_DELAY_NORMAL);
  Memo1.Lines.Add(DateTimeToStr(Now) + ' started');
  FStarted := True;
end;

procedure TForm2.StopApi;
begin
  ifAssigned(SensorEventListener) then
    FSensorManager.unregisterListener(SensorEventListener);
  Memo1.Lines.Add(DateTimeToStr(Now) + ' stopped');
  FStarted := False;
end;

{ TSensorEventListener }

constructor TSensorEventListener.Create(AParent: TForm2);
begin
  inherited Create;
  FParent := AParent;
end;

procedure TSensorEventListener.onAccuracyChanged(JSensorparam0: JSensor;
  Integerparam1: Integer);
begin
   // do stuff
end;

procedure TSensorEventListener.onSensorChanged(
  JSensorEventparam0: JSensorEvent);
begin
   // do stuff, especially with the JSensorEventparam0.values
end;

Post a Comment for "Delphi Androidapi Motion Detection"