アプリケーション間の連携をとるという事であれば、
WM_COPYDATAメッセージの利用といった伝統的な手法がありますが、
あれは異なるデバイス間では使用できないデメリットがあります。
そこで今回はTethering系コンポーネントを利用して
アンドロイドとPCを連携させ、スマホをリモコン化してみよう。
という企画です。
参考にさせて頂いたページはこちら
https://www.gesource.jp/programming/delphi/xe6/apptethering/manual.html
まずはソースから。相変わらず適当ですみません。
フォーム1(Form1)
//-------------------------------------------------- //-------------------------------------------------- procedure TForm1.BitBtn1Click(Sender: TObject); begin DataModule_Reciever.TetheringManager1.AutoConnect(3000); end; procedure TForm1.Button1Click(Sender: TObject); begin with DataModule_Reciever.TetheringAppProfile1 do begin Group:=LabeledEdit1.Text; Text :=LabeledEdit2.Text; end; end; procedure TForm1.Button2Click(Sender: TObject); var s:string; idx:integer; begin idx:=ListBox1.ItemIndex; if idx=-1 then exit; s:=ListBox1.Items[idx]; DataModule_Reciever.SendMesSub(s,Edit1.Text); end; //-------------------------------------------------- //-------------------------------------------------- procedure TForm1.Reload; var i,Cnt:integer; begin //Reload Cnt:=DataModule_Reciever.TetheringManager1.RemoteProfiles.Count; ListBox1.Clear; for i:=0 to Cnt-1 do ListBox1.Items.Add(DataModule_Reciever.TetheringManager1.RemoteProfiles[i].ProfileText); end;
データモジュール(DataModule_Reciever)
procedure TDataModule_Reciever.TetheringManager1EndAutoConnect(Sender: TObject); begin //接続チェック Form1.Reload; end; procedure TDataModule_Reciever.Timer1Timer(Sender: TObject); var Cnt:integer; s:string; begin Cnt:=TetheringManager1.RemoteProfiles.Count; if Cnt > 0 then s := '接続中('+Cnt.ToString+')' else s := '接続していません。'; Form1.StatusBar1.panels[0].Text:=s; if ConnectCheckStr<>s then begin ConnectCheckStr:=s; Form1.Reload; end; end; procedure TDataModule_Reciever.TetheringAppProfile1ResourceReceived( const Sender: TObject; const AResource: TRemoteResource); begin //--------------------- // データ受信イベント //--------------------- Form1.Edit1.Text:=AResource.Value.AsString; // end; procedure TDataModule_Reciever.SendMesSub(TargetDeviceProf,Mes:string); var RemoteProfile: TTetheringProfileInfo; s:string; begin for RemoteProfile in TetheringManager1.RemoteProfiles do begin if (RemoteProfile.ProfileGroup = TetheringAppProfile1.Group) and (RemoteProfile.ProfileText = TargetDeviceProf) then begin //------------------- // 文字列を送信する //------------------- TetheringAppProfile1.SendString(RemoteProfile, 'サンプル', //受信側はAResource.Hintで取得する Mes //受信側はAResource.Value.AsStringで取得する ); Exit; end; end; end;
ひとつのフォームでまとめても良かったんですが、
自分の開発スタイルとして非ビジュアルコンポーネントは
データモジュールに置いているのでこんな感じに分かれています。
雰囲気をつかんでもらえればと。
フォームはこんな感じ。
・LebeledEditでGroupとProfileIDの入力欄を設置
・Buttonでその設定をコンポーネントプロパティにセット
・ListBoxで接続中のデバイスのProfileIDを表示
・なぜかBitBtnで接続ボタン。
・Editで転送文字列の入力欄を設置
・ボタン(Button2)で文字列転送ボタンを設置
・フォーム下にステータスバーを設置してパネルを作成。
という構成になっています。
データモジュールには、
・TetheringManager
・TetheringAppProfile
・Timer
コンポーネントを設置。
TetheringAppProfileコンポーネントのManagerプロパティにTetheringManagerを設定。
単純な話、これだけで構成したアプリケーションを2つ立ち上げて
GroupとProfileIDを適切に設定した上で接続ボタンを押せば
接続確認はできます。
あとは、片方のアプリから他方のアプリに文字列を転送して
その文字列に応じて処理をすればOKと言うことになります。
その際、文字列の入力には音声入力を使用すると
最近の流行っぽくなるんじゃないでしょうか。
では説明を。
まず接続準備として上にも書いた通り
TetheringAppProfileコンポーネントの
MagnagerプロパティにTetheringManagerコンポーネントを設定
Gropupプロパティに接続するためのグループ名を設定します
⇒ グループ名は任意で
Textプロパティに識別名を設定します ⇒ こちらも任意で
これが準備。
後は、TetheringManagerコンポーネントのAutoConnectメソッドで自動接続。
タイムアウトのカウントを設定できます;
自動で接続してくれるので便利なんですが、
自分で決定できないのはちょいと不自由かなと。
今までの経験からすると、複数(3台以上)のデバイスを接続する場合は
接続作業を繰り返す必要があるようです。
ちなみに、ウチの環境ではうまく繋がらないことが多くあります。
Andoroid端末とPCではうまく繋がりません。
PCで2つアプリを立ち上げ、それぞれを接続。
その後にスマホで接続を試みると繋がるという奇妙な挙動を見せます。
原因は良くわかりませんが、その方法でつながるので、
今は良しとしています。
で、AutoConnectメソッドを実行するとEndAutoConnectイベントが発生するので
そこで処理。
上のサンプルでは接続状況を処理するForm1.Reloadを呼んでいます。
ReoadではTetheringManager1.RemoteProfiles[i].ProfileTextを列挙しています。
TetheringAppProfileのTextプロパティになります。
で、接続状況をリアルタイムで監視する必要があるのですが、
それはタイマーコンポーネントで監視します。
TetheringManagerコンポーネントのRemoteProfiles.Countプロパティで
接続数が確認できるようなので0かそれ以外で接続・未接続の判断ができます。
で、ConnectCheckStrというグローバル変数があります。
これは前回表示した接続状況を文字列として保存しています。
前回と異なる文字列になった場合はReloadを呼び出して接続状況を更新します。
接続が完了したら後は文字列を送信するだけです。
送信部分はSendMesSubで、
受信部分はTetheringAppProfileのResourceReceivedイベントで
それぞれ処理します。
送信に関しては送信したいTetheringAppProfileコンポーネントを見つけて送信する。
という方法になります。
その判断をするのに必要なのがGroupプロパティとTextプロパティです。
見つかればTetheringAppProfilコンポーネントのSendStringメソッドで
文字列を送信します。
受信はTetheringAppProfileコンポーネントのResourceReceivedイベントにて。
やり方はソースを見ていただければ分かるかと(手抜き)
ということでこんな感じでしょうか。