Skip to content

Commit 51bf69f

Browse files
committed
Added PDF Viewer snippets.
1 parent ce81ef6 commit 51bf69f

File tree

4 files changed

+366
-18
lines changed

4 files changed

+366
-18
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ wearComposeMaterial = "1.5.0-beta01"
7575
wearComposeMaterial3 = "1.5.0-beta01"
7676
wearToolingPreview = "1.0.0"
7777
webkit = "1.13.0"
78+
pdfViewerFragment = "1.0.0-alpha09"
7879

7980
[libraries]
8081
accompanist-adaptive = "com.google.accompanist:accompanist-adaptive:0.37.3"
@@ -182,6 +183,7 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa
182183
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okHttp" }
183184
play-services-wearable = { module = "com.google.android.gms:play-services-wearable", version.ref = "playServicesWearable" }
184185
wear-compose-material3 = { module = "androidx.wear.compose:compose-material3", version.ref = "wearComposeMaterial3" }
186+
androidx-pdf-viewer-fragment = {module = "androidx.pdf:pdf-viewer-fragment", version.ref = "pdfViewerFragment" }
185187

186188
[plugins]
187189
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }

misc/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ dependencies {
6363
implementation(libs.kotlinx.serialization.json)
6464
ksp(libs.hilt.compiler)
6565

66+
implementation(libs.google.android.material)
67+
implementation(libs.androidx.pdf.viewer.fragment)
68+
6669
implementation(libs.androidx.constraintlayout)
6770
implementation(libs.androidx.lifecycle.runtime)
6871
implementation(libs.androidx.window)
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.snippets
18+
19+
import android.net.Uri
20+
import android.os.Build
21+
import android.os.Bundle
22+
import android.os.ext.SdkExtensions
23+
import androidx.activity.result.contract.ActivityResultContracts.GetContent
24+
import androidx.annotation.RequiresApi
25+
import androidx.annotation.RequiresExtension
26+
import androidx.appcompat.app.AppCompatActivity
27+
import androidx.core.view.WindowCompat
28+
import androidx.fragment.app.FragmentManager
29+
import androidx.fragment.app.FragmentTransaction
30+
import androidx.pdf.viewer.fragment.PdfStylingOptions
31+
import androidx.pdf.viewer.fragment.PdfViewerFragment
32+
import com.google.android.material.button.MaterialButton
33+
import java.util.logging.Level.INFO
34+
import java.util.logging.Level.SEVERE
35+
import java.util.logging.Logger
36+
37+
class PdfViewerKotlinSnippets {
38+
39+
@RequiresApi(Build.VERSION_CODES.R)
40+
fun onCreate(savedInstanceState: Bundle?) {
41+
42+
// [START android_pdf_viewer_extension_version_kotlin]
43+
if (SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S) >= 13) {
44+
// Load the fragment and document.
45+
}
46+
// [END android_pdf_viewer_extension_version_kotlin]
47+
48+
}
49+
50+
// [START android_pdf_viewer_create_compat_activity_kotlin]
51+
class MainActivity : AppCompatActivity() {
52+
override fun onCreate(savedInstanceState: Bundle?) {
53+
super.onCreate(savedInstanceState)
54+
setContentView(R.layout.activity_main)
55+
56+
val getContentButton: MaterialButton = findViewById(R.id.launch_button)
57+
val searchButton: MaterialButton = findViewById(R.id.search_button)
58+
}
59+
}
60+
// [END android_pdf_viewer_create_compat_activity_kotlin]
61+
62+
63+
// [START android_pdf_viewer_extend_fragment_kotlin]
64+
@RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
65+
class PdfViewerFragmentExtended : PdfViewerFragment() {
66+
private val myLogger : Logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)
67+
68+
override fun onLoadDocumentSuccess() {
69+
myLogger.log(INFO, "// Log document success.")
70+
}
71+
72+
override fun onLoadDocumentError(error: Throwable) {
73+
myLogger.log(SEVERE, "// Log document error.")
74+
}
75+
}
76+
// [END android_pdf_viewer_extend_fragment_kotlin]
77+
78+
/** Enable nested classes. **/
79+
class ClassHolder {
80+
81+
// [START android_pdf_viewer_create_fragment_kotlin]
82+
class MainActivity : AppCompatActivity() {
83+
private var pdfViewerFragment: PdfViewerFragment? = null
84+
85+
override fun onCreate(savedInstanceState: Bundle?) {
86+
super.onCreate(savedInstanceState)
87+
88+
// ...
89+
90+
if (pdfViewerFragment == null) {
91+
pdfViewerFragment =
92+
supportFragmentManager
93+
.findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
94+
}
95+
96+
}
97+
98+
// Used to instantiate and commit the fragment.
99+
@RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
100+
private fun initialisePdfViewerFragment() {
101+
// This condition can be skipped if you want to create a new fragment everytime.
102+
if (pdfViewerFragment == null) {
103+
val fragmentManager: FragmentManager = supportFragmentManager
104+
105+
// Fragment initialization.
106+
pdfViewerFragment = PdfViewerFragmentExtended()
107+
val transaction: FragmentTransaction = fragmentManager.beginTransaction()
108+
109+
// Replace an existing fragment in a container with an instance of a new fragment.
110+
transaction.replace(
111+
R.id.fragment_container_view,
112+
pdfViewerFragment!!,
113+
PDF_VIEWER_FRAGMENT_TAG
114+
)
115+
transaction.commitAllowingStateLoss()
116+
fragmentManager.executePendingTransactions()
117+
}
118+
}
119+
120+
companion object {
121+
private const val MIME_TYPE_PDF = "application/pdf"
122+
private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
123+
}
124+
}
125+
// [END android_pdf_viewer_create_fragment_kotlin]
126+
127+
}
128+
129+
/** Enable nested classes. **/
130+
class ClassHolder2 {
131+
132+
// [START android_pdf_viewer_enable_document_search_kotlin]
133+
class MainActivity : AppCompatActivity() {
134+
@RequiresExtension(extension = Build.VERSION_CODES.S, version = 13)
135+
override fun onCreate(savedInstanceState: Bundle?) {
136+
super.onCreate(savedInstanceState)
137+
var pdfViewerFragment: PdfViewerFragment? = null
138+
val searchButton: MaterialButton = findViewById(R.id.search_button)
139+
searchButton.setOnClickListener {
140+
pdfViewerFragment?.isTextSearchActive = pdfViewerFragment?.isTextSearchActive == false
141+
}
142+
143+
// Ensure WindowInsetsCompat are passed to content views without being consumed by the decor
144+
// view. These insets are used to calculate the position of the search view.
145+
WindowCompat.setDecorFitsSystemWindows(window, false)
146+
}
147+
}
148+
// [END android_pdf_viewer_enable_document_search_kotlin]
149+
150+
}
151+
152+
/** Enable nested classes. **/
153+
class ClassHolder3: AppCompatActivity() {
154+
155+
private var pdfViewerFragment: PdfViewerFragment? = null
156+
private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
157+
158+
override fun onCreate(savedInstanceState: Bundle?) {
159+
super.onCreate(savedInstanceState)
160+
161+
// ...
162+
163+
if (pdfViewerFragment == null) {
164+
pdfViewerFragment =
165+
supportFragmentManager
166+
.findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
167+
}
168+
169+
}
170+
171+
// [START android_pdf_viewer_launch_file_picker_kotlin]
172+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
173+
class MainActivity : AppCompatActivity() {
174+
private var pdfViewerFragment: PdfViewerFragment? = null
175+
private var filePicker =
176+
registerForActivityResult(GetContent()) { uri: Uri? ->
177+
uri?.let {
178+
initialisePdfViewerFragment()
179+
pdfViewerFragment?.documentUri = uri
180+
}
181+
}
182+
183+
override fun onCreate(savedInstanceState: Bundle?) {
184+
super.onCreate(savedInstanceState)
185+
// ...
186+
val getContentButton: MaterialButton = findViewById(R.id.launch_button)
187+
getContentButton.setOnClickListener { filePicker.launch(MIME_TYPE_PDF, null) }
188+
}
189+
190+
private fun initialisePdfViewerFragment() {
191+
// ...
192+
}
193+
194+
companion object {
195+
private const val MIME_TYPE_PDF = "application/pdf"
196+
// ...
197+
}
198+
}
199+
// [END android_pdf_viewer_launch_file_picker_kotlin]
200+
201+
// [START android_pdf_viewer_style_fragment_kotlin]
202+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
203+
private fun initialisePdfViewerFragment() {
204+
// This condition can be skipped if you want to create a new fragment everytime
205+
if (pdfViewerFragment == null) {
206+
val fragmentManager: FragmentManager = supportFragmentManager
207+
208+
// Create styling options
209+
val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
210+
211+
// Fragment initialization
212+
pdfViewerFragment = PdfViewerFragment.newInstance(stylingOptions)
213+
214+
// .. execute fragment transaction
215+
}
216+
}
217+
// [END android_pdf_viewer_style_fragment_kotlin]
218+
219+
}
220+
221+
// [START android_pdf_viewer_style_fragment_constructor_kotlin]
222+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
223+
class StyledPdfViewerFragment: PdfViewerFragment {
224+
225+
constructor() : super()
226+
227+
private constructor(pdfStylingOptions: PdfStylingOptions) : super(pdfStylingOptions)
228+
229+
companion object {
230+
fun newInstance(): StyledPdfViewerFragment {
231+
val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
232+
return StyledPdfViewerFragment(stylingOptions)
233+
}
234+
}
235+
}
236+
// [END android_pdf_viewer_style_fragment_constructor_kotlin]
237+
238+
/** Enable nested classes. **/
239+
class ClassHolder4 {
240+
241+
// [START android_pdf_viewer_full_code_kotlin]
242+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
243+
class MainActivity : AppCompatActivity() {
244+
245+
private var pdfViewerFragment: PdfViewerFragment? = null
246+
private var filePicker =
247+
registerForActivityResult(GetContent()) { uri: Uri? ->
248+
uri?.let {
249+
initialisePdfViewerFragment()
250+
pdfViewerFragment?.documentUri = uri
251+
}
252+
}
253+
254+
override fun onCreate(savedInstanceState: Bundle?) {
255+
super.onCreate(savedInstanceState)
256+
setContentView(R.layout.activity_main)
257+
258+
if (pdfViewerFragment == null) {
259+
pdfViewerFragment =
260+
supportFragmentManager
261+
.findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
262+
}
263+
264+
val getContentButton: MaterialButton = findViewById(R.id.launch_button)
265+
val searchButton: MaterialButton = findViewById(R.id.search_button)
266+
267+
getContentButton.setOnClickListener { filePicker.launch(MIME_TYPE_PDF) }
268+
searchButton.setOnClickListener {
269+
pdfViewerFragment?.isTextSearchActive = pdfViewerFragment?.isTextSearchActive == false
270+
}
271+
}
272+
273+
private fun initialisePdfViewerFragment() {
274+
// This condition can be skipped if you want to create a new fragment everytime
275+
if (pdfViewerFragment == null) {
276+
val fragmentManager: FragmentManager = supportFragmentManager
277+
278+
// Create styling options
279+
// val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
280+
281+
// Fragment initialization
282+
// For customization
283+
// pdfViewerFragment = PdfViewerFragment.newInstance(stylingOptions)
284+
pdfViewerFragment = PdfViewerFragmentExtended()
285+
val transaction: FragmentTransaction = fragmentManager.beginTransaction()
286+
287+
// Replace an existing fragment in a container with an instance of a new fragment
288+
transaction.replace(
289+
R.id.fragment_container_view,
290+
pdfViewerFragment!!,
291+
PDF_VIEWER_FRAGMENT_TAG
292+
)
293+
transaction.commitAllowingStateLoss()
294+
fragmentManager.executePendingTransactions()
295+
}
296+
}
297+
298+
companion object {
299+
private const val MIME_TYPE_PDF = "application/pdf"
300+
private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
301+
}
302+
}
303+
// [END android_pdf_viewer_full_code_kotlin]
304+
305+
}
306+
307+
}

0 commit comments

Comments
 (0)