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 コードです。正常なファイルと失敗したファイルの唯一の違いは、ディレクトリの深さです。最初のレベルの深さは 1 つだけです。1 つのディレクトリともう 1 つのディレクトリには 3 レベルの深さがあります。コピーもOKな他のファイルがいくつかあり、すべてのディレクトリの深さは1レベルしかありません。

ここで何が問題なのかは誰でも知っています。できる限り深く掘り下げたので、これ以上デバッグすることはできません。

それが役立つ場合は、実際のデバイスである Samsung Galaxy Nexus でテストしています。

編集:

私が変更した場合:

assets/internal/media/images/concert/object4.png

assets/internal/media/images/concert/object.png

その後、動作します。なんてこった。説明はありますか?私が見たところ、数字はAndroidおよびアセットファイル名の有効な文字であるはずです

4

0 に答える 0