Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

dart - How to get all PDF files from internal as well as external storage in Flutter?

I want to show All pdf files present in internal as well as external storage, So on tapping that particular file, i want to open that file in full screen dialog.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So in order to do that you need to:

  • Grant access to external storage in a directory where there are your PDF file. Let's call that folder <external storage>/pdf.
  • List all file of that directory a display them to the user.
  • Open the selected file with an application that can visualize PDF.

In order to do all that thinks I suggest you to use those flutter packages:

With path_provider you can get the external storage directory of an Android device.

Directory extDir = await getExternalStorageDirectory();
String pdfPath = extDir + "/pdf/";

In order to access external storage you need to set this permission request in the ApplicationManifest.xml:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

You could also only use READ_EXTERNAL_STORAGE but then the simple_permission plugin won't work.

With the simple_permission plugin then you go and ask user to be granted external storage access:

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

Once we have been granted external storage access we an list our PDF directory:

List<FileSystemEntity> _files;
_files = dir.listSync(recursive: true, followLinks: false);

And show them in a ListView:

return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemCount: _files.length,
      itemBuilder: (context, i) {
        return _buildRow(_files.elementAt(i).path);
      });

Than you have to open them with a viewer when the user tap on them.

To do that there isn't an easy way, because with Android we need to build a ContentUri and give access to this URI to the exteranl application viewer.

So we do that in Android and we use flutter platform channels to call the Android native code.

Dart:

static const platform =
      const MethodChannel('it.versionestabile.flutterapp000001/pdfViewer');
var args = {'url': fileName};
          platform.invokeMethod('viewPdf', args);

Native Java Code:

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

And after all we can have our PDF list and viewable on Android.

enter image description here enter image description here enter image description here

You have a lot to study. I hope this could be an useful playground for you.

This is for External Storage, but you can get Also the Internal and Temporary directory and act similarly as here.

If you wanna do the same thing on iOS you need to create the same Native Code pdfViewer also on iOS project. Refer alway to flutter platform channels in order to do it. And remember that the external storage doesn't exists on iOS devices. So you could use only the application sandbox document folder or the temporary one.

GitHub repo.

Happy coding.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...