Delphi Tokyo Android:如何获取可用磁盘空间?
获取Delphi Tokyo Android设备可用磁盘空间的解决方案
针对你在Moto G4 Play(Android 6.0.1)上遇到的问题,我整理了两种靠谱的实现方式,同时帮你理清之前踩的坑:
一、先解决你之前的疑问
关于
android.mtp.MtpStorageInfo的getFreeSpace无效:
这个类是用来获取通过MTP协议连接的外部设备(比如电脑通过MTP访问手机时的存储)的信息,并非手机本地存储的API,所以在普通应用里调用自然拿不到正确结果。关于
TJALStatFs未定义:
你应该是混淆了类名,Delphi中对应的正确类是TJStatFs,需要引用Androidapi.JNI.Os单元,同时确保项目引入了Androidapi.JNI.IO、Androidapi.JNI.Provider这些JNI相关单元(新建Android项目默认会包含,老项目可能需要手动添加到uses)。
二、两种可用的示例代码
方法1:用JFile直接获取外部存储可用空间(推荐)
这种方式更简洁,直接调用Android原生API获取指定目录的可用空间,适合获取外部SD卡或内部共享存储的空间:
uses Androidapi.JNI.IO, Androidapi.JNI.Provider, Androidapi.Helpers, System.SysUtils; function GetExternalUsableSpace: Double; var ExternalDir: JFile; SpaceBytes: Int64; begin // 获取系统外部存储目录(对应手机的SD卡或内部共享存储) ExternalDir := TJEnvironment.JavaClass.getExternalStorageDirectory; if Assigned(ExternalDir) then begin // getUsableSpace:返回应用实际可使用的空间(排除系统预留) // getFreeSpace:返回当前剩余空间(包含系统预留,不推荐) SpaceBytes := ExternalDir.getUsableSpace; // 转换为GB单位(方便展示) Result := SpaceBytes / (1024 * 1024 * 1024); end else Result := 0; end; // 调用示例: procedure TForm1.Button1Click(Sender: TObject); var FreeGB: Double; begin FreeGB := GetExternalUsableSpace; ShowMessage(Format('外部存储可用空间:%.2f GB', [FreeGB])); end;
方法2:用TJStatFs获取指定路径的可用空间
如果你需要获取自定义路径的存储信息,比如应用私有目录,可以用这种方式:
uses Androidapi.JNI.Os, Androidapi.JNI.IO, Androidapi.JNI.Provider, System.SysUtils; function GetPathUsableSpace(const Path: string): Double; var StatFs: TJStatFs; BlockSize, AvailableBlocks: Int64; begin StatFs := TJStatFs.JavaClass.init(StringToJString(Path)); try // 获取每个存储块的大小(Android 4.3+用getBlockSizeLong,低版本用getBlockSize) BlockSize := StatFs.getBlockSizeLong; // 获取可用的存储块数量(Android 4.3+用getAvailableBlocksLong) AvailableBlocks := StatFs.getAvailableBlocksLong; // 计算总可用字节数,再转成GB Result := (BlockSize * AvailableBlocks) / (1024 * 1024 * 1024); finally StatFs.free; end; end; // 调用示例:获取外部存储路径的可用空间 procedure TForm1.Button2Click(Sender: TObject); var ExternalPath: string; FreeGB: Double; begin ExternalPath := JStringToString(TJEnvironment.JavaClass.getExternalStorageDirectory.getAbsolutePath); FreeGB := GetPathUsableSpace(ExternalPath); ShowMessage(Format('%s 可用空间:%.2f GB', [ExternalPath, FreeGB])); end;
三、Android 6.0+权限注意事项
你的设备是Android 6.0.1,属于动态权限管控版本,必须申请READ_EXTERNAL_STORAGE权限才能正常获取存储信息:
- 在
AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- 在应用启动时或调用存储API前,动态申请权限:
uses Androidapi.Helpers, Androidapi.JNI.App; const PERMISSION_READ_STORAGE = 'android.permission.READ_EXTERNAL_STORAGE'; REQUEST_CODE_STORAGE = 1; procedure RequestStoragePermission; begin // 检查是否已授权 if TAndroidHelper.Context.checkSelfPermission(StringToJString(PERMISSION_READ_STORAGE)) <> TJPackageManager.JavaClass.PERMISSION_GRANTED then begin // 向用户申请权限 TAndroidHelper.Activity.requestPermissions( TJavaObjectArray<JString>.Create(1, StringToJString(PERMISSION_READ_STORAGE)), REQUEST_CODE_STORAGE ); end; end; // 处理权限申请结果(需要在Form的OnCreate或Activity的事件中绑定) procedure TForm1.ActivityPermissionsResult(RequestCode: Integer; Permissions: TArray<string>; GrantResults: TArray<Integer>); begin inherited; if RequestCode = REQUEST_CODE_STORAGE then begin if (Length(GrantResults) > 0) and (GrantResults[0] = TJPackageManager.JavaClass.PERMISSION_GRANTED) then begin // 权限已授予,可以调用存储API了 ShowMessage('权限已授权,现在可以获取存储信息'); end else begin ShowMessage('需要存储权限才能获取磁盘空间'); end; end; end;
内容的提问来源于stack exchange,提问作者El Diablo
相关产品推荐
相关产品推荐

