FireMonkey インターフェイスを使用して写真を撮る

提供: RAD Studio
移動先: 案内検索

モバイル チュートリアル:写真を撮って共有する、テキストを共有する(iOS および Android) への移動


このチュートリアルでは、IFMXPhotoLibrary および IFMXCameraService インターフェイスを使用して、モバイル デバイスで写真を撮って処理する方法を説明します。

アプリケーションのユーザー インターフェイスの構築

フォーム デザイナに以下のコンポーネントをドロップします。

  • TToolBar コンポーネント
    • このツールバー上に 2 つの TSpeedButton コンポーネントを配置します。このボタンを使用して、デバイスのカメラで写真を撮ったり、デバイスのフォト ライブラリから写真を選択します。
    • [オブジェクト インスペクタ]で、ボタンの以下のプロパティを指定します。
      • StyleLookup プロパティを、それぞれ cameratoolbuttonborderedsearchtoolbuttonbordered に設定します。
      • Align プロパティを、それぞれ LeftRight に設定します。
  • TImage コンポーネント
    • Align プロパティを Client に設定します。

このサンプル アプリケーションのフォームは、次の図のようになります。ここではまだ、フォーム デザイナ[スタイル][ビュー]は設定していません。

AppMasterUserInterface.png

メモ: スタイルビューの選択に関する詳細については、「スタイル セレクタ」および「FireMonkey ビューの利用」を参照してください。

デバイス カメラでの写真の撮影

モバイル デバイスのカメラで写真を撮るには、IFMXCameraService インターフェイスを使用します。手順は以下のとおりです。

  1. コード エディタを開き、以下の行がコードに含まれていない場合には追加します。
    Delphi の場合:
    uses
      System.Messaging, System.Permissions, FMX.MediaLibrary, FMX.Platform;
    
    C++ の場合:
    #include <System.Messaging.hpp>
    #include <System.Permissions.hpp>
    #include <FMX.MediaLibrary.hpp>
    #include <FMX.Platform.hpp>
    
  2. フォーム定義の private セクションに次の手続きヘッダーを追加します。
    Delphi の場合:
     procedure DoDidFinish(Image: TBitmap);
     procedure DoMessageListener(const Sender: TObject; const M: TMessage);
    
    C++ の場合:
    void __fastcall DoDidFinish(TBitmap *Image);
    void __fastcall DoMessageListener(const TObject *Sender, TMessage const *M);
    
  3. implementation セクションで、DoDidFinishDoMessageListener を次のように定義します。
    Delphi の場合:
     procedure TForm1.DoDidFinish(Image: TBitmap);
    begin
      Image1.Bitmap.Assign(Image);
    end;
    
    procedure TForm1.DoMessageListener(const Sender: TObject; const M: TMessage);
    begin
      if M is TMessageDidFinishTakingImageFromLibrary then
        Image1.Bitmap.Assign(TMessageDidFinishTakingImageFromLibrary(M).Value);
    end;
    
    C++ の場合:
    void __fastcall TForm1::DoDidFinish(TBitmap *Image) {
    	Image1->Bitmap->Assign(Image);
    }
    
    void __fastcall TForm1::DoMessageListener(const TObject *Sender, TMessage const *M) {
    	TMessageDidFinishTakingImageFromLibrary const *v = dynamic_cast<TMessageDidFinishTakingImageFromLibrary const *>(M);
    	if (v) {
    		Image1->Bitmap->Assign(v->Value);
    	}
    }
    
  4. フォーム デザイナSpeedButton1 ボタンをダブルクリックし、コード エディタonClick イベント ハンドラを次のように実装します。
    Delphi の場合:
    procedure TForm1.SpeedButton1Click(Sender: TObject);
    var
      Service: IFMXCameraService;
      Params: TParamsPhotoQuery;
    begin
      if TPlatformServices.Current.SupportsPlatformService(IFMXCameraService, Service) then
      begin
        Params.Editable := True;
        // Specifies whether to save a picture to device Photo Library
        Params.NeedSaveToAlbum := True;
        Params.RequiredResolution := TSize.Create(640, 640);
        Params.OnDidFinishTaking := DoDidFinish;
    {$IF Defined(ANDROID)}
        if TOSVersion.Check(11) then
          Service.TakePhoto(SpeedButton1, Params)
        else
          PermissionsService.RequestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE'],
            procedure(const Permissions: TClassicStringDynArray; const GrantResults: TClassicPermissionStatusDynArray)
            begin
              if (Length(GrantResults) = 1) and (GrantResults[0] = TPermissionStatus.Granted) then
                Service.TakePhoto(SpeedButton1, Params)
              else
                ShowMessage('Cannot take a photo because the required permission has not been granted')
            end);
    {$ELSE}
        Service.TakePhoto(SpeedButton1, Params);
    {$ENDIF}
      end
      else
        ShowMessage('This device does not support the camera service');
    end;
    
    C++ の場合:
    void __fastcall TForm1::SpeedButton1Click(TObject *Sender) {
        _di_IFMXCameraService service;
        TParamsPhotoQuery params;
        if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXCameraService), &service)) {
            params.Editable = true;
            // Specifies whether to save a picture to device Photo Library
            params.NeedSaveToAlbum = true;
            params.RequiredResolution = TSize(640, 640);
            params.OnDidFinishTaking = DoDidFinish;
    #if defined(_PLAT_ANDROID)
            if (TOSVersion::Check(11)) {
                service->TakePhoto(SpeedButton1, params);
            } else {
                PermissionsService()->RequestPermissions({ "android.permission.WRITE_EXTERNAL_STORAGE" },
                    [this, service, params](const TClassicStringDynArray Permissions, const TClassicPermissionStatusDynArray GrantResults) {
                        if (GrantResults.Length == 1 && GrantResults[0] == TPermissionStatus::Granted) {
                            service->TakePhoto(SpeedButton1, params);
                        } else {
                            ShowMessage("Cannot take a photo because the required permission has not been granted");
                        }
                    });
            }
    #else
            service->TakePhoto(SpeedButton1, params);
    #endif
        } else {
            ShowMessage("This device does not support the camera service");
        }
    }
    
メモ: FireMonkey アプリケーション プロジェクトの作成時、Camera project オプション([プロジェクト|オプション...|アプリケーション|使用する権限にあり、デフォルトでは有効になっている)は、アプリケーションの動作に予期しない影響を与えます。アプリケーションがカメラに直接アクセスせず(たとえば、TCameraComponent コンポーネントを利用するなど)、代わりに別のアプリケーション(たとえば、組み込みのカメラ アプリケーション)にその実行を依頼する場合でも、マニフェスト ファイルで CAMERA 使用権限が宣言されるとすぐに、IFMXCameraService プラットフォーム サービスに対する予期しない要求された使用権限となります。アプリケーションが不要な使用権限を要求しないように、Camera project オプションを無効にすることを検討してください。
メモ: プラットフォーム サービス IFMXCameraServiceIFMXTakenImageService の更新された実装では、取得した画像の編集がサポートされなくなりました。これは、「Android」プラットフォームにこの操作に対するビルドイン サポートがないためです。つまり、TParamsPhotoQuery.Editable フィールドは現在、無視されるようになりました。

アプリケーションを実行する

F9 を押すか[実行|実行]を選択して、モバイル デバイス上でアプリケーションを実行します。デバイスのカメラを起動するには、アプリケーションのツールバーにあるカメラ アイコンをタップします。

iOS Android

TakePicture IOS.png

TakePicture Android.png

この写真を使用するには:

  • Android デバイスでは[OK]をクリックします。
  • iOS デバイスでは[Use]をクリックします。

デバイスのフォト ライブラリに写真を保存する

デバイス カメラで撮った写真をアプリケーションで自動的にデバイスのフォト ライブラリに保存する場合には、TakePhoto メソッドの第2パラメータの NeedSaveToAlbumTrue に設定します(上記手順のステップ 4のコード スニペットを参照)。

そうすると、アプリケーションはデバイスのフォト ライブラリ内のアルバムに写真を保存します。このアルバムの名前は、デバイスのオペレーティング システムによって異なります。

OS バージョン   アルバム名  
iOS カメラ ロール
Android カメラ

デバイスのフォト ライブラリの写真の選択

FireMonkey で定義されている IFMXTakenImageService インターフェイスを使用すると、デバイスのフォト ライブラリから写真を選択することができます。

アプリケーションでデバイスのフォト ライブラリから写真を選択する手順は以下のとおりです。

  1. フォーム デザイナSpeedButton2 ボタン(写真選択用のボタン)をダブルクリックし、コード エディタonClick イベント ハンドラを次のように実装します。
    Delphi の場合:
    procedure TForm1.SpeedButton2Click(Sender: TObject);
    var
      Service: IFMXTakenService;
      Params: TParamsPhotoQuery;
    begin
      if TPlatformServices.Current.SupportsPlatformService(IFMXTakenService, Service) then
      begin
        Params.RequiredResolution := TSize.Create(640, 640);
        Params.OnDidFinishTaking := DoDidFinish;
        Service.TakeImageFromLibrary(SpeedButton2, Params);
      end;
    end;
    
    C++ の場合:
    void __fastcall TForm1::SpeedButton2Click(TObject *Sender) {
        _di_IFMXTakenImageService service;
        TParamsPhotoQuery params;
        if (TPlatformServices::Current->SupportsPlatformService(__uuidof(IFMXTakenImageService), &service) {
            params.RequiredResolution = TSize(640, 640);
            params.OnDidFinishTaking = DoDidFinish;
            service->TakeImageFromLibrary(SpeedButton2, params);
        } else {
            ShowMessage("This device does not support the photo library service");
        }
    }
    
  2. [構造]ビューForm1 を選択し、[オブジェクト インスペクタ][イベント]タブを開いて、OnCreate の隣の空のフィールドをダブルクリックします。その後、onFormCreate イベント ハンドラを次のように実装します。
    Delphi の場合:
     procedure TForm1.FormCreate(Sender: TObject);
    begin
    TMessageManager.DefaultManager.SubscribeToMessage(TMessageDidFinishTakingImageFromLibrary, DoMessageListener);
    end;
    
    C++ の場合:
    void __fastcall TForm1::FormCreate(TObject *Sender) {
    	TMessageManager::DefaultManager->SubscribeToMessage(__classid(TMessageDidFinishTakingImageFromLibrary),
    		TMessageListenerMethod(&DoMessageListener));
    }
    
  3. アプリケーションをコンパイルして実行します。写真を選択するには、検索ボタンをタップし、デバイスのフォト ライブラリから目的の写真を選択します。
    iOS Android

    TakePhotoFromLibraryAction.PNG

    Android SelectfromLibrary.png

    メモ: iPad デバイスでは、アプリケーションはサムネイル画像を、TakeImageFromLibrary メソッドの第1パラメータで指定されたコントロール要素の横にあるポップアップ ウィンドウに表示します。サンプル プロジェクトでは、SpeedButton2 は検索ボタンを参照しています。
メモ: プラットフォーム サービス IFMXCameraServiceIFMXTakenImageService の更新された実装では、取得した画像の編集がサポートされなくなりました。これは、「Android」プラットフォームにこの操作に対するビルドイン サポートがないためです。つまり、TParamsPhotoQuery.Editable フィールドは現在、無視されるようになりました。

関連項目