Delphi 12.1中PermissionsService.RequestPermissions()无法正常申请文件读写权限
问题排查与解决方案
你的问题核心是Android版本权限机制变更加上Delphi 12.1默认目标SDK升级导致的:
- 从Android 13(API 33)开始,Google废弃了
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE通用存储权限,改用细分的媒体权限(针对图片、视频、音频)或MANAGE_EXTERNAL_STORAGE(针对全文件访问)。 - Delphi 12.1默认目标SDK已升级到API 33+,此时调用旧权限申请时,Android系统会直接返回未授权状态,不会弹出权限申请窗口。
具体修复步骤
1. 明确权限需求
根据业务场景选择对应权限:
- 仅访问媒体文件(图片/视频/音频):使用新的媒体权限(推荐,符合Google Play规范)
- 需访问所有文件(含非媒体):使用
MANAGE_EXTERNAL_STORAGE权限(注意:该权限需Google Play特殊审核,普通应用不建议滥用)
2. 修改代码适配新权限
场景一:访问媒体文件
适配不同Android版本的权限逻辑:
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.Permissions, Androidapi.Jni.Os, Fmx.DialogService, Androidapi.Helpers, Androidapi.Jni.GraphicsContentViewText; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure PermissionRequestResult(Sender: TObject; const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray); procedure ExplainReason(Sender: TObject; const APermissions: TClassicStringDynArray; const APostRationaleProc: TProc); procedure FormShow(Sender: TObject); private FPermissions: TArray<string>; public end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.ExplainReason(Sender: TObject; const APermissions: TClassicStringDynArray; const APostRationaleProc: TProc); begin TDialogService.ShowMessage('应用需要访问媒体文件以完成相关功能', procedure(const AResult: TModalResult) begin APostRationaleProc; end); end; procedure TForm1.FormCreate(Sender: TObject); begin // 根据Android版本选择对应权限 if TOSVersion.Check(13) then begin // Android 13+ 使用细分媒体权限,按需添加图片/视频/音频权限 FPermissions := [ JStringToString(TJManifest_permission.JavaClass.READ_MEDIA_IMAGES), JStringToString(TJManifest_permission.JavaClass.READ_MEDIA_VIDEO), JStringToString(TJManifest_permission.JavaClass.READ_MEDIA_AUDIO) ]; end else begin // Android 12及以下保留旧权限 FPermissions := [ JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE), JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE) ]; end; end; procedure TForm1.FormShow(Sender: TObject); begin PermissionsService.RequestPermissions(FPermissions, PermissionRequestResult, ExplainReason); end; procedure TForm1.PermissionRequestResult(Sender: TObject; const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray); var AllGranted: Boolean; I: Integer; begin AllGranted := True; for I := 0 to High(AGrantResults) do begin if AGrantResults[I] <> TPermissionStatus.Granted then begin AllGranted := False; Break; end; end; if AllGranted then TDialogService.ShowMessage('权限已获取') else TDialogService.ShowMessage('所需权限未获取'); end; end.
场景二:全文件访问(谨慎使用)
若必须访问所有文件,需使用MANAGE_EXTERNAL_STORAGE权限,且需引导用户到系统设置手动开启:
procedure TForm1.FormCreate(Sender: TObject); begin if TOSVersion.Check(11) then // Android 11+ 需要该权限 FPermissions := [JStringToString(TJManifest_permission.JavaClass.MANAGE_EXTERNAL_STORAGE)] else FPermissions := [ JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE), JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE) ]; end; procedure TForm1.PermissionRequestResult(Sender: TObject; const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray); begin if (Length(AGrantResults) > 0) and (AGrantResults[0] = TPermissionStatus.Granted) then TDialogService.ShowMessage('权限已获取') else begin TDialogService.ShowMessage('请在系统设置中为应用开启文件访问权限', procedure(const AResult: TModalResult) begin if AResult = mrOk then TAndroidHelper.Context.startActivity(TAndroidHelper.IntentSetAction(TJIntent.JavaClass.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)); end); end; end;
3. 配置AndroidManifest.xml
确保对应权限在清单文件中声明:
- 媒体权限:勾选
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO(通过Project Options > Application > Android > Permissions勾选,或手动编辑AndroidManifest.template.xml) - 全文件访问权限:勾选
MANAGE_EXTERNAL_STORAGE
额外注意事项
- Delphi 12.1的PermissionsService已适配新权限,需确保使用正确的权限常量。
- 建议将应用目标SDK升级到API 33+,以符合Google Play上架要求。
- Android 13+访问媒体文件时,无需申请
WRITE_EXTERNAL_STORAGE权限,写入媒体库操作会自动授权。
内容的提问来源于stack exchange,提问作者Lettergold Lettergold
相关产品推荐
相关产品推荐

