Getting started with Flutter
This guide shows how to add Nutrient Flutter SDK to an Android, iOS, or web project. By the end, you’ll load a PDF document in the default Nutrient user interface (UI).
You can find the Flutter library on pub.dev(opens in a new tab) and GitHub(opens in a new tab).
Requirements
Install the required tools for the platforms you want to support:
- The latest stable version of Flutter(opens in a new tab)
- The latest stable version of Android Studio(opens in a new tab)
- The Android NDK(opens in a new tab)
- An Android Virtual Device(opens in a new tab) or a hardware device
- The [latest stable version of Xcode][xcode]
- The latest stable version of CocoaPods(opens in a new tab). If you haven’t installed CocoaPods, follow the CocoaPods installation guide(opens in a new tab). Check your CocoaPods version by running
pod --version. - The latest stable version of Chrome(opens in a new tab)
Create a project
If you already have a project that runs on Android, iOS, and web with the latest Flutter version, skip to the section on how to install the Nutrient dependency. Otherwise, create a project named nutrient_demo with the Flutter CLI:
flutter create --org com.example.nutrient_demo nutrient_demoInstall the Nutrient dependency
Nutrient Flutter SDK exposes two APIs:
- The bindings API, which drives each platform’s native SDK through language bindings.
- The legacy method-channel API.
This guide uses the bindings API, which is the recommended API for new projects.
The bindings API uses federated packages. List each package as a direct dependency so the native plugins register at runtime. In your terminal, change to your project directory and add the packages:
flutter pub add nutrient_flutter nutrient_flutter_platform_interface nutrient_flutter_android nutrient_flutter_ios nutrient_flutter_web path_providerThis command adds the packages to the dependencies section of your pubspec.yaml file:
dependencies: nutrient_flutter: ^<latest-version> nutrient_flutter_platform_interface: ^<latest-version> nutrient_flutter_android: ^<latest-version> nutrient_flutter_ios: ^<latest-version> nutrient_flutter_web: ^<latest-version> path_provider: ^<latest-version>path_provider isn’t part of Nutrient Flutter SDK. This guide uses it later to copy the bundled sample PDF to a readable file path. If your app already loads documents from a path it controls, you don’t need path_provider.
Follow the setup instructions for each platform you want to support.
Android setup
Update your Android project so it can build and host the Nutrient viewer.
Open the app’s Gradle build file,
android/app/build.gradle:Terminal window open android/app/build.gradleModify the compile SDK version and the minimum SDK version:
android {compileSdkVersion flutter.compileSdkVersioncompileSdkVersion 36...defaultConfig {minSdkVersion flutter.minSdkVersionminSdkVersion 24...}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}// If you have this block, update the `jvmTarget` to 17.kotlinOptions {jvmTarget = '1.8'jvmTarget = '17'}...}Set the launcher activity to
NutrientFlutterActivityand enable trial mode auto-initialization. Inandroid/app/src/main/AndroidManifest.xml, point the launcher<activity>to the activity provided bynutrient_flutter_android, and add thenutrient_automatic_initializemetadata inside<application>:<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><application ...><activityandroid:name=".MainActivity"android:name="com.nutrient.nutrient_flutter_android.NutrientFlutterActivity"android:exported="true"android:launchMode="singleTop"android:theme="@style/LaunchTheme"...>...</activity><meta-dataandroid:name="nutrient_automatic_initialize"android:value="true"tools:replace="android:value" /></application></manifest>NutrientFlutterActivityis provided bynutrient_flutter_android, so you don’t need a customMainActivityor the AndroidX AppCompat dependency. Thenutrient_automatic_initializemetadata is required because the bindings API initializes the SDK throughNutrientDocumentViewinstead of the legacy method channel. Set it totrueto enable trial mode auto-initialization on first SDK use.Update both
LaunchThemeandNormalThemeto extend a Nutrient parent theme.NutrientFlutterActivityis AppCompat-based and is applied with@style/LaunchThemewhile the process starts, soLaunchThememust also extend a Nutrient theme — leaving it on the stock Flutter parent triggers an AppCompat theme crash beforeNormalThemeis ever applied.In
android/app/src/main/res/values/styles.xml:<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"><style name="LaunchTheme" parent="@style/PSPDFKit.Theme"><item name="android:windowBackground">@drawable/launch_background</item></style><style name="NormalTheme" parent="Theme.AppCompat.Light.NoActionBar"><style name="NormalTheme" parent="@style/PSPDFKit.Theme.Default"><item name="android:windowBackground">?android:colorBackground</item></style>In
android/app/src/main/res/values-night/styles.xml, use the dark variant:<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"><style name="LaunchTheme" parent="@style/PSPDFKit.Theme.Dark"><item name="android:windowBackground">@drawable/launch_background</item></style><style name="NormalTheme" parent="Theme.AppCompat.NoActionBar"><style name="NormalTheme" parent="@style/PSPDFKit.Theme.Dark"><item name="android:windowBackground">?android:colorBackground</item></style>This configures the Nutrient UI theme. For more information, refer to the appearance styling guide.
iOS setup
Update your iOS project so CocoaPods can install the native Nutrient iOS SDK dependency.
Open
Runner.xcworkspacefrom theiosfolder in Xcode:Terminal window open ios/Runner.xcworkspaceEnsure the iOS deployment target is set to 17.0 or higher. In Xcode, select the Runner target, and under General > Minimum Deployments, set iOS to
17.0.Open your project’s Podfile in a text editor:
Terminal window open ios/PodfileUpdate the platform to iOS 17, which is the minimum required version for Nutrient iOS SDK:
# platform :ios, '9.0'platform :ios, '17.0'
Web setup
Set up web assets with either the CDN or a local installation.
Use the CDN to load Nutrient Web SDK.
Add the following script to the
<head>section of yourindex.htmlfile:<!DOCTYPE html><html><head><!-- ... other head elements ... --><script src="https://cdn.cloud.nutrient.io/pspdfkit-web@1.19.0/nutrient-viewer.js"></script></head><body><!-- ... body content ... --></body></html>The snippet above pins the latest Nutrient Web SDK version. To use a different version, choose one from the Nutrient Web SDK changelog.
We recommend the CDN option for development and production because it pins a specific SDK version.
Nutrient Web SDK files are distributed as an archive that you can extract manually.
Download the framework(opens in a new tab). The download starts immediately and saves a
.tar.gzarchive likePSPDFKit-Web-binary-{% $LATEST_VERSIONS.WEB_SDK %}.tar.gzto your computer.After the download completes, extract the archive and copy the entire contents of its
distfolder to your project’sweb/assetsfolder, or any other folder inside the web subfolder.Make sure your
assetsfolder contains thenutrient-viewer.jsfile and anutrient-viewer-libdirectory with the library assets.Make sure your server sets the
Content-Type: application/wasmMIME type. For more information, refer to the troubleshooting guide.Include the Nutrient library in your
index.htmlfile:<script src="assets/nutrient-viewer.js"></script>Set
useCDNtofalsein aWebViewConfiguration, and pass it to the configuration’swebConfigfield. This makes the SDK load assets from your local files instead of the CDN:NutrientDocumentView(documentPath: documentPath,configuration: NutrientViewConfiguration(webConfig: WebViewConfiguration(useCDN: false,),),)For more information, refer to the asset loading guide.
Display a PDF
Initialize the SDK once at startup, and then display a document with NutrientDocumentView. The bindings API ships a built-in default adapter for each platform, so a basic viewer doesn’t need an adapter. Call Nutrient.initialize() with no arguments.
Replace the contents of
lib/main.dartwith the following:import 'dart:io';import 'package:flutter/foundation.dart' show kIsWeb;import 'package:flutter/material.dart';import 'package:flutter/services.dart' show rootBundle;import 'package:nutrient_flutter/bindings.dart';import 'package:path_provider/path_provider.dart';const String documentPath = 'PDFs/Document.pdf';Future<void> main() async {WidgetsFlutterBinding.ensureInitialized();// No license key runs the SDK in trial mode (watermarked). No adapter is// needed for a basic viewer — the SDK registers its built-in default adapter// for the current platform. Pass an adapter only to customize the viewer or// reach platform-specific APIs.await Nutrient.initialize();runApp(const MyApp());}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(home: DocumentPage());}}class DocumentPage extends StatelessWidget {DocumentPage({super.key});// Resolved once when the page is created and reused across rebuilds.final Future<String> _documentPath = _resolveDocument();@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Nutrient')),body: FutureBuilder<String>(future: _documentPath,builder: (context, snapshot) {if (snapshot.hasError) {return Center(child: Text('Failed to load: ${snapshot.error}'));}if (!snapshot.hasData) {return const Center(child: CircularProgressIndicator());}return NutrientDocumentView(documentPath: snapshot.data!);},),);}}// Native viewers need a real file path, so the bundled asset is copied to the// OS temp directory. On web, the viewer loads the asset path directly.Future<String> _resolveDocument() async {if (kIsWeb) return documentPath;final bytes = await rootBundle.load(documentPath);final dir = await getTemporaryDirectory();final file = File('${dir.path}/Document.pdf');await file.writeAsBytes(bytes.buffer.asUint8List(), flush: true);return file.path;}To remove the trial watermark, pass your license keys to
Nutrient.initialize()withandroidLicenseKey,iosLicenseKey, and/orwebLicenseKey. Get a trial license(opens in a new tab) to obtain license keys. To customize the viewer or call platform-specific native APIs, register a platform adapter. For more information, refer to the platform adapters guide.Add the PDF document you want to display in your project’s
assetsdirectory. You can use this quickstart guide PDF as an example.Create a
PDFsdirectory:Terminal window mkdir PDFsCopy the sample document into the new
PDFsdirectory:Terminal window cp ~/Downloads/Document.pdf PDFs/Document.pdfRegister the
assetsdirectory inpubspec.yaml:# The following section is specific to Flutter.flutter:assets:- PDFs/...Depending on your platform, start your Android emulator(opens in a new tab) or iOS simulator(opens in a new tab), or connect a device. If Chrome is installed on your computer, Flutter launches it automatically.
Run the app:
Terminal window flutter run
Next steps
To learn more about Flutter, refer to these resources:
- Opening a PDF in Flutter
- Download and display a PDF in Flutter
- How to customize our Flutter PDF SDK
- Advances in hybrid technologies
- How we maintain our public Flutter project using a private monorepo
- How to build a Flutter PDF viewer