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.
