XE6发布文件 在Deployment Manager中添加待发布的文件,Remote Path写入assets\internal\或assets\就可以...

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.

转载于:https://www.cnblogs.com/yuyang2100/p/4957395.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值