Unit1.pas 10 KB

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