Android rendering PDF files - Local & Remote URL

Android provides the PdfRenderer class for rendering PDF files within an app. While it allows for PDF rendering, the implementation can be quite tedious process, as it requires managing tasks like opening the document, rendering individual pages, and handling scaling etc. For a quicker and more efficient solution, using a reliable third-party library is often a better option.

android rendering pdf file tutorial
Today, in this article we'll see how to render PDF files using AndroidPdfViewer library. We'll cover how to load the PDF from local memory and from a network URL using the Retrofit library.

1. Adding the dependencies

Let's start by creating a new project in Android Studio and add the necessary dependencies.
  1. In Android Studio, create a new project from File => New Project and choose Empty View Activity to create the project using Kotlin language.
  2. Open the app's build.gradle and add the PDF library depency. We would also need to add Retrofit and Okhttp libraries to make the network call.
    build.gradle
    
    dependencies {
        // LiveData & ViewModels
        implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.6"
        implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6"
    
        // PDF viewer
        implementation "com.github.barteksc:android-pdf-viewer:3.2.0-beta.1"
    
        // Retrofit
        implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.14"
        implementation "com.squareup.retrofit2:converter-gson:2.11.0"
        implementation "com.squareup.retrofit2:retrofit:2.11.0"
        implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2"}
    

2. Loading local PDF

The PDF library provides PDFView component that can be included in your xml layout. Loading the PDF from local storage is pretty straight forward.

First add the PDFView component to the layout file.

<com.github.barteksc.pdfviewer.PDFView
        android:id="@+id/pdfView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
And load the PDF using any of the methods below. You need to implement the file chooser intent to get the file Uri.

// provide the document to load the PDF
pdfView.fromUri(Uri)

// or use the other methods
pdfView.fromFile(File)

pdfView.fromBytes(byte[])

pdfView.fromStream(InputStream)

pdfView.fromSource(DocumentSource)

android loading local pdf

3. Loading PDF from Remote URL

The library doesn't offer a method to render the PDF from a remote URL directly. Instead the file has to be downloaded first and then rendered. To download the file, we are going to use Retrofit networking library. Below is the final project structure that we are going to create shortly.
android preview pdf project structure

3.1 Adding Retrofit Library

In this tutorial, we are going to keep very basic setup needed for Retrofit. You can further customise the library and use a dependency framework like Hilt for easier integration.{alertInfo}
  1. Create a new package called utils and create a class named SingletonHolder.kt. Using this class, we can create the singleton instance of class objects.
  2. Create another package called remote and create NullOnEmptyConverterFactory.kt, Api.kt and ApiService.kt files under it. In Api service file, we initialise OkHttp interceptor and Retrofit by providing necessary configuration. In ApiService file, we define all the http endpoints necessary for the app. For this example, we only need one method to download PDF from url.
    ApiService.kt
    
    package info.androidhive.androidpdf.remote
    
    import okhttp3.ResponseBody
    import retrofit2.Call
    import retrofit2.http.GET
    import retrofit2.http.Url
    
    interface ApiService {
        @GET
        fun getFile(@Url url: String?): Call<ResponseBody>
    }
        

3.2 Rendering PDF from URL

Now that we have the network layer ready, let's create an activity to display the PDF. This activity follows the basic MVVM structure that involves creating an activity, fragment, view model and a repository class.
  1. Create a new package called pdf to add keep all the pdf releated files under one package
  2. Right click on pdf package and select New => Activity => Fragment + ViewModel and name them as ViewPdfActivity, ViewPdfFragment, and ViewPdfViewModel.
  3. Open AndroidManifest.xml and add INTERNET permission. Add configChanges attribute to ViewPdfActivity to avoid restarting the activity on device orientation changes.
    SingletonHolder.kt
    
    <uses-permission android:name="android.permission.INTERNET" />
    
    <activity 
                android:name=".ui.pdf.ViewPdfActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
                android:exported="false"
                android:parentActivityName=".ui.home.MainActivity" />
        
  4. Create ViewPdfRepository.kt and add the below content. This repository takes care of making the HTTP call and fetches the pdf file content.
    ViewPdfRepository.kt
    
    package info.androidhive.androidpdf.ui.pdf
    
    import info.androidhive.androidpdf.remote.ApiService
    import okhttp3.ResponseBody
    import retrofit2.Response
    
    class ViewPdfRepository(private val api: ApiService) {
        fun getFile(url: String?): Response<ResponseBody>? {
            return try {
                api.getFile(url).execute()
            } catch (e: Exception) {
                null
            }
        }
    }
        
  5. Create ViewPdfViewModel.kt and add the below code. This viewmodel talks to repository and gets the file data into a live data variable. This live data will be observed in the fragment.
  6. Open the layout file of the fragment fragment_view_pdf.xml and add the PDFView component. We are also adding a progress indicator that will be displayed while the file is being downloaded.
  7. Finally open ViewPdfFragment.kt and do the below changes. Here we pass the PDF url to view model and display the PDF once it is downloaded.
  8. Now, to view the PDF, launch the pdf viewer activity by passing the PDF HTTP url.
    SingletonHolder.kt
    
    binding.btnSample1.setOnClickListener {
                openPdf(
                    "Lorem ipsum ", // pdf title
                    "https://firebasestorage.googleapis.com/v0/b/project-8525323942962534560.appspot.com/o/samples%2Fpdf%2Ffile-example_PDF_1MB.pdf?alt=media&amp;token=ea88122f-0524-4022-b401-f8ec1035901f"
                )
            }
    
    
    // function to open pdf viewer activity
    private fun openPdf(title: String, url: String) {
            startActivity(Intent(this, ViewPdfActivity::class.java).apply {
                putExtra("title", title)
                putExtra("pdf_url", url)
            })
        }
        

andorid rendering pdf from url landscape mode
I hope this article provided good insights into rendering PDF files on Android. You can refer the full code here.

Cheers!
Happy Coding 🤗
Previous Post Next Post

نموذج الاتصال