SMS送信して結果を受信するAndroidアプリケーション ~Delphiソースコード集
1.Delphiを起動
Delphiを起動して新規FMXプロジェクトを作成し、ターゲットプラットフォームをAndroidに設定して、 フォームにTButtonを2つ、TTrackbarを1つ、TMediaPlayerを1つ、TTimerを1つ配置します。(スタイル:をAndroidに切り替えると、実行時に近い表示になるので便利です。)
プロジェクトとユニットを保存します。
Delphi XE10.3.xの場合
Delphi XE10.3.xは、C:\Program Files (x86)\Embarcadero\Studio\20.0\source\fmx\FMX.Media.Android.pasに不具合があるので、 このファイルを保存したプロジェクトと同じフォルダ内にコピーし、以下2行を修正します。修正したら、「プロジェクトに追加(Shift+F11)」で修正したFMX.Media.Android.pasを追加します。
function TAndroidMedia.GetCurrent: TMediaTime; begin 1114行目 Result := Round(FPlayer.getCurrentPosition * MediaTimeScale / MSecsPerSec);} ↓以下に修正 Result := FPlayer.getCurrentPosition * int64(MediaTimeScale) div int64(MSecsPerSec); end; function TAndroidMedia.GetDuration: TMediaTime; begin 1119行目 Result := Round(FPlayer.getDuration * MediaTimeScale / MSecsPerSec); ↓以下に修正 Result := FPlayer.getDuration * int64(MediaTimeScale) div int64(MSecsPerSec); end;
2.権限設定
プロジェクト⇒オプションをクリックし、アプリケーション⇒使用する権限 から 「音声の録音」にチェックを入れて(True)、「保存」ボタンを押します。3.ソースコードの記述
Button1を押したら録音します。Button2を押したら再生します。unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Media, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, System.Permissions, FMX.Media.Android; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; TrackBar1: TTrackBar; MediaPlayer1: TMediaPlayer; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure TrackBar1Change(Sender: TObject); private { private 宣言 } FFileName:String; FAudioCaptureDevice:TAudioCaptureDevice; procedure PermissionRequestResult( Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); procedure RequestPermissions(); public { public 宣言 } end; var Form1: TForm1; implementation uses System.IOUtils, Androidapi.Helpers, Androidapi.JNI.Os, Androidapi.Jni.Support, FMX.DialogService, FMX.Platform; {$R *.fmx} procedure TForm1.Button1Click(Sender: TObject); begin if Button1.Tag=0 then begin //録音開始 if FileExists(FFileName) then DeleteFile(FFileName); FAudioCaptureDevice.StartCapture; Button1.Text:='録音停止'; Button1.Tag:=1; Button2.Enabled:=False; end else begin //録音停止 FAudioCaptureDevice.StopCapture; Button1.Text:='録音開始'; Button1.Tag:=0; Button2.Enabled:=True; end; end; procedure TForm1.Button2Click(Sender: TObject); begin if Button2.Tag=0 then begin //再生開始 TImer1.Enabled:=True; Button2.Text:='再生停止'; Button2.Tag:=1; Button1.Enabled:=False; MediaPlayer1.Clear; MediaPlayer1.FileName:=FFileName; MediaPlayer1.Play; end else begin //再生停止 Timer1.Enabled:=False; Button2.Text:='再生開始'; Button2.Tag:=0; if Assigned(FAudioCaptureDevice) then Button1.Enabled:=True; MediaPlayer1.Stop; MediaPlayer1.Clear; TrackBar1.Value:=0; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Button1.Text:='録音開始'; Button2.Text:='再生開始'; Timer1.Enabled:=False; TImer1.Interval:=200; //録音、再生のファイル名を設定 {$IF DEFINED(ANDROID) OR DEFINED(IOS)} FFileName:=TPath.Combine( System.IOUtils.TPath.GetDocumentsPath,'test.mp3'); {$ELSE} FFileName:=TPath.Combine( System.IOUtils.TPath.GetDocumentsPath,'test.wav'); {$ENDIF} //再生ファイルが無い場合は再生ボタンを使用不可にする if not FileExists(FFileName) then Button2.Enabled:=False; //録音デバイスの取得 FAudioCaptureDevice := TCaptureDeviceManager.Current.DefaultAudioCaptureDevice; if Assigned(FAudioCaptureDevice) then //録音デバイスにファイル名を設定する FAudioCaptureDevice.FileName:=FFileName else //録音デバイスが無い場合は録音ボタンを使用不可にする Button1.Enabled:=False; //権限の取得 APIレベル23以降 RequestPermissions(); end; procedure TForm1.FormDestroy(Sender: TObject); begin if Button1.Tag=1 then FAudioCaptureDevice.StopCapture; if Button2.Tag=1 then MediaPlayer1.Stop; end; procedure TForm1.PermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); begin //音声の録音の権限があるか if (AGrantResults[0]<>TPermissionStatus.Granted) then begin //権限がない場合 //「□今後は表示しない」チェックボックスにチェックが入っているか if (TJActivityCompat.JavaClass.shouldShowRequestPermissionRationale( TAndroidHelper.Activity, TJManifest_permission.JavaClass.RECORD_AUDIO)) then begin //「□今後は表示しない」チェックボックスにチェックが入っていない場合 // 非同期でダイアログを表示して説明と許可を要求 TDialogService.MessageDialog( '許可しないとアプリが動作しません。',TMsgDlgType.mtInformation, [TMsgDlgBtn.mbOK],TMsgDlgBtn.mbOk,0, procedure (const AResult: TModalResult) begin //2回目以降は「□今後は表示しない」チェックボックスが表示される RequestPermissions(); end); end else begin //「□今後は表示しない」チェックボックスにチェックが入っている TDialogService.MessageDialog( '権限が無いため終了します。「設定⇒アプリと通知」から権限を設定してください。', TMsgDlgType.mtError,[TMsgDlgBtn.mbOK],TMsgDlgBtn.mbOK,0, procedure(const AResult:TModalResult) begin Application.Terminate; end ); end; end; end; procedure TForm1.RequestPermissions; var FPmsRecordAudio: string; begin FPmsRecordAudio:=JStringToString( TJManifest_permission.JavaClass.RECORD_AUDIO); PermissionsService.RequestPermissions( [FPmsRecordAudio],PermissionRequestResult); end; procedure TForm1.Timer1Timer(Sender: TObject); begin if MediaPlayer1.State=TMediaState.Playing then begin TrackBar1.Tag:=1; TrackBar1.Min:=0; {$IFDEF ANDROID} //FMX.Media.Android.pasのバグ対応(XE10.2.x以下) //TrackBar1.Max:=MediaPlayer1.Duration; //TrackBar1.Value:=MediaPlayer1.CurrentTime; //XE10.3以降 TrackBar1.Max:= MediaPlayer1.Duration * MSecsPerSec / MediaTimeScale; TrackBar1.Value:= MediaPlayer1.CurrentTime * MSecsPerSec / MediaTimeScale; {$ELSE} TrackBar1.Max:= MediaPlayer1.Duration * MSecsPerSec / MediaTimeScale; TrackBar1.Value:= MediaPlayer1.CurrentTime * MSecsPerSec / MediaTimeScale; {$ENDIF} TrackBar1.Tag := 0; if MediaPlayer1.CurrentTime>=MediaPlayer1.Duration then Button2Click(nil); end else begin Button2Click(nil); end; end; procedure TForm1.TrackBar1Change(Sender: TObject); begin if TrackBar1.Tag=0 then begin {$IFDEF ANDROID} //FMX.Media.Android.pasのバグ対応 MediaPlayer1.CurrentTime := Round(TrackBar1.Value); {$ELSE} MediaPlayer1.CurrentTime := Round(TrackBar1.Value * MediaTimeScale / MSecsPerSec); {$ENDIF} end; end; end.