使用Delphi 10 Seattle Update 1创建Android应用程序。
基本目标是让应用程序每隔几(4)小时弹出一个通知,提醒用户起床和移动。
我创建了基本UI并创建了后台服务。在服务中,我可以使用TNotificationCenter发布通知,但我需要定期发布通知。
根据以下网站的建议......
我意识到我无法使用TTimer和Android服务。我还试图从AndroidServiceStartCommand和AndroidServiceCreate事件创建一个TTask,TThread.CreateAnonymousThread和一个老式的TThread后代。
所有这些都在sleep命令完成后抛出相同的错误。 “Project MoveProof.apk引发了异常类Segment fault(11)”
以下是我现在使用的代码....
unit UnitServiceMain;
interface
uses
System.SysUtils
, System.Classes
, System.Android.Service
, System.Notification
, AndroidApi.JNI.GraphicsContentViewText
, Androidapi.JNI.Os
;
type
TServiceThread = class;
TNotes = Array of String;
TAndroidServiceDM = class(TAndroidService)
NotificationCenterNotes: TNotificationCenter;
function AndroidServiceStartCommand(const Sender: TObject; const Intent: JIntent; Flags, StartId: Integer): Integer;
procedure AndroidServiceCreate(Sender: TObject);
procedure AndroidServiceDestroy(Sender: TObject);
private
FNotes: TArray<string>;
FThread: TServiceThread;
public
var Running: Boolean;
Procedure LoadArray;
Property Notes:TArray<string> read FNotes;
end;
TServiceThread = class(TThread)
public
Procedure Execute; override;
Procedure DoNotification;
end;
var
AndroidServiceDM: TAndroidServiceDM;
implementation
{%CLASSGROUP 'FMX.Controls.TControl'}
{$R *.dfm}
Uses
System.Threading
, Androidapi.JNI.App
;
{ TServiceThread }
procedure TServiceThread.DoNotification;
Var
NoteId: Integer;
MyNotification: TNotification;
begin
while (AndroidServiceDM <> nil) and AndroidServiceDM.Running do
Begin
try
if (AndroidServiceDM <> nil) and AndroidServiceDM.Running then
Begin
AndroidServiceDM.NotificationCenterNotes.CancelAll;
NoteID := Random(High(AndroidServiceDM.Notes));
MyNotification := AndroidServiceDM.NotificationCenterNotes.CreateNotification;
try
MyNotification.Name := 'LoveNoteMessage'+InttoStr(NoteID);
MyNotification.EnableSound := False;
MyNotification.Number := NoteID;
MyNotification.Title := 'Michael Said...';
MyNotification.AlertBody := AndroidServiceDM.Notes[NoteID];
AndroidServiceDM.NotificationCenterNotes.PresentNotification(MyNotification);
finally
MyNotification.DisposeOf;
end;
End;
except
on Exception do
// Need to log this...
end;
end;
end;
procedure TServiceThread.Execute;
begin
inherited;
Sleep( 20000 );
Synchronize(DoNotification);
end;
procedure TAndroidServiceDM.LoadArray;
begin
if Length(FNotes) = 0 then
Begin
FNotes := TArray<string>.Create
(
'Get up and move.',
'Time to keep moving.',
'Lets take a walk.',
'Move.'
);
End;
end;
procedure TAndroidServiceDM.AndroidServiceCreate(Sender: TObject);
begin
Randomize;
LoadArray;
end;
procedure TAndroidServiceDM.AndroidServiceDestroy(Sender: TObject);
begin
FThread.Terminate;
FThread := Nil;
end;
function TAndroidServiceDM.AndroidServiceStartCommand(const Sender: TObject; const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
JavaService.stopSelf;
Result := TJService.JavaClass.START_STICKY;
if not Running then
begin
Running := True;
FThread := TServiceThread.Create(False);
end;
end;
end.
我对线程没有经验,所以也许我在做同步时出错了。任何帮助将不胜感激。
答案 0 :(得分:0)
没有必要将DoNotification放入线程中。只需在AndroidServiceCreate中设置一个带有永久循环的TTask,然后检查已用时间,当它通过时,再调用DoNotification。
T := TTask.Run (procedure
begin
TimeNow := Now;
Count := 0;
while true do
begin
sleep(20000);
if SecondsBetween(TimeNow, Now) >= Floor(4 * 60 * 60) then
begin
DoNotification;
TimeNow := Now;
end;
end;
end);
您的通知看起来比它需要的更复杂,并且您在那里使用的不必要的循环可能是您的分段错误的原因。
myNotification := NotificationCenter1.CreateNotification;
try
MyNotification.Name := 'ServiceNotification';
MyNotification.Title := 'Android Service Notification';
MyNotification.AlertBody := 'hello host, I'm your service'
MyNotification.FireDate := Now;
NotificationCenter1.PresentNotification(MyNotification);
finally
myNotification.DisposeOf;
end;
Delphi中Android服务的经验法则是编写最简单的代码来完成工作,而不是更多。
答案 1 :(得分:-1)
如323go建议的那样,您不需要服务来执行此操作。
服务只应在明确需要时使用,因为它会消耗系统资源并耗尽电池寿命,因此只需要使用它们。
您可以使用本地AlarmManager.setRepeating
方法,该方法将在您指定的自定义时间间隔内创建本机定期通知,但解决方案是Android特定的
请参阅我的回答Custom notification interval
请注意,对于您的情况,MyNotification.RepeatIntervalinMills
是毫秒的间隔,您希望触发通知,因此在4小时的情况下,它将是
MyNotification.RepeatIntervalinMills := 14400000 // That is 4 hours in Milliseconds