Delphi で Android 開発をしている3000万人の皆さん!こんにちは!
今回は Delphi だけで Broadcast Receiver を実装する方法です。
思ってるより簡単に作れますが、はまりポイントも。
ソースにコメントを書いたので、詳しくは実際のソースをご覧ください!
uBroadcastReceiver ソース
unit uBraodcastReceiver;interfaceusesSystem.Classes, System.Generics.Collections, FMX.Platform, Androidapi.JNIBridge, Androidapi.JNI.App, Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes, Androidapi.Helpers // XE6 では FMX.Helpers.Android にしてください;type// 直接 class(TJavaLocal, JFMXBroadcastReceiverListener) を定義するとダメ!// グローバル変数にインスタンスをつっこんでも削除されて、Broadcast 受信で// アプリが落ちる!// なので、TInterfacedObject を継承していないクラスから派生したクラスの// インナークラスとして JFMXBroadcastReceiverListener を定義する// このクラスは自動的に削除されないため、上手く動作する!TBroadcastReceiver = classpublic type// Broadcast Receiver を通知するイベント// JString にしているので、Intent.ACTION_XXX と equals で比較可能TBroadcastReceiverEvent = procedure(const iAction: JString) of object;// JFMXBroadcastReceiver を実装した JavaClass として Listener を定義TBroadcastReceiverListener =class(TJavaLocal, JFMXBroadcastReceiverListener)private varFBroadcastReceiver: TBroadcastReceiver;publicconstructor Create(const iBroadcastReceiver: TBroadcastReceiver);// Broadcast Receiver から呼び出されるコールバックprocedure onReceive(context: JContext; intent: JIntent); cdecl;end;private var// つぎの2つは保存しないと消えて無くなる!FBroadcastReceiverListener: JFMXBroadcastReceiverListener;FReceiver: JFMXBroadcastReceiver;// 通知対象の ACTION を保持している変数FActions: TList<String>;// イベントハンドラFOnReceived: TBroadcastReceiverEvent;protectedconstructor Create;// Broadcast Receiver の設定と解除procedure SetReceiver;procedure UnsetReceiver;publicdestructor Destroy; override;// 通知して欲しい ACTION の登録と削除procedure AddAction(const iActions: array of JString);procedure RemoveAction(const iAction: JString);procedure ClearAction;// Boradcast Receiver を受け取った時のイベントproperty OnReceived: TBroadcastReceiverEventread FOnReceived write FOnReceived;end;// Boradcast Receiver のインスタンスを返すfunction BroadcastReceiver: TBroadcastReceiver;implementationusesSystem.UITypes, Androidapi.NativeActivity, FMX.Forms;// Braodcast Receiver の唯一のインスタンスvarGBroadcastReceiver: TBroadcastReceiver = nil;function BroadcastReceiver: TBroadcastReceiver;beginif (GBroadcastReceiver = nil) thenGBroadcastReceiver := TBroadcastReceiver.Create;Result := GBroadcastReceiver;end;{ TBroadcastReceiver.TBroadcastReceiverListener }constructor TBroadcastReceiver.TBroadcastReceiverListener.Create(const iBroadcastReceiver: TBroadcastReceiver);begininherited Create;FBroadcastReceiver := iBroadcastReceiver;end;procedure TBroadcastReceiver.TBroadcastReceiverListener.onReceive(context: JContext;intent: JIntent);varJStr: String;Str: String;procedure CallEvent;varAction: String;begin// Broadcast は Delphi のメインスレッドで届くわけでは無いので// Synchronize で呼び出すAction := JStr;TThread.CreateAnonymousThread(procedurebeginTThread.Synchronize(TThread.CurrentThread,procedurebeginif (Assigned(FBroadcastReceiver.FOnReceived)) thenFBroadcastReceiver.FOnReceived(StringToJString(Action));end);end).Start;end;begin// Broadcast を受け取ったら、このメソッドが呼ばれる!JStr := JStringToString(intent.getAction);for Str in FBroadcastReceiver.FActions doif (Str = JStr) thenCallEvent;end;{ TReceiverListener }procedure TBroadcastReceiver.AddAction(const iActions: array of JString);varStr: String;JStr: String;Action: JString;OK: Boolean;Changed: Boolean;beginChanged := False;for Action in iActions dobeginOK := True;JStr := JStringToString(Action);for Str in FActions doif (Str = JStr) thenbeginOK := False;Break;end;if (OK) then beginFActions.Add(JStr);Changed := True;end;end;if (Changed) thenSetReceiver;end;procedure TBroadcastReceiver.ClearAction;beginFActions.Clear;UnsetReceiver;end;constructor TBroadcastReceiver.Create;begininherited;FActions := TList<String>.Create;// Boardcast Receiver を設定SetReceiver;end;destructor TBroadcastReceiver.Destroy;begin// Broadcast Receiver を解除UnsetReceiver;FActions.DisposeOf;inherited;end;procedure TBroadcastReceiver.RemoveAction(const iAction: JString);vari: Integer;JStr: String;beginJStr := JStringToString(iAction);for i := 0 to FActions.Count - 1 doif (FActions[i] = JStr) thenbeginFActions.Delete(i);SetReceiver;Break;end;end;procedure TBroadcastReceiver.SetReceiver;varFilter: JIntentFilter;Str: String;beginif (FReceiver <> nil) thenUnsetReceiver;// Intent Filter を作成Filter := TJIntentFilter.JavaClass.init;for Str in FActions doFilter.addAction(StringToJString(Str));// TBroadcastReceiverListener を実体とした BroadcastReceiver を作成FBroadcastReceiverListener := TBroadcastReceiverListener.Create(Self);FReceiver :=TJFMXBroadcastReceiver.JavaClass.init(FBroadcastReceiverListener);try// レシーバーとして登録SharedActivityContext.getApplicationContext.registerReceiver(FReceiver,Filter);exceptend;end;procedure TBroadcastReceiver.UnsetReceiver;begin// アプリケーションが終了中でなければ、BroadcastReceiver を解除if(FReceiver <> nil) and(not (SharedActivityContext as JActivity).isFinishing)thentrySharedActivityContext.getApplicationContext.unregisterReceiver(FReceiver);exceptend;FReceiver := nil;end;initializationfinalizationif (GBroadcastReceiver <> nil) thenGBroadcastReceiver.DisposeOf;end.
使用方法
type// JString は Androidapi.JNI.JavaTypes に// JIntent は Androidapi.JNI.GraphicsContentViewText に// JStringToString は Androidapi.Helpers に// それぞれ定義されていますTForm1 = class(TForm)procedure FormCreate(Sender: TObject);privateprocedure Received(const iAction: JString);publicend;varForm1: TForm1;implementationusesuBraodcastReceiver;{$R *.fmx}procedure TForm1.FormCreate(Sender: TObject);beginBroadcastReceiver.OnReceived := Received;// スクリーン ON / OFF を受け取るように設定BroadcastReceiver.AddAction([TJIntent.JavaClass.ACTION_SCREEN_OFF,TJIntent.JavaClass.ACTION_SCREEN_ON]);end;procedure TForm1.Received(const iAction: JString);beginLog.d('Broadcast Received = ' + JStringToString(iAction));end;
清水と申します。XE7を使用していて
返信削除色々を探していてこちらにたどり着いたのですが
SMS(ショートメール)の送信結果(送信できた、出来なかった、出来なかった場合の理由等)を取得する方法はどのような書式になりますか?
SMS の送信結果は BroadcastReceiver とは関係ないです。
削除Intent を利用して SMS を送信するアプリを立ち上げますが、結果を返してくれるかどうかは SMS アプリ次第です。
なお、結果を受け取るためには startActivityForResult を試用します。