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

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

Androidのフォトライブラリ(フォト、ギャラリー)アクテビティを起動して選択した写真を表示する

~フォトライブラリから選択写真を受け渡して表示するアプリを作成する



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

ファイル⇒新規作成⇒マルチデバイス アプリケーション -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以降は外部ストレージへのアクセス権限をプログラムで制御する必要がある。(どうしてわざわざこんな面倒な仕様に変えるのでしょう。Googleさん。)
キーボードの「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ケーブルでつないで右ペインの「ターゲット」の実機をダブルクリックして選択したら、「実行」ボタンをクリックして実機で実行できます。



Copyright 2019 Mam