4

我正在使用 Delphi XE5 和 Firemonkey 玩一个适用于 IOS 和 Android 的应用程序。虽然在 IOS 上应用程序运行良好,但无法在 Android 上启动。原因是在启动阶段它在 System.StartUpCopy.pas 单元中失败。

我有一些与应用程序一起部署的文件(多媒体内容和 XML)。虽然它们在 IOS 上都可以正常复制,但其中一些在 Android 上失败。部署配置是使用 Delphi 中的部署管理器完成的。

  • 以下是可以的:assets/internal/profiles/default.xml
  • 但是这个失败了:assets/internal/media/images/concert/object4.png

它在运行此代码的第 97 行的“System.StartUpCopy”内失败

ReadCount := AAsset_read(LAssetFile, @Buffer[0], MAX_BUFF_LEN);

但是问题在获得“LAssetFile”的地方有点高

LAssetFile := AAssetManager_open(LAssetManager, M.AsUtf8(OrigFileName).ToPointer, AASSET_MODE_BUFFER);

"AAssetManager_open" 返回nil。为什么我不知道,因为我不知道如何从 API 中获取一些错误代码。整个代码块看起来像这样

function CopyAssetToFile(LAssetManager: PAAssetManager; const AssetFolder, AssetName: string;
              const DestinationRoot, DestFolder, FileName: string): Boolean;
var
  OrigFileName,
  DestFileName,
  DestinationPath: string;
  ReadCount, WriteCount: Integer;
  LAssetFile: PAAsset;
  FileHandle: THandle;
  Buffer: TBytes;
  M: TMarshaller;
begin
  Result := True;

  if AssetFolder = '' then
    OrigFileName := AssetName
  else
    OrigFileName := IncludeTrailingPathDelimiter(AssetFolder) +  AssetName;

  if DestFolder <> '' then
  begin
    DestinationPath := IncludeTrailingPathDelimiter(DestinationRoot) + DestFolder;
    DestFileName := IncludeTrailingPathDelimiter(DestinationRoot) + IncludeTrailingPathDelimiter(DestFolder) + FileName;
  end
  else
  begin
    DestinationPath := DestinationRoot;
    DestFileName := IncludeTrailingPathDelimiter(DestinationRoot) + FileName
  end;

  if not FileExists(DestFileName) then //do not overwrite files
  begin
    // Second Create an intermediate buffer.
    SetLength(Buffer, MAX_BUFF_LEN);
    LAssetFile := nil;
    try
      if not DirectoryExists(DestinationPath) then
      begin
        if not ForceDirectories(DestinationPath) then
        begin
          Exit(False);
        end;
      end;
      // We have a valid AssetManager. Start
      LAssetFile := AAssetManager_open(LAssetManager, M.AsUtf8(OrigFileName).ToPointer, AASSET_MODE_BUFFER);
      FileHandle := FileCreate(DestFileName);
      try
        if FileHandle = THandle(-1) then
        begin
          Exit(False);
        end;
        repeat
          ReadCount := AAsset_read(LAssetFile, @Buffer[0], MAX_BUFF_LEN);
          WriteCount := FileWrite(FileHandle, Buffer, 0, ReadCount);
        until (ReadCount <= 0) or (ReadCount <> WriteCount);

      finally
        FileClose(FileHandle);
      end;
    finally
      if (LAssetFile <> nil) then
        AAsset_close(LAssetFile);
      SetLength(Buffer, 0);
    end;
  end;
end;

这是原始的 XE5 代码。现在,我在正常文件和失败文件之间看到的唯一区别是目录深度。第一个只有一个级别深度,例如。一个目录,另一个有 3 级深度。我还有一些其他文件也可以复制,并且都只有一级目录深度。

任何人都知道这里可能出了什么问题。我无法进一步调试,因为我已经尽可能深入了。

如果它有助于我在实际设备上进行测试,三星 Galaxy Nexus。

编辑:

发现如果我改变:

资产/内部/媒体/图像/音乐会/object4.png

资产/内部/媒体/图像/音乐会/object.png

然后它工作。哇。有什么解释吗?我看了看,数字应该是 android 和资产文件名的有效字符

4

0 回答 0