Unit1.pas 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. unit Unit1;
  2. interface
  3. uses
  4. System.Messaging,
  5. System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  6. FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  7. FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo;
  8. type
  9. TForm1 = class(TForm)
  10. mmo1: TMemo;
  11. btn1: TButton;
  12. btn2: TButton;
  13. btn3: TButton;
  14. btn4: TButton;
  15. chkAllowMultiSelect: TCheckBox;
  16. procedure btn2Click(Sender: TObject);
  17. procedure btn1Click(Sender: TObject);
  18. procedure btn3Click(Sender: TObject);
  19. procedure btn4Click(Sender: TObject);
  20. procedure FormCreate(Sender: TObject);
  21. procedure FormDestroy(Sender: TObject);
  22. private
  23. { Private declarations }
  24. procedure DoReceivedImagePath(const Sender: TObject; const M: TMessage);
  25. procedure DoCancelReceivingImage(const Sender: TObject; const M: TMessage);
  26. public
  27. { Public declarations }
  28. end;
  29. var
  30. Form1: TForm1;
  31. implementation
  32. {$R *.fmx}
  33. uses
  34. {$IFDEF ANDROID}
  35. Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Provider,
  36. Androidapi.JNI.JavaTypes, Androidapi.JNI.App, Androidapi.JNI.Net,
  37. Androidapi.Helpers, ksAndroid.Helpers,
  38. FMX.Platform.Android,
  39. {$ENDIF}
  40. FMX.Platform;
  41. type
  42. TOpenFileCallback = reference to procedure(const ACode: Integer; const APath: string; const APathes: TStrings);
  43. TOpenFileEvent = procedure (const ACode: Integer; const APath: string; const APathes: TStrings) of object;
  44. const
  45. FILE_SELECT_CODE = 0;
  46. var
  47. FMessageChooserID: Integer = 0;
  48. FOpenFileCallback: TOpenFileCallback;
  49. FOpenFileEvent: TOpenFileEvent;
  50. FAction: JString;
  51. // https://stackoverflow.com/questions/31002388/android-intent-extra-allow-multiple-allows-only-single-picking
  52. procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);
  53. var
  54. I: Integer;
  55. LCode: Integer;
  56. FileName:string;
  57. LURI: Jnet_Uri;
  58. LClipData: JClipData;
  59. LList: TStringList;
  60. begin
  61. if (not Assigned(M)) or (not (M is TMessageResultNotification))
  62. or (TMessageResultNotification(M).RequestCode <> FILE_SELECT_CODE) then
  63. Exit;
  64. LCode := TMessageResultNotification(M).ResultCode;
  65. FileName := '';
  66. LList := nil;
  67. {$IFDEF DEBUG}
  68. if LCode = TJActivity.JavaClass.RESULT_CANCELED then
  69. Log.d('---HandleActivityMessage-RESULT_CANCELED');
  70. if LCode = TJActivity.JavaClass.RESULT_FIRST_USER then
  71. Log.d('---HandleActivityMessage-RESULT_FIRST_USER');
  72. {$ENDIF}
  73. if LCode = TJActivity.JavaClass.RESULT_OK then begin
  74. if TMessageResultNotification(M).Value <> nil then begin
  75. with TMessageResultNotification(M).Value do begin
  76. LURI := getData;
  77. if LURI <> nil then
  78. FileName := TAndroidHelperEx.FileFromUri(LURI)
  79. else begin
  80. LClipData := getClipData;
  81. if LClipData <> nil then begin
  82. LList := TStringList.Create;
  83. for I := 0 to LClipData.getItemCount - 1 do begin
  84. LURI := LClipData.getItemAt(I).getUri;
  85. if LURI <> nil then
  86. LList.Add(TAndroidHelperEx.FileFromUri(LURI))
  87. {$IFDEF DEBUG}
  88. else
  89. Log.d('---HandleActivityMessage-getClipData.getItemAt(%d).getUri:nil', [I]);
  90. {$ENDIF}
  91. end;
  92. end
  93. {$IFDEF DEBUG}
  94. else
  95. Log.d('---HandleActivityMessage-getData & getClipData:nil');
  96. {$ENDIF}
  97. end;
  98. end;
  99. end
  100. else begin
  101. {$IFDEF DEBUG}
  102. Log.d('---HandleActivityMessage-Value:nil');
  103. {$ENDIF}
  104. end;
  105. end;
  106. {$IFDEF DEBUG}
  107. Log.d('---HandleActivityMessage-ResultCode:%d-', [LCode]);
  108. {$ENDIF}
  109. if Assigned(FOpenFileCallback) then
  110. FOpenFileCallback(LCode, FileName, LList);
  111. if Assigned(FOpenFileEvent) then
  112. FOpenFileEvent(LCode, FileName, LList);
  113. if Assigned(LList) then
  114. FreeAndNil(LList);
  115. if FMessageChooserID <> 0 then begin
  116. TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FMessageChooserID);
  117. FMessageChooserID := 0;
  118. FOpenFileCallback := nil;
  119. FOpenFileEvent := nil;
  120. end;
  121. end;
  122. function OpenFileDialog(AExt, ADir: string; AData: Jnet_Uri = nil; AAllowMultiSelect: Boolean = False; AOpenFileCallback: TOpenFileCallback = nil; AOpenFileEvent: TOpenFileEvent = nil): Boolean;
  123. var
  124. LIntent: JIntent;
  125. LType: string;
  126. begin
  127. Result := False;
  128. LType := '';
  129. if (LType = '') or (AExt = '*.*') or (AExt = '*') then
  130. LType := ''
  131. else if Pos('/', AExt) > 0 then
  132. LType := AExt
  133. else
  134. LType := JStringToString(TAndroidHelperEx.GetMimeType(AExt));
  135. if LType = '' then
  136. LType := '*/*';
  137. LIntent := TJIntent.JavaClass.init(FAction);
  138. LIntent.setType(StringToJString(LType));
  139. if AAllowMultiSelect then
  140. LIntent.putExtra(TJIntent.JavaClass.EXTRA_ALLOW_MULTIPLE, true);
  141. if not FAction.equals(TJIntent.JavaClass.ACTION_PICK) then
  142. LIntent.addCategory(TJIntent.JavaClass.CATEGORY_OPENABLE);
  143. if AData <> nil then
  144. LIntent.setData(AData)
  145. else if ADir <> '' then
  146. LIntent.setData(TAndroidHelperEx.UriParse(ADir));
  147. if FMessageChooserID = 0 then begin
  148. FMessageChooserID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification, HandleActivityMessage);
  149. FOpenFileCallback := AOpenFileCallback;
  150. FOpenFileEvent := AOpenFileEvent;
  151. end;
  152. try
  153. try
  154. //Result := TAndroidHelperEx.StartActivity(TJIntent.JavaClass.createChooser(Intent, StrToJCharSequence(ATitle)), FILE_SELECT_CODE)
  155. Result := TAndroidHelperEx.StartActivity(LIntent, FILE_SELECT_CODE);
  156. except
  157. raise Exception.Create('File Manager not found');
  158. end;
  159. finally
  160. Form1.mmo1.Lines.Add(Format('OpenFileDialog:%s', [BoolToStr(Result, True)]));
  161. end;
  162. end;
  163. procedure TForm1.btn1Click(Sender: TObject);
  164. begin
  165. //Intent.setData(TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI) // 这个可以用来限定APP,比如这个就是 图库
  166. //Intent.setData(TJContactsContract_Contacts.JavaClass.CONTENT_URI) // 联系人,不指定这个的话会直接取消
  167. FAction := TJIntent.JavaClass.ACTION_PICK;
  168. OpenFileDialog('*/*', '', TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI, chkAllowMultiSelect.IsChecked,
  169. procedure(const ACode: Integer; const APath: string; const APathes: TStrings) begin
  170. if APath <> '' then
  171. mmo1.Lines.Add(APath)
  172. else if Assigned(APathes) then
  173. mmo1.Lines.AddStrings(APathes)
  174. else
  175. mmo1.Lines.Add(Format('Error code: %d', [ACode]));
  176. end
  177. )
  178. end;
  179. procedure TForm1.btn2Click(Sender: TObject);
  180. begin
  181. FAction := TJIntent.JavaClass.ACTION_GET_CONTENT;
  182. OpenFileDialog('*/*', '', nil, chkAllowMultiSelect.IsChecked,
  183. procedure(const ACode: Integer; const APath: string; const APathes: TStrings) begin
  184. if APath <> '' then
  185. mmo1.Lines.Add(APath)
  186. else if Assigned(APathes) then
  187. mmo1.Lines.AddStrings(APathes)
  188. else
  189. mmo1.Lines.Add(Format('Error code: %d', [ACode]));
  190. end
  191. )
  192. end;
  193. procedure TForm1.btn3Click(Sender: TObject);
  194. begin
  195. FAction := TJIntent.JavaClass.ACTION_OPEN_DOCUMENT;
  196. OpenFileDialog('*/*', '', nil, chkAllowMultiSelect.IsChecked,
  197. procedure(const ACode: Integer; const APath: string; const APathes: TStrings) begin
  198. if APath <> '' then
  199. mmo1.Lines.Add(APath)
  200. else if Assigned(APathes) then
  201. mmo1.Lines.AddStrings(APathes)
  202. else
  203. mmo1.Lines.Add(Format('Error code: %d', [ACode]));
  204. end
  205. )
  206. end;
  207. procedure TForm1.btn4Click(Sender: TObject);
  208. var
  209. FSize: TSize;
  210. begin
  211. FSize.cx := TCanvasManager.DefaultCanvas.GetAttribute(TCanvasAttribute.MaxBitmapSize);
  212. FSize.cy := TCanvasManager.DefaultCanvas.GetAttribute(TCanvasAttribute.MaxBitmapSize);
  213. MainActivity.getFMXMediaLibrary.takeImageFromLibrary(FSize.Width, FSize.Height, False);
  214. end;
  215. procedure TForm1.DoCancelReceivingImage(const Sender: TObject; const M: TMessage);
  216. begin
  217. if (M is TMessageCancelReceivingImage) then
  218. mmo1.Lines.Add('TMessageCancelReceivingImage');
  219. end;
  220. procedure TForm1.DoReceivedImagePath(const Sender: TObject; const M: TMessage);
  221. begin
  222. if (M is TMessageReceivedImagePath) then
  223. mmo1.Lines.Add(Format('TMessageReceivedImagePath: %s', [(M as TMessageReceivedImagePath).Value]));
  224. end;
  225. procedure TForm1.FormCreate(Sender: TObject);
  226. begin
  227. TMessageManager.DefaultManager.SubscribeToMessage(TMessageCancelReceivingImage, DoCancelReceivingImage);
  228. TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedImagePath, DoReceivedImagePath);
  229. end;
  230. procedure TForm1.FormDestroy(Sender: TObject);
  231. begin
  232. TMessageManager.DefaultManager.Unsubscribe(TMessageReceivedImagePath, DoReceivedImagePath);
  233. TMessageManager.DefaultManager.Unsubscribe(TMessageCancelReceivingImage, DoCancelReceivingImage);
  234. end;
  235. end.