Open a local PDF file on Android
Nutrient Android SDK allows you to open PDF and image (PNG or JPEG) files from your device’s local storage. This guide covers how to open a PDF document from local storage.
Never hardcode absolute paths
Directories where your app stores files aren’t guaranteed to be stable between different devices or even between app restarts, and paths to your app’s files may change over time if the app is moved to an adopted storage device. We recommend using methods from Context
to access different special file system directories. More specifically:
-
Use
Context#getFilesDir
to get the path to the file system directory where your internal files are stored. Use this path instead of hardcoding the device-dependent path/data/data/<application_package/files
. -
Use
Context#getExternalFilesDir(null)
to get the path to the primary shared/external storage device where your application can place the persistent files it owns. Use this path instead of hardcoding the device-dependent path/storage/emulated/0/
.
💡 Tip: If you need to persist paths to files (for example, in a database or in settings), only relative paths should be persisted.
Accessing the external storage
Android devices support shared “external storage” that can be used for storing files. These can be removable (for example, SD cards or USB hard drives) or non-removable (internal). External storage can become unavailable for multiple reasons and does not enforce any security restrictions for accessing your files. Make sure that your application handles these situations correctly.
Storage Access Framework
Use the Storage Access Framework if you’re running on Android 4.4+ and you want to allow users to browse and open documents from device storage.
💡 Tip: You can find a complete example of how to access files through the Storage Access Framework inside
ExternalDocumentExample
of the Catalog app.
Permissions to external storage
To read or write files on the external storage, your app must acquire READ_EXTERNAL_STORAGE
or WRITE_EXTERNAL_STORAGE
permissions. To acquire these permissions, add them to your manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.app.package"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
If your app targets Android 6.0+, these permissions aren’t granted to your app automatically after installation. You need to explicitly ask for them in your activity:
override fun onCreate(savedInstanceState: Bundle?) { ... // Request permission here. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_ASK_FOR_PERMISSION) } } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { if (requestCode == REQUEST_ASK_FOR_PERMISSION) { if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission has been granted. } else { if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // User denied permission. } else { // User asked to "Never ask again" when denying permission. } } } }
@Override protected void onCreate(Bundle savedInstanceState) { ... // Request permission here. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_ASK_FOR_PERMISSION); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_ASK_FOR_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission has been granted. } else { if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // User denied permission. } else { // User asked to "Never ask again" when denying permission. } } } }
💡 Tip: Since Android 4.4+, these permissions have no longer been required when accessing external files of your app (stored in the
Context#getExternalFilesDir(null)
directory).
Scoped directory access
Note that READ_EXTERNAL_STORAGE
and WRITE_EXTERNAL_STORAGE
permissions allow access to all public directories on the external storage, which could make your users worried or suspicious.
Use Scoped Directory Access if you’re running on Android 7.0+ and you only need to access a specific directory on the external storage. This provides a permissions UI that clearly states which directory your application is requesting access to.