I need to create a function in my Android App that allows user to open the phone gallery, select more than one picture a time, then save the selected pictures in my local DB. What I need is the way to use Android Intent to get the selected pictures (files name and path). Hope you can understand my question.
I'm using this code:
if TPlatformServices.Current.SupportsPlatformService(IFMXTakenImageService,
IInterface(ImageService)) then
begin
Params.RequiredResolution := TSize.Create(640, 640);
Params.OnDidFinishTaking := DoDidFinish;
ImageService.TakeImageFromLibrary(SpeedButton2, Params);
end;
procedure TfGallery.DoDidFinish(Image: TBitmap);
begin
Image1.Bitmap.Assign(Image);
end;
Unfortunately this code can return one image a time from gallery.
Edit - Based on the answer of Nick Cardoso, the following code works for the first part of the problem:
Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_PICK);
intent.setType(StringToJString('image/*'));
intent.setAction(TjIntent.JavaClass.ACTION_GET_CONTENT);
Intent.putExtra(TJIntent.JavaClass.EXTRA_ALLOW_MULTIPLE,true);
LaunchActivity(Intent);
The code above works to select multiple pictures. Now I'm stuck to find a solution to get back (in a callback function) the selected files in Delphi!
Edit - 25/02/2024 The following code is the result of many tests. Finally it works
procedure TfGallery.SelectImagesFromGallery;
var
Intent: JIntent;
begin
FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification,
HandleActivityMessage);
Intent := TJIntent.Create;
Intent.setAction(TJIntent.JavaClass.ACTION_PICK);
Intent.setType(StringToJString('image/*'));
Intent.setAction(TjIntent.JavaClass.ACTION_GET_CONTENT);
Intent.putExtra(TJIntent.JavaClass.EXTRA_ALLOW_MULTIPLE, True);
// LaunchActivity(Intent);
TAndroidHelper.Activity.startActivityForResult(Intent, 0);
end;
procedure TfGallery.HandleActivityMessage(const Sender: TObject; const M: TMessage);
begin
// showmessage('HandleActivityMessage');
if M is TMessageResultNotification then
OnActivityResult(TMessageResultNotification(M).RequestCode, TMessageResultNotification(M).ResultCode,
TMessageResultNotification(M).Value);
end;
function TfGallery.OnActivityResult(RequestCode, ResultCode: Integer; Data: JIntent): Boolean;
var
ClipData: JClipData;
ClipDataItemCount, I: Integer;
ImagePaths: TArray<string>;
Uri: Jnet_Uri;
begin
Result := False;
TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FMessageSubscriptionID);
FMessageSubscriptionID := 0;
if ResultCode = TJActivity.JavaClass.RESULT_OK then
begin
ClipData := Data.getClipData();
if Assigned(ClipData) then
begin
ClipDataItemCount := ClipData.getItemCount();
SetLength(ImagePaths, ClipDataItemCount);
for I := 0 to ClipDataItemCount - 1 do
begin
Uri := ClipData.getItemAt(I).getUri();
ImagePaths[I] := JStringToString(Uri.toString());
showmessage('ImagePaths[I] = '+INTTOSTR(I) + ' -- '+ImagePaths[I]);
end;
// Ora ImagePaths contiene i percorsi delle immagini selezionate
// Puoi procedere con l'elaborazione dei percorsi delle immagini come desiderato
// ...
end;
end
else if ResultCode = TJActivity.JavaClass.RESULT_CANCELED then
begin
Toast('You cancelled the scan', ShortToast);
end;
Result := True;
end;
Usage:
procedure TfGallery.Button3Click(Sender: TObject);
begin
SelectImagesFromGallery();
end;
I'll start with a Disclaimer - I don't write Delphi. Your question was the first time I've heard of Firemonkey and I expect that the same is true of the majority of Android Developers (hence the low answer rate).
My understanding is that behind the scenes Firemonkey fires off ordinary Android Intents to interact with standard components. This means if we can switch the intent to one which return multiple images, we have a solution.
If you are targeting only Android 18 and higher, it's simply a matter of adding the EXTRA_ALLOW_MULTIPLE
extra to the existing photo chooser Intent. With pure Android that is as simple as adding the following and reading back the clip data (like in this answer):
pickerIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE);
If you're targeting older Android versions you could instead include a custom library like this one (or one of these) into your project and target that activity with a new intent.
My research shows that Firemonkey allows custom actions, you'll have to research yourself how to implement one, as you'll better understand the code you read.
However this post (which seems like required reading) showed me it is possible to create your own Intents, which means the code inside your initial action will be similar to this (If you can find the sources for the current TakeImageFromLibrary action you can base your code off of that):
Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_PICK);
//OR Intent := TJIntent.JavaClass.init(StringToJString('com.some.library.client.SOME_ACTION'));
Intent.putExtra(TJIntent.JavaClass.EXTRA_ALLOW_MULTIPLE);
LaunchActivity(Intent);
Additional note: default behaviour for selecting multiple in the gallery is long press