unit Unit1; interface uses System.Messaging, {$IF DEFINED(ANDROID) AND (RTLVersion >= 33)} Androidapi.JNI.Os, System.Permissions, {$ENDIF} 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.ScrollBox, FMX.Memo; type TForm1 = class(TForm) mmo1: TMemo; btn1: TButton; btn2: TButton; btn3: TButton; btn4: TButton; chkAllowMultiSelect: TCheckBox; procedure btn2Click(Sender: TObject); procedure btn1Click(Sender: TObject); procedure btn3Click(Sender: TObject); procedure btn4Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } {$IF DEFINED(ANDROID) AND (RTLVersion >= 33)} procedure PermissionsCheck; procedure PermissionsResultHandler(const APermissions: TArray; const AGrantResults: TArray); {$ENDIF} procedure DoReceivedImagePath(const Sender: TObject; const M: TMessage); procedure DoCancelReceivingImage(const Sender: TObject; const M: TMessage); public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} uses {$IFDEF ANDROID} Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Provider, Androidapi.JNI.JavaTypes, Androidapi.JNI.App, Androidapi.JNI.Net, Androidapi.Helpers, ksAndroid.Helpers, FMX.Platform.Android, {$ENDIF} FMX.Platform; type TOpenFileCallback = reference to procedure(const ACode: Integer; const APath: string; const APathes: TStrings); TOpenFileEvent = procedure (const ACode: Integer; const APath: string; const APathes: TStrings) of object; const FILE_SELECT_CODE = 0; var FOpenFileMessageID: Integer = 0; FOpenFileCallback: TOpenFileCallback = nil; FOpenFileEvent: TOpenFileEvent = nil; FOpenFileAction: JString = nil; // https://stackoverflow.com/questions/31002388/android-intent-extra-allow-multiple-allows-only-single-picking procedure HandleActivityMessage(const Sender: TObject; const M: TMessage); var I: Integer; LCode: Integer; FileName:string; LURI: Jnet_Uri; LClipData: JClipData; LList: TStringList; begin if (not Assigned(M)) or (not (M is TMessageResultNotification)) or (TMessageResultNotification(M).RequestCode <> FILE_SELECT_CODE) then Exit; LCode := TMessageResultNotification(M).ResultCode; FileName := ''; LList := nil; {$IFDEF DEBUG} if LCode = TJActivity.JavaClass.RESULT_CANCELED then Log.d('---HandleActivityMessage-RESULT_CANCELED'); if LCode = TJActivity.JavaClass.RESULT_FIRST_USER then Log.d('---HandleActivityMessage-RESULT_FIRST_USER'); {$ENDIF} if LCode = TJActivity.JavaClass.RESULT_OK then begin if TMessageResultNotification(M).Value <> nil then begin with TMessageResultNotification(M).Value do begin LURI := getData; if LURI <> nil then FileName := TAndroidHelperEx.FileFromUri(LURI) else begin LClipData := getClipData; if LClipData <> nil then begin LList := TStringList.Create; for I := 0 to LClipData.getItemCount - 1 do begin LURI := LClipData.getItemAt(I).getUri; if LURI <> nil then LList.Add(TAndroidHelperEx.FileFromUri(LURI)) {$IFDEF DEBUG} else Log.d('---HandleActivityMessage-getClipData.getItemAt(%d).getUri:nil', [I]); {$ENDIF} end; end {$IFDEF DEBUG} else Log.d('---HandleActivityMessage-getData & getClipData:nil'); {$ENDIF} end; end; end else begin {$IFDEF DEBUG} Log.d('---HandleActivityMessage-Value:nil'); {$ENDIF} end; end; {$IFDEF DEBUG} Log.d('---HandleActivityMessage-ResultCode:%d-', [LCode]); {$ENDIF} if Assigned(FOpenFileCallback) then FOpenFileCallback(LCode, FileName, LList); if Assigned(FOpenFileEvent) then FOpenFileEvent(LCode, FileName, LList); if Assigned(LList) then FreeAndNil(LList); if FOpenFileMessageID <> 0 then begin TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FOpenFileMessageID); FOpenFileMessageID := 0; FOpenFileCallback := nil; FOpenFileEvent := nil; end; end; function OpenFileDialog(AOpenFileCallback: TOpenFileCallback; AOpenFileEvent: TOpenFileEvent; AExt, ADir: string; AData: Jnet_Uri; AAllowMultiSelect: Boolean): Boolean; var LIntent: JIntent; LType: string; begin Result := False; LType := ''; if (LType = '') or (AExt = '*.*') or (AExt = '*') then LType := '' else if Pos('/', AExt) > 0 then LType := AExt else LType := JStringToString(TAndroidHelperEx.GetMimeType(AExt)); if LType = '' then LType := '*/*'; if FOpenFileAction = nil then //默认值 FOpenFileAction := TJIntent.JavaClass.ACTION_GET_CONTENT; LIntent := TJIntent.JavaClass.init(FOpenFileAction); LIntent.setType(StringToJString(LType)); if AAllowMultiSelect then LIntent.putExtra(TJIntent.JavaClass.EXTRA_ALLOW_MULTIPLE, true); if not FOpenFileAction.equals(TJIntent.JavaClass.ACTION_PICK) then LIntent.addCategory(TJIntent.JavaClass.CATEGORY_OPENABLE); if AData <> nil then LIntent.setData(AData) else if ADir <> '' then LIntent.setData(TAndroidHelperEx.UriParse(ADir)); if FOpenFileMessageID = 0 then begin FOpenFileMessageID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification, HandleActivityMessage); FOpenFileCallback := AOpenFileCallback; FOpenFileEvent := AOpenFileEvent; end; try try //Result := TAndroidHelperEx.StartActivity(TJIntent.JavaClass.createChooser(Intent, StrToJCharSequence(ATitle)), FILE_SELECT_CODE) Result := TAndroidHelperEx.StartActivity(LIntent, FILE_SELECT_CODE); except raise Exception.Create('File Manager not found'); end; finally Form1.mmo1.Lines.Add(Format('OpenFileDialog:%s', [BoolToStr(Result, True)])); end; end; procedure TForm1.btn1Click(Sender: TObject); begin //Intent.setData(TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI) // 这个可以用来限定APP,比如这个就是 图库 //Intent.setData(TJContactsContract_Contacts.JavaClass.CONTENT_URI) // 联系人,不指定这个的话会直接取消 FOpenFileAction := TJIntent.JavaClass.ACTION_PICK; OpenFileDialog(procedure(const ACode: Integer; const APath: string; const APathes: TStrings) begin if APath <> '' then mmo1.Lines.Add(APath) else if Assigned(APathes) then mmo1.Lines.AddStrings(APathes) else mmo1.Lines.Add(Format('Error code: %d', [ACode])); end, nil, '*/*', '', TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI, chkAllowMultiSelect.IsChecked ) end; procedure TForm1.btn2Click(Sender: TObject); begin FOpenFileAction := TJIntent.JavaClass.ACTION_GET_CONTENT; OpenFileDialog(procedure(const ACode: Integer; const APath: string; const APathes: TStrings) begin if APath <> '' then mmo1.Lines.Add(APath) else if Assigned(APathes) then mmo1.Lines.AddStrings(APathes) else mmo1.Lines.Add(Format('Error code: %d', [ACode])); end, nil, '*/*', '', nil, chkAllowMultiSelect.IsChecked ) end; procedure TForm1.btn3Click(Sender: TObject); begin FOpenFileAction := TJIntent.JavaClass.ACTION_OPEN_DOCUMENT; OpenFileDialog(procedure(const ACode: Integer; const APath: string; const APathes: TStrings) begin if APath <> '' then mmo1.Lines.Add(APath) else if Assigned(APathes) then mmo1.Lines.AddStrings(APathes) else mmo1.Lines.Add(Format('Error code: %d', [ACode])); end, nil, '*/*', '', nil, chkAllowMultiSelect.IsChecked ) end; procedure TForm1.btn4Click(Sender: TObject); var FSize: TSize; begin FSize.cx := TCanvasManager.DefaultCanvas.GetAttribute(TCanvasAttribute.MaxBitmapSize); FSize.cy := TCanvasManager.DefaultCanvas.GetAttribute(TCanvasAttribute.MaxBitmapSize); MainActivity.getFMXMediaLibrary.takeImageFromLibrary(FSize.Width, FSize.Height, False); end; procedure TForm1.DoCancelReceivingImage(const Sender: TObject; const M: TMessage); begin if (M is TMessageCancelReceivingImage) then mmo1.Lines.Add('TMessageCancelReceivingImage'); end; procedure TForm1.DoReceivedImagePath(const Sender: TObject; const M: TMessage); begin if (M is TMessageReceivedImagePath) then mmo1.Lines.Add(Format('TMessageReceivedImagePath: %s', [(M as TMessageReceivedImagePath).Value])); end; procedure TForm1.FormCreate(Sender: TObject); begin TMessageManager.DefaultManager.SubscribeToMessage(TMessageCancelReceivingImage, DoCancelReceivingImage); TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedImagePath, DoReceivedImagePath); end; procedure TForm1.FormDestroy(Sender: TObject); begin TMessageManager.DefaultManager.Unsubscribe(TMessageReceivedImagePath, DoReceivedImagePath); TMessageManager.DefaultManager.Unsubscribe(TMessageCancelReceivingImage, DoCancelReceivingImage); end; procedure TForm1.FormShow(Sender: TObject); begin {$IF DEFINED(ANDROID) AND (RTLVersion >= 33)} PermissionsCheck; {$ENDIF} end; {$IF DEFINED(ANDROID) AND (RTLVersion >= 33)} procedure TForm1.PermissionsCheck; begin if TJBuild_VERSION.JavaClass.SDK_INT >= 23 then PermissionsService.RequestPermissions([JStringToString(TJManifest_permission.JavaClass.CAMERA), JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE), JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE)], PermissionsResultHandler); end; procedure TForm1.PermissionsResultHandler(const APermissions: TArray; const AGrantResults: TArray); begin if PermissionsService.IsEveryPermissionGranted( [JStringToString(TJManifest_permission.JavaClass.CAMERA), JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE), JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE)]) then mmo1.Lines.Add('Permission granted') else mmo1.Lines.Add('Permission not granted'); end; {$ENDIF} end.