Delphi AndroidAPi运动检测

时间:2017-09-08 18:46:33

标签: android delphi firemonkey

我想直接使用AndroidApi编码运动检测器(Accelerometer)。我目前已经使用TMotionSensor和TSensorManager测试了实现(每个Embarcadero示例),但两者似乎都有耗电问题(即手机变热)。

我的TSensorManager实现如下所示:

procedure TfrmTabbed.InitSensorMan;
var
  FSensors: TSensorArray;
  Sensor: TCustomSensor;
begin
  TSensorManager.Current.Activate;
  FSensors := TSensorManager.Current.GetSensorsByCategory(TSensorCategory.Motion);
  FSensor := nil;
  for Sensor in FSensors do
  begin
    if TCustomMotionSensor(Sensor).SensorType = TMotionSensorType.Accelerometer3D then
    begin
      FSensor := TCustomMotionSensor(Sensor);
      Break;
    end;
  end;
  MotionTimer.Interval := 250; 
  MotionTimer.Active := True;
end;

现在,使用How to detect movement of an android device?作为参考,我开始编写如下代码:

uses
  Androidapi.Sensor,
  Androidapi.JNI.JavaTypes;

{$R *.fmx}

procedure TForm2.FormCreate(Sender: TObject);
var
  Obj: JObject;
  SensorManager: JSensorManager;
begin

  Obj := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.SENSOR_SERVICE);
  if Obj <> nil then
  begin
     SensorManager := TJsensorManager.Wrap(Obj);

  end;

我想任何熟悉这个领域的人都会意识到JSensorManager中的任何地方都没有声明C:\Program Files (x86)\Embarcadero\Studio\18.0\source。有一个Androidapi.JNI.Telephony.pas,但没有Androidapi.JNI.Sensor(s).pas

我的问题是,是否可以通过这种方式从Delphi访问SENSOR_SERVICE,如果是这样,我该如何实现它?

附录

我试过Java2op。似乎需要JDK的一个非常特定的版本(1.7.25?)才能生成预期的&#34;类或接口&#34;错误。所以我尝试了Java2Pas。免费版本只解析Android.jar,但这似乎足以满足我的目的。

1 个答案:

答案 0 :(得分:0)

对于那些试图在Delphi Android 10.x中尝试做同样(或类似)事情的人,特别是听众,这是我(几乎完成)的答案。

注意:

  1. 在Android中已弃用SensorListener。改为使用SensorEventListener。

  2. Java2pas错误地编写了android.hardware.SensorEventListener.pas中的JSensorEventListener。那是JSensorEventListener = interface(JObject)。必须更正为JSensorEventListener = interface(IJavaInstance)

  3. android.hardware.SensorEvent values声明中缺少_Getvalues属性和JSensorEvent函数。只需从JSensorEventClass

  4. 复制它们即可

    以下是代码:

    unit Unit2;
    
    interface
    
    uses    
     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
     ;
    
    type
    
      TSensorEventListener = 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
      if Assigned(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;