问题描述
我想直接使用AndroidApi对运动检测器(加速度计)进行编码。我目前已经测试了使用TMotionSensor和TSensorManager的实现(每个Embarcadero示例),但是两者似乎都存在功耗问题(即电话变热)。
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 TSensorManager, but both seem to have power drain issues (ie. the phone gets hot).
我的TSensorManager实现如下:
My TSensorManager implementation looks like this:
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;
现在,使用作为参考,我开始编写如下代码:
So now, using How to detect movement of an android device? as a reference, I start writing code like this:
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.pas
!
I guess anyone who is familiar with this area, will realize that there's no JSensorManager
declared anywhere in C:\Program Files (x86)\Embarcadero\Studio\18.0\source
. There's a Androidapi.JNI.Telephony.pas
, but no Androidapi.JNI.Sensor(s).pas
!
我的问题是,是否可以通过这种方式从Delphi访问SENSOR_SERVICE,如果可以,该如何实现?
My question is, is it possible to access the SENSOR_SERVICE from Delphi in this way, and if so, how can I implement it?
附录
我尝试了Java2op。似乎要求JDK的特定版本(1.7.25?)不会产生期望的类或接口错误。因此,我尝试使用。免费版本仅解析Android.jar,但这似乎足以满足我的需求。
I tried Java2op. It seems to require a very specific version (1.7.25?) of the JDK to not produce a "class or interface expected" error. So I tried Java2Pas instead. The free version only parses Android.jar, but that seems to be sufficient for my purposes.
推荐答案
这是我的(即将完成) )回答尝试在Delphi Android 10.x中执行相同(或相似)操作(尤其是使用侦听器)的人。
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.
注意:
-
SensorListener在Android中已被弃用。
SensorListener has been deprecated in Android. Use SensorEventListener instead.
Java2pas在 android.hardware.SensorEventListener.pas
中错误地将JSensorEventListener编码。它是 JSensorEventListener = interface(JObject)
。必须将其更正为 JSensorEventListener = interface(IJavaInstance)
。
Java2pas coded the JSensorEventListener in android.hardware.SensorEventListener.pas
incorrectly. It was JSensorEventListener = interface(JObject)
. It must be corrected to JSensorEventListener = interface(IJavaInstance)
.
在 android.hardware.SensorEvent
中,值$ c
JSensorEvent
声明缺少$ c>属性和 _Getvalues
函数。只需从 JSensorEventClass
复制它们。
In android.hardware.SensorEvent
, the values
property and the _Getvalues
function, was missing from the JSensorEvent
declaration. Just copy them from the JSensorEventClass
.
这里是代码:
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;
这篇关于Delphi AndroidAPi运动检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!