Мне нужно запустить службу Android, которая продолжает работать, даже если приложение закрыто пользователем или уничтожено ОС. В папке документов приложения есть база данных SQLite, и службе необходимо получить доступ к этой базе данных и вставить некоторые данные в течение длительного времени.
Я пробовал много стратегий, но ни одна не сработала. .
Моя основная попытка — создать локальную службу, используя START_STICKY и вызывая StartForeground() в событии StartCommand. >
Модуль служебных данных:
Код: Выделить всё
unit UDMService;
interface
uses
System.SysUtils,
System.Classes, System.IOUtils,
System.Android.Service,
AndroidApi.JNI.GraphicsContentViewText,
Androidapi.JNI.Os, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error,
FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef,
FireDAC.Stan.ExprFuncs, FireDAC.ConsoleUI.Wait, FireDAC.DApt,
FireDAC.Phys.SQLiteWrapper.Stat, Data.DB, FireDAC.Comp.Client;
type
TThreadTeste = class(TThread)
protected
procedure Execute; override;
end;
TDM = class(TAndroidService)
fdConDados: TFDConnection;
FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink;
function AndroidServiceStartCommand(const Sender: TObject;
const Intent: JIntent; Flags, StartId: Integer): Integer;
private
{ Private declarations }
FThreadGravarTabela: TThread;
procedure ConectarBanco;
procedure GerarRegistroTabela;
procedure GerarRegistrosTabela;
procedure StartForeground;
public
{ Public declarations }
end;
var
DM: TDM;
implementation
{%CLASSGROUP 'FMX.Controls.TControl'}
{$R *.dfm}
uses Androidapi.JNI.App, Androidapi.JNI.Support, Androidapi.Helpers;
procedure TDM.StartForeground;
var
{$if COMPILERVERSION > 34}
LBuilder: Japp_NotificationCompat_Builder;
{$else}
LBuilder: JNotificationCompat_Builder;
{$endif}
begin
try
//if FIsForeground or not TAndroidHelperEx.CheckBuildAndTarget(26) then
//Exit; // 10 then
Terminate;
end;
finally
AQuery.Free;
end;
end;
end.
Код: Выделить всё
unit UMainApp;
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, System.Android.Service,
FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLiteWrapper.Stat,
FireDAC.Phys.SQLiteDef, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.SQLite,
FireDAC.FMXUI.Wait, Data.DB, FireDAC.Comp.Client, System.IOUtils,
FMX.Memo.Types, FireDAC.DApt, FMX.ScrollBox, FMX.Memo, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView;
type
TForm1 = class(TForm)
Button1: TButton;
FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink;
fdConDados: TFDConnection;
mmLog: TMemo;
ButAtualizarLista: TButton;
ListView1: TListView;
procedure butStartServiceClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ButAtualizarListaClick(Sender: TObject);
private
{ Private declarations }
ConexaoServico : TLocalServiceConnection;
procedure AtualizarEstruturaBase;
function GetDadosTabelaTestes: TDataSet;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.AtualizarEstruturaBase;
function TabelaExiste(const pTable: String): Boolean;
begin
var AQuery: TFDQuery := TFDQuery.Create(nil);
AQuery.Connection := fdConDados;
try
AQuery.Open('PRAGMA table_info(' + QuotedStr(pTable) + ')');
result := AQuery.RecordCount > 0;
finally
AQuery.Free;
end;
end;
const SQL_CRIAR_TABELA_TESTES =
'CREATE TABLE tabela'
+ ' (id INTEGER PRIMARY KEY AUTOINCREMENT,'
+ ' data DATETIME)';
begin
var AQuery: TFDQuery := TFDQuery.Create(nil);
AQuery.Connection := fdConDados;
try
if not (TabelaExiste('tabela')) then
AQuery.ExecSQL(SQL_CRIAR_TABELA_TESTES);
finally
AQuery.Free;
end;
end;
procedure TForm1.ButAtualizarListaClick(Sender: TObject);
begin
ListView1.Items.Clear;
var ADataSet: TDataSet := GetDadosTabelaTestes;
with ADataSet do
begin
First;
while not (Eof) do
begin
ListView1.Items.Add.Text := Format('%d - %s',
[FieldBYName('id').AsInteger,
FormatDateTime('dd/mm/yyyy hh:nn:ss', FieldByName('data').AsDateTime)]);
Next;
end;
end;
end;
procedure TForm1.butStartServiceClick(Sender: TObject);
begin
ConexaoServico := TLocalServiceConnection.Create;
TThread.CreateAnonymousThread(
procedure
begin
ConexaoServico.StartService('MyService2');
end).Start;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
try
fdconDados.Params.Values['Database'] := TPath.Combine(TPath.GetDocumentsPath, 'MyServicePOC.db3');
fdconDados.Params.Add('SharedCache=False');
fdconDados.UpdateOptions.LockWait := True;
fdconDados.Connected := True;
AtualizarEstruturaBase;
except
on e: exception do
mmLog.Lines.Add('[TForm1.FormCreate]'+e.Message)
end;
end;
function TForm1.GetDadosTabelaTestes: TDataSet;
begin
fdConDados.ExecSQL('SELECT * FROM tabela ORDER BY id, data', result);
end;
end.
Сервис создан как «Локальный». Я попытался создать ту же группу проектов, используя опцию «Удаленно» для службы, но данные не вставляются в базу данных приложения.
Может ли кто-нибудь помочь с этой проблемой?
Подробнее здесь: https://stackoverflow.com/questions/783 ... -is-closed