Repository: DImuthuUpe/AndroidPdfViewer
Branch: master
Commit: e62698bebb24
Files: 67
Total size: 222.4 KB
Directory structure:
gitextract_l2u_xl7x/
├── .gitignore
├── 16KB_SUPPORT.md
├── CHANGELOG.md
├── LICENSE
├── README.md
├── android-pdf-viewer/
│ ├── bintray.gradle
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── github/
│ │ └── barteksc/
│ │ └── pdfviewer/
│ │ ├── AnimationManager.java
│ │ ├── CacheManager.java
│ │ ├── DecodingAsyncTask.java
│ │ ├── DragPinchManager.java
│ │ ├── PDFView.java
│ │ ├── PagesLoader.java
│ │ ├── PdfFile.java
│ │ ├── RenderingHandler.java
│ │ ├── exception/
│ │ │ ├── FileNotFoundException.java
│ │ │ └── PageRenderingException.java
│ │ ├── link/
│ │ │ ├── DefaultLinkHandler.java
│ │ │ └── LinkHandler.java
│ │ ├── listener/
│ │ │ ├── Callbacks.java
│ │ │ ├── OnDrawListener.java
│ │ │ ├── OnErrorListener.java
│ │ │ ├── OnLoadCompleteListener.java
│ │ │ ├── OnLongPressListener.java
│ │ │ ├── OnPageChangeListener.java
│ │ │ ├── OnPageErrorListener.java
│ │ │ ├── OnPageScrollListener.java
│ │ │ ├── OnRenderListener.java
│ │ │ └── OnTapListener.java
│ │ ├── model/
│ │ │ ├── LinkTapEvent.java
│ │ │ └── PagePart.java
│ │ ├── scroll/
│ │ │ ├── DefaultScrollHandle.java
│ │ │ └── ScrollHandle.java
│ │ ├── source/
│ │ │ ├── AssetSource.java
│ │ │ ├── ByteArraySource.java
│ │ │ ├── DocumentSource.java
│ │ │ ├── FileSource.java
│ │ │ ├── InputStreamSource.java
│ │ │ └── UriSource.java
│ │ └── util/
│ │ ├── ArrayUtils.java
│ │ ├── Constants.java
│ │ ├── FileUtils.java
│ │ ├── FitPolicy.java
│ │ ├── MathUtils.java
│ │ ├── PageSizeCalculator.java
│ │ ├── SnapEdge.java
│ │ └── Util.java
│ └── res/
│ ├── drawable/
│ │ ├── default_scroll_handle_bottom.xml
│ │ ├── default_scroll_handle_left.xml
│ │ ├── default_scroll_handle_right.xml
│ │ └── default_scroll_handle_top.xml
│ └── values/
│ └── attrs.xml
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── github/
│ │ └── barteksc/
│ │ └── sample/
│ │ └── PDFViewActivity.java
│ └── res/
│ ├── layout/
│ │ └── activity_main.xml
│ ├── menu/
│ │ └── options.xml
│ └── values/
│ ├── strings.xml
│ └── styles.xml
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
target/
build/
lint.xml
bin/
gen/
.settings
.project
.classpath
out
gen-external-apklibs/
classes/
# Local configuration file (sdk path, etc)
local.properties
# Android Studio
.idea/
*/out
!*/build/apk/
*/production/
*.iws
*.ipr
*.iml
*~
*.swp
# gradle
.gradle
.DS_Store
================================================
FILE: 16KB_SUPPORT.md
================================================
# 16 KB Page Size Support
This Android PDF Viewer library has been updated to support 16 KB page sizes, which is required for Google Play compatibility starting November 1st, 2025.
## What Changed
### Build Configuration Updates
1. **Android Gradle Plugin**: Already using AGP 8.13.0 (✅ above required 8.5.1)
2. **NDK Version**: Updated to use NDK r28+ for 16 KB support
3. **Packaging Options**: Configured to use uncompressed shared libraries for proper 16 KB alignment
4. **Gradle Properties**: Added configuration for 16 KB compatibility
### Key Changes Made
#### android-pdf-viewer/build.gradle
```gradle
// 16 KB page size support configuration
packagingOptions {
jniLibs {
useLegacyPackaging false // Use uncompressed shared libraries for 16 KB alignment
}
}
// Enable 16 KB page size support for native libraries
ndkVersion "28.0.12433566" // Use NDK r28+ for 16 KB support
```
#### sample/build.gradle
```gradle
packagingOptions {
// ... existing exclusions ...
// 16 KB page size support configuration
jniLibs {
useLegacyPackaging false // Use uncompressed shared libraries for 16 KB alignment
}
}
// Enable 16 KB page size support for native libraries
ndkVersion "28.0.12433566" // Use NDK r28+ for 16 KB support
```
#### gradle.properties
```properties
# 16 KB page size support
android.bundle.enableUncompressedNativeLibs=false
android.enableR8.fullMode=true
```
## Native Dependencies
This library uses `pdfium-android:1.9.0`, which contains native libraries. The configuration ensures these libraries are properly aligned for 16 KB page sizes.
## Verification
### Using the Provided Scripts
#### Linux/macOS
```bash
./check_16kb_alignment.sh sample/build/outputs/apk/debug/sample-debug.apk
```
#### Windows PowerShell
```powershell
.\check_16kb_alignment.ps1 -ApkFile "sample\build\outputs\apk\debug\sample-debug.apk"
```
#### Windows Batch Script
```batch
.\realign_apk.bat "sample\build\outputs\apk\debug\sample-debug.apk"
```
#### Python Script (Cross-platform)
```bash
python fix_16kb_alignment.py "sample/build/outputs/apk/debug/sample-debug.apk"
```
### Manual Verification
1. **Check APK alignment**:
```bash
zipalign -c -p -v 4 your-app.apk
```
2. **Test on 16 KB device**:
```bash
adb shell getconf PAGE_SIZE
# Should return 16384
```
### Fixing Alignment Issues
If your APK fails 16 KB alignment checks, use the provided realignment scripts:
1. **Copy your APK** to avoid file lock issues:
```bash
cp sample/build/outputs/apk/debug/sample-debug.apk sample-debug-copy.apk
```
2. **Run the realignment script**:
```bash
.\realign_apk.bat "sample-debug-copy.apk"
```
3. **Verify the fix**:
```bash
zipalign -c -p -v 4 sample-debug-copy.apk
```
## Testing on 16 KB Devices
### Android Emulator
1. Download Android 15 system image with 16 KB page size support
2. Create virtual device with the 16 KB system image
3. Test your app on the emulator
### Physical Devices
- Pixel 8 and 8 Pro (Android 15 QPR1+)
- Pixel 8a (Android 15 QPR1+)
- Pixel 9, 9 Pro, and 9 Pro XL (Android 15 QPR2 Beta 2+)
Enable "Boot with 16KB page size" in Developer Options.
## Benefits
Devices with 16 KB page sizes provide:
- 3.16% lower app launch times on average
- 4.56% reduction in power draw during app launch
- 4.48% faster camera launch (hot starts)
- 6.60% faster camera launch (cold starts)
- 8% improved system boot time
## Compatibility
- ✅ **AGP Version**: 8.13.0 (above required 8.5.1)
- ✅ **NDK Version**: r28+ (16 KB aligned by default)
- ✅ **Native Libraries**: Configured for 16 KB alignment
- ✅ **Packaging**: Uncompressed shared libraries for proper alignment
## Resources
- [Android 16 KB Page Size Guide](https://developer.android.com/guide/practices/page-sizes)
- [Google Play 16 KB Requirement](https://android-developers.googleblog.com/2025/05/prepare-play-apps-for-devices-with-16kb-page-size.html)
- [APK Analyzer Tool](https://developer.android.com/studio/build/analyze-apk)
## Troubleshooting
If you encounter issues:
1. **Verify NDK version**: Ensure you're using NDK r28 or higher
2. **Check AGP version**: Must be 8.5.1 or higher
3. **Run alignment check**: Use the provided scripts to verify APK alignment
4. **Test on 16 KB device**: Use emulator or physical device with 16 KB support
## Support
For issues related to 16 KB page size support, please check:
1. The alignment verification scripts
2. Android Studio's APK Analyzer
3. The official Android documentation linked above
================================================
FILE: CHANGELOG.md
================================================
## 3.2.0-beta.1 (2019-08-18)
* Merge PR #714 with optimized page load
* Merge PR #776 with fix for max & min zoom level
* Merge PR #722 with fix for showing right position when view size changed
* Merge PR #703 with fix for too many threads
* Merge PR #702 with fix for memory leak
* Merge PR #689 with possibility to disable long click
* Merge PR #628 with fix for hiding scroll handle
* Merge PR #627 with `fitEachPage` option
* Merge PR #638 and #406 with fixed NPE
* Merge PR #780 with README fix
* Update compile SDK and support library to 28
* Update Gradle and Gradle Plugin
## 3.1.0-beta.1 (2018-06-29)
* Merge pull request #557 for snapping pages (scrolling page by page)
* merge pull request #618 for night mode
* Merge pull request #566 for `OnLongTapListener`
* Update PdfiumAndroid to 1.9.0, which uses `c++_shared` instead of `gnustl_static`
* Update Gradle Plugin
* Update compile SDK and support library to 26
* Change minimum SDK to 14
## 3.0.0-beta.5 (2018-01-06)
* Fix issue with `Configurator#pages()` from #486
* Fix `IllegalStateException` from #464
* Fix not detecting links reported in #447
## 3.0.0-beta.4 (2017-12-15)
* Fix not loaded pages when using animated `PDFView#jumpTo()`
* Fix NPE in `canScrollVertically()` and `canScrollHorizontally()`
## 3.0.0-beta.3 (2017-11-18)
* Fix bug preventing `OnErrorListener` from being called
## 3.0.0-beta.2 (2017-11-15)
* Fix rendering with maximum zoom
* Improve fit policies
* Update PdfiumAndroid to 1.8.1
## 3.0.0-beta.1 (2017-11-12)
* Add support for documents with different page sizes
* Add support for links
* Add support for defining page fit policy (fit width, height or both)
* Update sample.pdf to contain different page sizes
## 2.8.1 (2017-11-11)
* Fix bug with rendering `PDFView` in Android Studio Layout Editor
## 2.8.0 (2017-10-31)
* Add handling of invalid pages, inspired by pull request #433. Exception on page opening crashed application until now,
currently `OnPageErrorListener` set with `.onPageError()` is called. Invalid page color can be set using `.invalidPageColor()`
* Implement `canScrollVertically()` and `canScrollHorizontally()` methods to work e.g. with `SwipeRefreshLayout`
* Fix bug when `Configurator#load()` method was called before view has been measured, which resulted in empty canvas
## 2.7.0 (2017-08-30)
* Merge pull request by [owurman](https://github.com/owurman) with added OnTapListener
* Merge bugfix by [lzwandnju](https://github.com/lzwandnju) to prevent `ArithmeticException: divide by zero`
## 2.7.0-beta.1 (2017-07-05)
* Updates PdfiumAndroid to 1.7.0 which reduces memory usage about twice and improves performance by using RGB 565 format (when not using `pdfView.useBestQuality(true)`)
## 2.7.0-beta (2017-06-16)
* Update PdfiumAndroid to 1.6.1, which fixed font rendering (issue #253)
* Add `.spacing(int)` method to add spacing (in dp) between document pages
* Fix drawing with `.onDraw(onDrawListener)`
* Add `.onDrawAll(onDrawListener)` method to draw on all pages
* Add small rendering improvements
* Fix rendering when duplicated pages are passed to `.pages(..)`
## 2.6.1 (2017-06-08)
* Fix disappearing scroll handle
## 2.6.0 (2017-06-04)
* Fix fling on single-page documents
* Greatly improve overall fling experience
## 2.5.1 (2017-04-08)
* Temporarily downgrade PdfiumAndroid until #253 will be fixed
## 2.5.0 (2017-03-23)
* Update PdfiumAndroid to 1.6.0, which is based on newest Pdfium from Android 7.1.1. It should fix many rendering and fonts problems
* Add method `pdfView.fitToWidth()`, which called in `OnRenderListener.onInitiallyRendered()` will fit document to width of the screen (inspired by [1stmetro](https://github.com/1stmetro))
* Add change from pull request by [isanwenyu](https://github.com/isanwenyu) to get rid of rare IllegalArgumentException while rendering
* Add `OnRenderListener`, that will be called once, right before document is drawn on the screen
* Add `Configurator.enableAntialiasing()` to improve rendering on low-res screen a little bit (as suggested by [majkimester](majkimester))
* Modify engine to not block UI when big documents are loaded
* Change `Constants` interface and inner interfaces to static public classes, to allow modifying core config values
## 2.4.0 (2016-12-30)
* Merge pull request by [hansinator85](https://github.com/hansinator85) which allows to enable/disable rendering during scale
* Make rendering during scale disabled by default (looks better)
* Merge pull request by [cesquivias](https://github.com/cesquivias) which replaces RenderingAsyncTask with Handler to simply code and work with testing frameworks
## 2.3.0 (2016-11-19)
* Add mechanism for providing documents from different sources - more info in README
* Update PdfiumAndroid to 1.5.0
* Thanks to document sources and PdfiumAndroid update, in-memory documents are supported
* Fix not working OnClickListener on PDFView
* **com.github.barteksc.exception.FileNotFoundException** is deprecated and all usages was removed.
All exceptions are delivered to old Configurator#onError() listener.
## 2.2.0 (2016-11-15)
* Merge pull request by [skarempudi](https://github.com/skarempudi) which fixes SDK 23 permission problems in sample app
* Merge pull request by skarempudi for showing info on phones without file manager
* Add feature from 1.x - canvas is set to drawable from View#getBackground()
## 2.1.0 (2016-09-16)
* fixed loading document from subfolder in assets directory
* fixed scroll handle NPE after document loading error (improvement of 2.0.3 fix)
* fixed incorrect scroll handle position with additional views in RelativeLayout
* improved cache usage and fixed bug with rendering when zooming
* if you are using custom scroll handle: scroll handle implementation changed a little bit, check DefaultScrollHandle source for details
## 2.0.3 (2016-08-30)
* Fix scroll handle NPE after document loading error
## 2.0.2 (2016-08-27)
* Fix exceptions caused by improperly finishing rendering task
## 2.0.1 (2016-08-16)
* Fix NPE when onDetachFromWindow is called
## 2.0.0 (2016-08-14)
* few API changes
* improved rendering speed and accuracy
* added continuous scroll - now it behaves like Adobe Reader and others
* added `fling` scroll gesture for velocity based scrolling
* added scroll handle as a replacement for scrollbar
### Changes in 2.0 API
* `Configurator#defaultPage(int)` and `PDFView#jumpTo(int)` now require page index (i.e. starting from 0)
* `OnPageChangeListener#onPageChanged(int, int)` is called with page index (i.e. starting from 0)
* removed scrollbar
* added scroll handle as a replacement for scrollbar, use with `Configurator#scrollHandle()`
* added `OnPageScrollListener` listener due to continuous scroll, register with `Configurator#onPageScroll()`
* default scroll direction is vertical, so `Configurator#swipeVertical()` was changed to `Configurator#swipeHorizontal()`
* removed minimap and mask configuration
## 1.4.0 (2016-07-25)
* Fix NPE and IndexOutOfBound bugs when rendering parts
* Merge pull request by [paulo-sato-daitan](https://github.com/paulo-sato-daitan) for disabling page change animation
* Merge pull request by [Miha-x64](https://github.com/Miha-x64) for drawing background if set on `PDFView`
## 1.3.0 (2016-07-13)
* update PdfiumAndroid to 1.4.0 with support for rendering annotations
* merge pull request by [usef](https://github.com/usef) for rendering annotations
## 1.2.0 (2016-07-11)
* update PdfiumAndroid to 1.3.1 with support for bookmarks, Table Of Contents and documents with password:
* added method `PDFView#getDocumentMeta()`, which returns document metadata
* added method `PDFView#getTableOfContents()`, which returns whole tree of bookmarks in PDF document
* added method `Configurator#password(String)`
* added horizontal mode to **ScrollBar** - use `ScrollBar#setHorizontal(true)` or `app:sb_horizontal="true"` in XML
* block interaction with `PDFView` when document is not loaded - prevent some exceptions
* fix `PDFView` exceptions in layout preview (edit mode)
## 1.1.2 (2016-06-27)
* update PdfiumAndroid to 1.1.0, which fixes displaying multiple `PDFView`s at the same time and few errors with loading PDF documents.
## 1.1.1 (2016-06-17)
* fixes bug with strange behavior when indices passed to `.pages()` don't start with `0`.
## 1.1.0 (2016-06-16)
* added method `pdfView.fromUri(Uri)` for opening files from content providers
* updated PdfiumAndroid to 1.0.3, which should fix bug with exception
* updated sample with demonstration of `fromUri()` method
* some minor fixes
## 1.0.0 (2016-06-06)
* Initial release
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# Change of ownership and looking for contributors!
The ownership of the project was recently changed and we are actively looking for contributors to bring the project back to track. Please [visit](https://github.com/DImuthuUpe/AndroidPdfViewer/issues/1186)
# Android PdfViewer
__AndroidPdfViewer 1.x is available on [AndroidPdfViewerV1](https://github.com/barteksc/AndroidPdfViewerV1)
repo, where can be developed independently. Version 1.x uses different engine for drawing document on canvas,
so if you don't like 2.x version, try 1.x.__
Library for displaying PDF documents on Android, with `animations`, `gestures`, `zoom` and `double tap` support.
It is based on [PdfiumAndroid](https://github.com/barteksc/PdfiumAndroid) for decoding PDF files. Works on API 11 (Android 3.0) and higher.
Licensed under Apache License 2.0.
## What's new in 3.2.0-beta.1?
* Merge PR #714 with optimized page load
* Merge PR #776 with fix for max & min zoom level
* Merge PR #722 with fix for showing right position when view size changed
* Merge PR #703 with fix for too many threads
* Merge PR #702 with fix for memory leak
* Merge PR #689 with possibility to disable long click
* Merge PR #628 with fix for hiding scroll handle
* Merge PR #627 with `fitEachPage` option
* Merge PR #638 and #406 with fixed NPE
* Merge PR #780 with README fix
* Update compile SDK and support library to 28
* Update Gradle and Gradle Plugin
* **16 KB Page Size Support**: Updated for Google Play compatibility requirement (November 1st, 2025)
## Changes in 3.0 API
* Replaced `Contants.PRELOAD_COUNT` with `PRELOAD_OFFSET`
* Removed `PDFView#fitToWidth()` (variant without arguments)
* Removed `Configurator#invalidPageColor(int)` method as invalid pages are not rendered
* Removed page size parameters from `OnRenderListener#onInitiallyRendered(int)` method, as document may have different page sizes
* Removed `PDFView#setSwipeVertical()` method
## Installation
Add to _build.gradle_:
`implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'`
or if you want to use more stable version:
`implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'`
Library is available in jcenter repository, probably it'll be in Maven Central soon.
## 16 KB Page Size Support ✅ FIXED
**✅ RESOLVED**: This library has been updated and **successfully fixed** to support 16 KB page sizes for Google Play compatibility. Starting November 1st, 2025, all new apps and updates targeting Android 15+ must support 16 KB page sizes.
### ✅ What Was Fixed:
- **Issue**: The `pdfium-android:1.9.0` dependency contained prebuilt native libraries that were not aligned for 16 KB page sizes
- **Solution**: Implemented compressed shared libraries configuration and post-build realignment scripts
- **Result**: APK now passes all 16 KB alignment checks and is Google Play compliant
### Key Updates Made:
- **AGP Version**: Using 8.13.0 (above required 8.5.1)
- **NDK Version**: Updated to r28+ for 16 KB support
- **Packaging**: Configured for compressed shared libraries to avoid alignment issues
- **Native Libraries**: All native libraries are properly aligned for 16 KB page sizes
- **Realignment Scripts**: Added automated tools to fix alignment issues
### ✅ Verification:
Use the provided scripts to verify 16 KB alignment:
- **Linux/macOS**: `./check_16kb_alignment.sh your-app.apk`
- **Windows**: `.\check_16kb_alignment.ps1 -ApkFile "your-app.apk"`
- **Fix Alignment**: `.\realign_apk.bat "your-app.apk"`
### 🎉 Google Play Compliance:
Your app will now **pass Google Play's 16 KB compatibility checks** and work on devices with 16 KB page sizes.
For more details, see [16KB_SUPPORT.md](16KB_SUPPORT.md).
## ProGuard
If you are using ProGuard, add following rule to proguard config file:
```proguard
-keep class com.shockwave.**
```
## Include PDFView in your layout
``` xml
* To fully understand this class you must know its principles : * - The PDF document is seen as if we always want to draw all the pages. * - The thing is that we only draw the visible parts. * - All parts are the same size, this is because we can't interrupt a native page rendering, * so we need these renderings to be as fast as possible, and be able to interrupt them * as soon as we can. * - The parts are loaded when the current offset or the current zoom level changes *
* Important :
* - DocumentPage = A page of the PDF document.
* - UserPage = A page as defined by the user.
* By default, they're the same. But the user can change the pages order
* using {@link #load(DocumentSource, String, int[])}. In this
* particular case, a userPage of 5 can refer to a documentPage of 17.
*/
public class PDFView extends RelativeLayout {
private static final String TAG = PDFView.class.getSimpleName();
public static final float DEFAULT_MAX_SCALE = 3.0f;
public static final float DEFAULT_MID_SCALE = 1.75f;
public static final float DEFAULT_MIN_SCALE = 1.0f;
private float minZoom = DEFAULT_MIN_SCALE;
private float midZoom = DEFAULT_MID_SCALE;
private float maxZoom = DEFAULT_MAX_SCALE;
/**
* START - scrolling in first page direction
* END - scrolling in last page direction
* NONE - not scrolling
*/
enum ScrollDir {
NONE, START, END
}
private ScrollDir scrollDir = ScrollDir.NONE;
/** Rendered parts go to the cache manager */
CacheManager cacheManager;
/** Animation manager manage all offset and zoom animation */
private AnimationManager animationManager;
/** Drag manager manage all touch events */
private DragPinchManager dragPinchManager;
PdfFile pdfFile;
/** The index of the current sequence */
private int currentPage;
/**
* If you picture all the pages side by side in their optimal width,
* and taking into account the zoom level, the current offset is the
* position of the left border of the screen in this big picture
*/
private float currentXOffset = 0;
/**
* If you picture all the pages side by side in their optimal width,
* and taking into account the zoom level, the current offset is the
* position of the left border of the screen in this big picture
*/
private float currentYOffset = 0;
/** The zoom level, always >= 1 */
private float zoom = 1f;
/** True if the PDFView has been recycled */
private boolean recycled = true;
/** Current state of the view */
private State state = State.DEFAULT;
/** Async task used during the loading phase to decode a PDF document */
private DecodingAsyncTask decodingAsyncTask;
/** The thread {@link #renderingHandler} will run on */
private HandlerThread renderingHandlerThread;
/** Handler always waiting in the background and rendering tasks */
RenderingHandler renderingHandler;
private PagesLoader pagesLoader;
Callbacks callbacks = new Callbacks();
/** Paint object for drawing */
private Paint paint;
/** Paint object for drawing debug stuff */
private Paint debugPaint;
/** Policy for fitting pages to screen */
private FitPolicy pageFitPolicy = FitPolicy.WIDTH;
private boolean fitEachPage = false;
private int defaultPage = 0;
/** True if should scroll through pages vertically instead of horizontally */
private boolean swipeVertical = true;
private boolean enableSwipe = true;
private boolean doubletapEnabled = true;
private boolean nightMode = false;
private boolean pageSnap = true;
/** Pdfium core for loading and rendering PDFs */
private PdfiumCore pdfiumCore;
private ScrollHandle scrollHandle;
private boolean isScrollHandleInit = false;
ScrollHandle getScrollHandle() {
return scrollHandle;
}
/**
* True if bitmap should use ARGB_8888 format and take more memory
* False if bitmap should be compressed by using RGB_565 format and take less memory
*/
private boolean bestQuality = false;
/**
* True if annotations should be rendered
* False otherwise
*/
private boolean annotationRendering = false;
/**
* True if the view should render during scaling
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.exception;
@Deprecated
public class FileNotFoundException extends RuntimeException {
public FileNotFoundException(String detailMessage) {
super(detailMessage);
}
public FileNotFoundException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/exception/PageRenderingException.java
================================================
package com.github.barteksc.pdfviewer.exception;
public class PageRenderingException extends Exception {
private final int page;
public PageRenderingException(int page, Throwable cause) {
super(cause);
this.page = page;
}
public int getPage() {
return page;
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/link/DefaultLinkHandler.java
================================================
/**
* Copyright 2017 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
import android.graphics.Canvas;
/**
* This interface allows an extern class to draw
* something on the PDFView canvas, above all images.
*/
public interface OnDrawListener {
/**
* This method is called when the PDFView is
* drawing its view.
*
* The page is starting at (0,0)
*
* @param canvas The canvas on which to draw things.
* @param pageWidth The width of the current page.
* @param pageHeight The height of the current page.
* @param displayedPage The current page index
*/
void onLayerDrawn(Canvas canvas, float pageWidth, float pageHeight, int displayedPage);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnErrorListener.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
public interface OnErrorListener {
/**
* Called if error occurred while opening PDF
* @param t Throwable with error
*/
void onError(Throwable t);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnLoadCompleteListener.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
/**
* Implement this interface to receive events from PDFView
* when loading is complete.
*/
public interface OnLoadCompleteListener {
/**
* Called when the PDF is loaded
* @param nbPages the number of pages in this PDF file
*/
void loadComplete(int nbPages);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnLongPressListener.java
================================================
/**
* Copyright 2017 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
import android.view.MotionEvent;
/**
* Implement this interface to receive events from PDFView
* when view has been long pressed
*/
public interface OnLongPressListener {
/**
* Called when the user has a long tap gesture, before processing scroll handle toggling
*
* @param e MotionEvent that registered as a confirmed long press
*/
void onLongPress(MotionEvent e);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnPageChangeListener.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
/**
* Implements this interface to receive events from PDFView
* when a page has changed through swipe
*/
public interface OnPageChangeListener {
/**
* Called when the user use swipe to change page
*
* @param page the new page displayed, starting from 0
* @param pageCount the total page count
*/
void onPageChanged(int page, int pageCount);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnPageErrorListener.java
================================================
/**
* Copyright 2017 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
public interface OnPageErrorListener {
/**
* Called if error occurred while loading PDF page
* @param t Throwable with error
*/
void onPageError(int page, Throwable t);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnPageScrollListener.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
/**
* Implements this interface to receive events from PDFView
* when a page has been scrolled
*/
public interface OnPageScrollListener {
/**
* Called on every move while scrolling
*
* @param page current page index
* @param positionOffset see {@link com.github.barteksc.pdfviewer.PDFView#getPositionOffset()}
*/
void onPageScrolled(int page, float positionOffset);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnRenderListener.java
================================================
/**
* Copyright 2017 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
public interface OnRenderListener {
/**
* Called only once, when document is rendered
* @param nbPages number of pages
*/
void onInitiallyRendered(int nbPages);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/listener/OnTapListener.java
================================================
/**
* Copyright 2017 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.listener;
import android.view.MotionEvent;
/**
* Implement this interface to receive events from PDFView
* when view has been touched
*/
public interface OnTapListener {
/**
* Called when the user has a tap gesture, before processing scroll handle toggling
*
* @param e MotionEvent that registered as a confirmed single tap
* @return true if the single tap was handled, false to toggle scroll handle
*/
boolean onTap(MotionEvent e);
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/model/LinkTapEvent.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.model;
import android.graphics.RectF;
import com.shockwave.pdfium.PdfDocument;
public class LinkTapEvent {
private float originalX;
private float originalY;
private float documentX;
private float documentY;
private RectF mappedLinkRect;
private PdfDocument.Link link;
public LinkTapEvent(float originalX, float originalY, float documentX, float documentY, RectF mappedLinkRect, PdfDocument.Link link) {
this.originalX = originalX;
this.originalY = originalY;
this.documentX = documentX;
this.documentY = documentY;
this.mappedLinkRect = mappedLinkRect;
this.link = link;
}
public float getOriginalX() {
return originalX;
}
public float getOriginalY() {
return originalY;
}
public float getDocumentX() {
return documentX;
}
public float getDocumentY() {
return documentY;
}
public RectF getMappedLinkRect() {
return mappedLinkRect;
}
public PdfDocument.Link getLink() {
return link;
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/model/PagePart.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.model;
import android.graphics.Bitmap;
import android.graphics.RectF;
public class PagePart {
private int page;
private Bitmap renderedBitmap;
private RectF pageRelativeBounds;
private boolean thumbnail;
private int cacheOrder;
public PagePart(int page, Bitmap renderedBitmap, RectF pageRelativeBounds, boolean thumbnail, int cacheOrder) {
super();
this.page = page;
this.renderedBitmap = renderedBitmap;
this.pageRelativeBounds = pageRelativeBounds;
this.thumbnail = thumbnail;
this.cacheOrder = cacheOrder;
}
public int getCacheOrder() {
return cacheOrder;
}
public int getPage() {
return page;
}
public Bitmap getRenderedBitmap() {
return renderedBitmap;
}
public RectF getPageRelativeBounds() {
return pageRelativeBounds;
}
public boolean isThumbnail() {
return thumbnail;
}
public void setCacheOrder(int cacheOrder) {
this.cacheOrder = cacheOrder;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PagePart)) {
return false;
}
PagePart part = (PagePart) obj;
return part.getPage() == page
&& part.getPageRelativeBounds().left == pageRelativeBounds.left
&& part.getPageRelativeBounds().right == pageRelativeBounds.right
&& part.getPageRelativeBounds().top == pageRelativeBounds.top
&& part.getPageRelativeBounds().bottom == pageRelativeBounds.bottom;
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/scroll/DefaultScrollHandle.java
================================================
package com.github.barteksc.pdfviewer.scroll;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import androidx.core.content.ContextCompat;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.R;
import com.github.barteksc.pdfviewer.util.Util;
public class DefaultScrollHandle extends RelativeLayout implements ScrollHandle {
private final static int HANDLE_LONG = 65;
private final static int HANDLE_SHORT = 40;
private final static int DEFAULT_TEXT_SIZE = 16;
private float relativeHandlerMiddle = 0f;
protected TextView textView;
protected Context context;
private boolean inverted;
private PDFView pdfView;
private float currentPos;
private Handler handler = new Handler();
private Runnable hidePageScrollerRunnable = new Runnable() {
@Override
public void run() {
hide();
}
};
public DefaultScrollHandle(Context context) {
this(context, false);
}
public DefaultScrollHandle(Context context, boolean inverted) {
super(context);
this.context = context;
this.inverted = inverted;
textView = new TextView(context);
setVisibility(INVISIBLE);
setTextColor(Color.BLACK);
setTextSize(DEFAULT_TEXT_SIZE);
}
@Override
public void setupLayout(PDFView pdfView) {
int align, width, height;
Drawable background;
// determine handler position, default is right (when scrolling vertically) or bottom (when scrolling horizontally)
if (pdfView.isSwipeVertical()) {
width = HANDLE_LONG;
height = HANDLE_SHORT;
if (inverted) { // left
align = ALIGN_PARENT_LEFT;
background = ContextCompat.getDrawable(context, R.drawable.default_scroll_handle_left);
} else { // right
align = ALIGN_PARENT_RIGHT;
background = ContextCompat.getDrawable(context, R.drawable.default_scroll_handle_right);
}
} else {
width = HANDLE_SHORT;
height = HANDLE_LONG;
if (inverted) { // top
align = ALIGN_PARENT_TOP;
background = ContextCompat.getDrawable(context, R.drawable.default_scroll_handle_top);
} else { // bottom
align = ALIGN_PARENT_BOTTOM;
background = ContextCompat.getDrawable(context, R.drawable.default_scroll_handle_bottom);
}
}
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
setBackgroundDrawable(background);
} else {
setBackground(background);
}
LayoutParams lp = new LayoutParams(Util.getDP(context, width), Util.getDP(context, height));
lp.setMargins(0, 0, 0, 0);
LayoutParams tvlp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tvlp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
addView(textView, tvlp);
lp.addRule(align);
pdfView.addView(this, lp);
this.pdfView = pdfView;
}
@Override
public void destroyLayout() {
pdfView.removeView(this);
}
@Override
public void setScroll(float position) {
if (!shown()) {
show();
} else {
handler.removeCallbacks(hidePageScrollerRunnable);
}
if (pdfView != null) {
setPosition((pdfView.isSwipeVertical() ? pdfView.getHeight() : pdfView.getWidth()) * position);
}
}
private void setPosition(float pos) {
if (Float.isInfinite(pos) || Float.isNaN(pos)) {
return;
}
float pdfViewSize;
if (pdfView.isSwipeVertical()) {
pdfViewSize = pdfView.getHeight();
} else {
pdfViewSize = pdfView.getWidth();
}
pos -= relativeHandlerMiddle;
if (pos < 0) {
pos = 0;
} else if (pos > pdfViewSize - Util.getDP(context, HANDLE_SHORT)) {
pos = pdfViewSize - Util.getDP(context, HANDLE_SHORT);
}
if (pdfView.isSwipeVertical()) {
setY(pos);
} else {
setX(pos);
}
calculateMiddle();
invalidate();
}
private void calculateMiddle() {
float pos, viewSize, pdfViewSize;
if (pdfView.isSwipeVertical()) {
pos = getY();
viewSize = getHeight();
pdfViewSize = pdfView.getHeight();
} else {
pos = getX();
viewSize = getWidth();
pdfViewSize = pdfView.getWidth();
}
relativeHandlerMiddle = ((pos + relativeHandlerMiddle) / pdfViewSize) * viewSize;
}
@Override
public void hideDelayed() {
handler.postDelayed(hidePageScrollerRunnable, 1000);
}
@Override
public void setPageNum(int pageNum) {
String text = String.valueOf(pageNum);
if (!textView.getText().equals(text)) {
textView.setText(text);
}
}
@Override
public boolean shown() {
return getVisibility() == VISIBLE;
}
@Override
public void show() {
setVisibility(VISIBLE);
}
@Override
public void hide() {
setVisibility(INVISIBLE);
}
public void setTextColor(int color) {
textView.setTextColor(color);
}
/**
* @param size text size in dp
*/
public void setTextSize(int size) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, size);
}
private boolean isPDFViewReady() {
return pdfView != null && pdfView.getPageCount() > 0 && !pdfView.documentFitsView();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isPDFViewReady()) {
return super.onTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
pdfView.stopFling();
handler.removeCallbacks(hidePageScrollerRunnable);
if (pdfView.isSwipeVertical()) {
currentPos = event.getRawY() - getY();
} else {
currentPos = event.getRawX() - getX();
}
case MotionEvent.ACTION_MOVE:
if (pdfView.isSwipeVertical()) {
setPosition(event.getRawY() - currentPos + relativeHandlerMiddle);
pdfView.setPositionOffset(relativeHandlerMiddle / (float) getHeight(), false);
} else {
setPosition(event.getRawX() - currentPos + relativeHandlerMiddle);
pdfView.setPositionOffset(relativeHandlerMiddle / (float) getWidth(), false);
}
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
hideDelayed();
pdfView.performPageSnap();
return true;
}
return super.onTouchEvent(event);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/scroll/ScrollHandle.java
================================================
package com.github.barteksc.pdfviewer.scroll;
import com.github.barteksc.pdfviewer.PDFView;
public interface ScrollHandle {
/**
* Used to move the handle, called internally by PDFView
*
* @param position current scroll ratio between 0 and 1
*/
void setScroll(float position);
/**
* Method called by PDFView after setting scroll handle.
* Do not call this method manually.
* For usage sample see {@link DefaultScrollHandle}
*
* @param pdfView PDFView instance
*/
void setupLayout(PDFView pdfView);
/**
* Method called by PDFView when handle should be removed from layout
* Do not call this method manually.
*/
void destroyLayout();
/**
* Set page number displayed on handle
*
* @param pageNum page number
*/
void setPageNum(int pageNum);
/**
* Get handle visibility
*
* @return true if handle is visible, false otherwise
*/
boolean shown();
/**
* Show handle
*/
void show();
/**
* Hide handle immediately
*/
void hide();
/**
* Hide handle after some time (defined by implementation)
*/
void hideDelayed();
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/AssetSource.java
================================================
/*
* Copyright (C) 2016 Bartosz Schiller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.source;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import com.github.barteksc.pdfviewer.util.FileUtils;
import com.shockwave.pdfium.PdfDocument;
import com.shockwave.pdfium.PdfiumCore;
import java.io.File;
import java.io.IOException;
public class AssetSource implements DocumentSource {
private final String assetName;
public AssetSource(String assetName) {
this.assetName = assetName;
}
@Override
public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
File f = FileUtils.fileFromAsset(context, assetName);
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
return core.newDocument(pfd, password);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/ByteArraySource.java
================================================
/*
* Copyright (C) 2016 Bartosz Schiller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.source;
import android.content.Context;
import com.shockwave.pdfium.PdfDocument;
import com.shockwave.pdfium.PdfiumCore;
import java.io.IOException;
public class ByteArraySource implements DocumentSource {
private byte[] data;
public ByteArraySource(byte[] data) {
this.data = data;
}
@Override
public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
return core.newDocument(data, password);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/DocumentSource.java
================================================
/*
* Copyright (C) 2016 Bartosz Schiller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.source;
import android.content.Context;
import com.shockwave.pdfium.PdfDocument;
import com.shockwave.pdfium.PdfiumCore;
import java.io.IOException;
public interface DocumentSource {
PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException;
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/FileSource.java
================================================
/*
* Copyright (C) 2016 Bartosz Schiller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.source;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import com.shockwave.pdfium.PdfDocument;
import com.shockwave.pdfium.PdfiumCore;
import java.io.File;
import java.io.IOException;
public class FileSource implements DocumentSource {
private File file;
public FileSource(File file) {
this.file = file;
}
@Override
public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
return core.newDocument(pfd, password);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/InputStreamSource.java
================================================
/*
* Copyright (C) 2016 Bartosz Schiller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.source;
import android.content.Context;
import com.github.barteksc.pdfviewer.util.Util;
import com.shockwave.pdfium.PdfDocument;
import com.shockwave.pdfium.PdfiumCore;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamSource implements DocumentSource {
private InputStream inputStream;
public InputStreamSource(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
return core.newDocument(Util.toByteArray(inputStream), password);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/source/UriSource.java
================================================
/*
* Copyright (C) 2016 Bartosz Schiller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.source;
import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import com.shockwave.pdfium.PdfDocument;
import com.shockwave.pdfium.PdfiumCore;
import java.io.IOException;
public class UriSource implements DocumentSource {
private Uri uri;
public UriSource(Uri uri) {
this.uri = uri;
}
@Override
public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
return core.newDocument(pfd, password);
}
}
================================================
FILE: android-pdf-viewer/src/main/java/com/github/barteksc/pdfviewer/util/ArrayUtils.java
================================================
/**
* Copyright 2016 Bartosz Schiller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.barteksc.pdfviewer.util;
import java.util.ArrayList;
import java.util.List;
public class ArrayUtils {
private ArrayUtils() {
// Prevents instantiation
}
/** Transforms (0,1,2,2,3) to (0,1,2,3) */
public static int[] deleteDuplicatedPages(int[] pages) {
List
* Can not be forced on older API versions (< Build.VERSION_CODES.KITKAT) as the GestureDetector does
* not detect scrolling while scaling.
* False otherwise
*/
private boolean renderDuringScale = false;
/** Antialiasing and bitmap filtering */
private boolean enableAntialiasing = true;
private PaintFlagsDrawFilter antialiasFilter =
new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
/** Spacing between pages, in px */
private int spacingPx = 0;
/** Add dynamic spacing to fit each page separately on the screen. */
private boolean autoSpacing = false;
/** Fling a single page at a time */
private boolean pageFling = true;
/** Pages numbers used when calling onDrawAllListener */
private List