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了?