├── .gitignore
├── LICENSE
├── README.md
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── com
│ └── shockwave
│ └── pdfiumtest
│ └── ApplicationTest.java
└── main
├── AndroidManifest.xml
├── java
└── com
│ └── shockwave
│ └── pdfiumtest
│ ├── MainActivity.java
│ └── PdfActivity.java
└── res
├── layout
├── activity_main.xml
├── activity_pdf.xml
└── layout_pdf_page.xml
├── menu
├── menu_main.xml
└── menu_pdf.xml
├── mipmap-hdpi
└── ic_launcher.png
├── mipmap-mdpi
└── ic_launcher.png
├── mipmap-xhdpi
└── ic_launcher.png
├── mipmap-xxhdpi
└── ic_launcher.png
├── values-w820dp
└── dimens.xml
└── values
├── dimens.xml
├── strings.xml
└── styles.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 Bekket McClane
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #PdfiumAndroid Demo App
2 | Demo app for this [library](https://github.com/mshockwave/PdfiumAndroid)
3 | **Caution: Since I haven't push this demo app to Maven central, please put the library in the same project manually**
--------------------------------------------------------------------------------
/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 21
5 | buildToolsVersion "21.1.2"
6 |
7 | defaultConfig {
8 | applicationId "com.shockwave.pdfiumtest"
9 | minSdkVersion 10
10 | targetSdkVersion 21
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:22.0.0'
25 | compile project(':pdfium')
26 | }
27 |
--------------------------------------------------------------------------------
/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/mac/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/src/androidTest/java/com/shockwave/pdfiumtest/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.shockwave.pdfiumtest;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/main/java/com/shockwave/pdfiumtest/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.shockwave.pdfiumtest;
2 |
3 | import android.content.Intent;
4 | import android.net.Uri;
5 | import android.support.v7.app.ActionBarActivity;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 |
12 | import com.shockwave.pdfium.PdfDocument;
13 | import com.shockwave.pdfium.PdfiumCore;
14 |
15 | import java.io.FileInputStream;
16 | import java.io.FileNotFoundException;
17 | import java.io.IOException;
18 |
19 |
20 | public class MainActivity extends ActionBarActivity {
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_main);
26 |
27 | }
28 |
29 | public void pickFileOnClick(View v){
30 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
31 | intent.setType("file/pdf");
32 | startActivityForResult(intent, 1);
33 | }
34 | @Override
35 | public void onActivityResult(int reqCode, int result, Intent intent){
36 | if(reqCode == 1){
37 | if(result == RESULT_OK){
38 | Uri data = intent.getData();
39 | Log.i("Main", "File path: " + data.getPath());
40 |
41 | Intent pdfIntent = new Intent(this, PdfActivity.class);
42 | pdfIntent.setData(data);
43 | startActivity(pdfIntent);
44 | }
45 | }
46 | }
47 |
48 | @Override
49 | public boolean onCreateOptionsMenu(Menu menu) {
50 | // Inflate the menu; this adds items to the action bar if it is present.
51 | getMenuInflater().inflate(R.menu.menu_main, menu);
52 | return true;
53 | }
54 |
55 | @Override
56 | public boolean onOptionsItemSelected(MenuItem item) {
57 | // Handle action bar item clicks here. The action bar will
58 | // automatically handle clicks on the Home/Up button, so long
59 | // as you specify a parent activity in AndroidManifest.xml.
60 | int id = item.getItemId();
61 |
62 | //noinspection SimplifiableIfStatement
63 | if (id == R.id.action_settings) {
64 | return true;
65 | }
66 |
67 | return super.onOptionsItemSelected(item);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/shockwave/pdfiumtest/PdfActivity.java:
--------------------------------------------------------------------------------
1 | package com.shockwave.pdfiumtest;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Matrix;
5 | import android.graphics.Rect;
6 | import android.graphics.RectF;
7 | import android.net.Uri;
8 | import android.support.v7.app.ActionBarActivity;
9 | import android.os.Bundle;
10 | import android.util.Log;
11 | import android.view.GestureDetector;
12 | import android.view.MotionEvent;
13 | import android.view.ScaleGestureDetector;
14 | import android.view.SurfaceHolder;
15 | import android.view.SurfaceView;
16 |
17 | import com.shockwave.pdfium.PdfDocument;
18 | import com.shockwave.pdfium.PdfiumCore;
19 |
20 | import java.io.FileInputStream;
21 | import java.io.IOException;
22 | import java.util.concurrent.ExecutorService;
23 | import java.util.concurrent.Executors;
24 |
25 |
26 | public class PdfActivity extends ActionBarActivity {
27 | private static final String TAG = PdfActivity.class.getName();
28 |
29 | private PdfiumCore mPdfCore;
30 |
31 | private PdfDocument mPdfDoc = null;
32 | private FileInputStream mDocFileStream = null;
33 |
34 | private GestureDetector mSlidingDetector;
35 | private ScaleGestureDetector mZoomingDetector;
36 |
37 | private int mCurrentPageIndex = 0;
38 | private int mPageCount = 0;
39 |
40 | private SurfaceHolder mPdfSurfaceHolder;
41 | private boolean isSurfaceCreated = false;
42 |
43 | private final Rect mPageRect = new Rect();
44 | private final RectF mPageRectF = new RectF();
45 | private final Rect mScreenRect = new Rect();
46 | private final Matrix mTransformMatrix = new Matrix();
47 | private boolean isScaling = false;
48 | private boolean isReset = true;
49 |
50 |
51 | private final ExecutorService mPreLoadPageWorker = Executors.newSingleThreadExecutor();
52 | private final ExecutorService mRenderPageWorker = Executors.newSingleThreadExecutor();
53 | private Runnable mRenderRunnable;
54 |
55 | @Override
56 | protected void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 | setContentView(R.layout.activity_pdf);
59 |
60 | mPdfCore = new PdfiumCore(this);
61 |
62 | mSlidingDetector = new GestureDetector(this, new SlidingDetector());
63 | mZoomingDetector = new ScaleGestureDetector(this, new ZoomingDetector());
64 |
65 | Intent intent = getIntent();
66 | Uri fileUri;
67 | if( (fileUri = intent.getData()) == null){
68 | finish();
69 | return ;
70 | }
71 |
72 | mRenderRunnable = new Runnable() {
73 | @Override
74 | public void run() {
75 | loadPageIfNeed(mCurrentPageIndex);
76 |
77 | resetPageFit(mCurrentPageIndex);
78 | mPdfCore.renderPage(mPdfDoc, mPdfSurfaceHolder.getSurface(), mCurrentPageIndex,
79 | mPageRect.left, mPageRect.top,
80 | mPageRect.width(), mPageRect.height());
81 |
82 | mPreLoadPageWorker.submit(new Runnable() {
83 | @Override
84 | public void run() {
85 | loadPageIfNeed(mCurrentPageIndex + 1);
86 | loadPageIfNeed(mCurrentPageIndex + 2);
87 | }
88 | });
89 | }
90 | };
91 |
92 | SurfaceView surfaceView = (SurfaceView)findViewById(R.id.view_surface_main);
93 | surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
94 | @Override
95 | public void surfaceCreated(SurfaceHolder holder) {
96 | isSurfaceCreated = true;
97 | updateSurface(holder);
98 | if (mPdfDoc != null) {
99 | mRenderPageWorker.submit(mRenderRunnable);
100 | }
101 | }
102 |
103 | @Override
104 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
105 | Log.w(TAG, "Surface Changed");
106 | updateSurface(holder);
107 | if(mPdfDoc != null){
108 | mRenderPageWorker.submit(mRenderRunnable);
109 | }
110 | }
111 |
112 | @Override
113 | public void surfaceDestroyed(SurfaceHolder holder) {
114 | isSurfaceCreated = false;
115 | Log.w(TAG, "Surface Destroy");
116 | }
117 | });
118 |
119 | try{
120 | mDocFileStream = new FileInputStream(fileUri.getPath());
121 |
122 | mPdfDoc = mPdfCore.newDocument(mDocFileStream.getFD());
123 | Log.d("Main", "Open Document");
124 |
125 | mPageCount = mPdfCore.getPageCount(mPdfDoc);
126 | Log.d(TAG, "Page Count: " + mPageCount);
127 |
128 | }catch(IOException e){
129 | e.printStackTrace();
130 | Log.e("Main", "Data uri: " + fileUri.toString());
131 | }
132 | }
133 |
134 | private void loadPageIfNeed(final int pageIndex){
135 | if( pageIndex >= 0 && pageIndex < mPageCount && !mPdfDoc.hasPage(pageIndex) ){
136 | Log.d(TAG, "Load page: " + pageIndex);
137 | mPdfCore.openPage(mPdfDoc, pageIndex);
138 | }
139 | }
140 |
141 | private void updateSurface(SurfaceHolder holder){
142 | mPdfSurfaceHolder = holder;
143 | mScreenRect.set(holder.getSurfaceFrame());
144 | }
145 |
146 | private void resetPageFit(int pageIndex){
147 | float pageWidth = mPdfCore.getPageWidth(mPdfDoc, pageIndex);
148 | float pageHeight = mPdfCore.getPageHeight(mPdfDoc, pageIndex);
149 | float screenWidth = mPdfSurfaceHolder.getSurfaceFrame().width();
150 | float screenHeight = mPdfSurfaceHolder.getSurfaceFrame().height();
151 |
152 | /**Portrait**/
153 | if(screenWidth < screenHeight){
154 | if( (pageWidth / pageHeight) < (screenWidth / screenHeight) ){
155 | //Situation one: fit height
156 | pageWidth *= (screenHeight / pageHeight);
157 | pageHeight = screenHeight;
158 |
159 | mPageRect.top = 0;
160 | mPageRect.left = (int)(screenWidth - pageWidth) / 2;
161 | mPageRect.right = (int)(mPageRect.left + pageWidth);
162 | mPageRect.bottom = (int)pageHeight;
163 | }else{
164 | //Situation two: fit width
165 | pageHeight *= (screenWidth / pageWidth);
166 | pageWidth = screenWidth;
167 |
168 | mPageRect.left = 0;
169 | mPageRect.top = (int)(screenHeight - pageHeight) / 2;
170 | mPageRect.bottom = (int)(mPageRect.top + pageHeight);
171 | mPageRect.right = (int)pageWidth;
172 | }
173 | }else{
174 |
175 | /**Landscape**/
176 | if( pageWidth > pageHeight ){
177 | //Situation one: fit height
178 | pageWidth *= (screenHeight / pageHeight);
179 | pageHeight = screenHeight;
180 |
181 | mPageRect.top = 0;
182 | mPageRect.left = (int)(screenWidth - pageWidth) / 2;
183 | mPageRect.right = (int)(mPageRect.left + pageWidth);
184 | mPageRect.bottom = (int)pageHeight;
185 | }else{
186 | //Situation two: fit width
187 | pageHeight *= (screenWidth / pageWidth);
188 | pageWidth = screenWidth;
189 |
190 | mPageRect.left = 0;
191 | mPageRect.top = 0;
192 | mPageRect.bottom = (int)(mPageRect.top + pageHeight);
193 | mPageRect.right = (int)pageWidth;
194 | }
195 | }
196 |
197 | isReset = true;
198 | }
199 |
200 | private void rectF2Rect(RectF inRectF, Rect outRect){
201 | outRect.left = (int)inRectF.left;
202 | outRect.right = (int)inRectF.right;
203 | outRect.top = (int)inRectF.top;
204 | outRect.bottom = (int)inRectF.bottom;
205 | }
206 |
207 | @Override
208 | public boolean onTouchEvent(MotionEvent event){
209 | boolean ret;
210 |
211 | ret = mZoomingDetector.onTouchEvent(event);
212 | if(!isScaling) ret |= mSlidingDetector.onTouchEvent(event);
213 | ret |= super.onTouchEvent(event);
214 |
215 | return ret;
216 | }
217 |
218 | private class SlidingDetector extends GestureDetector.SimpleOnGestureListener {
219 |
220 | private boolean checkFlippable(){
221 | return ( mPageRect.left >= mScreenRect.left &&
222 | mPageRect.right <= mScreenRect.right );
223 | }
224 |
225 | @Override
226 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
227 | if(!isSurfaceCreated) return false;
228 | Log.d(TAG, "Drag");
229 |
230 | distanceX *= -1f;
231 | distanceY *= -1f;
232 |
233 | if( (mPageRect.left <= mScreenRect.left && mPageRect.right <= mScreenRect.right && distanceX < 0) ||
234 | (mPageRect.right >= mScreenRect.right && mPageRect.left >= mScreenRect.left && distanceX > 0) )
235 | distanceX = 0f;
236 | if( (mPageRect.top <= mScreenRect.top && mPageRect.bottom <= mScreenRect.bottom && distanceY < 0) ||
237 | (mPageRect.bottom >= mScreenRect.bottom && mPageRect.top >= mScreenRect.top && distanceY > 0) )
238 | distanceY = 0f;
239 |
240 | //Portrait restriction
241 | if(isReset && mScreenRect.width() < mScreenRect.height()) distanceX = distanceY = 0f;
242 | if(isReset && mScreenRect.height() <= mScreenRect.width()) distanceX = 0f;
243 |
244 | if(distanceX == 0f && distanceY == 0f) return false;
245 |
246 | Log.d(TAG, "DistanceX: " + distanceX);
247 | Log.d(TAG, "DistanceY: " + distanceY);
248 | mPageRect.left += distanceX;
249 | mPageRect.right += distanceX;
250 | mPageRect.top += distanceY;
251 | mPageRect.bottom += distanceY;
252 |
253 | mPdfCore.renderPage(mPdfDoc, mPdfSurfaceHolder.getSurface(), mCurrentPageIndex,
254 | mPageRect.left, mPageRect.top,
255 | mPageRect.width(), mPageRect.height());
256 |
257 | return true;
258 | }
259 |
260 | @Override
261 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
262 | if(!isSurfaceCreated) return false;
263 | if(velocityX == 0f) return false;
264 |
265 | if(!checkFlippable()){
266 | Log.d(TAG, "Not flippable");
267 | return false;
268 | }
269 |
270 | if(velocityX < -200f){ //Forward
271 | if(mCurrentPageIndex < mPageCount - 1){
272 | Log.d(TAG, "Flip forward");
273 | mCurrentPageIndex++;
274 | Log.d(TAG, "Next Index: " + mCurrentPageIndex);
275 |
276 | mRenderPageWorker.submit(mRenderRunnable);
277 | }
278 | return true;
279 | }
280 |
281 | if(velocityX > 200f){ //Backward
282 | Log.d(TAG, "Flip backward");
283 | if(mCurrentPageIndex > 0){
284 | mCurrentPageIndex--;
285 | Log.d(TAG, "Next Index: " + mCurrentPageIndex);
286 |
287 | mRenderPageWorker.submit(mRenderRunnable);
288 | }
289 | return true;
290 | }
291 |
292 | return false;
293 | }
294 | }
295 | private class ZoomingDetector extends ScaleGestureDetector.SimpleOnScaleGestureListener {
296 | private float mAccumulateScale = 1f;
297 |
298 | @Override
299 | public boolean onScaleBegin(ScaleGestureDetector detector){
300 | isScaling = true;
301 | return true;
302 | }
303 |
304 | @Override
305 | public boolean onScale(ScaleGestureDetector detector){
306 | if(!isSurfaceCreated) return false;
307 |
308 |
309 | mAccumulateScale *= detector.getScaleFactor();
310 | mAccumulateScale = Math.max(1f, mAccumulateScale);
311 | float scaleValue = (mAccumulateScale > 1f)? detector.getScaleFactor() : 1f;
312 | mTransformMatrix.setScale(scaleValue, scaleValue,
313 | detector.getFocusX(), detector.getFocusY());
314 | mPageRectF.set(mPageRect);
315 |
316 | mTransformMatrix.mapRect(mPageRectF);
317 |
318 | rectF2Rect(mPageRectF, mPageRect);
319 |
320 | mPdfCore.renderPage(mPdfDoc, mPdfSurfaceHolder.getSurface(), mCurrentPageIndex,
321 | mPageRect.left, mPageRect.top,
322 | mPageRect.width(), mPageRect.height());
323 |
324 | isReset = false;
325 |
326 | return true;
327 | }
328 |
329 | @Override
330 | public void onScaleEnd(ScaleGestureDetector detector){
331 | if(mAccumulateScale == 1f && !mScreenRect.contains(mPageRect)){
332 | resetPageFit(mCurrentPageIndex);
333 |
334 | mPdfCore.renderPage(mPdfDoc, mPdfSurfaceHolder.getSurface(), mCurrentPageIndex,
335 | mPageRect.left, mPageRect.top,
336 | mPageRect.width(), mPageRect.height());
337 | }
338 |
339 | isScaling = false;
340 | }
341 | }
342 |
343 | @Override
344 | public void onDestroy(){
345 | try{
346 | if(mPdfDoc != null && mDocFileStream != null){
347 | mPdfCore.closeDocument(mPdfDoc);
348 | Log.d("Main", "Close Document");
349 |
350 | mDocFileStream.close();
351 | }
352 | }catch(IOException e){
353 | e.printStackTrace();
354 | }finally{
355 | super.onDestroy();
356 | }
357 | }
358 | }
359 |
--------------------------------------------------------------------------------
/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/res/layout/activity_pdf.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/res/layout/layout_pdf_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/main/res/menu/menu_pdf.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mshockwave/PdfiumAndroid-Demo-App/54d3dd0e965a38b33032b99349d85d1cf5641815/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mshockwave/PdfiumAndroid-Demo-App/54d3dd0e965a38b33032b99349d85d1cf5641815/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mshockwave/PdfiumAndroid-Demo-App/54d3dd0e965a38b33032b99349d85d1cf5641815/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mshockwave/PdfiumAndroid-Demo-App/54d3dd0e965a38b33032b99349d85d1cf5641815/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PdfiumTest
3 |
4 | Hello world!
5 | Settings
6 | PdfActivity
7 |
8 |
--------------------------------------------------------------------------------
/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------