Blog Post

How to open a PDF in Flutter using advance_pdf_viewer2

Reinhard Hafenscher
Illustration: How to open a PDF in Flutter using advance_pdf_viewer2
Information

This article was first published in June 2019 and was updated in June 2023.

Flutter lets you create mobile apps in Dart. It’s developed by Google, and it allows you to create Android and iOS apps from a single shared codebase. In this post, you’ll use Flutter to build an app that opens a PDF with the press of a button.

In the first part of this tutorial, you’ll use an open source Dart package to present the PDF. In the second part, you’ll see how easy it is to integrate the Flutter PDF library to add even more PDF features to your app.

Opening a PDF with advance_pdf_viewer

This section covers the steps for how to open a PDF in Flutter with advance_pdf_viewer. We’ll assume you already followed the installation instructions to set up the Flutter command-line tools on your machine.

Step 1 — Creating a new Flutter app

You can use the flutter command to create a new Flutter app from the command line (this example uses the name opening_a_pdf for the app):

flutter create opening_a_pdf

For the rest of the tutorial, you’ll work in opening_a_pdf:

cd opening_a_pdf

Step 2 — Setting up dependencies

You’ll use advance_pdf_viewer and path_provider, which can be used to display PDFs. First, add them to your pubspec.yaml:

dependencies:
   advance_pdf_viewer: ^2.0.1
   path_provider:

You’ll also add a PDF to your assets. To do that, you need to declare an assets folder:

flutter:
   assets:
      - PDFs/

Then, create a PDFs folder next to your pubspec.yaml file and put a PDF to test with in it. Add your PDF document in this new folder. You can use the Quickstart Guide PDF as an example.

Finally, install the packages from the command line using the following:

flutter packages get

Step 3 — Writing the app

Now you can start writing your app. First, replace the current contents of main.dart with a more stripped-down example displaying a single button:

import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:advance_pdf_viewer/advance_pdf_viewer.dart';

// Change this to fit the PDF file you're using to test.
const String _documentPath = 'PDFs/Document.pdf';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Load PDF - Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Load PDF - Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isLoaded = false;
  late PDFDocument document;

  @override
  void initState() {
    super.initState();
  }

  // This method will load PDF document and update the state.
  void _openDocument() async {
    PDFDocument doc = await PDFDocument.fromAsset(_documentPath);
    setState(() {
      _isLoaded = true;
      document = doc;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: const Center(child: Text('Press to load document')),
      ),
      floatingActionButton: ElevatedButton(
        onPressed: () => { _openDocument() },
        child: const Text('Load PDF'),
        ),
    );
  }
}

Next, add some code to open the PDF using advance_pdf_viewer. First, update _MyHomePageState, so the new widget body looks like this:

{
  // ...
  body: Center(
    child: !_isLoaded
        ? const Center(child: Text('Press to load document'))
        : PDFViewer(document: document),
  ),
  // ...
}

This will use the provided PDFViewer to display the PDF included in the assets. Then, hook up your button to load the document and display the loaded PDF in PDFViewer. Additionally, replace FloatingActionButton with ElevatedButton:

{
  // body: Center(
  ...
    ),
-   floatingActionButton: FloatingActionButton(
-      onPressed: _incrementCounter,
-      tooltip: 'Increment',
-      child: const Icon(Icons.add),
-   ),

+   floatingActionButton: ElevatedButton(
+     onPressed: () => { _openDocument() },
+     child: const Text('Load PDF'),
+   ),

  ...
}

Now the onPressed callback will render the PDFViewer onto the current view after preparing the test PDF. The image below shows how it looks on iOS.

A simple Flutter-based PDF view on iOS

After these steps, you can now tap a button and scroll through a PDF document. However, you can’t do anything else; you only have the scrolling view mode.

But this is where Nutrient comes in: It includes all the features you need — and more — without you having to configure anything.

Opening a PDF with Nutrient

To start, follow the integration guide for Android and iOS.

As a next step, you’ll change the method for loading the PDF document.

  1. Remove the _openDocument method:

-  void _openDocument() async {
-    PDFDocument doc = await PDFDocument.fromAsset(_documentPath);
-    setState(() {
-    _isLoaded = true;
-    document = doc;
-   });
- }
  1. Import path_provider as a dependency:

import 'package:path_provider/path_provider.dart';
  1. Add the prepareTestPdf method:

+ Future<String> prepareTestPdf() async {
+   final ByteData bytes =
+   await DefaultAssetBundle.of(context).load(_documentPath);
+   final Uint8List list = bytes.buffer.asUint8List();
+
+   final tempDir = await getTemporaryDirectory();
+   final tempDocumentPath = '${tempDir.path}/$_documentPath';
+
+   final file = await File(tempDocumentPath).create(recursive: true);
+   file.writeAsBytesSync(list);
+   return tempDocumentPath;
+ }
  1. Update the floating button action.

Once this is done, replace the button in _MyHomePageState so it opens the PDF with Nutrient instead:

ElevatedButton(
  onPressed: () => {
        // You need to prepare the test PDF, and then you can display the PDF.
        prepareTestPdf().then((path) {
          Pspdfkit.present(path);
        })
      },
  child: const Text('Open PDF with PSPDFKit'),
),

For this to work, you also need to add a new import:

import 'package:pspdfkit_flutter/pspdfkit.dart';
  1. Set the license key.

Finally, initialize Nutrient by adding the following to _MyHomePageState:

@override
initState() {
  super.initState();
  // Replace.
  Pspdfkit.setLicenseKey("YOUR_LICENSE_KEY_GOES_HERE");
}

In iOS, you’ll need to update the View controller-based status bar appearance in the project configuration. To do this, go to the iOS folder in the project’s root directory > iOS > Runner. Open Info.plist in the text editor and change the configuration so it looks like this:

<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

Final result

Now you can view a PDF in Nutrient! Not only that, but you can also create annotations, look at the document’s outline, fill out forms, and lots of other things. The image below shows what it looks like now.

Nutrient on iOS

Complete code

Here’s the full main.dart file with all changes you made:

import 'dart:io';
import 'dart:typed_data';

import 'package:advance_pdf_viewer/advance_pdf_viewer.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pspdfkit_flutter/pspdfkit.dart';
import 'package:flutter/material.dart';

const String _documentPath = 'PDFs/Document.pdf';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Load PDF - Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Load PDF - Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isLoaded = false;
  late PDFDocument document;

  @override
  void initState() {
    super.initState();

    Pspdfkit.setLicenseKey("YOUR_LICENSE_KEY_GOES_HERE");
  }

  Future<String> prepareTestPdf() async {
    final ByteData bytes =
    await DefaultAssetBundle.of(context).load(_documentPath);
    final Uint8List list = bytes.buffer.asUint8List();

    final tempDir = await getTemporaryDirectory();
    final tempDocumentPath = '${tempDir.path}/$_documentPath';

    final file = await File(tempDocumentPath).create(recursive: true);
    file.writeAsBytesSync(list);
    return tempDocumentPath;
  }

  void _openDocument() async {
    PDFDocument doc = await PDFDocument.fromAsset(_documentPath);
    setState(() {
      _isLoaded = true;
      document = doc;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: !_isLoaded
            ? const Center(child: Text('Press to load document'))
            : PDFViewer(document: document),
      ),
      floatingActionButton: ElevatedButton(
        //   onPressed: () => { _openDocument() },
        //   child: const Text('Load PDF'),
        //   ),
        onPressed: () => {
          // You need to prepare the test PDF, and then you can display the PDF.
          prepareTestPdf().then((path) {
            Pspdfkit.present(path);
          })
        },
        child: const Text('Open PDF with PSPDFKit'),
      ),
    );
  }
}

Conclusion

As you saw, adding PDF support to your app using advance_pdf_viewer is a breeze.

If your Flutter project requires more advanced PDF functionality, such as PDF annotations or PDF form filling, consider using a commercial library.

Our Flutter PDF SDK comes with more than 30 out-of-the-box features and has well-documented APIs to handle advanced use cases. Try our PDF library for free, and check out our demos to see what’s possible.

Nutrient also comes with great customer support, so please reach out to us if you have any questions about our Flutter integration.

FAQ

Here are a few frequently asked questions about opening PDFs in Flutter.

How can I open a PDF in Flutter?

You can use advance_pdf_viewer2 or Nutrient to open PDFs in Flutter. Nutrient offers advanced features but requires a license key to remove watermarks.

Can I try Nutrient for free in my Flutter app?

Yes, you can try Nutrient for free without a license key, but a watermark will appear on the PDF.

Do I need additional setup for iOS and Android with Nutrient?

Yes, you need to follow platform-specific setup instructions for both Android and iOS, which are detailed in Nutrient’s integration guides.

Can I display local PDF files in my app?

Yes, you can display local PDF files by adding them to your project’s assets and loading them with advance_pdf_viewer2 or Nutrient.

What are the main benefits of using Nutrient over advance_pdf_viewer2?

Nutrient offers additional features like annotations, form filling, and text extraction, making it suitable for apps that need robust PDF functionality.

Related products

PSPDFKit for Flutter

Product page Guides Example Projects

Share post
Free trial Ready to get started?
Free trial