無音で写真撮影する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)対応となっています。
写真を撮影して、保存するソースコードはごく僅かです。
