Yesterday I received an email from one of our readers and he asked me to fix his issue where he was not able to open PDF from the storage when the user clicked on the button. And his application was running flawlessly on an older version of Android. After Android 11, his application was not working as per his plan.
I thought to resolve this, but he didn’t share the complete code, so I thought, why not create a demo application from scratch for our readers?
While developing the demo application to open PDF files, I got the following errors: “android.os.FileUriExposedException: file:///storage/emulated/0/TRENDOCEANS.pdf exposed beyond app through Intent.getData()” and “Couldn’t find meta-data for provider with authority”. If you also get this kind of error, then you can read our dedicated article on this issue.
Table of Contents
Open PDF Programmatically using Intent
Before starting the process, let me walk through the concept of our demo application. First and foremost, we will ask for permission. Then, the user will see a button that will invoke intent to open a pdf file that is already available in the root folder of the device, and that’s it.
Create new project in Android Studio
I’m not going to show you how to create a new project in Android Studio because you know how to do it very well. Still, if you want, then take a glimpse at how to create a new project in Android Studio, which is very similar to this project.
Create Basic Layout in activity_main.xml
After creating a new project, the first thing you need to do is modify activity_main.xml to add a button that will invoke the openPDF() method, which we are going to create in the MainActivity file. And the rest of the options are just for visual appeal that you can skip for now.
Now you will modify AndroidManifest.xml to add <uses-permission></uses-permission> and <provider></provider> tag nested with <meta></meta> tag.
A first <uses-permission/> advisable to list out the available applications to support the particular actions.
I would recommend you read this article for a better perspective on package filtering.
And the last <uses-permission/> is necessary for the latest Android version. If you are using Android 12, you will see two types of permission are available compared to the previous Android version when you want to read files.
At the bottom, you need to add <provider/> tag which is nested with <meta/> tag to provide a location to access the storage directory.
At present, you cannot access any file directly. First, you need to add <provider/> <meta/> tag and specify the location in @xml/file_path.xml “Couldn’t find meta-data for provider with authority.”
Create file_path in xml resource
The file @xml/file_path will get highlighted in red to indicate the missing file. Simply, you just need to hover on @xml/file_path and click on Create xml resource file to create the missing file.
The next screen will ask you to enter the following details. After making the changes, click on “OK” to move ahead.
And copy the below content to @xml/file_path to read the root directory of the external storage with the “external_file” name.
Modify MainActivity to open PDF file in external applications
First, you need to add a static constant value for permission check under the MainActivity class. You can simply copy the below code and paste it into your editor.
Inside the onCreate method, you need to call verifyStoragePermission (this). After that, initialize the button to set a click listener. Under the click listener, create a new method called openPDF ().
This verifyStoragePermission method is used to request and verify read permission.
The first step will be used to check the current status of permission. If it’s –1, then it will prompt you to accept the permission. For Android 12, devices need extra permission to read all files.
That’s a reason you need to use Intent to ask permission to read all file access permissions.
Inside openPDF(), you need to specify the location of the PDF file using the File class and save the value in a file variable which you will use in uriPdfPath to declare the path; after that, using Intent, you can call an external app to read the PDF.
Earlier, we used “Uri path = Uri.fromFile(file);” to get the URI of a location, but it’s not working anymore, so you have to use “Uri uriPdfPath = FileProvider.getUriForFile()” and specify the .provider to declare the location you are going to access in @xml/file_path.xml.
And that’s a reason for the following error: “android.os.FileUriExposedException: file:///storage/emulated/0/TRENDOCEANS.pdf exposed beyond app through Intent.getData()”
Before running the application please verify the code of MainActivity.
Run application to read PDF
Once the application is ready install it on your device and tests the functionality before that keep the PDF in the specified location of your device.
That’s all to open PDF programmatically using Intent in Android.
Along with that, we have shown you the method to resolve “android.os.FileUriExposedException: file:///storage/emulated/0/TRENDOCEANS.pdf exposed beyond app through Intent.getData()” and “Couldn’t find meta-data for provider with authority”.
And I’ll upload this project on Github for your reference.
A man with a tech effusive, who has explored some of the amazing technology stuff and exploring more, While moving towards, I had a chance to work on Android Development, Linux, AWS, DevOps with several Open source tools.
One of my life mottos “Always be lifelong Students.”