XE6發佈文件
在Deployment Manager中添加待發布的文件,Remote Path寫入
assets\internal\或
assets\就能夠
其中
assets\internal\會把文件發佈到
TPath.GetDocumentsPath(也就是/data/data/.../files)目錄下
assets\會把文件發佈到
TPath.GetSharedDocumentsPath(也就是/mnt/sdcard/Android/data/.../files)目錄下 另外修改了System.StartUpCopy單元,支持設置assets\sdcard\xxx 會把文件發佈到/mnt/sdcard/xxx目錄下 { ******************************************************* } { } { CodeGear Delphi Runtime Library } { Copyright(c) 2013-2014 Embarcadero Technologies, Inc. } { } { ******************************************************* } ///使用說明 ///在Deployment Manager中,設置assets\internal\,文件將會發布到TPath.GetDocumentsPath(也就是/data/data/.../files) ///設置assets\會把文件發佈到TPath.GetSharedDocumentsPath(也就是/mnt/sdcard/Android/data/.../files)目錄下 ///設置assets\sdcard\xxx 會把文件發佈到/mnt/sdcard/xxx目錄下 {$HPPEMIT LINKUNIT} unit System.StartUpCopy; interface uses System.SysUtils; type EStartUpCopyException = class(Exception); implementation uses {$IFDEF ANDROID} Androidapi.AssetManager, Androidapi.NativeActivity, Androidapi.IOUtils, Posix.Unistd, System.RTLConsts, Androidapi.ExternalSDCardPath, {$ENDIF ANDROID} {$IFDEF IOS} iOSapi.Foundation, {$ENDIF} System.IOUtils; {$IFDEF ANDROID} type TASSETS_TYPE = (atExternal, atInternal, atSDCard); const MAX_BUFF_LEN = 65536; ASSETS_ROOT = 'assets'; ASSETS_ROOT_D = 'assets' + PathDelim; ASSETS_ROOT_D_LENGTH = Length(ASSETS_ROOT_D); ASSETS_INTERNAL = 'internal'; ASSETS_INTERNAL_D = 'internal' + PathDelim; ASSETS_DEPLOY_DIR = 'deployinfo'; ASSETS_FILENAME = 'deployedassets.txt'; ASSETS_FILENAME_PATH = ASSETS_DEPLOY_DIR + PathDelim + ASSETS_FILENAME; ASSETS_SDCard = 'sdcard'; ASSETS_SDCard_D = 'sdcard' + PathDelim; ASSETS_SDCard_D_LENGTH = Length(ASSETS_SDCard_D); {$ENDIF ANDROID} {$IFDEF ANDROID} 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); if LAssetFile <> nil then begin 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; end else raise EStartUpCopyException.CreateFmt(SAssetFileNotFound, [OrigFileName]); finally if (LAssetFile <> nil) then AAsset_close(LAssetFile); SetLength(Buffer, 0); end; end; end; function ReadAssetsDeployFile(AssetManager: PAAssetManager; var FileContent: string): Boolean; var Buffer: array [0 .. MAX_BUFF_LEN - 1] of char; LAssetFile: PAAsset; ReadCount: Integer; M: TMarshaller; begin Result := False; LAssetFile := AAssetManager_open(AssetManager, M.AsUtf8(ASSETS_FILENAME_PATH).ToPointer, AASSET_MODE_BUFFER); if Assigned(LAssetFile) then begin try repeat ReadCount := AAsset_read(LAssetFile, @Buffer, MAX_BUFF_LEN); if ReadCount > 0 then FileContent := FileContent + UTF8Tostring(@Buffer); until (ReadCount <= 0); Result := True; finally AAsset_close(LAssetFile); end; end; end; procedure CopyAssetsToFiles; var AssetManager: PAAssetManager; RootDir: string; InternalPath: string; ExternalPath: string; SDCardPath: String; {$REGION 'CopyAssetFolder'} procedure CopyAssetFolder(const LAssetManager: PAAssetManager; const FromFolder, ToFolder: string; IsInternal: TASSETS_TYPE = atExternal); var LAssetDir: PAAssetDir; LFile: MarshaledAString; FileName: string; M: TMarshaller; begin // Listing the files on root directory LAssetDir := AAssetManager_openDir(LAssetManager, M.AsUtf8(FromFolder).ToPointer); if LAssetDir <> nil then begin try LFile := AAssetDir_getNextFileName(LAssetDir); while LFile <> nil do begin FileName := UTF8Tostring(LFile); case IsInternal of atInternal: begin CopyAssetToFile(LAssetManager, FromFolder, FileName, InternalPath, ToFolder, FileName); end; atSDCard: begin if SDCardPath = '' then raise EStartUpCopyException.Create(SExternalExtorageNotAvailable); CopyAssetToFile(LAssetManager, FromFolder, FileName, SDCardPath, ToFolder, FileName); end; else begin if ExternalPath = '' then raise EStartUpCopyException.Create(SExternalExtorageNotAvailable); CopyAssetToFile(LAssetManager, FromFolder, FileName, ExternalPath, ToFolder, FileName); end; end; LFile := AAssetDir_getNextFileName(LAssetDir); end; finally AAssetDir_close(LAssetDir); end; end; end; {$ENDREGION} {$REGION 'CopyAssetFile'} procedure CopyAssetFile(const LAssetManager: PAAssetManager; const FromFile, ToFile: string; IsInternal: TASSETS_TYPE = atExternal); var FileName: string; FromFolder: string; ToFolder: string; begin FromFolder := ExtractFilePath(FromFile); ToFolder := ExtractFilePath(ToFile); FileName := ExtractFilename(FromFile); case IsInternal of atInternal: begin CopyAssetToFile(LAssetManager, FromFolder, FileName, InternalPath, ToFolder, FileName) end; atSDCard: begin if SDCardPath = '' then raise EStartUpCopyException.Create(SExternalExtorageNotAvailable); CopyAssetToFile(LAssetManager, FromFolder, FileName, SDCardPath, ToFolder, FileName); end; else begin if ExternalPath = '' then raise EStartUpCopyException.Create(SExternalExtorageNotAvailable); CopyAssetToFile(LAssetManager, FromFolder, FileName, ExternalPath, ToFolder, FileName); end; end; end; {$ENDREGION} {$REGION 'ProcessDeployedFiles'} procedure ProcessDeployedFiles(const LAssetManager: PAAssetManager; LFilesStr: string); var I: Integer; FileName: string; AFiles: TArray<string>; begin AFiles := LFilesStr.Split([string(#13#10)], ExcludeEmpty); for I := Low(AFiles) to High(AFiles) do begin FileName := AFiles[I].Replace('\', '/').Replace('./', ''); if FileName.StartsWith(ASSETS_ROOT_D) then begin FileName := FileName.Substring(ASSETS_ROOT_D_LENGTH); if FileName.StartsWith(ASSETS_INTERNAL_D) then begin CopyAssetFile(AssetManager, FileName, FileName.Substring(Length(ASSETS_INTERNAL_D)), atInternal); end else if FileName.StartsWith(ASSETS_SDCard) then begin CopyAssetFile(AssetManager, FileName, FileName.Substring(ASSETS_SDCard_D_LENGTH), atSDCard); end else begin CopyAssetFile(AssetManager, FileName, FileName, atExternal); end; end; end; end; {$ENDREGION} var DeployedFiles: string; begin InternalPath := GetFilesDir; ExternalPath := GetExternalFilesDir; SDCardPath := GetExternalSDCardPath(); AssetManager := ANativeActivity(System.DelphiActivity^).AssetManager; if (AssetManager <> nil) then begin if ReadAssetsDeployFile(AssetManager, DeployedFiles) then ProcessDeployedFiles(AssetManager, DeployedFiles) else begin RootDir := ''; CopyAssetFolder(AssetManager, RootDir, RootDir, atExternal); RootDir := ASSETS_INTERNAL; CopyAssetFolder(AssetManager, RootDir, '', atInternal); RootDir := 'StartUp'; CopyAssetFolder(AssetManager, RootDir, RootDir, atExternal); RootDir := ASSETS_SDCard; CopyAssetFolder(AssetManager, RootDir, RootDir, atSDCard); end; end; end; procedure CopyStartUpFiles; begin CopyAssetsToFiles; end; {$ELSE !ANDROID} procedure CopyStartUpFiles; var Source, Destination: string; procedure DoCopyFiles(const Src: string; const Dst: string); var SearchRec: TSearchRec; Res: Integer; begin Res := FindFirst(Src + '*', faAnyFile, SearchRec); while Res = 0 do begin if (SearchRec.Attr and faDirectory) = faDirectory then begin if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then begin if ForceDirectories(Dst + SearchRec.Name) then // Do the recurse thing... DoCopyFiles(Src + SearchRec.Name + PathDelim, Dst + SearchRec.Name + PathDelim); end; end else begin if not FileExists(Dst + SearchRec.Name) then begin TFile.Copy(Src + SearchRec.Name, Dst + SearchRec.Name, False); // copy without overwriting. end end; Res := FindNext(SearchRec); end; end; {$IFDEF IOS} var Bundle: NSBundle; {$ENDIF} begin {$IFDEF IOS} Bundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle); Source := UTF8Tostring(Bundle.bundlePath.UTF8String) + PathDelim + 'StartUp' + PathDelim; {$ELSE} Source := ExtractFilePath(ParamStr(0)) + 'StartUp' + PathDelim; {$ENDIF} if DirectoryExists(Source) then begin Destination := GetHomePath + PathDelim; DoCopyFiles(Source, Destination); end; end; {$ENDIF ANDROID} initialization begin CopyStartUpFiles; end; end.