Skip to content

Commit b82f869

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

File tree

5 files changed

+376
-18
lines changed

5 files changed

+376
-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: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
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+
157+
override fun onCreate(savedInstanceState: Bundle?) {
158+
super.onCreate(savedInstanceState)
159+
160+
// ...
161+
162+
if (pdfViewerFragment == null) {
163+
pdfViewerFragment =
164+
supportFragmentManager
165+
.findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
166+
}
167+
168+
}
169+
170+
// [START android_pdf_viewer_launch_file_picker_kotlin]
171+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
172+
class MainActivity : AppCompatActivity() {
173+
private var pdfViewerFragment: PdfViewerFragment? = null
174+
private var filePicker =
175+
registerForActivityResult(GetContent()) { uri: Uri? ->
176+
uri?.let {
177+
initialisePdfViewerFragment()
178+
pdfViewerFragment?.documentUri = uri
179+
}
180+
}
181+
182+
override fun onCreate(savedInstanceState: Bundle?) {
183+
super.onCreate(savedInstanceState)
184+
// ...
185+
val getContentButton: MaterialButton = findViewById(R.id.launch_button)
186+
getContentButton.setOnClickListener { filePicker.launch(MIME_TYPE_PDF, null) }
187+
}
188+
189+
private fun initialisePdfViewerFragment() {
190+
// ...
191+
}
192+
193+
companion object {
194+
private const val MIME_TYPE_PDF = "application/pdf"
195+
// ...
196+
}
197+
}
198+
// [END android_pdf_viewer_launch_file_picker_kotlin]
199+
200+
// [START android_pdf_viewer_style_fragment_kotlin]
201+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
202+
private fun initialisePdfViewerFragment() {
203+
// This condition can be skipped if you want to create a new fragment everytime
204+
if (pdfViewerFragment == null) {
205+
val fragmentManager: FragmentManager = supportFragmentManager
206+
207+
// Create styling options
208+
val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
209+
210+
// Fragment initialization
211+
pdfViewerFragment = PdfViewerFragment.newInstance(stylingOptions)
212+
213+
// .. execute fragment transaction
214+
}
215+
}
216+
// [END android_pdf_viewer_style_fragment_kotlin]
217+
218+
companion object {
219+
private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
220+
}
221+
222+
}
223+
224+
// [START android_pdf_viewer_style_fragment_constructor_kotlin]
225+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
226+
class StyledPdfViewerFragment: PdfViewerFragment {
227+
228+
constructor() : super()
229+
230+
private constructor(pdfStylingOptions: PdfStylingOptions) : super(pdfStylingOptions)
231+
232+
companion object {
233+
fun newInstance(): StyledPdfViewerFragment {
234+
val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
235+
return StyledPdfViewerFragment(stylingOptions)
236+
}
237+
}
238+
}
239+
// [END android_pdf_viewer_style_fragment_constructor_kotlin]
240+
241+
/** Enable nested classes. **/
242+
class ClassHolder4 {
243+
244+
// [START android_pdf_viewer_full_code_kotlin]
245+
@RequiresExtension(extension=Build.VERSION_CODES.S, version=13)
246+
class MainActivity : AppCompatActivity() {
247+
248+
private var pdfViewerFragment: PdfViewerFragment? = null
249+
private var filePicker =
250+
registerForActivityResult(GetContent()) { uri: Uri? ->
251+
uri?.let {
252+
initialisePdfViewerFragment()
253+
pdfViewerFragment?.documentUri = uri
254+
}
255+
}
256+
257+
override fun onCreate(savedInstanceState: Bundle?) {
258+
super.onCreate(savedInstanceState)
259+
setContentView(R.layout.activity_main)
260+
261+
if (pdfViewerFragment == null) {
262+
pdfViewerFragment =
263+
supportFragmentManager
264+
.findFragmentByTag(PDF_VIEWER_FRAGMENT_TAG) as PdfViewerFragment?
265+
}
266+
267+
val getContentButton: MaterialButton = findViewById(R.id.launch_button)
268+
val searchButton: MaterialButton = findViewById(R.id.search_button)
269+
270+
getContentButton.setOnClickListener { filePicker.launch(MIME_TYPE_PDF) }
271+
searchButton.setOnClickListener {
272+
pdfViewerFragment?.isTextSearchActive = pdfViewerFragment?.isTextSearchActive == false
273+
}
274+
}
275+
276+
private fun initialisePdfViewerFragment() {
277+
// This condition can be skipped if you want to create a new fragment everytime
278+
if (pdfViewerFragment == null) {
279+
val fragmentManager: FragmentManager = supportFragmentManager
280+
281+
// Create styling options
282+
// val stylingOptions = PdfStylingOptions(R.style.pdfContainerStyle)
283+
284+
// Fragment initialization
285+
// For customization
286+
// pdfViewerFragment = PdfViewerFragment.newInstance(stylingOptions)
287+
pdfViewerFragment = PdfViewerFragmentExtended()
288+
val transaction: FragmentTransaction = fragmentManager.beginTransaction()
289+
290+
// Replace an existing fragment in a container with an instance of a new fragment
291+
transaction.replace(
292+
R.id.fragment_container_view,
293+
pdfViewerFragment!!,
294+
PDF_VIEWER_FRAGMENT_TAG
295+
)
296+
transaction.commitAllowingStateLoss()
297+
fragmentManager.executePendingTransactions()
298+
}
299+
}
300+
301+
companion object {
302+
private const val MIME_TYPE_PDF = "application/pdf"
303+
private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
304+
}
305+
}
306+
// [END android_pdf_viewer_full_code_kotlin]
307+
308+
companion object {
309+
private const val PDF_VIEWER_FRAGMENT_TAG = "pdf_viewer_fragment_tag"
310+
}
311+
312+
}
313+
314+
}

0 commit comments

Comments
 (0)