トップへ(mam-mam.net/)

Androidのフォトライブラリ(フォト、ギャラリー)アクテビティを起動して選択した写真を表示する ~Delphiでお手軽プログラミング

検索:

Androidのフォトライブラリ(フォト、ギャラリー)アクテビティを起動して選択した写真を表示する ~Delphiでお手軽プログラミング

TActionListのTTakePhotoFromLibraryActionを使用してAndroidのフォトライブラリ(フォト、ギャラリー)から選択した写真をアプリで表示する方法です。

(参考)
TTakePhotoFromLibraryActionは選択した写真を外部ストレージに保存してから取り出しているようです。
この為、Android6.0(API Level23)以降で使う場合には、外部ストレージへのアクセス権限が必要になり、権限取得などが面倒になります。
よって、「startActivityForResultでフォトライブラリを起動して選択した写真を表示する」をお勧めします。

プロジェクトの作成とファイルの保存

ファイル⇒新規作成⇒マルチデバイス アプリケーション -Delphi をクリックします。
「空のアプリケーション」を選択してOKを押します。
「すべて保存」ボタンを押して、プロジェクト(PhotoLibrary.dproj等)とユニット(Unit1.pas等)に名前を付けて保存します。

ターゲット設定、画面設計

(PCに実機をUSBで接続して)右上ペインのターゲットプラットフォームを展開して「Android64ビット」(接続した実機)をダブルクリックして切り替えます。
右下ペインのパレットからTPanelをドラッグし、プロパティ「Align」を[Top]に設定します。
右下ペインのパレットからTImageをドラッグし、プロパティ「Align」を[Client]に設定します。
  MultiResBitmapプロパティに白紙の画像ファイルを設定します。(2×2ドットのjpgファイルなどを事前に作成してあてがいます。)
右下ペインのパレットからTButtonをPanel1の上にドラッグします。
右下ペインのパレットからTActionListをドラッグします。

アクションの設定、ソースコードの記述

ActionList1をダブルクリックします。左上のボタンから「標準のアクションの新規作成」をクリックします。
メディアライブラリ⇒[TTakePhotoFromLibraryAction]を選択してOKボタンを押します。

TTakePhotoFromLibraryAction1を選択(クリック)します。

親ウィンドウにある左下ペイン「オブジェクトインスペクタ」の「イベント」タブを選択し、 [OnDidFinishTaking]の右の空欄をダブルクリックします。

OnDidFinishTakingのプロトタイプ宣言等が自動で記述されたソースコードエディタに切り替わりますので、以下ソースを入力します。
procedure TForm1.TakePhotoFromLibraryAction1DidFinishTaking(Image: TBitmap);
begin
  Image1.Bitmap.Assign(Image);
end;



キーボードから「F12」キーを押してデザインに切り替えます。Button1をダブルクリックします。


OnClickのプロトタイプ宣言等が自動で記述されたソースコードエディタに切り替わりますので、以下ソースを入力します。
procedure TForm1.Button1Click(Sender: TObject);
begin
  TakePhotoFromLibraryAction1.ExecuteTarget(nil);
end;



「プロジェクト」⇒「オプション」をクリックします。

「アプリケーション」⇒「使用する権限」から[外部ストレージの読み取り][外部ストレージへの書き込み]にチェックを入れます。
保存ボタンをクリックします。

Android6(APIレベル23)以降の対応

Android6(APIレベル23)より前なら以上で動くのですが、APIレベル23以降は外部ストレージへのアクセス権限をプログラムで制御する必要がある。
キーボードの「F12」キーを押してデザインモードに切り替え、左上ペイン「構造」の[Form1]をクリックします。
左下ペインの「オブジェクトインスペクタ」の「イベント」タブを選択し、[OnCreate]の右側空欄をダブルクリックします。

以下ソースコードを追加します。
procedure TForm1.FormCreate(Sender: TObject);
begin
  RequestPermissions;
end;



更にたくさん以下赤字部分のソースコードを記述します。(赤字はすべてAPIレベル23以降対応ソースコードです)
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Actions,
  FMX.ActnList, FMX.StdActns, FMX.MediaLibrary.Actions, FMX.Objects,
  FMX.StdCtrls, FMX.Controls.Presentation,System.Permissions;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    Image1: TImage;
    ActionList1: TActionList;
    TakePhotoFromLibraryAction1: TTakePhotoFromLibraryAction;
    procedure TakePhotoFromLibraryAction1DidFinishTaking(Image: TBitmap);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private 宣言 }
  public
    { public 宣言 }
    procedure PermissionRequestResult(
      Sender: TObject; const APermissions: TArray<string>;
      const AGrantResults: TArray<TPermissionStatus>);
    procedure RequestPermissions();
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses
  Androidapi.Helpers, Androidapi.JNI.Os,
  Androidapi.Jni.Support, FMX.DialogService;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TakePhotoFromLibraryAction1.ExecuteTarget(nil);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  RequestPermissions;
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.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;

procedure TForm1.RequestPermissions;
var
    //外部ストレージの書き込み権限があると読み込み権限も発生する
    //FPmsReadExternalStorage:string;
    FPmsWriteExternalStorage:string;
begin
  FPmsWriteExternalStorage :=
    JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
  PermissionsService.RequestPermissions(
    [FPmsWriteExternalStorage],PermissionRequestResult);
end;

procedure TForm1.TakePhotoFromLibraryAction1DidFinishTaking(Image: TBitmap);
begin
  Image1.Bitmap.Assign(Image);
end;

end.

実機をつないで実行

実機をUSBケーブルでつないで右ペインの「ターゲット」の実機をダブルクリックして選択したら、「実行」ボタンをクリックして実機で実行できます。