delphi 10 seattle 安卓服务开发(三)
delphi 10 里面的安卓服务有四种,上面的一篇文章里面的图有介绍。
今天做一个remote service 的例子。(里面一部分代码是抄别人的,如果不太清楚,自行恶补)
remote service 实际上就是主程序包含服务模块,另外的一个程序可以调用。
由于delphi 10 的低级错误,需要手工修改一些东西。这一块可以参考http://blog.qdac.cc/?p=2839
为了不影响这个例子的顺利完成,本例中没有使用上面的修改。直接在本例中处理。
现在开工:
和以前一样,先建立一个远程服务
生成文件,保存目录。
打开servicedmp
输入以下代码
uses
Androidapi.Helpers;
function TAndroidServiceDM.AndroidServiceHandleMessage(const Sender: TObject;
const AMessage: JMessage): Boolean;
const
GET_STRING = 1234;
SERVICE_STRING = 4321;
var
LMessage: JMessage;
LBundle: JBundle;
begin
case AMessage.what of
GET_STRING:
begin
LBundle := TJBundle.Create; // we can not send String because is not parcelable
LMessage := TJMessage.Create;
LMessage.what := SERVICE_STRING;
LBundle.putString(TAndroidHelper.StringToJString('Key'), TAndroidHelper.StringToJString('这是服务来的消息!!!'));
LMessage.obj := LBundle;
AMessage.replyTo.send(LMessage);
Result := True;
end;
else
Result := False;
end;
end;
ok ,开始编译,出现错误,当然了。EMB 同志犯了低级错误。
进入手动模式,打开下面文件:
修改
现在编译,没问题了,好,保存。
现在我们建立一个新的工程,用来加入这个服务,并使用这个服务,界面如下:
注意获取数据的按钮的enabled:=False;
代码如下
unit mainp;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation,System.Android.Service, Androidapi.JNI.Os;
type
TForm3 = class(TForm)
Label1: TLabel;
Button1: TButton;
Button2: TButton;
GetDataButton: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure GetDataButtonClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FServiceConnection: TRemoteServiceConnection;
procedure OnServiceConnected(const ServiceMessenger: JMessenger);
procedure OnHandleMessage(const AMessage: JMessage);
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
const
GET_STRING = 1234;
SERVICE_STRING = 4321;
implementation
{$R *.fmx}
uses
AndroidApi.Helpers,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.Widget;
procedure TForm3.Button1Click(Sender: TObject);
begin
// 绑定服务
FServiceConnection.BindService(
// 包含服务的 APK 名称
'com.embarcadero.xalionhostapp',
// 服务名- 总是以 "com.embarcadero.services"开头
'com.embarcadero.services.xalionremoteservice');
end;
procedure TForm3.Button2Click(Sender: TObject);
begin
// 取消绑定
if FServiceConnection <> nil then
FServiceConnection.UnbindService;
GetDataButton.Enabled := False;
end;
procedure TForm3.FormCreate(Sender: TObject);
begin
// 初始化服务连接
FServiceConnection := TRemoteServiceConnection.Create;
FServiceConnection.OnConnected := OnServiceConnected;
FServiceConnection.OnHandleMessage := OnHandleMessage;
end;
procedure TForm3.FormDestroy(Sender: TObject);
begin
FServiceConnection.Free;
end;
procedure TForm3.GetDataButtonClick(Sender: TObject);
var
LMessage: JMessage;
begin
LMessage := TJMessage.JavaClass.obtain(nil, GET_STRING);
LMessage.replyTo := FServiceConnection.LocalMessenger;
FServiceConnection.ServiceMessenger.send(LMessage);
end;
procedure TForm3.OnHandleMessage(const AMessage: JMessage);
var
LStr: JString;
LBundle: JBundle;
begin
case AMessage.what of
SERVICE_STRING:
begin
LBundle := TJBundle.Wrap(AMessage.obj);
LStr := LBundle.getString(TAndroidHelper.StringToJString('Key'));
TJToast.JavaClass.makeText(TAndroidHelper.Context, LStr.subSequence(0, LStr.length),
TJToast.JavaClass.LENGTH_SHORT).show;
end;
else
FServiceConnection.Handler.Super.handleMessage(AMessage);
end;
end;
procedure TForm3.OnServiceConnected(const ServiceMessenger: JMessenger);
begin
GetDataButton.Enabled := True;
end;
end.
现在把刚才建立的服务加进去
编译运行。
是不是可以正常运行了?
先点一下绑定服务,等获取数据可以点时,点一下,就可以取到服务发来的消息了。
OK,这只是实现了内部的通讯,我们还需要另外做一个app. 让它也可以使用这个服务。
重新建立一个新的APP.
界面如下:
代码与主程序非常相似
unit mainp;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation,System.Android.Service, Androidapi.JNI.Os;
type
TForm3 = class(TForm)
Label1: TLabel;
Button1: TButton;
Button2: TButton;
GetDataButton: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure GetDataButtonClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FServiceConnection: TRemoteServiceConnection;
procedure OnServiceConnected(const ServiceMessenger: JMessenger);
procedure OnHandleMessage(const AMessage: JMessage);
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
const
GET_STRING = 1234;
SERVICE_STRING = 4321;
implementation
{$R *.fmx}
uses
AndroidApi.Helpers,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.Widget;
procedure TForm3.Button1Click(Sender: TObject);
begin
// 绑定服务
FServiceConnection.BindService(
// 包含服务的 APK 名称
'com.embarcadero.xalionhostapp',
// 服务名- 总是以 "com.embarcadero.services"开头
'com.embarcadero.services.xalionremoteservice');
end;
procedure TForm3.Button2Click(Sender: TObject);
begin
// 取消绑定
if FServiceConnection <> nil then
FServiceConnection.UnbindService;
GetDataButton.Enabled := False;
end;
procedure TForm3.FormCreate(Sender: TObject);
begin
// 初始化服务连接
FServiceConnection := TRemoteServiceConnection.Create;
FServiceConnection.OnConnected := OnServiceConnected;
FServiceConnection.OnHandleMessage := OnHandleMessage;
end;
procedure TForm3.FormDestroy(Sender: TObject);
begin
FServiceConnection.Free;
end;
procedure TForm3.GetDataButtonClick(Sender: TObject);
var
LMessage: JMessage;
begin
LMessage := TJMessage.JavaClass.obtain(nil, GET_STRING);
LMessage.replyTo := FServiceConnection.LocalMessenger;
FServiceConnection.ServiceMessenger.send(LMessage);
end;
procedure TForm3.OnHandleMessage(const AMessage: JMessage);
var
LStr: JString;
LBundle: JBundle;
begin
case AMessage.what of
SERVICE_STRING:
begin
LBundle := TJBundle.Wrap(AMessage.obj);
LStr := LBundle.getString(TAndroidHelper.StringToJString('Key'));
TJToast.JavaClass.makeText(TAndroidHelper.Context, LStr.subSequence(0, LStr.length),
TJToast.JavaClass.LENGTH_SHORT).show;
end;
else
FServiceConnection.Handler.Super.handleMessage(AMessage);
end;
end;
procedure TForm3.OnServiceConnected(const ServiceMessenger: JMessenger);
begin
GetDataButton.Enabled := True;
end;
end.
编译,运行。
点绑定服务,奇怪了,怎么获取数据不出来,反而出现了“程序无反应” 是否关闭?
唉。又是 EMB 同志的低级错误。
手动模式,打开主程序的目录。
打开这个文件
把这个替换成
<service android:exported="true" android:name="com.embarcadero.services.xalionremoteservice" />
如图
重新编译运行主程序。
现在再运行扩展程序。怎么样,ok了?