KngStr 5 lat temu
rodzic
commit
ef90fbf9df
1 zmienionych plików z 0 dodań i 3600 usunięć
  1. 0 3600
      Source/FlyFilesUtils.pas

+ 0 - 3600
Source/FlyFilesUtils.pas

@@ -1,3600 +0,0 @@
-unit FlyFilesUtils;
-
-(* ************************************************ *)
-(*                         *)
-(*  设计:爱吃猪头肉 & Flying Wang 2013-11-30   *)
-(*      上面的版权声明请不要移除。      *)
-(*      Ver 1.0.2014.808            *)
-(*                         *)
-(* ************************************************ *)
-
-//1.0.2014.1108
-//支持 UTF8 的检查。
-
-//1.0.2014.908
-//支持 XE7。
-
-//1.0.2014.808
-//增加函数 IsPadOrPC。
-
-//1.0.2014.805
-//增加安卓下的获取 内存 SD 卡空间的函数。
-
-//1.0.2014.419
-//增加对 XE6 的支持。
-
-//1.0.2014.225
-//增加对 JNI 的接口查找功能。不完善。
-
-//1.0.2013.1219
-//在 亚瑟(Arthur)  3140223 的启发下,增加了更多的 SD 目录。
-
-//1.0.2013.1217
-//增加一个 FindSDCardSubPath 函数,用于查找指定的目录。
-
-//1.0.2013.1206
-//增加 [佛山]N.E(1024317)  9:36:38 提供的几个 SD 卡的路径。
-
-interface
-
-uses System.SysUtils,
-  System.Classes,
-{$IFDEF ANDROID}
-  Androidapi.JNIBridge,
-  Androidapi.IOUtils,
-{$ENDIF ANDROID}
-{$IFDEF MSWINDOWS}
-  Winapi.Windows,
-{$ENDIF MSWINDOWS}
-{$IFDEF POSIX}
-  Posix.Dlfcn, Posix.Fcntl, Posix.SysStat, Posix.SysTime, Posix.SysTypes, Posix.Locale,
-{$ENDIF POSIX}
-{$IFDEF PC_MAPPED_EXCEPTIONS}
-  System.Internal.Unwinder,
-{$ENDIF PC_MAPPED_EXCEPTIONS}
-{$IFDEF MACOS}
-  Macapi.Mach, Macapi.CoreServices, Macapi.CoreFoundation,
-{$ENDIF MACOS}
-  System.SysConst,
-  System.IOUtils;
-
-var
-  Error_NotFoundFileManager_Str: string = 'Not Found FileManager.';
-
-
-///	<summary>
-///	  返回大小写敏感的文件或路径名称
-///	</summary>
-///	<param name="FileName">
-///	  文件或路径名
-///	</param>
-///	<param name="RootPath">
-///	  <para>
-///	    检查路径的根目录
-///	  </para>
-///	  <para>
-///	    当大小写检查到此目录时停止,不再继续检查。
-///	  </para>
-///	</param>
-function GetCaseSensitiveFileName(const FileName: string; RootPath: string = ''): string;
-
-
-const
-  ///	<summary>
-  ///	  外置设备的数量
-  ///	</summary>
-  OTGDeivceCount = 16;
-
-  ///	<summary>
-  ///	  USB 磁盘,例如 U 盘、移动硬盘等
-  ///	</summary>
-  UsbDiskStartIndex = 255;
-
-  ///	<summary>
-  ///	  外置光驱
-  ///	</summary>
-  CDROMStartIndex = 255 + OTGDeivceCount;
-
-const
-  ///	<summary>
-  ///	  默认的删除等待时间,单位微秒
-  ///	</summary>
-  DeleteDirectories_WaitMinSecond = 2000;
-
-
-///	<summary>
-///	  检查 SD 卡或路径是否可用
-///	</summary>
-function isPathCanUseNow(const PathOrDir: string; const Default: Boolean = True): Boolean;
-
-///	<summary>
-///	  检查 SD 卡或路径是否写入
-///	</summary>
-function TestPathCanWrite(const PathOrDir: string): Boolean;
-
-///	<summary>
-///	  获取 手机存储 或 SD 卡的路径
-///	</summary>
-///	<param name="Index">
-///	  0 为 手机存储 1 为 SD 卡
-///	</param>
-///	<returns>
-///	  <para>
-///	    如果找到,返回路径。带 / 或 \
-///	  </para>
-///	  <para>
-///	    没找到,返回一个错误的路径。
-///	  </para>
-///	</returns>
-function GetSDCardPath(Index: Integer = 0): string;
-
-///	<summary>
-///	  查找 手机存储 或 SD 卡上的某个路径
-///	</summary>
-///	<param name="SubPath">
-///	  被查找的子路径
-///	</param>
-///	<param name="Index">
-///	  0 为 手机存储 1 为 SD 卡
-///	</param>
-///	<returns>
-///	  如果找到,返回路径。带 / 或 \ 没找到,返回一个错误的路径。
-///	</returns>
-function FindSDCardSubPath(SubPath: string; Index: Integer = 0): string;
-
-///	<summary>
-///	  获取当成工程的运行路径
-///	</summary>
-function GetAppPath: string;
-
-///	<summary>
-///	  查找一个路径下的指定格式的文件
-///	</summary>
-///	<param name="Path">
-///	  路径,必须用通配符结束。例如 /*
-///	</param>
-///	<param name="Attr">
-///	  需要查找的文件的属性
-///	</param>
-///	<param name="List">
-///	  返回一个文件名或目录名的列表
-///	</param>
-///	<param name="JustFile">
-///	  是否只查找文件
-///	</param>
-///	<returns>
-///	  无意义
-///	</returns>
-function BuildFileListInAPath(const Path: string; const Attr: Integer; const List: TStrings;
-  JustFile: Boolean = False): Boolean; overload;
-
-///	<summary>
-///	  查找一个路径下的指定格式的文件
-///	</summary>
-///	<param name="Path">
-///	  路径,必须用通配符结束。例如 /*
-///	</param>
-///	<param name="Attr">
-///	  需要查找的文件的属性
-///	</param>
-///	<param name="JustFile">
-///	  是否只查找文件
-///	</param>
-///	<returns>
-///	  返回换行分割的文件名或目录的列表
-///	</returns>
-function BuildFileListInAPath(const Path: string; const Attr: Integer;
-  JustFile: Boolean = False): string; overload;
-
-///	<summary>
-///	  查找指定路径下的文件
-///	</summary>
-///	<param name="DirName">
-///	  路径
-///	</param>
-///	<param name="SearchFilter">
-///	  通配符组成的查找格式
-///	</param>
-///	<param name="FileAttribs">
-///	  需要查找的文件的属性
-///	</param>
-///	<param name="isIncludeSubDirName">
-///	  是否包含子目录的名字
-///	</param>
-///	<param name="Recursion">
-///	  是否递归找子目录
-///	</param>
-///	<param name="FullName">
-///	  是否返回完整路径
-///	</param>
-///	<returns>
-///	  返回换行分割的文件名或目录的列表
-///	</returns>
-function GetFileNamesFromDirectory(const DirName: string; const SearchFilter: string = '*';
-  const FileAttribs: Integer = faAnyFile; const isIncludeSubDirName: Boolean = False; const Recursion: Boolean = False;
-  const FullName: Boolean = False): string;
-
-//可以用 TDirectory.Delete 代替下面的功能。
-///	<summary>
-///	  删除目录下指定的文件
-///	</summary>
-///	<param name="Source">
-///	  被删除的文件路径,可以使用通配符
-///	</param>
-///	<param name="AbortOnFailure">
-///	  失败时是否退出
-///	</param>
-///	<param name="YesToAll">
-///	  删掉所有文件,包括只读的。仅 WIN32 下有效。
-///	</param>
-///	<param name="WaitMinSecond">
-///	  检查文件删除的等待时间,单位 微秒
-///	</param>
-///	<returns>
-///	  是否删除完成
-///	</returns>
-function DeleteDirectoryByEcho(const Source: string;
-  AbortOnFailure: Boolean = False; YesToAll: Boolean = True;
-  WaitMinSecond: Integer = DeleteDirectories_WaitMinSecond): Boolean;
-
-  ///	<summary>
-///	  获取指定路径的总存储大小
-///	</summary>
-function GetTotalSpaceSize(Path: string = PathDelim): UInt64;
-///	<summary>
-///	  获取指定路径的可以使用的存储大小
-///	</summary>
-function GetAvailableSpaceSize(Path: string = PathDelim): UInt64;
-///	<summary>
-///	  获取指定路径的剩余(包括不可使用的)存储大小
-///	</summary>
-function GetFreeSpaceSize(Path: string = PathDelim): UInt64;
-
-///	<summary>
-///	  获取总内存大小
-{$IFDEF ANDROID}
-///   感谢[上海]故国(370620516)
-{$ENDIF}
-///	</summary>
-function GetTotalMemorySize: UInt64;
-///	<summary>
-///	  获取剩余内存大小
-{$IFDEF ANDROID}
-///   感谢[上海]故国(370620516)
-{$ENDIF}
-///	</summary>
-function GetFreeMemorySize: UInt64;
-
-///	<summary>
-///	  安卓 IOS 返回是否是 PAD(平板)
-///   其他平台,返回 True
-///   很多手机的 DPI 是错的,所以获取的尺寸也就不正常了,
-///   所以个别手机会被识别成 PAD。
-///	</summary>
-function IsPadOrPC: Boolean;
-//function IsPadOrPC(MiniScreenInches: Single = 6.2): Boolean;
-//function IsPad: Boolean;
-
-
-///	<summary>
-///	  在其他 APP 中打开文件。
-///	</summary>
-function OpenFileOnExtApp(const FileName: string; Https: Boolean = True): Boolean;
-
-function NowGMT_UTC: TDateTime;
-
-///	<summary>
-///	  获取完整 URL 的 Encode 结果。
-///   Just UTF8
-///	</summary>
-function EncodeURLWithSchemeOrProtocol(const URL: string): string;
-
-//上面是跨平台函数。
-//下面是平台函数。
-
-{$IFDEF ANDROID}
-
-function GetVolumePaths: string;
-
-function GetExternalStoragePath: string;
-
-//var
-//  ExterStoragePathCanRead: Boolean = True;
-//  ExterStoragePathCanWrite: Boolean = True;
-//  SDMountedMessageReceived: Boolean = False;
-function GetExterStoragePath: string;
-function GetInnerStoragePath: string;
-
-///	<summary>
-///	  It check SDCard0 Removable
-///	</summary>
-function GetIsExternalStorageRemovable: Boolean;
-
-///	<summary>
-///   很多手机的 DPI 是错的,所以获取的尺寸也就不正常了。
-///	</summary>
-function GetScreenClientInches: Single;
-
-///	<summary>
-///	  获取安卓下剩余内存大小
-///	</summary>
-//function GetActiveMemorySize: UInt64;
-
-///	<summary>
-///	  查找一个 JAVA 类是否可以使用
-///	</summary>
-///	<param name="NamePath">
-///	  类的全路径
-///	</param>
-function IsCanFindJavaClass(const NamePath: string): Boolean;
-function IsCanFindJavaMethod(const MethodName, Signature: string; const CalssNamePath: string = ''): Boolean;
-function IsCanFindJavaStaticMethod(const MethodName, Signature: string; const CalssNamePath: string = ''): Boolean;
-
-type
-  TGetFileNameListener = reference to procedure(const IsOK: Boolean; const FileName:string);
-  TGetFileNameLIsternerMethod = procedure (const IsOK: Boolean; const FileName:string) of object;
-
-function OpenFileDialog(Title, FileExtension:string; GetFileNameCallBack: TGetFileNameListener): Boolean; overload;
-function OpenFileDialog(Title, FileExtension:string; GetFileNameCallBack: TGetFileNameLIsternerMethod): Boolean; overload;
-
-function CheckPermission(const APermissionName: string): Boolean;
-
-const
-  C_android_permission_EXTERNAL_STORAGE = 'android.permission.WRITE_EXTERNAL_STORAGE';
-//  C_android_permission_WRITE_MEDIA = 'android.permission.WRITE_MEDIA_STORAGE';
-function CanWriteExterStorage: Boolean;
-
-/// <summary>
-///   更新相册
-/// </summary>
-procedure UpdateAlbum(FileNames: string);
-
-function ReadNoSizeFileToString(const AFileName: string): string;
-function ReadFileToString(const AFileName: string): string;
-
-{$ENDIF}
-
-implementation
-
-uses
-{$IFDEF ANDROID}
-{$IF CompilerVersion >= 27.0} // >= XE6
-  Androidapi.Helpers,
-//  FMX.Helpers.Android,
-{$ENDIF}
-{$IF CompilerVersion < 28.0} // < XE7
-  FMX.Helpers.Android,
-{$ENDIF}
-  Androidapi.Jni,
-  Androidapi.JNI.Environment,
-  Androidapi.JNI.StatFs,
-  Androidapi.JNI.Stream2,
-  Androidapi.JNI.ActivityManager,
-  Androidapi.JNI.JavaTypes,
-  Androidapi.NativeActivity,
-  Androidapi.JNI.GraphicsContentViewText,
-  Androidapi.JNI.Util,
-  Androidapi.JNI.android.os.storage.StorageManager,
-  Androidapi.JNI.java.lang.FlyUtils,
-  Androidapi.JNI.Webkit,
-//  Androidapi.JNI.Embarcadero,
-  Androidapi.JNI.App,
-  Androidapi.JNI.Net,
-  Androidapi.JNI.Media,
-  Androidapi.JNI.Provider,
-{$ENDIF}
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-  iOSapi.Foundation,
-  Macapi.ObjectiveC,
-  FMX.Helpers.iOS,
-//  iOSapi.UIDevice2,
-{$ENDIF}
-{$IFDEF MSWINDOWS}
-  Winapi.ShellApi,
-{$ENDIF}
-//  FMX.Dialogs,
-{$IF CompilerVersion >= 29.0} //  XE8
-  System.NetEncoding,
-{$ELSE}
-  IdURI,
-{$ENDIF}
-  System.Rtti,
-  System.TypInfo,
-  System.Messaging,
-  System.Math;
-
-
-//来自 inc 内部的 类型。
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-type
-{ Used by other time functions.  }
-  tm = record
-    tm_sec: Integer;            // Seconds. [0-60] (1 leap second)
-    tm_min: Integer;            // Minutes. [0-59]
-    tm_hour: Integer;           // Hours.[0-23]
-    tm_mday: Integer;           // Day.[1-31]
-    tm_mon: Integer;            // Month.[0-11]
-    tm_year: Integer;           // Year since 1900
-    tm_wday: Integer;           // Day of week [0-6] (Sunday = 0)
-    tm_yday: Integer;           // Days of year [0-365]
-    tm_isdst: Integer;          // Daylight Savings flag [-1/0/1]
-    tm_gmtoff: LongInt;         // Seconds east of UTC
-    tm_zone: MarshaledAString;  // Timezone abbreviation
-  end;
-  {$EXTERNALSYM tm}
-  Ptm = ^tm;
-{$ELSEIF DEFINED(ANDROID)}
-{ Used by other time functions.  }
-type
-  tm = record
-    tm_sec: Integer;            // Seconds. [0-60] (1 leap second)
-    tm_min: Integer;            // Minutes. [0-59]
-    tm_hour: Integer;           // Hours.[0-23]
-    tm_mday: Integer;           // Day.[1-31]
-    tm_mon: Integer;            // Month.[0-11]
-    tm_year: Integer;           // Year since 1900
-    tm_wday: Integer;           // Day of week [0-6] (Sunday = 0)
-    tm_yday: Integer;           // Days of year [0-365]
-    tm_isdst: Integer;          // Daylight Savings flag [-1/0/1]
-    tm_gmtoff: LongInt;         // Seconds east of UTC
-    tm_zone: MarshaledAString;         // Timezone abbreviation
-  end;
-  {$EXTERNALSYM tm}
-  Ptm = ^tm;
-{$ENDIF}
-
-
-//来自 inc 的函数定义。
-{$IFDEF POSIX}
-const
-{$IFDEF UNDERSCOREIMPORTNAME}
-  _PU = '_';
-{$ELSE}
-  _PU = '';
-{$ENDIF}
-const
-  libc        = '/usr/lib/libc.dylib';
-  libpthread  = '/usr/lib/libpthread.dylib';
-  libiconv    = '/usr/lib/libiconv.dylib';
-  libdl       = '/usr/lib/libdl.dylib';
-
-{$IF not Declared(_PU)}
-const
-  // On Mac OSX, cdecl names have a preceeding underscore
-  // if x86 native backend.
-  {$IF Defined(UNDERSCOREIMPORTNAME)}
-  _PU = '_';
-  {$ELSE}
-  _PU = '';
-  {$ENDIF}
-  {$EXTERNALSYM _PU}
-{$ENDIF}
-
-const
-{$IFNDEF IOS}
-  _INODE_SUFFIX = '$INODE64';
-{$ELSE IOS}
-  _INODE_SUFFIX = '';
-{$ENDIF !IOS}
-  {$EXTERNALSYM _INODE_SUFFIX}
-
-//具体函数定义开始。
-function _system(Name: MarshaledAString): Integer; cdecl;
-  external libc name _PU + 'system';
-
-function tempnam(const Path: MarshaledAString; const Prefix: MarshaledAString): MarshaledAString; cdecl;
-  external libc name _PU + 'tempnam';
-{$EXTERNALSYM tempnam}
-procedure free(p: Pointer); cdecl;
-  external libc name _PU + 'free';
-{$EXTERNALSYM free}
-function gettimeofday(var timeval: timeval; timezone: Pointer): Integer; cdecl;
-  external libc name _PU + 'gettimeofday';
-{$EXTERNALSYM gettimeofday}
-function gmtime_r(var Timer: time_t; var UnixTime: tm): Ptm; cdecl;
-  external libc name _PU + 'gmtime_r';
-{$EXTERNALSYM gmtime_r}
-{$ENDIF}
-
-//可以开始写函数了。
-
-function NowGMT_UTC: TDateTime;
-{$IFDEF MSWINDOWS}
-var
-  SystemTime: TSystemTime;
-begin
-  GetSystemTime(SystemTime);
-  Result := EncodeDate(SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay) +
-    EncodeTime(SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds);
-end;
-{$ENDIF MSWINDOWS}
-{$IFDEF POSIX}
-var
-  T: time_t;
-  TV: timeval;
-  UT: tm;
-begin
-  gettimeofday(TV, nil);
-  T := TV.tv_sec;
-  gmtime_r(T, UT);
-  Result := EncodeDate(UT.tm_year + 1900, UT.tm_mon + 1, UT.tm_mday) +
-    EncodeTime(UT.tm_hour, UT.tm_min, UT.tm_sec, TV.tv_usec div 1000);
-end;
-{$ENDIF POSIX}
-
-function EncodeURLWithSchemeOrProtocol(const URL: string): string;
-var
-  Protocol: string;
-  AURL: string;
-  AIndex: Integer;
-begin
-{$IF CompilerVersion >= 29.0} //  XE8
-   AURL := URL.Trim;
-   Protocol := '';
-   AIndex := AURL.IndexOf('//');
-   if AIndex > 0 then
-   begin
-     Protocol := AURL.Substring(0, AIndex + 1); // has /
-     AURL := AURL.Substring(AIndex + 1); // has /
-   end;
-   Result := Protocol + TNetEncoding.URL.EncodePath(AURL);
-{$ELSE}
-   Result := TIdURI.URLEncode(Result);
-{$ENDIF}
-end;
-
-function EncodeURLWithOutSchemeOrProtocol(const URL: string; Https: Boolean = True): string;
-begin
-  Result := URL;
-  if FileExists(Result) then
-  begin
-{$IFDEF MSWINDOWS}
-{$ELSE}
-    if Result.Substring(0, 1) <> '/' then
-    begin
-      Result := '/' + Result;
-    end;
-    Result := 'file://' + Result;
-{$ENDIF}
-  end
-  else
-  begin
-    if Https then
-    begin
-      Result := 'https://' + URL;
-    end
-    else
-    begin
-      Result := 'http://' + URL;
-    end;
-    Result := EncodeURLWithSchemeOrProtocol(Result);
-  end;
-end;
-
-
-function OpenFileOnExtApp(const FileName: string; Https: Boolean = True): Boolean;
-{$IFDEF ANDROID}
-var
-  Intent: JIntent;
-  FileExtension: string;
-  mime: JMimeTypeMap;
-  MIMEType: JString;
-  TempStr,
-  FileToOpen: string;
-  AJFile: JFile;
-  AJUri: Jnet_Uri;
-begin
-// There may be an issue with the geo: prefix and URLEncode.
-// will need to research
-  Result := False;
-  if FileName = '' then
-    Exit;
-  FileExtension := AnsiLowerCase(ExtractFileExt(FileName));
-  if FileExtension = '' then
-    Exit;
-  mime := TJMimeTypeMap.JavaClass.getSingleton();
-  MIMEType := nil;
-  if mime <> nil then
-  begin
-    MIMEType := mime.getMimeTypeFromExtension(StringToJString(FileExtension.Substring(1)));
-  end;
-  if MIMEType <> nil then
-  begin
-    // 调用相应程序打开当前程序
-    Intent := TJIntent.Create;
-    Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
-    //TempStr := IncludeTrailingPathDelimiter(TPath.GetDocumentsPath)
-    TempStr := IncludeTrailingPathDelimiter(TPath.GetHomePath);
-{$IF CompilerVersion >= 33.0} //  RAD10.3
-    if FileExists(FileName) then
-    begin
-      FileToOpen := FileName;
-    end
-    else
-    begin
-      FileToOpen := EncodeURLWithOutSchemeOrProtocol(FileName, Https);
-    end;
-    if Pos(TempStr, FileToOpen) = 1 then
-    begin
-      AJFile := TJFile.JavaClass.init(StringToJString(FileToOpen));
-      AJUri := TAndroidHelper.JFileToJURI(AJFile);
-    end
-    else
-    begin
-{$ELSE}
-    begin
-{$ENDIF}
-      FileToOpen := EncodeURLWithOutSchemeOrProtocol(FileName, Https);
-      AJUri := StrToJURI(FileToOpen);
-    end;
-    Intent.setDataAndType(AJUri, MIMEType);
-    try
-      SharedActivity.startActivity(Intent);
-      Result := True;
-    except
-    end;
-  end;
-
-end;
-{$ELSE}
-{$IFDEF IOS}
-var
-  NSU: NSUrl;
-  AURL: string;
-begin
-  Result := False;
-  AURL := EncodeURLWithOutSchemeOrProtocol(FileName, Https);
-  // iOS doesn't like spaces, so URL encode is important.
-  NSU := StrToNSUrl(AURL);
-  if TOSVersion.Check(9) or SharedApplication.canOpenURL(NSU) then
-  try
-    Result := SharedApplication.openUrl(NSU);
-  except
-  end;
-end;
-{$ELSE}
-{$IFDEF MSWINDOWS}
-var
-  AURL: string;
-begin
-  Result := False;
-  AURL := EncodeURLWithOutSchemeOrProtocol(FileName, Https);
-  try
-    ShellExecute(GetActiveWindow, 'open', PChar(AURL), '', '', SW_MAXIMIZE);
-    Result := True;
-  except
-  end;
-end;
-{$ELSE}
-var
-  M:TMarshaller;
-  AURL: string;
-begin
-  Result := False;
-  //AURL := 'open -a Safari ' +  EncodeURLWithOutSchemeOrProtocol(AURL);
-  AURL := 'open ' +  EncodeURLWithOutSchemeOrProtocol(FileName, Https);
-  try
-    _system(M.AsAnsi(AURL, CP_UTF8).ToPointer);
-    Result := True;
-  except
-  end;
-//  raise Exception.Create('Not supported!');
-end;
-{$ENDIF MSWINDOWS}
-{$ENDIF IOS}
-{$ENDIF ANDROID}
-
-function IsPadOrPC: Boolean;
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-{$IFDEF IOS}
-begin
-  Result := IsPad;
-end;
-{$ELSE IOS}
-begin
-  Result := True;
-end;
-{$ENDIF IOS}
-{$ENDIF IOS or MACOS}
-{$IFDEF MSWINDOWS}
-begin
-  Result := True;
-end;
-{$ENDIF}
-{$IFDEF ANDROID}
-//var
-//  ScreenInches2,
-//  ScreenInches1,
-//  x,y: Double;
-//  dm: JDisplayMetrics;
-//begin
-//  Result := False;
-//  dm := GetJDisplayMetrics;
-//  if dm = nil then exit;
-//  x := dm.widthPixels;
-//  y := dm.heightPixels;
-//  try
-//    ScreenInches1 := Sqrt((x * x / dm.xdpi / dm.xdpi) + (y * y / dm.ydpi / dm.ydpi));
-//    ScreenInches2 := Sqr(x * x + y * Y ) / dm.densityDpi;
-//  except
-//    exit;
-//  end;
-//  Result := ScreenInches1 >= MiniScreenInches;
-//  if Result then
-//    Result := ScreenInches2 >= MiniScreenInches;
-//end;
-var
-  IsTablet: Boolean;
-begin
-  Result := False;
-  IsTablet := False;
-//  CallInUIThreadAndWaitFinishing(
-//  procedure
-//  begin
-    IsTablet := SharedActivity.getResources.getConfiguration.screenLayout and
-      TJConfiguration.JavaClass.SCREENLAYOUT_SIZE_MASK >= TJConfiguration.JavaClass.SCREENLAYOUT_SIZE_LARGE;
-//  end);
-  Result := IsTablet;
-end;
-{$ENDIF}
-
-function IsPad: Boolean;
-begin
-{$IFDEF MSWINDOWS}
-begin
-  //code by [龟山]Aone(1467948783)
-  Result := TOSVersion.Check(6, 1) and
-               (GetSystemMetrics(SM_TABLETPC) <> 0) and
-               ((GetSystemMetrics(SM_DIGITIZER) and NID_MULTI_INPUT) = NID_MULTI_INPUT);
-end;
-{$ELSE MSWINDOWS}
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-{$IFDEF IOS}
-begin
-  Result := IsPad;
-end;
-{$ELSE IOS}
-begin
-  Result := False;
-end;
-{$ENDIF IOS}
-{$ELSE} //IF DEFINED(IOS) or DEFINED(MACOS)
-  Result := IsPadOrPC;
-{$ENDIF IOS or MACOS}
-{$ENDIF MSWINDOWS}
-end;
-
-function GetTotalMemorySize: UInt64;
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-begin
-//  Result := TUIDevice2.Wrap(TUIDevice2.OCClass.currentDevice).totalMemory;
-  Result := NSRealMemoryAvailable;
-end;
-{$ENDIF}
-{$IFDEF MSWINDOWS}
-var
-  lpBuffer : TMEMORYSTATUSEX;
-begin
-  Result := 0;
-  ZeroMemory(@lpBuffer, Sizeof(TMEMORYSTATUSEX));
-  lpBuffer.dwLength := Sizeof(TMEMORYSTATUSEX);
-  GlobalMemoryStatusEx(lpBuffer);
-  Result := lpBuffer.ullTotalPhys;
-end;
-{$ENDIF}
-{$IFDEF ANDROID}
-var
-  Mgr: JActivityManager;
-  MgrNative: JObject;
-  MemInfo: JActivityManager_MemoryInfo;
-  AStrings: TStringList;
-  TempValue: string;
-  AReader: JReader;
-  ABufferedReader: JBufferedReader;
-begin
-  Result := 0;
-  MgrNative :=
-{$IF CompilerVersion >= 30.0} // >=RAD10
-    TAndroidHelper.Context
-{$ELSE}
-    SharedActivityContext
-{$ENDIF}
-    .getSystemService(TJContext.JavaClass.ACTIVITY_SERVICE);
-  if MgrNative <> nil then
-  begin
-    Mgr := TJActivityManager.Wrap((MgrNative as ILocalObject).GetObjectID);
-    MemInfo := TJActivityManager_MemoryInfo.JavaClass.init;
-    Mgr.getMemoryInfo(MemInfo);
-    try
-      Result := UInt64(MemInfo.totalMem);
-    except
-      //API level < 16
-      try
-        Result := UInt64(MemInfo.availMem);
-      except
-        Result := 0;
-      end;
-      if FileExists('/proc/meminfo') then
-      begin
-        AStrings := TStringList.Create;
-        try
-          AStrings.LineBreak := sLineBreak;
-          AStrings.NameValueSeparator := ':';
-          AStrings.Clear;
-          AReader := TJFileReader.JavaClass.init(StringToJString('/proc/meminfo')) as JReader;
-          ABufferedReader := TJBufferedReader.JavaClass.init(AReader);
-          repeat
-            TempValue := JStringToString(ABufferedReader.readLine);
-            if TempValue <> '' then
-            begin
-              AStrings.Add(TempValue);
-            end;
-          until (not ABufferedReader.ready);
-          ABufferedReader.close;
-          TempValue := AStrings.Values['MemTotal'].Trim;
-          AStrings.Clear;
-          AStrings.NameValueSeparator := ' ';
-          AStrings.Add(TempValue.Trim);
-          TempValue := AStrings.Names[0];
-//          ShowMessage(TempValue);
-          Result := StrToInt64Def(TempValue, Result div 1024) * 1024;
-        finally
-          FreeAndNil(AStrings);
-        end;
-      end;
-    end;
-  end;
-end;
-{$ENDIF}
-
-function GetFreeMemorySize: UInt64;
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-begin
-  //Result := Max(0, GetTotalMemorySize -
-  //  TUIDevice2.Wrap(TUIDevice2.OCClass.currentDevice).userMemory);
-  Result := NSRealMemoryAvailable;
-end;
-{$ENDIF}
-{$IFDEF MSWINDOWS}
-var
-  lpBuffer : TMEMORYSTATUSEX;
-begin
-  Result := 0;
-  ZeroMemory(@lpBuffer, Sizeof(TMEMORYSTATUSEX));
-  lpBuffer.dwLength := Sizeof(TMEMORYSTATUSEX);
-  GlobalMemoryStatusEx(lpBuffer);
-  Result := lpBuffer.ullAvailPhys;
-end;
-{$ENDIF}
-{$IFDEF ANDROID}
-var
-  Mgr: JActivityManager;
-  MgrNative: JObject;
-  MemInfo: JActivityManager_MemoryInfo;
-begin
-  Result := 0;
-  MgrNative :=
-{$IF CompilerVersion >= 30.0} // >=RAD10
-    TAndroidHelper.Context
-{$ELSE}
-    SharedActivityContext
-{$ENDIF}
-    .getSystemService(TJContext.JavaClass.ACTIVITY_SERVICE);
-  if MgrNative <> nil then
-  begin
-    Mgr := TJActivityManager.Wrap((MgrNative as ILocalObject).GetObjectID);
-    MemInfo := TJActivityManager_MemoryInfo.JavaClass.init;
-    Mgr.getMemoryInfo(MemInfo);
-    try
-      Result := UInt64(MemInfo.availMem);
-    except
-      Result := 0;
-    end;
-  end;
-end;
-{$ENDIF}
-
-function GetTotalSpaceSize(Path: string = PathDelim): UInt64;
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-var
-  Dict: NSDictionary;
-  P: Pointer;
-const
-  FoundationFwk: string = '/System/Library/Frameworks/Foundation.framework/Foundation';
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  Dict := TNSFileManager.Wrap(TNSFileManager.OCClass.defaultManager).attributesOfFileSystemForPath(NSStr(Path), nil);
-  if Dict = nil then
-    Exit;
-  P := Dict.objectForKey((CocoaNSStringConst(FoundationFwk, 'NSFileSystemSize') as ILocalObject).GetObjectID);
-  if P <> nil then
-    Result := TNSNumber.Wrap(P).unsignedLongLongValue;
-end;
-{$ENDIF}
-{$IFDEF MSWINDOWS}
-var
-  lpFreeBytesAvailableToCaller,
-  lpTotalNumberOfBytes,
-  lpTotalNumberOfFreeBytes: Int64;
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  lpTotalNumberOfBytes := MaxInt;
-  if GetDiskFreeSpaceEx(pchar(ExtractFileDrive(Path)),
-    lpFreeBytesAvailableToCaller,
-    lpTotalNumberOfBytes, @lpTotalNumberOfFreeBytes) then
-  begin
-    Result := UInt64(lpTotalNumberOfBytes);
-  end;
-end;
-{$ENDIF}
-{$IFDEF ANDROID}
-var
-  AJFile: JFile;
-  AJStatFs: JStatFs;
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  AJFile := TJFile.JavaClass.init(StringToJString(Path));
-  if AJFile = nil then exit;
-  AJStatFs := TJStatFs.JavaClass.init(AJFile.getPath);
-  if AJStatFs = nil then exit;
-  Result := UInt64(AJStatFs.getBlockSize) * UInt64(AJStatFs.getBlockCount);
-end;
-{$ENDIF}
-
-function GetFreeSpaceSize(Path: string = PathDelim): UInt64;
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-var
-  Dict: NSDictionary;
-  P: Pointer;
-const
-  FoundationFwk: string = '/System/Library/Frameworks/Foundation.framework/Foundation';
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  Dict := TNSFileManager.Wrap(TNSFileManager.OCClass.defaultManager).attributesOfFileSystemForPath(NSStr(Path), nil);
-  if Dict = nil then
-    Exit;
-  P := Dict.objectForKey((CocoaNSStringConst(FoundationFwk, 'NSFileSystemFreeSize') as ILocalObject).GetObjectID);
-  if P <> nil then
-    Result := TNSNumber.Wrap(P).unsignedLongLongValue;
-end;
-{$ENDIF}
-{$IFDEF MSWINDOWS}
-var
-  lpFreeBytesAvailableToCaller,
-  lpTotalNumberOfBytes,
-  lpTotalNumberOfFreeBytes: Int64;
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  lpTotalNumberOfFreeBytes := MaxInt;
-  if GetDiskFreeSpaceEx(pchar(ExtractFileDrive(Path)),
-    lpFreeBytesAvailableToCaller,
-    lpTotalNumberOfBytes, @lpTotalNumberOfFreeBytes) then
-  begin
-    Result := UInt64(lpTotalNumberOfFreeBytes);
-  end;
-end;
-{$ENDIF}
-{$IFDEF ANDROID}
-var
-  AJFile: JFile;
-  AJStatFs: JStatFs;
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  AJFile := TJFile.JavaClass.init(StringToJString(Path));
-  if AJFile = nil then exit;
-  AJStatFs := TJStatFs.JavaClass.init(AJFile.getPath);
-  if AJStatFs = nil then exit;
-  Result := UInt64(AJStatFs.getBlockSize) * UInt64(AJStatFs.getFreeBlocks);
-end;
-{$ENDIF}
-
-function GetAvailableSpaceSize(Path: string = PathDelim): UInt64;
-{$IF DEFINED(IOS) or DEFINED(MACOS)}
-begin
-  Result := GetFreeSpaceSize(Path);
-end;
-{$ENDIF}
-{$IFDEF MSWINDOWS}
-var
-  lpFreeBytesAvailableToCaller,
-  lpTotalNumberOfBytes,
-  lpTotalNumberOfFreeBytes: Int64;
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  lpFreeBytesAvailableToCaller := MaxInt;
-  if GetDiskFreeSpaceEx(pchar(ExtractFileDrive(Path)),
-    lpFreeBytesAvailableToCaller,
-    lpTotalNumberOfBytes, @lpTotalNumberOfFreeBytes) then
-  begin
-    Result := UInt64(lpFreeBytesAvailableToCaller);
-  end;
-end;
-{$ENDIF}
-{$IFDEF ANDROID}
-var
-  AJFile: JFile;
-  AJStatFs: JStatFs;
-begin
-  Result := 0;
-  if DirectoryExists(Path) or FileExists(Path) then
-  begin
-  end
-  else
-  begin
-    raise Exception.Create('Path " ' + Path +  '" not found.');
-  end;
-  AJFile := TJFile.JavaClass.init(StringToJString(Path));
-  if AJFile = nil then exit;
-    AJStatFs := TJStatFs.JavaClass.init(AJFile.getPath);
-  if AJStatFs = nil then exit;
-    Result := UInt64(AJStatFs.getBlockSize) * UInt64(AJStatFs.getAvailableBlocks);
-end;
-{$ENDIF}
-
-{$IFDEF ANDROID}
-
-function CanWriteExterStorage: Boolean;
-begin
-  Result := False;
-  Result := CheckPermission(C_android_permission_EXTERNAL_STORAGE);
-//  if Result and TOSVersion.Check(4) then
-//  begin
-// // 没有效果,而且返回 总是 False
-//    Result := CheckPermission(C_android_permission_WRITE_MEDIA);
-//  end;
-end;
-
-//copy form FMX.AddressBook.Android;
-function CheckPermission(const APermissionName: string): Boolean;
-var
-  PackageName: JString;
-begin
-  PackageName := TAndroidHelper.Context.getPackageName;
-//  if TOSVersion.Check(6) then
-//  begin
-//    Result := TAndroidHelper.Context.checkSelfPermission(StringToJString(APermissionName)) =
-//      TJPackageManager.JavaClass.PERMISSION_GRANTED;
-//    exit;
-//  end;
-  Result := TAndroidHelper.Context.getPackageManager.checkPermission(StringToJString(APermissionName), PackageName) =
-    TJPackageManager.JavaClass.PERMISSION_GRANTED;
-end;
-
-function isExternalStorageDocument(URI: Jnet_Uri): Boolean;
-begin
-  Result := False;
-  if URI = nil then exit;
-  Result := URI.getAuthority.equals(StringToJString('com.android.externalstorage.documents'));
-end;
-
-function isDownloadsDocument(URI: Jnet_Uri): Boolean;
-begin
-  Result := False;
-  if URI = nil then exit;
-  Result := URI.getAuthority.equals(StringToJString('com.android.providers.downloads.documents'));
-end;
-
-function isMediaDocument(URI: Jnet_Uri): Boolean;
-begin
-  Result := False;
-  if URI = nil then exit;
-  Result := URI.getAuthority.equals(StringToJString('com.android.providers.media.documents'));
-end;
-
-const
-  FILE_SELECT_CODE = 0;
-
-var
-  FMessageChooserID: Integer = 0;
-  FGetFileNameCallBack1: TGetFileNameListener;
-  FGetFileNameCallBack2: TGetFileNameLIsternerMethod;
-
-procedure HandleActivityMessageforChooser(const Sender: TObject; const M: TMessage);
-var
-  MediaDocument,
-  ExternalStorageDocument,
-  IsOK: Boolean;
-  DocType,
-  DocIDs,
-  FileScheme,
-  FileName:string;
-  URI: Jnet_Uri;
-  cursor: JCursor;
-  projection: TJavaObjectArray<JString>;
-  column_index: Integer;
-  DocIDInfos: TArray<string>;
-  TempDocIDStr: JString;
-  selection: JString;
-  selectionArgs: TJavaObjectArray<JString>;
-begin
-  IsOK := False;
-  FileName := '';
-  IsOK := M is TMessageResultNotification;
-  if IsOK and (TMessageResultNotification(M).RequestCode = FILE_SELECT_CODE) then
-  begin
-    IsOK := (TMessageResultNotification(M).ResultCode = TJActivity.JavaClass.RESULT_OK);
-  end;
-  if IsOK then
-  begin
-    IsOK := TMessageResultNotification(M).Value <> nil;
-  end;
-  if IsOK then
-  begin
-    URI := TMessageResultNotification(M).Value.getData;
-    IsOK := URI <> nil;
-  end;
-  FileName := '';
-  if IsOK then
-  begin
-    FileScheme := JStringToString(URI.getScheme);
-    if TOSVersion.Check(4, 4) and TJDocumentsContract.JavaClass.isDocumentUri(
-{$IF CompilerVersion >= 30.0} // >=RAD10
-      TAndroidHelper.Context
-{$ELSE}
-      SharedActivityContext
-{$ENDIF}
-      , URI) then
-    begin
-      //http://blog.csdn.net/u011200844/article/details/43703593
-      ExternalStorageDocument := False;
-      MediaDocument := False;
-      selection := nil;
-      selectionArgs := nil;
-      IsOK := False;
-      if isDownloadsDocument(URI) then
-      begin
-        TempDocIDStr := TJDocumentsContract.JavaClass.getDocumentId(URI);
-        URI := TJContentUris.JavaClass.withAppendedId(
-          TJnet_Uri.JavaClass.parse(StringToJString('content://downloads/public_downloads')),
-          TJLong.JavaClass.valueOf(TempDocIDStr).longValue);
-        //后面会继续处理。
-      end
-      else
-      begin
-        ExternalStorageDocument := isExternalStorageDocument(URI);
-        if not ExternalStorageDocument then
-          MediaDocument := isMediaDocument(URI);
-      end;
-      if ExternalStorageDocument or MediaDocument then
-      begin
-        DocIDs := JStringToString(TJDocumentsContract.JavaClass.getDocumentId(URI));
-        DocIDInfos := DocIDs.Split([':']);
-        if Length(DocIDInfos) > 1 then
-        begin
-          DocType := DocIDInfos[0];
-          if ExternalStorageDocument then
-          begin
-            if SameText(DocType, 'primary') then
-            begin
-              FileName := GetSDCardPath(0) + DocIDInfos[1];
-              IsOK := True;
-            end
-            else
-            begin
-              //后面会继续处理。
-            end;
-          end
-          else if MediaDocument then
-          begin
-            if SameText(DocType, 'image') then
-            begin
-              URI := TJImages_Media.JavaClass.EXTERNAL_CONTENT_URI;
-              IsOK := True;
-            end
-            else if SameText(DocType, 'video') then
-            begin
-              URI := TJVideo_Media.JavaClass.EXTERNAL_CONTENT_URI;
-              IsOK := True;
-            end
-            else if SameText(DocType, 'audio') then
-            begin
-              URI := TJAudio_Media.JavaClass.EXTERNAL_CONTENT_URI;
-              IsOK := True;
-            end;
-            if IsOK then
-            begin
-              selection := StringToJString('_id=?');
-              selectionArgs := TJavaObjectArray<JString>.Create(1);
-              selectionArgs.Items[0] := StringToJString(DocIDInfos[1]);
-              IsOK := False;
-              //后面会继续处理。
-            end;
-          end;
-        end;
-      end;
-    end
-    else
-      IsOK := SameText('file', FileScheme);
-  end
-  else exit;
-  if IsOK and FileName.IsEmpty then
-  begin
-    FileName := JStringToString(URI.getPath);
-  end
-  else if not IsOK then       
-  begin
-    IsOK := SameText('content', FileScheme);
-    if IsOK then
-    begin
-      IsOK := False;
-      projection := TJavaObjectArray<JString>.Create(1);
-      projection.Items[0] := StringToJString('_data');
-      try
-        cursor :=
-{$IF CompilerVersion >= 30.0} // >=RAD10
-          TAndroidHelper.Context
-{$ELSE}
-          SharedActivityContext
-{$ENDIF}
-          .getContentResolver().query(URI, projection, selection, selectionArgs, nil);
-          if (cursor <> nil) then
-          begin
-            column_index := cursor.getColumnIndexOrThrow(StringToJString('_data'));
-            if cursor.moveToFirst then
-            begin
-              FileName := JStringToString(cursor.getString(column_index));
-              IsOK := True;
-            end;
-          end;
-      except
-        IsOK := False;
-      end;
-    end;
-//    if not IsOK then
-//    begin
-//      FileName := JStringToString(URI.getPath);
-//      FileName := FileName.Trim;
-//      IsOK := not FileName.IsEmpty;
-//      if not IsOK then
-//      begin
-//          IsOK := FileName.IndexOf(PathDelim) <> -1;
-//      end;
-//      end;
-//    end;
-  end;
-  if IsOK then
-  begin
-    FileName := FileName.Trim;
-    IsOK := not FileName.IsEmpty;
-  end;
-//  if IsOK then
-//  begin
-////    IsOK := FileExists(FileName);
-//    IsOK := FileName.IndexOf(PathDelim) <> -1;
-//  end;
-  if Assigned(FGetFileNameCallBack1) then
-    FGetFileNameCallBack1(IsOK, FileName);
-  if Assigned(FGetFileNameCallBack2) then
-    FGetFileNameCallBack2(IsOK, FileName);
-end;
-
-function InternalOpenFileDialog(Title, FileExtension:string;
-  GetFileNameCallBack1: TGetFileNameListener;
-  GetFileNameCallBack2: TGetFileNameLIsternerMethod): Boolean;
-var
-  MIMEType: JString;
-  mime: JMimeTypeMap;
-  Intent: JIntent;
-  IntentChooser: JIntent;
-  sMIMEType: string;
-begin
-  Result := False;
-  FGetFileNameCallBack1 := GetFileNameCallBack1;
-  FGetFileNameCallBack2 := GetFileNameCallBack2;
-  if FileExtension.Substring(0,1) = '.' then
-  begin
-    FileExtension := FileExtension.Substring(1);
-  end;
-  if FileExtension  = '*.*' then
-  begin
-    FileExtension := '*/*';
-  end;
-  MIMEType := nil;
-  sMIMEType := '';
-  if FileExtension = 'file/*' then
-  begin
-    sMIMEType := 'file/*';
-  end
-  else if FileExtension = '*' then
-  begin
-    if TOSVersion.Check(4, 4) then
-    begin
-      sMIMEType := '*/*';
-    end
-    else
-    begin
-      sMIMEType := 'file/*';
-    end;
-  end
-  else if FileExtension = '*/*' then
-  begin
-    sMIMEType := '*/*';
-  end
-  else if FileExtension = '' then
-  begin
-    sMIMEType := '*/*';
-  end
-  else
-  begin
-    FileExtension := AnsiLowerCase(FileExtension);
-    //http://www.oschina.net/code/snippet_1269559_25060
-    mime := TJMimeTypeMap.JavaClass.getSingleton;
-    if mime <> nil then
-    begin
-      MIMEType := mime.getMimeTypeFromExtension(StringToJString(FileExtension));
-    end;
-  end;
-  if MIMEType <> nil then
-  begin
-    sMIMEType := JStringToString(MIMEType).Trim;
-  end;
-  if sMIMEType.IsEmpty then
-    sMIMEType := '*/*'; // File/* 有时候打不开
-  //http://www.cnblogs.com/linlf03/archive/2013/08/19/3267732.html
-//  if TOSVersion.Check(4, 4) then
-//  begin
-//    Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_OPEN_DOCUMENT);
-//  end
-//  else
-  begin
-    Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_GET_CONTENT);
-  end;
-  Intent.setType(StringToJString(sMIMEType));
-  Intent.addCategory(TJIntent.JavaClass.CATEGORY_OPENABLE);
-  IntentChooser := TJIntent.JavaClass.createChooser(Intent, StrToJCharSequence(Title));
-  if FMessageChooserID <> 0 then
-    TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FMessageChooserID);
-  FMessageChooserID := 0;
-  FMessageChooserID := TMessageManager.DefaultManager.SubscribeToMessage(
-    TMessageResultNotification, HandleActivityMessageforChooser);
-  try
-{$IF CompilerVersion >= 30.0} // >=RAD10
-    TAndroidHelper.Activity
-{$ELSE}
-    SharedActivity
-{$ENDIF}
-    .startActivityForResult(IntentChooser, FILE_SELECT_CODE);
-    Result := True;
-  except
-    raise Exception.Create(Error_NotFoundFileManager_Str);
-  end;
-end;
-
-function OpenFileDialog(Title, FileExtension:string; GetFileNameCallBack: TGetFileNameListener): Boolean;
-begin
-  Result := InternalOpenFileDialog(Title, FileExtension, GetFileNameCallBack, nil);
-end;
-
-function OpenFileDialog(Title, FileExtension:string; GetFileNameCallBack: TGetFileNameLIsternerMethod): Boolean;
-begin
-  Result := InternalOpenFileDialog(Title, FileExtension, nil, GetFileNameCallBack);
-end;
-
-var
-  FExterStoragePath: string = '';
-  FInnerStoragePath: string = '';
-  FVolumePaths: string = '';
-  FSDRegisteredReceiver: Boolean = False;
-
-//type
-//  TSDBroadcastListener = class(TJavaLocal, JFMXBroadcastReceiverListener)
-//  private
-//    //[Weak] FTestObj: TForm1;  //TForm1 是拿来测试,不是必须的。
-//  public
-//    constructor Create;
-//    //看上去,下面的函数属于线程中
-//    procedure onReceive(context: JContext; intent: JIntent); cdecl;
-//  end;
-//
-//var
-//  //安卓下消息3元素。
-//  FSDBroadcastReceiver: JFMXBroadcastReceiver;
-//  FSDIntentFilter: JIntentFilter;
-//  FSDBroadcastListener: TSDBroadcastListener;
-//  //你的 APP 安卓对象。
-//  FActivity: JNativeActivity;
-//
-//
-//{ TSDBroadcastListener }
-//
-//constructor TSDBroadcastListener.Create;
-//begin
-//  inherited Create;
-//  InnerStoragePath := GetSDCardPath(0);
-//  ExterStoragePath := GetSDCardPath(1);
-//  ExterStoragePathCanRead := False;
-//  ExterStoragePathCanWrite := False;
-//  SDMountedMessageReceived := False;
-//end;
-//
-//procedure TSDBroadcastListener.onReceive(context: JContext; intent: JIntent);
-//var
-//  Action,
-//  ExternalPath,
-//  TempStr1, TempStr2, TempStr3,
-//  TempStr: string;
-//  AJFile: JFile;
-//begin
-//  //这里就是处理消息的地方。
-//  Action := JStringToString(intent.getAction);
-//  TempStr1 := JStringToString(TJIntent.JavaClass.ACTION_MEDIA_MOUNTED);
-//  TempStr2 := JStringToString(TJIntent.JavaClass.ACTION_MEDIA_UNMOUNTED);
-//  ExternalPath := IncludeTrailingPathDelimiter(GetExternalStoragePath);
-//  if SameText(Action, TempStr1) or SameText(Action, TempStr2) then
-//  begin
-//    TempStr := JStringToString(intent.getData.getPath);// 外置设备路径
-//    TempStr := IncludeTrailingPathDelimiter(TempStr);
-//    if TOSVersion.Check(5) and SameFileName(TempStr, ExternalPath) then
-//    begin
-//      //说明内外卡交换了。这是 5.0 的特点。
-//      InnerStoragePath := ExterStoragePath;
-//      ExterStoragePath := TempStr;
-//    end;
-//    if SameFileName(TempStr, ExterStoragePath) then
-//    begin
-//      if SameText(Action, TempStr1) then
-//      begin
-//        ExterStoragePathCanRead := True;
-//        AJFile := TJFile.JavaClass.init(
-//          StringToJString(ExcludeTrailingPathDelimiter(TempStr)));
-//        if AJFile <> nil then
-//        begin
-//          ExterStoragePathCanRead := AJFile.canRead;
-//          ExterStoragePathCanWrite := AJFile.canWrite;
-//        end;
-//        SDMountedMessageReceived := True;
-//      end;
-//    end;
-//  end;
-//  TempStr1 := JStringToString(TJIntent.JavaClass.ACTION_MEDIA_REMOVED);
-//  TempStr2 := JStringToString(TJIntent.JavaClass.ACTION_MEDIA_SHARED);
-//  TempStr3 := JStringToString(TJIntent.JavaClass.ACTION_MEDIA_EJECT);
-//  if SameText(Action, TempStr1) or
-//    SameText(Action, TempStr2) or SameText(Action, TempStr3) then
-//  begin
-//    TempStr := JStringToString(intent.getData.getPath);// 外置设备路径
-//    TempStr := IncludeTrailingPathDelimiter(TempStr);
-//    if SameFileName(TempStr, ExterStoragePath) then
-//    begin
-//      ExterStoragePathCanRead := False;
-//      ExterStoragePathCanWrite := False;
-//    end;
-//  end;
-//end;
-//
-//procedure RegisterSDReceiver;
-//begin
-//  if FSDRegisteredReceiver then exit;
-//  FActivity := TJNativeActivity.Wrap(PANativeActivity(System.DelphiActivity)^.clazz);
-//  //FActivity :=
-//{$IF CompilerVersion >= 30.0} // >=RAD10
-//    TAndroidHelper.Activity
-//{$ELSE}
-//    SharedActivity
-//{$ENDIF};
-//  FSDBroadcastListener := TSDBroadcastListener.Create;
-//  FSDBroadcastReceiver := TJFMXBroadcastReceiver.JavaClass.init(FSDBroadcastListener);
-//
-//  //http://blog.csdn.net/yigelangmandeshiren/article/details/8145059
-//  FSDIntentFilter := TJIntentFilter.JavaClass.init(TJIntent.JavaClass.ACTION_MEDIA_MOUNTED);
-//  FSDIntentFilter.setPriority(1000);// 设置最高优先级
-//  FSDIntentFilter.addAction(TJIntent.JavaClass.ACTION_MEDIA_EJECT);
-//  FSDIntentFilter.addAction(TJIntent.JavaClass.ACTION_MEDIA_REMOVED);
-//  FSDIntentFilter.addAction(TJIntent.JavaClass.ACTION_MEDIA_SHARED);
-//  FSDIntentFilter.addAction(TJIntent.JavaClass.ACTION_MEDIA_UNMOUNTED);
-//  FSDIntentFilter.addDataScheme(StringToJString('file'));
-//
-//  //注册消息接收器。别忘了 unregisterReceiver(FBroadcastReceiver);
-//  FActivity.registerReceiver(FSDBroadcastReceiver, FSDIntentFilter);
-//end;
-//
-//procedure UnRegisterSDReceiver;
-//begin
-//  if not FSDRegisteredReceiver then exit;
-//  FActivity.unregisterReceiver(FSDBroadcastReceiver);
-//  FreeAndNil(FSDBroadcastListener);
-//  FSDBroadcastReceiver := nil;
-//  FSDIntentFilter := nil;
-//  FActivity := nil;
-//end;
-
-function GetIsExternalStorageRemovable: Boolean;
-begin
-  Result := True;
-  try
-    Result := TJEnvironment.JavaClass.isExternalStorageRemovable;
-  except
-    //低版本可能发生错误。
-  end;
-end;
-
-function GetExterStoragePath: string;
-//var
-//  AJstr: JString;
-begin
-  if FExterStoragePath.Trim = '' then
-  begin
-    FExterStoragePath := GetSDCardPath(1);
-    if GetIsExternalStorageRemovable then
-    begin
-      FExterStoragePath := GetSDCardPath(0);
-    end;
-  end;
-  Result := FExterStoragePath.Trim;
-  if not DirectoryExists(ExcludeTrailingPathDelimiter(Result)) then
-    Result := '';
-//  AJstr := TJSystem.JavaClass.getenv(StringToJString('SECONDARY_STORAGE'));
-//  if AJstr <> nil then
-//    Result := IncludeTrailingPathDelimiter(JStringToString(AJstr));
-end;
-
-function GetInnerStoragePath: string;
-//var
-//  AJstr: JString;
-begin
-  if FInnerStoragePath.Trim = '' then
-  begin
-    FInnerStoragePath := GetSDCardPath(0);
-    if GetIsExternalStorageRemovable then
-    begin
-      FInnerStoragePath := GetSDCardPath(1);
-    end;
-  end;
-  Result := FInnerStoragePath.Trim;
-  if not DirectoryExists(ExcludeTrailingPathDelimiter(Result)) then
-    Result := '';
-
-//  ExterStoragePath := GetSDCardPath(1);
-//  AJstr := TJSystem.JavaClass.getenv(StringToJString('EXTERNAL_STORAGE'));
-//  if AJstr <> nil then
-//    Result := IncludeTrailingPathDelimiter(JStringToString(AJstr));
-end;
-
-function GetVolumePaths: string;
-var
-  Sm: JStorageManager;
-  SmNative: JObject;
-  AList: TStrings;
-  VolumePaths: TJavaObjectArray<JString>;
-  I: Integer;
-begin
-  Result := '';
-  if not IsCanFindJavaMethod('getVolumePaths',
-    '()[Ljava/lang/String;', 'android/os/storage/StorageManager') then
-  begin
-    //可以返回点别的。
-    exit;
-  end;
-  Sm := nil;
-  SmNative :=
-{$IF CompilerVersion >= 30.0} // >=RAD10
-    TAndroidHelper.Context
-{$ELSE}
-    SharedActivityContext
-{$ENDIF}
-    .getSystemService(TJContext.JavaClass.STORAGE_SERVICE);
-  if SmNative <> nil then
-  begin
-    Sm := TJStorageManager.Wrap((SmNative as ILocalObject).GetObjectID);
-  end;
-  //不打算兼容 2.X 了。
-  if (Sm <> nil) and TOSVersion.Check(4) then
-  begin
-    AList := TStringList.Create;
-    try
-      try
-        VolumePaths := Sm.getVolumePaths;
-        for I := 0 to VolumePaths.Length - 1 do
-        begin
-          AList.Add(JStringToString(VolumePaths.Items[I]));
-        end;
-      except
-      end;
-      VolumePaths := nil;
-      Result := AList.Text;
-      FVolumePaths := Result;
-    finally
-      FreeAndNil(AList);
-    end;
-  end;
-end;
-
-//function GetActiveMemorySize: UInt64;
-//var
-//  AStringVs,
-//  AStrings: TStringList;
-//  TempValue: string;
-//  ABufferedReader: JBufferedReader;
-//  V1, V2: UInt64;
-//begin
-//  Result := 0;
-//  if FileExists('/proc/meminfo') then
-//  begin
-//    AStrings := TStringList.Create;
-//    AStringVs := TStringList.Create;
-//    try
-//      AStrings.LineBreak := sLineBreak;
-//      AStrings.NameValueSeparator := ':';
-//      AStrings.Clear;
-//      ABufferedReader := TJBufferedReader.JavaClass.init(
-//        JReader(TJFileReader.JavaClass.init(StringToJString('/proc/meminfo'))));
-//      repeat
-//        TempValue := JStringToString(ABufferedReader.readLine);
-//        if TempValue <> '' then
-//        begin
-//          AStrings.Add(TempValue);
-//        end;
-//      until (not ABufferedReader.ready);
-//      ABufferedReader.close;
-//      V1 := 0;
-//      TempValue := AStrings.Values['Mapped'].Trim;
-//      AStringVs.Clear;
-//      AStringVs.NameValueSeparator := ' ';
-//      AStringVs.Add(TempValue.Trim);
-//      TempValue := AStringVs.Names[0];
-//      V2 := StrToInt64Def(TempValue, 0);
-//      V1 := V1 + V2;
-//      TempValue := AStrings.Values['Inactive'].Trim;
-//      AStringVs.Clear;
-//      AStringVs.NameValueSeparator := ' ';
-//      AStringVs.Add(TempValue.Trim);
-//      TempValue := AStringVs.Names[0];
-//      V2 := StrToInt64Def(TempValue, 0);
-//      V1 := V1 + V2;
-//      Result := V1 * 1024;
-//    finally
-//      FreeAndNil(AStringVs);
-//      FreeAndNil(AStrings);
-//    end;
-//  end;
-//  if Result = 0 then
-//  begin
-//    Result := GetFreeMemorySize;
-//  end;
-//end;
-
-function GetScreenClientInches: Single;
-var
-  x,y: Double;
-  dm: JDisplayMetrics;
-begin
-  Result := 3;
-  dm := GetJDisplayMetrics;
-  if dm = nil then exit;
-  x := dm.widthPixels;
-  y := dm.heightPixels;
-//  x := System.Math.Power(x / dm.xdpi, 2);
-//  y := System.Math.Power(y / dm.ydpi, 2);
-//  Result := Sqrt(x + y);
-  if (dm.densityDpi > dm.xdpi) and (dm.densityDpi > dm.ydpi) then
-  begin
-    Result := Sqrt(x * x + y * y ) / dm.densityDpi;
-  end
-  else
-  begin
-    Result := Sqrt((x * x / dm.xdpi / dm.xdpi) + (y * y / dm.ydpi / dm.ydpi));
-  end;
-end;
-
-function IsCanFindJavaClass(const NamePath: string): Boolean;
-var
-  PEnv: PJNIEnv;
-{$IF CompilerVersion < 30.0} // < RAD10
-  PActivity: PANativeActivity;
-{$ELSE}
-  ContextClass: JNIClass;
-{$ENDIF}
-  TempClass: JNIClass;
-  AMS: MarshaledAString;
-begin
-  try
-    TempClass := nil;
-{$IF CompilerVersion < 30.0} // < RAD10
-    PActivity := PANativeActivity(System.DelphiActivity);
-    PActivity^.vm^.AttachCurrentThread(PActivity^.vm, @PEnv, nil);
-{$ELSE}
-    PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @PEnv, nil);
-    ContextClass := nil;
-    ContextClass := PEnv^.GetObjectClass(PEnv, System.JavaContext);
-{$ENDIF}
-    AMS := MarshaledAString(Utf8Encode(NamePath.Trim.Replace('.', '/', [rfReplaceAll])));
-    try
-    TempClass := PEnv^.FindClass(PEnv, AMS);
-    PEnv^.ExceptionClear(PEnv);
-    Result := TempClass <> nil;
-    finally
-      if TempClass <> nil then
-        PEnv^.DeleteLocalRef(PEnv, TempClass);
-{$IF CompilerVersion < 30.0} // < RAD10
-{$ELSE}
-      if ContextClass <> nil then
-        PEnv^.DeleteLocalRef(PEnv, ContextClass);
-{$ENDIF}
-    end;
-  except
-    Result := False;
-  end;
-end;
-
-function IsCanFindJavaMethod(const MethodName, Signature: string; const CalssNamePath: string = ''): Boolean;
-var
-  PEnv: PJNIEnv;
-{$IF CompilerVersion < 30.0} // < RAD10
-  PActivity: PANativeActivity;
-{$ELSE}
-  ContextClass: JNIClass;
-{$ENDIF}
-  ActivityClass: JNIClass;
-  GetMethod: JNIMethodID;
-  ASignature: string;
-  AMSMethodName, AMSSignature: MarshaledAString;
-begin
-  try
-    AMSMethodName := MarshaledAString(Utf8Encode(MethodName.Trim));
-
-{$IF CompilerVersion < 30.0} // < RAD10
-    PActivity := PANativeActivity(System.DelphiActivity);
-    PActivity^.vm^.AttachCurrentThread(PActivity^.vm, @PEnv, nil);
-{$ELSE}
-    PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @PEnv, nil);
-    ContextClass := nil;
-    ContextClass := PEnv^.GetObjectClass(PEnv, System.JavaContext);
-{$ENDIF}
-    ActivityClass := nil;
-    try
-      if CalssNamePath.Trim <> '' then
-      begin
-        ASignature := CalssNamePath.Trim.Replace('.', '/', [rfReplaceAll]);
-        AMSSignature := MarshaledAString(Utf8Encode(ASignature));
-        ActivityClass := PEnv^.FindClass(PEnv, AMSSignature);
-        PEnv^.ExceptionClear(PEnv);
-      end
-      else
-      begin
-{$IF CompilerVersion < 30.0} // < RAD10
-        ActivityClass := PEnv^.GetObjectClass(PEnv, PActivity^.clazz);
-{$ELSE}
-        ActivityClass := PEnv^.GetObjectClass(PEnv, System.JavaContext);
-{$ENDIF}
-      end;
-      if ActivityClass <> nil then
-      begin
-        ASignature := Signature.Trim;
-        AMSSignature := MarshaledAString(Utf8Encode(ASignature));
-        GetMethod := PEnv^.GetMethodID(PEnv, ActivityClass, AMSMethodName, AMSSignature);
-        PEnv^.ExceptionClear(PEnv);
-        Result := GetMethod <> nil;
-      end;
-    finally
-      if ActivityClass <> nil then
-        PEnv^.DeleteLocalRef(PEnv, ActivityClass);
-{$IF CompilerVersion < 30.0} // < RAD10
-{$ELSE}
-      if ContextClass <> nil then
-        PEnv^.DeleteLocalRef(PEnv, ContextClass);
-{$ENDIF}
-    end;
-  except
-    Result := False;
-  end;
-end;
-
-function IsCanFindJavaStaticMethod(const MethodName, Signature: string; const CalssNamePath: string = ''): Boolean;
-var
-  PEnv: PJNIEnv;
-{$IF CompilerVersion < 30.0} // < RAD10
-  PActivity: PANativeActivity;
-{$ELSE}
-  ContextClass: JNIClass;
-{$ENDIF}
-  ActivityClass: JNIClass;
-  GetMethod: JNIMethodID;
-  ASignature: string;
-  AMSMethodName, AMSSignature: MarshaledAString;
-begin
-  try
-    AMSMethodName := MarshaledAString(Utf8Encode(MethodName.Trim));
-
-{$IF CompilerVersion < 30.0} // < RAD10
-    PActivity := PANativeActivity(System.DelphiActivity);
-    PActivity^.vm^.AttachCurrentThread(PActivity^.vm, @PEnv, nil);
-{$ELSE}
-    PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @PEnv, nil);
-    ContextClass := nil;
-    ContextClass := PEnv^.GetObjectClass(PEnv, System.JavaContext);
-{$ENDIF}
-    ActivityClass := nil;
-    try
-      if CalssNamePath.Trim <> '' then
-      begin
-        ASignature := CalssNamePath.Trim.Replace('.', '/', [rfReplaceAll]);
-        AMSSignature := MarshaledAString(Utf8Encode(ASignature));
-        ActivityClass := PEnv^.FindClass(PEnv, AMSSignature);
-        PEnv^.ExceptionClear(PEnv);
-      end
-      else
-      begin
-{$IF CompilerVersion < 30.0} // < RAD10
-        ActivityClass := PEnv^.GetObjectClass(PEnv, PActivity^.clazz);
-{$ELSE}
-        ActivityClass := PEnv^.GetObjectClass(PEnv, System.JavaContext);
-{$ENDIF}
-      end;
-      if ActivityClass <> nil then
-      begin
-        ASignature := Signature.Trim;
-        AMSSignature := MarshaledAString(Utf8Encode(ASignature));
-        GetMethod := PEnv^.GetStaticMethodID(PEnv, ActivityClass, AMSMethodName, AMSSignature);
-        PEnv^.ExceptionClear(PEnv);
-        Result := GetMethod <> nil;
-      end;
-    finally
-      if ActivityClass <> nil then
-        PEnv^.DeleteLocalRef(PEnv, ActivityClass);
-{$IF CompilerVersion < 30.0} // < RAD10
-{$ELSE}
-      if ContextClass <> nil then
-        PEnv^.DeleteLocalRef(PEnv, ContextClass);
-{$ENDIF}
-    end;
-  except
-    Result := False;
-  end;
-end;
-
-procedure UpdateAlbum(FileNames: string);
-var
-  AJStrList:  TJavaObjectArray<JString>;
-  I: Integer;
-begin
-  With TStringList.Create do
-  begin
-    try
-      Text := FileNames;
-      AJStrList := TJavaObjectArray<JString>.Create(Count);
-      for I := 0 to Count - 1 do
-      begin
-        AJStrList.Items[I] := StringToJString(Strings[I]);
-      end;
-    finally
-      Free;
-    end;
-  end;
-  TJMediaScannerConnection.JavaClass.scanFile(TAndroidHelper.Context, AJStrList,
-    nil, nil);
-end;
-
-function ReadFileToString(const AFileName: string): string;
-var
-  AReader: JReader;
-  ABufferedReader: JBufferedReader;
-  TempValue: string;
-begin
-  Result := '';
-  if not FileExists(AFileName) then exit;
-  AReader := TJFileReader.JavaClass.init(StringToJString(AFileName)) as JReader;
-  ABufferedReader := TJBufferedReader.JavaClass.init(AReader);
-  repeat
-    TempValue := JStringToString(ABufferedReader.readLine);
-    if TempValue <> '' then
-    begin
-      Result := Result + sLineBreak + TempValue;
-    end;
-  until (not ABufferedReader.ready);
-  ABufferedReader.close;
-end;
-
-function ReadNoSizeFileToString(const AFileName: string): string;
-begin
-  Result := '';
-  if not FileExists(AFileName) then exit;
-  With TFileStream.Create(AFileName, fmOpenRead) do
-  try
-    if Size = -1 then exit;
-  finally
-    Free;
-  end;
-  Result := ReadFileToString(AFileName);
-end;
-
-{$ENDIF}
-
-{$IFDEF ANDROID}
-
-function GetJniPath(MethodName, Signature: MarshaledAString): string;
-var
-  PEnv: PJniEnv;
-  ActivityClass: JNIClass;
-  FileClass: JNIClass;
-  GetMethod: JNIMethodID;
-  GetPathMethod: JNIMethodID;
-  PActivity: PANativeActivity;
-  StrPathObject: JNIObject;
-  FileObject: JNIObject;
-begin
-
-  PActivity := PANativeActivity(System.DelphiActivity);
-  PActivity^.vm^.AttachCurrentThread(PActivity^.vm, @PEnv, nil);
-  ActivityClass := PEnv^.GetObjectClass(PEnv, PActivity^.clazz);
-
-  GetMethod := PEnv^.GetMethodID(PEnv, ActivityClass, MethodName, Signature);
-  FileObject := PEnv^.CallObjectMethodA(PEnv, PActivity^.clazz, GetMethod, PJNIValue(ArgsToJNIValues([nil])));
-  if FileObject = nil then
-    Exit('');
-  FileClass := PEnv^.GetObjectClass(PEnv, FileObject);
-
-  GetPathMethod := PEnv^.GetMethodID(PEnv, FileClass, 'getPath', '()Ljava/lang/String;');
-  StrPathObject := PEnv^.CallObjectMethodA(PEnv, FileObject, GetPathMethod, PJNIValue(ArgsToJNIValues([])));
-
-  Result := JNIStringToString(PEnv, StrPathObject);
-
-  PEnv^.DeleteLocalRef(PEnv, StrPathObject);
-  PEnv^.DeleteLocalRef(PEnv, FileClass);
-  PEnv^.DeleteLocalRef(PEnv, FileObject);
-  PEnv^.DeleteLocalRef(PEnv, ActivityClass);
-
-end;
-
-function JNIgetExternalStorageDirectory(SubPath: string): string;
-begin
-//  if SubPath <> '' then
-//  begin
-//    Result := IncludeTrailingPathDelimiter(
-//      GetJniPath('getExternalStorageDirectory', '()Landroid/os/Environment;')
-//      ) + SubPath;
-//  end
-//  else
-//  begin
-//    Result := GetJniPath('getExternalStorageDirectory', '()Landroid/os/Environment;');
-//  end;
-
-  try
-    if SubPath <> '' then
-    begin
-      Result := IncludeTrailingPathDelimiter(JStringToString(
-        TJEnvironment.JavaClass.getExternalStorageDirectory.getPath)) + SubPath;
-    end
-    else
-    begin
-      Result := JStringToString(TJEnvironment.JavaClass.getExternalStorageDirectory.getPath);
-    end;
-  except
-    //低版本可能发生错误。
-  end;
-end;
-
-function GetExternalStoragePath: string;
-begin
-  Result := IncludeTrailingPathDelimiter(JNIgetExternalStorageDirectory(''));
-end;
-
-//function isPathCanWrite(const PathOrDir: string; const Default: Boolean = True): Boolean;
-//var
-//  ADir: string;
-//begin
-//  Result := False;
-//  ADir := ExcludeTrailingPathDelimiter(PathOrDir);
-//  if not DirectoryExists(ADir) then exit;
-//  Result := True;
-//  try
-////明明无权限写入,却返回 canWrite 为 True
-//    if not TJFile.JavaClass.init(StringToJString(ADir)).canWrite then
-//    begin
-//      Result := False;
-//    end;
-//  except
-//    Result := False;
-//  end;
-//end;
-
-function isPathCanUseNow(const PathOrDir: string; const Default: Boolean = True): Boolean;
-var
-  ADir: string;
-begin
-  Result := False;
-  ADir := ExcludeTrailingPathDelimiter(PathOrDir);
-  if not DirectoryExists(ADir) then exit;
-  try
-//    //下面的代码不能正确的区分内外 SD。
-//    Result := TJEnvironment.JavaClass.getExternalStorageState.equals(TJEnvironment.JavaClass.MEDIA_MOUNTED);
-//    if GetExterStoragePath.Trim = '' then exit;
-    Result := True;
-//    if FindJavaMethod('getStorageState',
-//      '(Ljava/io/File;)Ljava/lang/String;', 'android/os/Environment') then
-//    begin
-//      // 这个接口 5.0 会死锁。还是不用了。
-//      if not TJEnvironment.JavaClass.getStorageState(
-//        TJFile.JavaClass.init(StringToJString(ADir))).equals(
-//          TJEnvironment.JavaClass.MEDIA_MOUNTED) then
-//      begin
-//        Result := False;
-//      end;
-//    end
-//    else
-    begin
-      if not TJFile.JavaClass.init(StringToJString(ADir)).canRead then
-      begin
-        Result := False;
-      end;
-    end;
-  except
-  end;
-end;
-{$ELSE}
-function isPathCanUseNow(const PathOrDir: string; const Default: Boolean = True): Boolean;
-begin
-  Result := False;
-  if not DirectoryExists(ExcludeTrailingPathDelimiter(PathOrDir)) then exit;
-  Result := Default;
-end;
-{$ENDIF ANDROID}
-
-function TestPathCanWrite(const PathOrDir: string): Boolean;
-var
-  ATempFile,
-  ADir: string;
-  AHandle: THandle;
-begin
-  Result := False;
-  ADir := ExcludeTrailingPathDelimiter(PathOrDir);
-  if not DirectoryExists(ADir) then exit;
-  repeat
-    ATempFile := System.IOUtils.TPath.GetTempFileName;
-    try
-      if FileExists(ATempFile) then
-        System.IOUtils.TFile.Delete(ATempFile);
-    except
-    end;
-    ATempFile := IncludeTrailingPathDelimiter(ADir) + ExtractFileName(ATempFile);
-  until not FileExists(ATempFile);
-//  ATempFile := GetTempFileName(ADir);
-//  if FileExists(ATempFile) then
-//  begin
-//    System.IOUtils.TFile.Delete(ATempFile);
-//  end;
-  try
-    AHandle := INVALID_HANDLE_VALUE;
-{$IF Defined(MSWINDOWS)}
-    AHandle := FileCreate(ATempFile, 0);
-{$ELSEIF Defined(POSIX)}
-    AHandle := FileCreate(ATempFile, FileAccessRights);
-{$ENDIF POSIX}
-    if AHandle = INVALID_HANDLE_VALUE then
-    begin
-      Result := False;
-    end
-    else
-    begin
-      Result := True;
-      FileClose(AHandle);
-    end;
-  except
-    Result := False;
-  end;
-  if FileExists(ATempFile) then
-  begin
-    System.IOUtils.TFile.Delete(ATempFile);
-    Result := True;
-  end;
-end;
-
-//function GetTempFileName(const ATempPath: string): string;
-//{$IFDEF MSWINDOWS}
-//var
-//  ErrCode: UINT;
-//begin
-//  SetLength(Result, MAX_PATH);
-//
-//  SetLastError(ERROR_SUCCESS);
-//  ErrCode := Winapi.Windows.GetTempFileName(PChar(
-//    IncludeTrailingPathDelimiter(ATempPath)
-//    ), 'tmp', 0, PChar(Result)); // DO NOT LOCALIZE
-//  if ErrCode = 0 then
-//    raise EInOutError.Create(SysErrorMessage(GetLastError));
-//
-//  SetLength(Result, StrLen(PChar(Result)));
-//  if FileExists(Result) then
-//  begin
-//    System.IOUtils.TFile.Delete(Result);
-//  end;
-//end;
-//{$ENDIF}
-//{$IFDEF POSIX}
-//var
-//  LTempPath: TBytes;
-//  M: TMarshaller;
-//  LRet: MarshaledAString;
-//begin
-////   char * tempnam(const char *dir, const char *pfx);
-//
-//  { Obtain a temporary file name }
-//  // This code changed from getting the temp name from the temp path via system
-//  // to get the temp name inside the specified temp path. We get the system temp path.
-////  LTempPath := TEncoding.UTF8.GetBytes(string(tmpnam(nil)));
-//  LRet := tempnam(MarshaledAString(M.AsUTF8(
-// //返回的路径没有包含 ATempPath
-//    IncludeTrailingPathDelimiter(ATempPath)
-//    ).ToPointer),nil);
-//  LTempPath := TEncoding.UTF8.GetBytes(string(LRet));
-//  free(LRet);
-//
-//  { Convert to UTF16 or leave blank on possible error }
-//  if LTempPath <> nil then
-//    Result := TEncoding.UTF8.GetString(LTempPath)
-//  else
-//    Result := '';
-//end;
-//{$ENDIF POSIX}
-
-
-{$IFDEF ANDROID}
-function FileSystemAttributes(const Path: string): TFileSystemAttributes;
-begin
-  Result := [fsSymLink, fsCaseSensitive];
-//  For android platform we can use the function PathConf on the same way
-//  that is used on IOS, but the problem is that for android we only can check
-//  _PC_2_SYMLINKS name, and that call is failing on version 2.3.3.
-
-end;
-{$ENDIF ANDROID}
-
-function ExpandFileNameCase2(const FileName, RootPath: string; out MatchFound: TFilenameCaseMatch): string;
-var
-  SR: System.SysUtils.TSearchRec;
-  FullPath, Name: string;
-  Status: Integer;
-{$IFDEF POSIX}
-  FoundOne: Boolean;
-  Scans: Byte;
-  FirstLetter, TestLetter: string;
-{$ENDIF POSIX}
-begin
-  Result := ExpandFileName(FileName);
-  MatchFound := mkNone;
-
-  if FileName = '' then // Stop for empty strings, otherwise we risk to get info infinite loop.
-    Exit;
-
-  FullPath := ExtractFilePath(Result);
-  Name := ExtractFileName(Result);
-
-  // if FullPath is not the root directory  (portable)
-  if not SameFileName(FullPath, IncludeTrailingPathDelimiter(ExtractFileDrive(FullPath))) then
-  begin  // Does the path need case-sensitive work?
-    Status := FindFirst(ExcludeTrailingPathDelimiter(FullPath), faAnyFile, SR);
-    System.SysUtils.FindClose(SR);   // close search before going recursive
-    if Status <> 0 then
-    begin
-      if SameFileName(IncludeTrailingPathDelimiter(FullPath), IncludeTrailingPathDelimiter(RootPath)) then
-      begin
-      end
-      else
-      begin
-        FullPath := ExcludeTrailingPathDelimiter(FullPath);
-        FullPath := ExpandFileNameCase2(FullPath, RootPath, MatchFound);
-        if MatchFound = mkNone then
-          Exit;    // if we can't find the path, we certainly can't find the file!
-      end;
-      FullPath := IncludeTrailingPathDelimiter(FullPath);
-    end;
-  end;
-
-  // Path is validated / adjusted.  Now for the file itself
-  try
-    if System.SysUtils.FindFirst(FullPath + Name, faAnyFile, SR)= 0 then    // exact match on filename
-    begin
-      if not (MatchFound in [mkSingleMatch, mkAmbiguous]) then  // path might have been inexact
-      begin
-        if Name = SR.Name then
-          MatchFound := mkExactMatch
-        else
-          MatchFound := mkSingleMatch;
-      end;
-      Exit(FullPath + SR.Name);
-    end;
-  finally
-    System.SysUtils.FindClose(SR);
-  end;
-
-{$IFDEF POSIX}
-{ Scan the directory.
-  To minimize the number of filenames tested, scan the directory
-  using upper/lowercase first letter + wildcard.
-  This results in two scans of the directory (particularly on Linux) but
-  vastly reduces the number of times we have to perform an expensive
-  locale-charset case-insensitive string compare.  }
-
-  FoundOne := False;
-
-  if (fsCaseSensitive in FileSystemAttributes(FullPath)) or
-     (fsCasePreserving in FileSystemAttributes(FullPath)) then
-  begin
-    // First, scan for lowercase first letter
-    FirstLetter := AnsiLowerCase(Name[Low(string)]);
-    for Scans := 0 to 1 do
-    begin
-      Status := FindFirst(FullPath + FirstLetter + '*', faAnyFile, SR);
-      while Status = 0 do
-      begin
-        if AnsiSameText(SR.Name, Name) then
-        begin
-          if FoundOne then
-          begin  // this is the second match
-            MatchFound := mkAmbiguous;
-            Exit;
-          end
-          else
-          begin
-            FoundOne := True;
-            Result := FullPath + SR.Name;
-          end;
-        end;
-        Status := FindNext(SR);
-      end;
-      FindClose(SR);
-      TestLetter := AnsiUpperCase(Name[Low(string)]);
-      if TestLetter = FirstLetter then
-        Break;
-      FirstLetter := TestLetter;
-    end;
-
-    if MatchFound <> mkAmbiguous then
-    begin
-      if FoundOne then
-        MatchFound := mkSingleMatch
-      else
-        MatchFound := mkNone;
-    end;
-  end;
-{$ENDIF POSIX}
-end;
-
-function BuildFileListInAPath(const Path: string; const Attr: Integer;
-  JustFile: Boolean = False): string;
-var
-  AList: TStringList;
-begin
-  Result := '';
-  AList := TStringList.Create;
-  try
-    BuildFileListInAPath(Path, Attr, AList, JustFile);
-    Result := AList.Text;
-  finally
-    FreeAndNil(AList);
-  end;
-end;
-
-function BuildFileListInAPath(const Path: string; const Attr: Integer; const List: TStrings;
-  JustFile: Boolean = False): Boolean;
-var
-  SearchRec: TSearchRec;
-  R: Integer;
-begin
-  Assert(List <> nil);
-  R := System.SysUtils.FindFirst(ExcludeTrailingPathDelimiter(Path), Attr, SearchRec);
-  Result := R = 0;
-  try
-    if Result then
-    begin
-      while R = 0 do
-      begin
-        if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
-        begin
-          if ((SearchRec.Attr and faDirectory) = faDirectory) then
-          begin
-            if not JustFile then
-              List.Add(SearchRec.Name);
-          end
-          else
-            List.Add(SearchRec.Name);
-        end;
-        R := System.SysUtils.FindNext(SearchRec);
-      end;
-      Result := R = 0;
-    end;
-  finally
-    System.SysUtils.FindClose(SearchRec);
-  end;
-end;
-
-
-function faAttrToFileAttributes(
-  const Attributes: Integer): TFileAttributes;
-begin
-{$IFDEF MSWINDOWS}
-  Result := [];
-
-  if Attributes and faReadOnly <> 0 then
-    Include(Result, TFileAttribute.faReadOnly);
-  if Attributes and faHidden <> 0 then
-    Include(Result, TFileAttribute.faHidden);
-  if Attributes and faSysFile <> 0 then
-    Include(Result, TFileAttribute.faSystem);
-  if Attributes and faDirectory <> 0 then
-    Include(Result, TFileAttribute.faDirectory);
-  if Attributes and faArchive <> 0 then
-    Include(Result, TFileAttribute.faArchive);
-  if Attributes and faSymLink <> 0 then
-    Include(Result, TFileAttribute.faSymLink);
-  if Attributes and faNormal <> 0 then
-    Include(Result, TFileAttribute.faNormal);
-  if Attributes and faTemporary <> 0 then
-    Include(Result, TFileAttribute.faTemporary);
-  if Attributes and faCompressed <> 0 then
-    Include(Result, TFileAttribute.faCompressed);
-  if Attributes and faEncrypted <> 0 then
-    Include(Result, TFileAttribute.faEncrypted);
-{$ENDIF MSWINDOWS}
-{$IFDEF POSIX}
-  Result := [];
-  if Attributes and faDirectory <> 0 then
-    Include(Result, TFileAttribute.faDirectory);
-  if Attributes and faArchive <> 0 then
-    Include(Result, TFileAttribute.faNormal);
-  if Attributes and faSymLink <> 0 then
-    Include(Result, TFileAttribute.faSymLink);
-  if Attributes and faNormal <> 0 then
-    Include(Result, TFileAttribute.faNormal);
-{$ENDIF POSIX}
-end;
-
-{$IFDEF MSWINDOWS}
-{$ELSE}
-//好像不一定有效果。
-function FileSetAttr(const FileName: string; Attr: Integer; FollowLink: Boolean = True): Integer;
-var
-  AFileAttributes: TFileAttributes;
-begin
-//  Result := faInvalid;
-//  AFileAttributes := faAttrToFileAttributes(Attr);
-//  TFile.SetAttributes(FileName, AFileAttributes);
-  Result := 0;
-end;
-{$ENDIF MSWINDOWS}
-
-function DeleteTreeByEcho(const Source: string; AbortOnFailure: Boolean = False;
-  YesToAll: Boolean = True;
-  WaitMinSecond: Integer = DeleteDirectories_WaitMinSecond): Boolean;
-var
-  Files: TStringList;
-  LPath: string; // writable copy of Path
-  FileName: string;
-  I: Integer;
-  PartialResult: Boolean;
-  Attr: Integer;
-  isDir: Boolean;
-  ToDeleteDir: string;
-  T: TDateTime;
-  FWaitSecond, FWaitMinSecond: Integer;
-begin
-  Result := False;
-  if not DirectoryExists(ExtractFileDir(Source)) then
-  begin
-    exit;
-  end;
-  if Trim(Source) = PathDelim then
-  begin
-    exit;
-  end;
-  isDir := DirectoryExists(Source);
-  Result := True;
-  Files := TStringList.Create;
-  try
-    if isDir then
-    begin
-      LPath := IncludeTrailingPathDelimiter(Source);
-      ToDeleteDir := LPath + '\*.*';
-    end
-    else
-    begin
-      LPath := IncludeTrailingPathDelimiter(ExtractFilePath(Source));
-      ToDeleteDir := Source;
-    end;
-    BuildFileListInAPath(ToDeleteDir, faAnyFile, Files);
-    for I := 0 to Files.Count - 1 do
-    begin
-      FileName := LPath + PathDelim + Files[I];
-      PartialResult := True;
-      // If the current file is itself a directory then recursively delete it
-      Attr := FileGetAttr(FileName);
-      if (Attr <> faInvalid) and ((Attr and faDirectory) <> 0) then
-      begin
-        PartialResult := DeleteTreeByEcho(FileName, AbortOnFailure, YesToAll,
-          WaitMinSecond);
-      end
-      else
-      begin
-        if YesToAll then
-        begin
-          // Set attributes to normal in case it's a readonly file
-          PartialResult := FileSetAttr(FileName, faNormal) = 0;
-        end
-        else
-        begin
-          if ((Attr and faSysFile) <> 0) or ((Attr and faReadOnly) <> 0) or (Attr = faInvalid)
-          then
-          begin
-            PartialResult := False;
-          end;
-        end;
-        if PartialResult then
-          PartialResult := System.SysUtils.DeleteFile(FileName); //TFile.Delete()
-      end;
-      if not PartialResult then
-      begin
-        Result := False;
-        if AbortOnFailure then
-        begin
-          Break;
-        end;
-      end;
-    end;
-  finally
-    FreeAndNil(Files);
-  end;
-  if Result and isDir then
-  begin
-    if YesToAll then
-    begin
-      // Finally remove the directory itself
-      Result := FileSetAttr(LPath, faNormal or faDirectory) = 0;
-    end
-    else
-    begin
-      Attr := FileGetAttr(LPath);
-      if ((Attr and faSysFile) <> 0) or ((Attr and faReadOnly) <> 0) or (Attr = faInvalid) then
-      begin
-        Result := False;
-      end;
-    end;
-    if Result then
-    begin
-{$IOCHECKS OFF}
-      RmDir(LPath);
-      T := Now;
-      FWaitSecond := WaitMinSecond div 1000;
-      FWaitMinSecond := WaitMinSecond mod 1000;
-      while DirectoryExists(LPath) do
-      begin
-        if T + EncodeTime(0, 0, FWaitSecond, FWaitMinSecond) < now then
-        begin
-          break;
-        end;
-        Sleep(1);
-      end;
-{$IFDEF IOCHECKS_ON}
-{$IOCHECKS ON}
-{$ENDIF IOCHECKS_ON}
-      // Result := IOResult = 0;
-      Result := not DirectoryExists(LPath);
-      // if not Result then
-      // begin
-      // ShowMessage(LPath);
-      // end;
-    end;
-  end;
-end;
-
-function DeleteDirectoryByEcho(const Source: string;
-  AbortOnFailure: Boolean = False; YesToAll: Boolean = True;
-  WaitMinSecond: Integer = DeleteDirectories_WaitMinSecond): Boolean;
-var
-  T: TDateTime;
-  FWaitSecond, FWaitMinSecond: Integer;
-begin
-  Result := False;
-  if not DirectoryExists(ExtractFileDir(Source)) then
-  begin
-    exit;
-  end;
-  if Trim(Source) = PathDelim then
-  begin
-    exit;
-  end;
-  Result := DeleteTreeByEcho(Source, AbortOnFailure, YesToAll, WaitMinSecond);
-  if Result then
-  begin
-    T := Now;
-    FWaitSecond := WaitMinSecond div 1000;
-    FWaitMinSecond := WaitMinSecond mod 1000;
-    while DirectoryExists(Source) do
-    begin
-      if T + EncodeTime(0, 0, FWaitSecond, FWaitMinSecond) < now then
-      begin
-        break;
-      end;
-      Sleep(1);
-    end;
-  end;
-end;
-
-function GetFileNamesFromDirectory(const DirName: string; const SearchFilter: string = '*';
-  const FileAttribs: Integer = faAnyFile; const isIncludeSubDirName: Boolean = False; const Recursion: Boolean = False;
-  const FullName: Boolean = False): string;
-var
-  SubList, FileNameList: TStrings;
-  DirPath: string;
-  SearchRec: TSearchRec;
-  i: Integer;
-begin
-  Result := '';
-  if Trim(SearchFilter) = '' then
-  begin
-    exit;
-  end;
-  if DirectoryExists(DirName) then
-  begin
-    FileNameList := TStringList.Create;
-    try
-      try
-        DirPath := IncludeTrailingPathDelimiter(DirName);
-        // 得到该目录下指定类型文件的文件名
-        if System.SysUtils.FindFirst(DirPath + Trim(SearchFilter), FileAttribs, SearchRec) = 0 then
-        try
-          repeat
-            if isIncludeSubDirName or ((SearchRec.Attr and faDirectory) <> faDirectory) then
-            begin
-              if (SearchRec.Attr and faDirectory) = faDirectory then
-              begin
-                if (ExtractFileName(SearchRec.Name) = '.') or (ExtractFileName(SearchRec.Name) = '..') then
-                begin
-                  Continue;
-                end;
-              end;
-              if FullName then
-              begin
-                FileNameList.Add(ExpandFileName(SearchRec.Name));
-              end
-              else
-              begin
-                FileNameList.Add(ExtractFileName(SearchRec.Name));
-              end;
-            end;
-          until System.SysUtils.FindNext(SearchRec) <> 0;
-        finally
-          System.SysUtils.FindClose(SearchRec);
-        end;
-
-        // 递归该目录下所有子目录下的指定文件。
-        if Recursion and (System.SysUtils.FindFirst(DirPath + '*', faDirectory, SearchRec) = 0) then
-        try
-          repeat
-            if Recursion and ((SearchRec.Attr and faDirectory) = faDirectory) and
-              (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
-            begin
-              Result := GetFileNamesFromDirectory(DirPath + ExtractFileName(SearchRec.Name), SearchFilter,
-                FileAttribs, isIncludeSubDirName, Recursion, FullName);
-              SubList := TStringList.Create;
-              try
-                SubList.Clear;
-                SubList.Text := Result;
-                if not FullName then
-                begin
-                  for i := 0 to SubList.Count - 1 do
-                  begin
-                    SubList.Strings[i] := ExtractFileName(SearchRec.Name) + PathDelim + SubList.Strings[i];
-                  end;
-                end;
-                Result := '';
-                FileNameList.AddStrings(SubList);
-              finally
-                FreeAndNil(SubList);
-              end;
-            end;
-          until System.SysUtils.FindNext(SearchRec) <> 0;
-        finally
-          System.SysUtils.FindClose(SearchRec);
-        end;
-        Result := FileNameList.Text;
-      except
-        Result := '';
-      end;
-    finally
-      if FileNameList <> nil then
-      begin
-        FreeAndNil(FileNameList);
-      end;
-    end;
-  end;
-end;
-
-
-function GetCaseSensitiveFileName(const FileName: string; RootPath: string = ''): string;
-var
-  MatchFound: TFilenameCaseMatch;
-begin
-  Result := ExpandFileNameCase2(FileName, RootPath, MatchFound);
-end;
-
-function GetSDCardPath(Index: Integer = 0): string;
-begin
-  Result := FindSDCardSubPath('', Index);
-end;
-
-function FindSDCardSubPath(SubPath: string; Index: Integer = 0): string;
-var
-  PathDelimedSubPath: string;
-  UnPathDelimedSubPath: string;
-{$IFDEF ANDROID}
-  VolumePathList: TStrings;
-  UsbIndex,
-  CdRomIndex,
-  TempVolumeIndex,
-  I: Integer;
-  IsFoundDir0: Boolean;
-{$ENDIF ANDROID}
-begin
-  PathDelimedSubPath := '';
-  UnPathDelimedSubPath := SubPath;
-  if UnPathDelimedSubPath <> '' then
-  begin
-    if UnPathDelimedSubPath.Chars[0] = PathDelim then
-    begin
-      UnPathDelimedSubPath := UnPathDelimedSubPath.Substring(1);
-    end;
-    PathDelimedSubPath := PathDelim + UnPathDelimedSubPath;
-  end;
-{$IFDEF ANDROID}
-  Result := '/storage/emulated/' + IntToStr(Index) + PathDelimedSubPath;
-  if FVolumePaths.Trim = '' then GetVolumePaths;
-  VolumePathList := TStringList.Create;
-  try
-    VolumePathList.Text := FVolumePaths;
-    if Index = 0 then
-    begin
-      Result := JNIgetExternalStorageDirectory(UnPathDelimedSubPath);
-
-      if not DirectoryExists(Result) and (VolumePathList.Count > 0) then
-      begin
-        Result := VolumePathList[0];
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/emulated/' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard0' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard0' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard' + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard_ext0' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard_ext' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/sdcard' + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard_ext0' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard_ext' + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/emmc' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/nand' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/flash' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/emmc' + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/flash' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/flash' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/D' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/D' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/flash' + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/flash' + PathDelimedSubPath;
-      end;
-
-      //last
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard0' + PathDelimedSubPath;
-      end;
-    end
-    else if (Index < UsbDiskStartIndex) then
-    begin
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard' + IntToStr(Index + 1) + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := 'sdcard' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := 'sdcard' + IntToStr(Index + 1) + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard_ext' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard_ext' + IntToStr(Index + 1) + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard' + IntToStr(Index + 1) + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard_ext' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/mnt/sdcard_ext' + IntToStr(Index + 1) + PathDelimedSubPath;
-      end;
-
-      if not DirectoryExists(Result) and (VolumePathList.Count > Index) then
-      begin
-        Result := VolumePathList[Index];
-        if (Result.IndexOf('usbcd') >= 0) or
-        (Result.IndexOf('usb') >= 0) or
-        (Result.IndexOf('otg') >= 0) or
-        (Result.IndexOf('-rw') >= 0) or
-        (Result.IndexOf('_rw') >= 0) or
-        (Result.IndexOf('cdrom') >= 0) or
-        (Result.IndexOf('cd_rom') >= 0) or
-        (Result.IndexOf('cd-rom') >= 0) then
-        begin
-          Result := '';
-        end;
-      end;
-
-      if Index = 1 then
-      begin
-        if not DirectoryExists(Result) and (VolumePathList.Count = 2) then
-        begin
-          Result := VolumePathList[1];
-          if (Result.IndexOf('/storage/emulated/') < 0) and
-            (Result.IndexOf('/storage/sdcard') < 0) and
-            (Result.IndexOf('/mnt/sdcard') < 0) then
-          begin
-            Result := '';
-          end;
-        end;
-
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/extSdCard' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/external1' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/sdcard-ext' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/ext_card' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/extsd' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/_ExternalSD' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/external_sd' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/storage/removable_sdcard' + PathDelimedSubPath;
-        end;
-
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/extSdCard' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/external1' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/sdcard-ext' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/ext_card' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/extsd' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/_ExternalSD' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/external_sd' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := '/mnt/removable_sdcard' + PathDelimedSubPath;
-        end;
-
-        if not DirectoryExists(Result) then
-        begin
-          Result := 'tflash' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := 'removable_sdcard' + PathDelimedSubPath;
-        end;
-
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'tflash' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'extSdCard' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'external1' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'sdcard-ext' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'ext_card' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'extsd' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + '_ExternalSD' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'external_sd' + PathDelimedSubPath;
-        end;
-        if not DirectoryExists(Result) then
-        begin
-          Result := GetSDCardPath(0) + 'removable_sdcard' + PathDelimedSubPath;
-        end;
-      end;
-
-      //last
-      if not DirectoryExists(Result) then
-      begin
-        Result := '/storage/sdcard' + IntToStr(Index) + PathDelimedSubPath;
-      end;
-    end
-    else if (Index >= UsbDiskStartIndex) and (Index < UsbDiskStartIndex + OTGDeivceCount) then  //UsbDiskStartIndex
-    begin
-      UsbIndex := Index - UsbDiskStartIndex;
-      TempVolumeIndex := UsbIndex;
-      Result := '';
-      for I := 1 to VolumePathList.Count - 1 do
-      begin
-        Result := ExcludeTrailingPathDelimiter(VolumePathList[I]);
-        if (Result.IndexOf('/storage/usb') < 0) and
-          (Result.IndexOf('/storage/otg') < 0) and
-          (Result.IndexOf('/mnt/otg') < 0) and
-          (Result.IndexOf('/mnt/usb') < 0) then
-        begin
-          Result := '';
-        end
-        else if DirectoryExists(Result) then
-        begin
-          if (Result.IndexOf('usbcd') >= 0) then
-          begin
-            Result := '';
-          end
-          else if (Result.IndexOf('otgcd') >= 0) then
-          begin
-            Result := '';
-          end
-          else if (TempVolumeIndex = 0) and (Result.Chars[Result.Length] in ['2'..'9']) then
-          begin
-            Result := '';
-          end
-          else if (TempVolumeIndex <> 0) and (Result.Chars[Result.Length] <> IntToStr(TempVolumeIndex)) then
-          begin
-            Result := '';
-          end
-          else
-          begin
-            Result := Result + PathDelimedSubPath;
-            break;
-          end;
-        end;
-      end;
-      if (Result = '') or (not DirectoryExists(Result)) then
-      begin
-        if UsbIndex = 0 then
-        begin
-          Result := '/storage/udisk' + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/udisk' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'udisk' + PathDelimedSubPath;
-          end;
-
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbdisk' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbdisk' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbdisk' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbotg' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbotg' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbotg' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbdrive' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbdrive' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbdrive' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usb' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usb' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usb' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/otg' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/otg' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'otg' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'udisk' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usbotg' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usb' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'otg' + PathDelimedSubPath;
-          end;
-
-          //index = 0
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/udisk0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/udisk0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'udisk0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbdisk0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbdisk0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbdisk0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbotg0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbotg0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbotg0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbdrive0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbdrive0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbdrive0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usb0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usb0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usb0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'udisk0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usbotg0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usb0' + PathDelimedSubPath;
-          end;
-        end
-        else
-        begin
-          //index > 0
-          IsFoundDir0 := False;
-          Result := GetSDCardPath(UsbDiskStartIndex);
-          IsFoundDir0 := Result.Chars[Result.Length] = '0';
-          if not IsFoundDir0 then
-          begin
-            inc(TempVolumeIndex);
-          end;
-          Result := '/storage/udisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/udisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'udisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbdisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbdisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbdisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbotg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbotg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbotg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbdrive' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbdrive' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbdrive' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usb' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usb' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usb' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/otg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/otg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'otg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'udisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usbotg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usb' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'otg' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-        end;
-      end;
-
-      //last
-      if (Result = '') or (not DirectoryExists(Result)) then
-      begin
-        if UsbIndex = 0 then
-        begin
-          Result := '/storage/udisk' + PathDelimedSubPath;
-        end
-        else
-        begin
-          Result := '/storage/udisk' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-        end;
-      end;
-    end
-    else if (Index >= CDROMStartIndex) and (Index < CDROMStartIndex + OTGDeivceCount) then  //CDROMStartIndex
-    begin
-      CdRomIndex := Index - CDROMStartIndex;
-      TempVolumeIndex := CdRomIndex;
-      for I := 1 to VolumePathList.Count - 1 do
-      begin
-        Result := ExcludeTrailingPathDelimiter(VolumePathList[I]);
-        if (Result.IndexOf('/storage/cd') < 0) and
-          (Result.IndexOf('/mnt/cd') < 0) and
-          (Result.IndexOf('/storage/usbcd') < 0) and
-          (Result.IndexOf('/mnt/usbcd') < 0) then
-        begin
-          Result := '';
-        end
-        else if DirectoryExists(Result) then
-        begin
-          if (TempVolumeIndex = 0) and (Result.Chars[Result.Length] in ['2'..'9']) then
-          begin
-            Result := '';
-          end
-          else if (TempVolumeIndex <> 0) and (Result.Chars[Result.Length] <> IntToStr(TempVolumeIndex)) then
-          begin
-            Result := '';
-          end
-          else
-          begin
-            Result := Result + PathDelimedSubPath;
-            break;
-          end;
-        end;
-      end;
-      if (Result = '') or (not DirectoryExists(Result)) then
-      begin
-        if CdRomIndex = 0 then
-        begin
-          Result := '/storage/cd-rom' + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cd-rom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cd-rom' + PathDelimedSubPath;
-          end;
-
-          Result := '/storage/media_rw' + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/media_rw' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'media_rw' + PathDelimedSubPath;
-          end;
-
-          Result := '/storage/cd_rom' + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cd_rom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cd_rom' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbcdrom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbcdrom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbcdrom' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/cdrom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cdrom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cdrom' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'cd-rom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usbcdrom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'cdrom' + PathDelimedSubPath;
-          end;
-
-          Result := '/storage/cd-rom' + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cd-rom' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cd-rom' + PathDelimedSubPath;
-          end;
-
-          //index = 0
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/cd_rom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cd_rom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cd_rom0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbcdrom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbcdrom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbcdrom0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/cdrom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cdrom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cdrom0' + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'cd-rom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usbcdrom0' + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'cdrom0' + PathDelimedSubPath;
-          end;
-
-        end
-        else
-        begin
-          //index > 0
-          IsFoundDir0 := False;
-          Result := GetSDCardPath(CDROMStartIndex);
-          IsFoundDir0 := Result.Chars[Result.Length] = '0';
-          if not IsFoundDir0 then
-          begin
-            inc(TempVolumeIndex);
-          end;
-          Result := '/storage/cd_rom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cd_rom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cd_rom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/usbcdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/usbcdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'usbcdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/storage/cdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := '/mnt/cdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := 'cdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'cd-rom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'usbcdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-          if not DirectoryExists(Result) then
-          begin
-            Result := GetSDCardPath(0) + 'cdrom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-          end;
-        end;
-      end;
-
-      //last
-      if (Result = '') or (not DirectoryExists(Result)) then
-      begin
-        if CdRomIndex = 0 then
-        begin
-          Result := '/storage/cd-rom' + PathDelimedSubPath;
-        end
-        else
-        begin
-          Result := '/storage/cd-rom' + IntToStr(TempVolumeIndex) + PathDelimedSubPath;
-        end;
-      end;
-    end
-    else
-    begin
-      Result := JNIgetExternalStorageDirectory(UnPathDelimedSubPath);
-    end;
-  finally
-    FreeAndNil(VolumePathList);
-  end;
-{$ELSE}
-  if UnPathDelimedSubPath <> '' then
-  begin
-    Result := IncludeTrailingPathDelimiter(
-      System.IOUtils.TPath.GetSharedDocumentsPath) + UnPathDelimedSubPath;
-  end
-  else
-  begin
-    Result := System.IOUtils.TPath.GetSharedDocumentsPath;
-  end;
-{$ENDIF ANDROID}
-  Result := IncludeTrailingPathDelimiter(Result);
-end;
-
-function GetAppPath: string;
-begin
-{$IF Defined(ANDROID)}
-  Result := ExtractFilePath(
-    ExcludeTrailingPathDelimiter(
-    System.IOUtils.TPath.GetHomePath));
-{$ELSE}
-  Result := ExtractFilePath(ParamStr(0));
-{$ENDIF ANDROID}
-  Result := IncludeTrailingPathDelimiter(Result);
-end;
-
-//initialization
-//
-//finalization
-//  UnRegisterSDReceiver;
-
-end.