delphi 10 里面的安卓服務有四種,上面的一篇文章里面的圖有介紹。
今天做一個remote service 的例子。(里面一部分代碼是抄別人的,如果不太清楚,自行惡補)
remote service 實際上就是主程序包含服務模塊,另外的一個程序可以調用。
由於delphi 10 的低級錯誤,需要手工修改一些東西。這一塊可以參考http://blog.qdac.cc/?p=2839
為了不影響這個例子的順利完成,本例中沒有使用上面的修改。直接在本例中處理。
現在開工:
和以前一樣,先建立一個遠程服務
生成文件,保存目錄。
輸入以下代碼
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了?