Delphiでお手軽プログラミング

Delphiでお手軽プログラミングメニュー

Delphiで無音で写真撮影する「無音カメラ」Android用アプリケーションを作成します。



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






Copyright 2019 Mam