You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi Tokyo Android:如何获取可用磁盘空间?

获取Delphi Tokyo Android设备可用磁盘空间的解决方案

针对你在Moto G4 Play(Android 6.0.1)上遇到的问题,我整理了两种靠谱的实现方式,同时帮你理清之前踩的坑:

一、先解决你之前的疑问

  1. 关于android.mtp.MtpStorageInfo的getFreeSpace无效:
    这个类是用来获取通过MTP协议连接的外部设备(比如电脑通过MTP访问手机时的存储)的信息,并非手机本地存储的API,所以在普通应用里调用自然拿不到正确结果。

  2. 关于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权限才能正常获取存储信息:

  1. 在AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  1. 在应用启动时或调用存储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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:12:17