即將進入的這最後一個步驟,也是小弟我潛心研究在這塊花費時間最久的部分。為了簡化各位實做的難度,我們將直接藉助 blong 老大產出的 classes.dex,但是在 XE5 client 端的部分,由於 blong 老大給我們的 smaple code 太複雜,所以就讓小弟我現醜簡化一番。

首先,我們要下載在前言部分有提到的 blong 老大在 Delphi and Android services (part 2) 這篇文章中提供給我們的 source code,下載後解壓縮,你可以在 \DelphiServiceDemo\java\output\dex 目錄找到 blong 老大為我們編譯好的 classes.dex,先記得有這個檔案,我們稍晚會用到…

接下來,還是就新增一個專案,畫面類似如下

其中 Register Device 在 (b)申請 GCM 與設備端(client)註冊並取得 regID 的文章中已經說明過了,這邊就不再贅述。這次的重點,集中在 Register Receiver 這個 Button Click 下去該做些什麼事情。先在 Form private 的部分,宣告兩個全域變數,並 uses ActivityReceiverU,如下

接下來是 FormCreate 的部分

ActivityReceiverU 這個 Unit 的 source code,也就是小弟簡化的部分,則原文貼在下面

unit ActivityReceiverU;

interface

uses
  FMX.Types,
  Androidapi.JNIBridge,
  Androidapi.JNI.GraphicsContentViewText;

type
  JActivityReceiverClass = interface(JBroadcastReceiverClass)
  ['{2D4BB037-F6B6-4A64-ACD8-1137F4AB8743}']
    {Methods}
  end;

  [JavaSignature('com/blong/test/ActivityReceiver')]
  JActivityReceiver = interface(JBroadcastReceiver)
  ['{6B9B1B38-7117-4BEA-AE03-5687220D5F3B}']
    {Methods}
  end;

  TJActivityReceiver = class(TJavaGenericImport<JActivityReceiverClass, JActivityReceiver>)
  protected
    constructor _Create;
  public
    class function Create: JActivityReceiver;
    procedure OnReceive(Context: JContext; ReceivedIntent: JIntent);
  end;

implementation

uses
  System.Classes,
  System.SysUtils,
  FMX.Helpers.Android,
  Androidapi.NativeActivity,
  Androidapi.JNI,
  Androidapi.JNI.JavaTypes,
  FMX.Notification,
  Androidapi.JNI.Os;

{$REGION 'JNI setup code and callback'}
var
  FNotificationCenter : TNotificationCenter;
  ActivityReceiver: TJActivityReceiver;
  ARNContext: JContext;
  ARNReceivedIntent: JIntent;

procedure ActivityReceiverOnReceiveThreadSwitcher;
begin
  ActivityReceiver.OnReceive(ARNContext,ARNReceivedIntent);
end;

//This is called from the Java activity's onReceiveNative() method
procedure ActivityReceiverOnReceiveNative(PEnv: PJNIEnv; This: JNIObject; JNIContext, JNIReceivedIntent: JNIObject); cdecl;
begin
  ARNContext := TJContext.Wrap(JNIContext);
  ARNReceivedIntent := TJIntent.Wrap(JNIReceivedIntent);
  TThread.Synchronize(nil, ActivityReceiverOnReceiveThreadSwitcher);
end;

procedure RegisterDelphiNativeMethods;
var
  PEnv: PJNIEnv;
  ReceiverClass: JNIClass;
  NativeMethod: JNINativeMethod;
begin
  PEnv := TJNIResolver.GetJNIEnv;

  NativeMethod.Name := 'activityReceiverOnReceiveNative';
  NativeMethod.Signature := '(Landroid/content/Context;Landroid/content/Intent;)V';
  NativeMethod.FnPtr := @ActivityReceiverOnReceiveNative;

  ReceiverClass := TJNIResolver.GetJavaClassID('com.blong.test.ActivityReceiver');

  PEnv^.RegisterNatives(PEnv, ReceiverClass, @NativeMethod, 1);

  PEnv^.DeleteLocalRef(PEnv, ReceiverClass);
end;
{$ENDREGION}

{ TActivityReceiver }

constructor TJActivityReceiver._Create;
begin
  inherited;
end;

class function TJActivityReceiver.Create: JActivityReceiver;
begin
  Result := inherited Create;
  ActivityReceiver := TJActivityReceiver._Create;

  FNotificationCenter := TNotificationCenter.Create(nil);
end;

procedure TJActivityReceiver.OnReceive(Context: JContext;
  ReceivedIntent: JIntent);
var
  Notification : TNotification;
  lBundle : JBundle;
begin
  if FNotificationCenter.Supported then
  begin
    Notification := FNotificationCenter.CreateNotification;
    try
      lBundle := ReceivedIntent.getExtras;

      Notification.AlertBody := JStringToString(lBundle.getString(StringToJString('message')));
      FNotificationCenter.PresentNotification(Notification);
    finally
      Notification.DisposeOf;
    end;
  end;
end;

initialization
  RegisterDelphiNativeMethods;

end.

簡單說明其中的原理,就是在接收到 Google GCM Server 傳來的訊息後(觸發 OnReceive),把訊息轉丟給 NotificationCenter,讓這個訊息可以顯示在手機的訊息通知中心。

Register Receiver 這個 Button Click 下去後,當然就是呼叫 RegisterReceiver 這個函式,而這個函式的實做如下

都完成之後,記得調整這個專案的 Deployment ,其中 classes.dex 要改為文章中最前面提到的 blong 老大為我們編譯好的那個。

Sever 端傳送訊息的部分,這次是跟上一篇文章中提到的一樣沒改,要發送給設備端的訊息是 "data" : {"message" : "Hi Client"}

現在就把 app 執行起來,並且點選執行 Register Receiver,如果正常的話可以顯示「register ok」的訊息,表示 Receiver 註冊成功,接下來請在 Server 端點選「Send Test」,如果一切都順利的話,你應該可以很快在 client 端收到 GCM Server 傳來的訊息,並顯示在訊息中心...如下

是不是跟我們要傳送給設備端的訊息是一樣的呢?你也可以把訊息中心點開來看看

 

恭喜您...完成 GCM 從發送到接受整個步驟

 

to be continued...

arrow
arrow

    縹緲 發表在 痞客邦 留言(10) 人氣()