【问题标题】:How to get all PDF files from internal as well as external storage in Flutter?如何在 Flutter 中从内部和外部存储中获取所有 PDF 文件?
【发布时间】:2018-08-30 04:43:14
【问题描述】:

我想显示所有存在于内部和外部存储中的 pdf 文件,所以在点击该特定文件时,我想在全屏对话框中打开该文件。

【问题讨论】:

  • 在 Android 和 iOS 上都可以吗?您正在使用“内部”和“外部”关键字,所以我猜您正在考虑“Android 平台”。您是否打算仅在 Android Platorm 上使用您的应用程序?在 iOS 上,您只能访问您的应用程序沙箱“内部”存储。那么你的具体情况是什么?
  • 暂时只寻找Android平台,但如果你有两个解决方案,那就太好了! :)

标签: dart flutter


【解决方案1】:

我将此代码用于列表文件和目录

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);

【讨论】:

    【解决方案2】:

    因此,为了做到这一点,您需要:

    • 授予对 PDF 文件所在目录中外部存储的访问权限。我们称该文件夹为&lt;external storage&gt;/pdf
    • 列出该目录的所有文件并向用户显示。
    • 使用可以可视化 PDF 的应用程序打开所选文件。

    为了做所有我认为我建议你使用那些颤振包:

    通过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();
                    }
                  }
                });
      }
    }
    

    毕竟我们可以拥有我们的 PDF 列表并在 Android 上查看。

    你有很多东西要学。我希望这对你来说是一个有用的游乐场。

    这是用于外部存储,但您也可以获取内部和临时目录,并与此处类似。

    如果你想在 iOS 上做同样的事情,你需要在 iOS 项目上创建相同的 Native Code pdfViewer。请始终参考flutter platform channels 以执行此操作。请记住,iOS 设备上不存在外部存储。因此,您可以只使用应用程序沙箱文件夹或临时文件夹。

    GitHub repo.

    编码愉快。

    【讨论】:

      猜你喜欢
      • 2019-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      相关资源
      最近更新 更多