如何从 Flutter 的内部和外部存储中获取所有 PDF 文件?
How to get all PDF files from internal as well as external storage in Flutter?
我想显示内部和外部存储中存在的所有 pdf 文件,因此在点击该特定文件时,我想在全屏对话框中打开该文件。
因此,为了做到这一点,您需要:
- 在您的 PDF 文件所在的目录中授予对外部存储的访问权限。我们将该文件夹命名为
<external storage>/pdf
.
- 列出该目录的所有文件并向用户显示它们。
- 使用可以可视化 PDF 的应用程序打开所选文件。
为了完成我认为的所有事情,我建议您使用那些 flutter 包:
使用path_provider可以获取Android设备的外部存储目录。
Directory extDir = await getExternalStorageDirectory();
String pdfPath = extDir + "/pdf/";
为了访问外部存储,您需要在 ApplicationManifest.xml
中设置此权限请求:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
您也可以只使用 READ_EXTERNAL_STORAGE
,但 simple_permission 插件将无法使用。
使用 simple_permission 插件然后你去要求用户被授予外部存储访问权限:
bool externalStoragePermissionOkay = false;
_checkPermissions() async {
if (Platform.isAndroid) {
SimplePermissions
.checkPermission(Permission.WriteExternalStorage)
.then((checkOkay) {
if (!checkOkay) {
SimplePermissions
.requestPermission(Permission.WriteExternalStorage)
.then((okDone) {
if (okDone) {
debugPrint("${okDone}");
setState(() {
externalStoragePermissionOkay = okDone;
debugPrint('Refresh UI');
});
}
});
} else {
setState(() {
externalStoragePermissionOkay = checkOkay;
});
}
});
}
}
一旦我们被授予外部存储访问权限,我们就会列出我们的 PDF 目录:
List<FileSystemEntity> _files;
_files = dir.listSync(recursive: true, followLinks: false);
并在 ListView 中显示它们:
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: _files.length,
itemBuilder: (context, i) {
return _buildRow(_files.elementAt(i).path);
});
当用户点击它们时,您必须使用查看器打开它们。
要做到这一点没有简单的方法,因为使用 Android 我们需要构建一个 ContentUri 并向外部应用程序查看器提供对此 URI 的访问权限。
所以我们在 Android 中这样做,我们使用 flutter platform channels 调用 Android 本机代码。
飞镖:
static const platform =
const MethodChannel('it.versionestabile.flutterapp000001/pdfViewer');
var args = {'url': fileName};
platform.invokeMethod('viewPdf', args);
原生Java代码:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "it.versionestabile.flutterapp000001/pdfViewer";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("viewPdf")) {
if (call.hasArgument("url")) {
String url = call.argument("url");
File file = new File(url);
//*
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
file);
//*/
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(photoURI,"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(target);
result.success(null);
}
} else {
result.notImplemented();
}
}
});
}
}
毕竟我们可以在 Android 上查看我们的 PDF 列表。
你还有很多东西要学。我希望这对您来说是一个有用的游乐场。
这是用于外部存储,但您也可以获取内部和临时目录,并按照与此处类似的方式操作。
如果你想在 iOS 上做同样的事情,你需要在 iOS 项目上创建相同的本机代码 pdfViewer
。请始终参考 flutter platform channels 以执行此操作。请记住,iOS 设备上不存在外部存储。所以你可以只使用应用程序沙箱文档文件夹或临时文件夹。
编码愉快。
i use this code for list files and directories
Future<List<FileSystemEntity>> dirContents(Directory dir) {
var files = <FileSystemEntity>[];
var completer = Completer<List<FileSystemEntity>>();
var lister = dir.list(recursive: false);
lister.listen((file) async {
FileStat f = file.statSync();
if (f.type == FileSystemEntityType.directory) {
await dirContents(Directory(file.uri.toFilePath()));
} else if (f.type == FileSystemEntityType.file && file.path.endsWith('.pdf')) {
_files.add(file);
}
}, onDone: () {
completer.complete(files);
setState(() {
//
});
});
return completer.future;
}
Directory dir = Directory('/storage/emulated/0');
var files = await dirContents(dir);
print(files);
这是我列出下载文件夹中文件的代码
List<dynamic> filesList = [];
Future listDir() async {
Directory dir = Directory(
'/storage/emulated/0/Download');
await for (FileSystemEntity entity
in dir.list(recursive: true, followLinks: false)) {
FileSystemEntityType type = await FileSystemEntity.type(entity.path);
if (type == FileSystemEntityType.file &&
entity.path.endsWith('.pdf')) {
filesList.add(entity.path);
}
}
return filesList;}
我想显示内部和外部存储中存在的所有 pdf 文件,因此在点击该特定文件时,我想在全屏对话框中打开该文件。
因此,为了做到这一点,您需要:
- 在您的 PDF 文件所在的目录中授予对外部存储的访问权限。我们将该文件夹命名为
<external storage>/pdf
. - 列出该目录的所有文件并向用户显示它们。
- 使用可以可视化 PDF 的应用程序打开所选文件。
为了完成我认为的所有事情,我建议您使用那些 flutter 包:
使用path_provider可以获取Android设备的外部存储目录。
Directory extDir = await getExternalStorageDirectory();
String pdfPath = extDir + "/pdf/";
为了访问外部存储,您需要在 ApplicationManifest.xml
中设置此权限请求:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
您也可以只使用 READ_EXTERNAL_STORAGE
,但 simple_permission 插件将无法使用。
使用 simple_permission 插件然后你去要求用户被授予外部存储访问权限:
bool externalStoragePermissionOkay = false;
_checkPermissions() async {
if (Platform.isAndroid) {
SimplePermissions
.checkPermission(Permission.WriteExternalStorage)
.then((checkOkay) {
if (!checkOkay) {
SimplePermissions
.requestPermission(Permission.WriteExternalStorage)
.then((okDone) {
if (okDone) {
debugPrint("${okDone}");
setState(() {
externalStoragePermissionOkay = okDone;
debugPrint('Refresh UI');
});
}
});
} else {
setState(() {
externalStoragePermissionOkay = checkOkay;
});
}
});
}
}
一旦我们被授予外部存储访问权限,我们就会列出我们的 PDF 目录:
List<FileSystemEntity> _files;
_files = dir.listSync(recursive: true, followLinks: false);
并在 ListView 中显示它们:
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: _files.length,
itemBuilder: (context, i) {
return _buildRow(_files.elementAt(i).path);
});
当用户点击它们时,您必须使用查看器打开它们。
要做到这一点没有简单的方法,因为使用 Android 我们需要构建一个 ContentUri 并向外部应用程序查看器提供对此 URI 的访问权限。
所以我们在 Android 中这样做,我们使用 flutter platform channels 调用 Android 本机代码。
飞镖:
static const platform =
const MethodChannel('it.versionestabile.flutterapp000001/pdfViewer');
var args = {'url': fileName};
platform.invokeMethod('viewPdf', args);
原生Java代码:
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "it.versionestabile.flutterapp000001/pdfViewer";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("viewPdf")) {
if (call.hasArgument("url")) {
String url = call.argument("url");
File file = new File(url);
//*
Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
file);
//*/
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(photoURI,"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(target);
result.success(null);
}
} else {
result.notImplemented();
}
}
});
}
}
毕竟我们可以在 Android 上查看我们的 PDF 列表。
你还有很多东西要学。我希望这对您来说是一个有用的游乐场。
这是用于外部存储,但您也可以获取内部和临时目录,并按照与此处类似的方式操作。
如果你想在 iOS 上做同样的事情,你需要在 iOS 项目上创建相同的本机代码 pdfViewer
。请始终参考 flutter platform channels 以执行此操作。请记住,iOS 设备上不存在外部存储。所以你可以只使用应用程序沙箱文档文件夹或临时文件夹。
编码愉快。
i use this code for list files and directories
Future<List<FileSystemEntity>> dirContents(Directory dir) {
var files = <FileSystemEntity>[];
var completer = Completer<List<FileSystemEntity>>();
var lister = dir.list(recursive: false);
lister.listen((file) async {
FileStat f = file.statSync();
if (f.type == FileSystemEntityType.directory) {
await dirContents(Directory(file.uri.toFilePath()));
} else if (f.type == FileSystemEntityType.file && file.path.endsWith('.pdf')) {
_files.add(file);
}
}, onDone: () {
completer.complete(files);
setState(() {
//
});
});
return completer.future;
}
Directory dir = Directory('/storage/emulated/0');
var files = await dirContents(dir);
print(files);
这是我列出下载文件夹中文件的代码
List<dynamic> filesList = [];
Future listDir() async {
Directory dir = Directory(
'/storage/emulated/0/Download');
await for (FileSystemEntity entity
in dir.list(recursive: true, followLinks: false)) {
FileSystemEntityType type = await FileSystemEntity.type(entity.path);
if (type == FileSystemEntityType.file &&
entity.path.endsWith('.pdf')) {
filesList.add(entity.path);
}
}
return filesList;}