無音で写真撮影するAndroidアプリケーションを作る ~Delphiソースコード集
1.プロジェクトを作成
ファイル⇒新規作成⇒マルチデバイス アプリケーション -Delphiをクリックします。
「空のアプリケーション」を選択してOKを押します。
2.プロジェクトの保存
ファイル⇒すべて保存、またはすべて保存ボタンを押して、プロジェクトとユニットを保存します。「新しいフォルダ」ボタンを押して「TakeCamera」フォルダ等を作成し、ユニットはデフォルトの「Unit1.pas」、 プロジェクトは「NoSoundTakePicture.dproj」で保存します。
3.画面の作成
TPanel(コンポーネントパレットの検索ボックスにpanel等と入力して検索してもよい)をフォームに ドラッグ&ドロップし、プロパティを以下に設定します。Panel1.Align:Left
TButtonをPanel1にドラッグ&ドロップし、プロパティを以下に設定します。
Button1.Align:Top
Button1.Text:切り替え
もう1つTButtonをPanel1にドラッグ&ドロップし、プロパティを以下に設定します。
Button2.Align:Top
Button2.Text:撮影
TImageをフォームにドラッグ&ドロップし、プロパティを以下に設定します。
Image1.Align:Client
TCameraComponentをフォームにドラッグ&ドロップします。
4.プロジェクトオプションの設定
プロジェクト⇒オプション をクリックします。左ペインの アプリケーション⇒使用する権限 をクリックします。
ターゲットを、「すべての構成 - Androidプラットフォーム」に切り替えます。
カメラの使用、外部ストレージの読み取り、外部ストレージの書き込み のみにチェックをいれます。
5.ターゲットプラットフォームの切り替え
ターゲットプラットフォームをAndroidに切り替えます。以下は実機(507SH)をUSB接続して、 右ペインに表示された実機(507SH)をダブルクリックして選択しています。6.ソースコードの記述
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.StdCtrls, FMX.Controls.Presentation, FMX.Objects, FMX.Media, FMX.Platform, System.Permissions, FMX.MediaLibrary; type TForm1 = class(TForm) Image1: TImage; Panel1: TPanel; Button1: TButton; CameraComponent1: TCameraComponent; Button2: TButton; procedure FormCreate(Sender: TObject); procedure CameraComponent1SampleBufferReady( Sender: TObject; const ATime: TMediaTime); procedure Button2Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); private { private 宣言 } function AppEvent(iAppEvent:TApplicationEvent;iContext:TObject):Boolean; procedure PermissionRequestResult( Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); procedure RequestPermissions(); { public 宣言 } end; var Form1: TForm1; implementation {$R *.fmx} uses Androidapi.Helpers, Androidapi.JNI.JavaTypes, Androidapi.JNI.Os, Androidapi.Jni.Support, FMX.DialogService; procedure TForm1.PermissionRequestResult( Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); begin //カメラとストレージの権限があるか if (AGrantResults[0]<>TPermissionStatus.Granted) or (AGrantResults[1]<>TPermissionStatus.Granted) then begin //権限がない場合 //「□今後は表示しない」チェックボックスにチェックが入っているか if (TJActivityCompat.JavaClass.shouldShowRequestPermissionRationale( TAndroidHelper.Activity, TJManifest_permission.JavaClass.CAMERA)) or (TJActivityCompat.JavaClass.shouldShowRequestPermissionRationale( TAndroidHelper.Activity, TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE)) 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; function TForm1.AppEvent(iAppEvent: TApplicationEvent; iContext: TObject): Boolean; begin Result:=False; case iAppEvent of TApplicationEvent.BecameActive: begin //focus取得時 CameraComponent1.Active:=true; Sleep(100); CameraComponent1.Active:=False; Sleep(400); //オートフォーカスモードに設定する CameraComponent1.FocusMode:=TFocusMode.ContinuousAutoFocus; CameraComponent1.Active:=True; end; TApplicationEvent.WillBecomeInactive: begin //focus喪失時 CameraComponent1.Active:=False; end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin CameraComponent1.Active:=False; if CameraComponent1.Kind=TCameraKind.BackCamera then CameraComponent1.Kind:=TCameraKind.FrontCamera else CameraComponent1.Kind:=TCameraKind.BackCamera; CameraComponent1.Active:=True; end; procedure TForm1.Button2Click(Sender: TObject); var PhotoLibrary: IFMXPhotoLibrary; begin //撮影ボタンが押された if TPlatformServices.Current.SupportsPlatformService( IFMXPhotoLibrary, PhotoLibrary) then begin //Android標準のフォトアルバムに撮影画像を送って保存してもらう PhotoLibrary.AddImageToSavedPhotosAlbum(Image1.Bitmap); end; end; procedure TForm1.CameraComponent1SampleBufferReady(Sender: TObject; const ATime: TMediaTime); begin TThread.Synchronize( TThread.CurrentThread, procedure begin CameraComponent1.SampleBufferToBitmap(Image1.Bitmap,true); end ); end; procedure TForm1.FormCreate(Sender: TObject); var APPEventService:IFMXApplicationEventService; begin CameraComponent1.Kind:=TCameraKind.BackCamera; if TPlatformServices.Current.SupportsPlatformService( IFMXApplicationEventService) then begin try APPEventService:=IFMXApplicationEventService( TPlatformServices.Current.GetPlatformService( IFMXApplicationEventService ) ); except APPEventService:=nil; end; end; if (APPEventService<>nil) then APPEventService.SetApplicationEventHandler(AppEvent); RequestPermissions(); end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); begin if Key = vkHardwareBack then Key := 0; end; procedure TForm1.RequestPermissions(); var FPmsCamera: string; FPmsReadExternalStorage:string; FPmsWriteExternalStorage:string; begin FPmsCamera := JStringToString(TJManifest_permission.JavaClass.CAMERA); FPmsWriteExternalStorage := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE); PermissionsService.RequestPermissions( [FPmsCamera,FPmsWriteExternalStorage],PermissionRequestResult); end; end.
7.完成したアプリケーションを起動する
実行⇒実行 又はツールバーの「右三角」ボタンを押して実行します。コンパイルされ、実機にapkファイルが自動でインストールされ、アプリケーションが起動します。
ソースコードの大半は、Android6.0(APIレベル23)対応となっています。
写真を撮影して、保存するソースコードはごく僅かです。