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

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM