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およびアセットファイル名の有効な文字であるはずです