我的问题是Android版Delphi应用程序(Delphi 10 Seattle)可以“查看”外部SD卡上的文件,但无法搜索/列出手机存储中的文件,即/ storage / emulated / 0。
这是使用TDirectory.GetDirectories和TDirectory.GetFiles的简单文件浏览器(我们称其为Windows“打开对话框” Delphi组件的替代品)。默认情况下,权限“写入外部存储”设置为true。它在Android 5上运行正常,在三星和阿尔卡特手机上经过测试,但是在小米MI A2 Light,Android 9上,它在/ storage /路径上列出了基本文件夹,它可以浏览extSdCard,但是如果您单击“仿真”或“ sdcard0“,文件夹/文件列表为空:O
Android SDK已更新至最新版本29-Android10。
在Android清单文件中,我将最小sdk版本14设置为目标SDK版本14(我认为是Delphi 10 Seattle的默认版本),在小米手机上,它可以浏览外部SD卡,但不能浏览手机存储。
当我更改最小SDK版本14,目标SDK版本29时,应用程序也无法访问SD卡(在小米手机上,其他设备仍然可以):O
也许这是一些权限问题,但我不知道该如何解决:O
unit Main;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
FMX.ListView, System.IOUtils, FMX.StdCtrls, FMX.Controls.Presentation;
type
TForm1 = class(TForm)
Timer1: TTimer;
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
ListView1: TListView;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ListView1Tap(Sender: TObject; const [Ref] Point: TPointF);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
CurDir : string;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
//list /storage/ path
procedure TForm1.Button2Click(Sender: TObject);
var
f : integer;
List : TStringList;
FileNames : string;
begin
ListView1.Items.Clear;
List := TStringList.Create;
for FileNames in TDirectory.GetDirectories(CurDir) do List.Add(ExtractFileName(FileNames));
for FileNames in TDirectory.GetFiles(CurDir) do List.Add(ExtractFileName(FileNames));
for f:=0 to List.Count - 1 do
with ListView1.Items.Add do Text := List.Strings[f];
List.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CurDir := '/storage/';
end;
//interval 200ms, because onClick event is triggered before item is marked as selected
procedure TForm1.ListView1Tap(Sender: TObject; const [Ref] Point: TPointF);
begin
Timer1.Enabled := true;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
f : integer;
List : TStringList;
FileNames, Temp : string;
begin
Timer1.Enabled := false;
Temp := TListViewItem(ListView1.Selected).Text;
ListView1.Items.Clear;
List := TStringList.Create;
CurDir := System.IOUtils.TPath.Combine(CurDir, Temp);
for FileNames in TDirectory.GetDirectories(CurDir) do List.Add(ExtractFileName(FileNames));
for FileNames in TDirectory.GetFiles(CurDir) do List.Add(ExtractFileName(FileNames));
for f:=0 to List.Count - 1 do
with ListView1.Items.Add do Text := List.Strings[f];
List.Free;
end;
//back button
procedure TForm1.Button1Click(Sender: TObject);
var
f : integer;
List : TStringList;
FileNames : string;
begin
if Length(CurDir) <= 9 then Exit;
for f := Length(CurDir) downto 1 do if CurDir[f] = '/' then Break;
CurDir := Copy(CurDir,1, f);
CurDir := StringReplace(CurDir,'//', '/', [rfReplaceAll]);
if DirectoryExists(CurDir) then begin
List := TStringList.Create;
ListView1.Items.Clear;
for FileNames in TDirectory.GetDirectories(CurDir) do List.Add(ExtractFileName(FileNames));
for FileNames in TDirectory.GetFiles(CurDir) do List.Add(ExtractFileName(FileNames));
for f:=0 to List.Count - 1 do
with ListView1.Items.Add do Text := List.Strings[f];
List.Free;
end;
end;
end.