Display PDFs on Android with PdfActivity

PdfActivity is the most straightforward way of displaying a PDF document with all Nutrient features. PdfActivity extends Android’s AppCompatActivity and delivers the current Android and Material Design experience.

PdfActivity features

The activity hosts a PdfFragment for document viewing and editing. It also contains several configurable views:

This guide gives a short introduction on how to get started with PdfActivity.

Setting up the manifest

Before you can launch PdfActivity, you need to add it to your AndroidManifest.xml:

<application
    android:largeHeap="true">

    <activity
        android:name="com.pspdfkit.ui.PdfActivity"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar"
        android:windowSoftInputMode="adjustNothing" />

</application>

⚠️ Warning: Do not add android:configChanges to the PdfActivity entry, as it is not needed by Nutrient and may lead to undesired behavior of the document viewer.

Make sure you define the android:largeHeap="true" property on your <application> tag inside the manifest file. Rendering PDF files can be memory intensive, and this property will ensure your app has enough heap memory allocated in order to avoid hitting an OutOfMemoryError.

Activity theme

Since PdfActivity extends AppCompatActivity, you need to define a Theme.AppCompat-based theme via the android:theme attribute. You can either use a standard theme (e.g. Theme.AppCompat.Light.NoActionBar) or use any custom theme your app provides. Check out our appearance styling guide for more information on creating custom themes.

PdfActivity uses a custom toolbar system based on the app-compact Toolbar widget. Because of this, the used theme has to disable the default action bar. Either use any Theme.AppCompat.*.NoActionBar as a parent theme, or disable the action bar manually by adding the following styles to your custom theme:

<resources>
    <style name="MyCustomTheme">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionModeOverlay">true</item>
        ...
    </style>
</resources>

Launching the activity

Once you have added PdfActivity to your AndroidManifest.xml, you can start it by using its static helper methods for simple cases or, better yet, by building an Intent using PdfActivityIntentBuilder. You can open documents from a wide range of sources, including the local file system, your app’s assets, content providers, and any other custom data source you define.

Configuring the activity

When launching PdfActivity, you need to provide an instance of PdfActivityConfiguration. This configuration object allows you to configure the appearance and features of the activity. To create the configuration, use PdfActivityConfiguration.Builder:

// This will create the default configuration, or you can use a different builder
// method for configuring the activity.
val config = PdfActivityConfiguration.Builder(context).build()
// This will create the default configuration, or you can use a different builder
// method for configuring the activity.
final PdfActivityConfiguration config =
    new PdfActivityConfiguration.Builder(context)
        .build();

The above example creates the default activity configuration, but you can use any other configuration as well. The full list of available configuration options can be found in our API reference for PdfActivityConfiguration.Builder.

Launching from a URI using the static methods

Using a Uri, you can open documents from the local device file system, your app’s assets, or a document content provider (using Android’s Storage Access Framework). Use the PdfActivity.showDocument() call as a convenience for simple use cases:

val assetFile = Uri.parse("file:///android_asset/getting-started-guide.pdf")
PdfActivity.showDocument(context, assetFile, null, config)

val localDocument = Uri.fromFile(File(Environment.getExternalStorageDirectory(), "document.pdf"))
PdfActivity.showDocument(context, localDocument, null, config)

val contentProviderFile = Uri.parse("content://com.myapp.documents/repair-manuals/12345")
PdfActivity.showDocument(context, contentProviderFile, null, config)
final Uri assetFile = Uri.parse("file:///android_asset/getting-started-guide.pdf");
PdfActivity.showDocument(context, assetFile, null, config);

final Uri localDocument = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "document.pdf"));
PdfActivity.showDocument(context, localDocument, null, config);

final Uri contentProviderFile = Uri.parse("content://com.myapp.documents/repair-manuals/12345");
PdfActivity.showDocument(context, contentProviderFile, null, config);

ℹ️ Note: Access to files on the external storage requires the READ_EXTERNAL_STORAGE permission (and the WRITE_EXTERNAL_STORAGE permission if you want to write changes back to a PDF). Starting with Android 6.0 (API level 23), your app also needs to acquire the permissions at runtime before accessing any file on the external storage.

Launching from a URI or data providers using the intent builder

PdfActivityIntentBuilder provides full control over the document opening process. It allows you to control the source of the document (or multiple sources for joined documents), document passwords, content signatures, and custom activity for displaying the document.

URI

val assetFile = Uri.parse("file:///android_asset/getting-started-guide.pdf")
val intent = PdfActivityIntentBuilder.fromUri(context, assetFile).build()
context.startActivity(intent)
final Uri assetFile = Uri.parse("file:///android_asset/getting-started-guide.pdf");
final Intent intent = PdfActivityIntentBuilder.fromUri(context, assetFile).build();
context.startActivity(intent);

Data providers

Using a DataProvider, you can load documents from any non-standard document source — you can even define your own data provider. The full list of available data providers can be found in our data providers guide:

// Same as using the `file:///android_asset/` Uri prefix in the example above.
val provider = AssetDataProvider("getting-started-guide.pdf")
val intent = PdfActivityIntentBuilder.fromDataProvider(context, provider).build()
context.startActivity(intent)
// Same as using the `file:///android_asset/` Uri prefix in the example above.
final AssetDataProvider provider = new AssetDataProvider("getting-started-guide.pdf");
final Intent intent = PdfActivityIntentBuilder.fromDataProvider(context, provider).build();
context.startActivity(intent);

Compound documents

You can also open multiple documents at once, creating a single “compound document.” Simply pass a list of document Uri instances or a list of data providers to PdfActivityIntentBuilder:

val intent = PdfActivityIntentBuilder.fromUri(context, uri1, uri2, uri3).build()
context.startActivity(intent)
final Intent intent = PdfActivityIntentBuilder.fromUri(context, uri1, uri2, uri3).build();
context.startActivity(intent);

Compound documents are also the basis for merging two documents back into one using the document processing API.

More options

PdfActivityIntentBuilder provides more options than already stated, for example:

// Build the launching intent providing all required parameters.
val intent = PdfActivityIntentBuilder.fromUri(context, documentUri)
    .configuration(config)
    .activity(CustomActionsActivity.class)
    .passwords("some_password")
    .contentSignatures("some_doc_signature")
    .build()

// As with every other Android intent, you can add `Intent` extras.
intent.putExtra("username", "John Doe")
intent.putExtra("age", 36)

// You can modify the intent flags as well if you need to.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

// Finally, launch the activity.
context.startActivity(intent)
// Build the launching intent providing all required parameters.
final Intent intent = PdfActivityIntentBuilder.fromUri(context, documentUri)
    .configuration(config)
    .activity(CustomActionsActivity.class)
    .passwords("some_password")
    .contentSignatures("some_doc_signature")
    .build();

// As with every other Android intent, you can add `Intent` extras.
intent.putExtra("username", "John Doe");
intent.putExtra("age", 36);

// You can modify the intent flags as well if you need to.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

// Finally, launch the activity.
context.startActivity(intent);

💡 Tip: You can also use PdfActivityIntentBuilder for creating intents that can be used to launch an activity for results, or as a pending intent (e.g. for notifications).