├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── mindorks │ │ └── example │ │ └── openpdffile │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── MindOrks_Android_Online_Professional_Course-Syllabus.pdf │ ├── java │ │ └── com │ │ │ └── mindorks │ │ │ └── example │ │ │ └── openpdffile │ │ │ ├── MainActivity.kt │ │ │ ├── PdfViewActivity.kt │ │ │ ├── WebViewActivity.kt │ │ │ └── utils │ │ │ └── FileUtils.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_pdf_view.xml │ │ └── activity_web_view.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── mindorks │ └── example │ └── openpdffile │ └── ExampleUnitTest.kt ├── assets └── how-to-open-a-pdf-file-in-android-programmatically-banner.png ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | /.idea 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open PDF File Android Example - An example project to demonstrate how to open a PDF file in Android programmatically 2 | [![MindOrks](https://img.shields.io/badge/mindorks-opensource-blue.svg)](https://mindorks.com/open-source-projects) 3 | [![MindOrks Community](https://img.shields.io/badge/join-community-blue.svg)](https://mindorks.com/join-community) 4 | 5 |

6 | 7 |

8 |
9 | 10 | ## About this Project 11 | This project contains a sample app that shows how to open a PDF file in Android application programmatically. We will build the following in this project: 12 | * Open PDF in WebView 13 | * Open PDF from the assets folder using the AndroidPdfViewer library 14 | * Open PDF from the phone storage using the AndroidPdfViewer library 15 | * Download file from the internet using the PRDownloader library and then open that file using the AndroidPdfViewer library 16 | 17 | ## Step by Step guide 18 | Reference blog for this project - [How to open a PDF file in Android programmatically?](https://blog.mindorks.com/how-to-open-a-pdf-file-in-android-programmatically) 19 | 20 | ## Explore Android Online Tutorials and Courses To Learn More by MindOrks 21 | * [Ride-Sharing Uber Lyft Android App](https://github.com/MindorksOpenSource/ridesharing-uber-lyft-app) - Learn to build a ride-sharing Android Taxi Clone App like Uber, Lyft - Open-Source Project By MindOrks 22 | * [Android Tutorial](https://mindorks.com/android-tutorial) - All Free Android Tutorials by MindOrks 23 | * [Android Online Course for Professionals](https://bootcamp.mindorks.com) - In this online course, you’ll learn the Dagger, Kotlin, RxJava, MVVM Architecture, Architecture Components, Jetpack, LiveData, ViewModel, Room Database, Database Design, Multithreading, Memory Management, Networking, Caching, How Glide works, Unit Testing, and the best practices for Android Development. By the end of this online course, you will have all the skills you need to become a professional Android Developer. 24 | * [Android Online Course for Beginners](https://bootcamp.mindorks.com/android-training-for-beginners) - This course is for beginners for those who want to get started with Android Development. In this course, you will build two apps: TodoNotes and Ride-Sharing Uber Android App. 25 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.3" 8 | 9 | defaultConfig { 10 | applicationId "com.mindorks.example.openpdffile" 11 | minSdkVersion 21 12 | targetSdkVersion 29 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(dir: 'libs', include: ['*.jar']) 30 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 31 | implementation 'androidx.appcompat:appcompat:1.1.0' 32 | implementation 'androidx.core:core-ktx:1.2.0' 33 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 34 | testImplementation 'junit:junit:4.12' 35 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 37 | implementation 'com.github.barteksc:android-pdf-viewer:2.8.2' 38 | implementation 'com.mindorks.android:prdownloader:0.6.0' 39 | } 40 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/mindorks/example/openpdffile/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.example.openpdffile 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.mindorks.example.openpdffile", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/assets/MindOrks_Android_Online_Professional_Course-Syllabus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MindorksOpenSource/Open-PDF-File-Android-Example/3c4cc11771c2aa3d0ad452ebec998d4cc2d48d51/app/src/main/assets/MindOrks_Android_Online_Professional_Course-Syllabus.pdf -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/example/openpdffile/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.example.openpdffile 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import androidx.appcompat.app.AppCompatActivity 6 | import kotlinx.android.synthetic.main.activity_main.* 7 | 8 | class MainActivity : AppCompatActivity() { 9 | 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | setContentView(R.layout.activity_main) 13 | 14 | setUpOnClickListener() 15 | } 16 | 17 | private fun setUpOnClickListener() { 18 | buttonWebView.setOnClickListener { 19 | val intent = Intent(this, WebViewActivity::class.java) 20 | startActivity(intent) 21 | } 22 | buttonAssets.setOnClickListener { 23 | val intent = Intent(this, PdfViewActivity::class.java) 24 | intent.putExtra("ViewType", "assets") 25 | startActivity(intent) 26 | } 27 | buttonStorage.setOnClickListener { 28 | val intent = Intent(this, PdfViewActivity::class.java) 29 | intent.putExtra("ViewType", "storage") 30 | startActivity(intent) 31 | } 32 | buttonInternet.setOnClickListener { 33 | val intent = Intent(this, PdfViewActivity::class.java) 34 | intent.putExtra("ViewType", "internet") 35 | startActivity(intent) 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/example/openpdffile/PdfViewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.example.openpdffile 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.os.Bundle 7 | import android.view.View 8 | import android.widget.Toast 9 | import androidx.appcompat.app.AppCompatActivity 10 | import com.downloader.Error 11 | import com.downloader.OnDownloadListener 12 | import com.downloader.PRDownloader 13 | import com.mindorks.example.openpdffile.utils.FileUtils 14 | import kotlinx.android.synthetic.main.activity_pdf_view.* 15 | import java.io.File 16 | 17 | class PdfViewActivity : AppCompatActivity() { 18 | 19 | companion object { 20 | private const val PDF_SELECTION_CODE = 99 21 | } 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContentView(R.layout.activity_pdf_view) 26 | 27 | PRDownloader.initialize(applicationContext) 28 | checkPdfAction(intent) 29 | } 30 | 31 | private fun showPdfFromAssets(pdfName: String) { 32 | pdfView.fromAsset(pdfName) 33 | .password(null) 34 | .defaultPage(0) 35 | .onPageError { page, _ -> 36 | Toast.makeText( 37 | this@PdfViewActivity, 38 | "Error at page: $page", Toast.LENGTH_LONG 39 | ).show() 40 | } 41 | .load() 42 | } 43 | 44 | private fun selectPdfFromStorage() { 45 | Toast.makeText(this, "selectPDF", Toast.LENGTH_LONG).show() 46 | val browseStorage = Intent(Intent.ACTION_GET_CONTENT) 47 | browseStorage.type = "application/pdf" 48 | browseStorage.addCategory(Intent.CATEGORY_OPENABLE) 49 | startActivityForResult( 50 | Intent.createChooser(browseStorage, "Select PDF"), PDF_SELECTION_CODE 51 | ) 52 | } 53 | 54 | private fun showPdfFromUri(uri: Uri?) { 55 | pdfView.fromUri(uri) 56 | .defaultPage(0) 57 | .spacing(10) 58 | .load() 59 | } 60 | 61 | private fun showPdfFromFile(file: File) { 62 | pdfView.fromFile(file) 63 | .password(null) 64 | .defaultPage(0) 65 | .enableSwipe(true) 66 | .swipeHorizontal(false) 67 | .enableDoubletap(true) 68 | .onPageError { page, _ -> 69 | Toast.makeText( 70 | this@PdfViewActivity, 71 | "Error at page: $page", Toast.LENGTH_LONG 72 | ).show() 73 | } 74 | .load() 75 | } 76 | 77 | private fun downloadPdfFromInternet(url: String, dirPath: String, fileName: String) { 78 | PRDownloader.download( 79 | url, 80 | dirPath, 81 | fileName 82 | ).build() 83 | .start(object : OnDownloadListener { 84 | override fun onDownloadComplete() { 85 | Toast.makeText(this@PdfViewActivity, "downloadComplete", Toast.LENGTH_LONG) 86 | .show() 87 | val downloadedFile = File(dirPath, fileName) 88 | progressBar.visibility = View.GONE 89 | showPdfFromFile(downloadedFile) 90 | } 91 | 92 | override fun onError(error: Error?) { 93 | Toast.makeText( 94 | this@PdfViewActivity, 95 | "Error in downloading file : $error", 96 | Toast.LENGTH_LONG 97 | ) 98 | .show() 99 | } 100 | }) 101 | } 102 | 103 | private fun checkPdfAction(intent: Intent) { 104 | when (intent.getStringExtra("ViewType")) { 105 | "assets" -> { 106 | showPdfFromAssets(FileUtils.getPdfNameFromAssets()) 107 | } 108 | "storage" -> { 109 | selectPdfFromStorage() 110 | } 111 | "internet" -> { 112 | progressBar.visibility = View.VISIBLE 113 | val fileName = "myFile.pdf" 114 | downloadPdfFromInternet( 115 | FileUtils.getPdfUrl(), 116 | FileUtils.getRootDirPath(this), 117 | fileName 118 | ) 119 | } 120 | } 121 | } 122 | 123 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 124 | super.onActivityResult(requestCode, resultCode, data) 125 | if (requestCode == PDF_SELECTION_CODE && resultCode == Activity.RESULT_OK && data != null) { 126 | val selectedPdfFromStorage = data.data 127 | showPdfFromUri(selectedPdfFromStorage) 128 | } 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/example/openpdffile/WebViewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.example.openpdffile 2 | 3 | import android.os.Bundle 4 | import android.webkit.WebViewClient 5 | import androidx.appcompat.app.AppCompatActivity 6 | import com.mindorks.example.openpdffile.utils.FileUtils 7 | import kotlinx.android.synthetic.main.activity_web_view.* 8 | 9 | class WebViewActivity : AppCompatActivity() { 10 | 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | setContentView(R.layout.activity_web_view) 14 | webView.webViewClient = WebViewClient() 15 | webView.settings.setSupportZoom(true) 16 | webView.settings.javaScriptEnabled = true 17 | val url = FileUtils.getPdfUrl() 18 | webView.loadUrl("https://docs.google.com/gview?embedded=true&url=$url") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/example/openpdffile/utils/FileUtils.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.example.openpdffile.utils 2 | 3 | import android.content.Context 4 | import android.os.Environment 5 | import androidx.core.content.ContextCompat 6 | import java.io.File 7 | 8 | object FileUtils { 9 | 10 | fun getPdfNameFromAssets(): String { 11 | return "MindOrks_Android_Online_Professional_Course-Syllabus.pdf" 12 | } 13 | 14 | fun getPdfUrl(): String { 15 | return "https://mindorks.s3.ap-south-1.amazonaws.com/courses/MindOrks_Android_Online_Professional_Course-Syllabus.pdf" 16 | } 17 | 18 | fun getRootDirPath(context: Context): String { 19 | return if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) { 20 | val file: File = ContextCompat.getExternalFilesDirs( 21 | context.applicationContext, 22 | null 23 | )[0] 24 | file.absolutePath 25 | } else { 26 | context.applicationContext.filesDir.absolutePath 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 23 | 24 |