react-native-pdf-jsi 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -29,13 +29,24 @@ Starting November 1, 2025, Google Play will require apps to support 16KB page si
|
|
|
29
29
|
| **`react-native-pdf-jsi`** | ✅ Fully Supported | ✅ Compliant | ✅ None |
|
|
30
30
|
|
|
31
31
|
### **Technical Implementation:**
|
|
32
|
-
- ✅ **NDK
|
|
32
|
+
- ✅ **NDK r28+** - Latest Android development requirements
|
|
33
33
|
- ✅ **16KB Page Size Support** - Fully compliant with Google policy
|
|
34
34
|
- ✅ **Android 15+ Ready** - Future-proof architecture
|
|
35
35
|
- ✅ **Google Play Approved** - Meets all current and future requirements
|
|
36
36
|
- ✅ **Drop-in Replacement** - Easy migration from existing libraries
|
|
37
37
|
|
|
38
|
-
## 🎉 Version 2.
|
|
38
|
+
## 🎉 Version 2.2.1 - Production Ready with Real-World Fixes!
|
|
39
|
+
|
|
40
|
+
**Includes all the fixes from the GitHub community - tested and verified in production apps!**
|
|
41
|
+
|
|
42
|
+
### 🚀 **What's New in v2.2.1:**
|
|
43
|
+
- **✅ Community Verified Fixes** - Includes all solutions from GitHub issue #970
|
|
44
|
+
- **✅ NDK r28 Support** - Latest Android development toolchain (28.0.12674087)
|
|
45
|
+
- **✅ Android SDK 35** - Full support for Android 15+
|
|
46
|
+
- **✅ Enhanced 16KB Compliance** - Improved page size alignment with linker flags
|
|
47
|
+
- **✅ Production Tested** - Verified working in real Android Studio APK analyzer
|
|
48
|
+
|
|
49
|
+
## 🎉 Version 2.2.0 - Enhanced 16KB Compliance & Documentation!
|
|
39
50
|
|
|
40
51
|
**We've completely rewritten the core architecture with revolutionary performance improvements!**
|
|
41
52
|
|
|
@@ -148,17 +159,25 @@ yarn add react-native-pdf-jsi react-native-blob-util
|
|
|
148
159
|
## 🚀 **Quick Start**
|
|
149
160
|
|
|
150
161
|
```jsx
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
// Import the Pdf component from react-native-pdf-jsi
|
|
163
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
164
|
+
const Pdf = PdfModule.default;
|
|
165
|
+
|
|
166
|
+
// Use the component with the same API as react-native-pdf
|
|
167
|
+
<Pdf
|
|
168
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
169
|
+
style={{ flex: 1 }}
|
|
170
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
171
|
+
console.log(`PDF loaded: ${numberOfPages} pages`);
|
|
172
|
+
}}
|
|
173
|
+
onPageChanged={(page, numberOfPages) => {
|
|
174
|
+
console.log(`Current page: ${page} of ${numberOfPages}`);
|
|
175
|
+
}}
|
|
176
|
+
trustAllCerts={false}
|
|
177
|
+
/>
|
|
159
178
|
```
|
|
160
179
|
|
|
161
|
-
**
|
|
180
|
+
**Drop-in replacement for react-native-pdf with enhanced performance and Google Play compliance.**
|
|
162
181
|
|
|
163
182
|
Then follow the instructions for your platform to link react-native-pdf-jsi into your project:
|
|
164
183
|
|
|
@@ -275,127 +294,285 @@ protected List<ReactPackage> getPackages() {
|
|
|
275
294
|
|
|
276
295
|
### Basic Usage
|
|
277
296
|
|
|
278
|
-
```
|
|
279
|
-
import React from 'react';
|
|
280
|
-
import { StyleSheet, Dimensions, View } from 'react-native';
|
|
281
|
-
import Pdf from 'react-native-pdf-enhanced';
|
|
297
|
+
```jsx
|
|
298
|
+
import React, { useState } from 'react';
|
|
299
|
+
import { StyleSheet, Dimensions, View, Modal, TouchableOpacity, Text } from 'react-native';
|
|
282
300
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
//const source = require('./test.pdf'); // ios only
|
|
287
|
-
//const source = {uri:'bundle-assets://test.pdf' };
|
|
288
|
-
//const source = {uri:'file:///sdcard/test.pdf'};
|
|
289
|
-
//const source = {uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."};
|
|
290
|
-
//const source = {uri:"content://com.example.blobs/xxxxxxxx-...?offset=0&size=xxx"};
|
|
291
|
-
//const source = {uri:"blob:xxxxxxxx-...?offset=0&size=xxx"};
|
|
301
|
+
// Import the Pdf component from react-native-pdf-jsi
|
|
302
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
303
|
+
const Pdf = PdfModule.default;
|
|
292
304
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
</
|
|
311
|
-
|
|
312
|
-
|
|
305
|
+
export default function PDFExample() {
|
|
306
|
+
const [visible, setVisible] = useState(false);
|
|
307
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
308
|
+
const [totalPages, setTotalPages] = useState(0);
|
|
309
|
+
|
|
310
|
+
const source = {
|
|
311
|
+
uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf',
|
|
312
|
+
cache: true
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
return (
|
|
316
|
+
<View style={styles.container}>
|
|
317
|
+
<TouchableOpacity
|
|
318
|
+
style={styles.button}
|
|
319
|
+
onPress={() => setVisible(true)}
|
|
320
|
+
>
|
|
321
|
+
<Text style={styles.buttonText}>Open PDF</Text>
|
|
322
|
+
</TouchableOpacity>
|
|
323
|
+
|
|
324
|
+
<Modal
|
|
325
|
+
visible={visible}
|
|
326
|
+
animationType="slide"
|
|
327
|
+
onRequestClose={() => setVisible(false)}
|
|
328
|
+
>
|
|
329
|
+
<View style={styles.modalContainer}>
|
|
330
|
+
<View style={styles.header}>
|
|
331
|
+
<Text style={styles.pageInfo}>
|
|
332
|
+
Page {currentPage} of {totalPages}
|
|
333
|
+
</Text>
|
|
334
|
+
<TouchableOpacity
|
|
335
|
+
style={styles.closeButton}
|
|
336
|
+
onPress={() => setVisible(false)}
|
|
337
|
+
>
|
|
338
|
+
<Text style={styles.closeButtonText}>Close</Text>
|
|
339
|
+
</TouchableOpacity>
|
|
340
|
+
</View>
|
|
341
|
+
|
|
342
|
+
<Pdf
|
|
343
|
+
source={source}
|
|
344
|
+
style={styles.pdf}
|
|
345
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
346
|
+
console.log(`📄 PDF loaded: ${numberOfPages} pages`);
|
|
347
|
+
setTotalPages(numberOfPages);
|
|
348
|
+
}}
|
|
349
|
+
onPageChanged={(page, numberOfPages) => {
|
|
350
|
+
console.log(`📄 Current page: ${page}`);
|
|
351
|
+
setCurrentPage(page);
|
|
352
|
+
}}
|
|
353
|
+
onError={(error) => {
|
|
354
|
+
console.error('📄 PDF Error:', error);
|
|
355
|
+
}}
|
|
356
|
+
trustAllCerts={false}
|
|
357
|
+
/>
|
|
358
|
+
</View>
|
|
359
|
+
</Modal>
|
|
360
|
+
</View>
|
|
361
|
+
);
|
|
313
362
|
}
|
|
314
363
|
|
|
315
364
|
const styles = StyleSheet.create({
|
|
316
365
|
container: {
|
|
317
366
|
flex: 1,
|
|
318
|
-
justifyContent: '
|
|
367
|
+
justifyContent: 'center',
|
|
319
368
|
alignItems: 'center',
|
|
320
|
-
|
|
369
|
+
padding: 20,
|
|
370
|
+
},
|
|
371
|
+
button: {
|
|
372
|
+
backgroundColor: '#007AFF',
|
|
373
|
+
paddingHorizontal: 20,
|
|
374
|
+
paddingVertical: 10,
|
|
375
|
+
borderRadius: 8,
|
|
376
|
+
},
|
|
377
|
+
buttonText: {
|
|
378
|
+
color: 'white',
|
|
379
|
+
fontSize: 16,
|
|
380
|
+
fontWeight: 'bold',
|
|
381
|
+
},
|
|
382
|
+
modalContainer: {
|
|
383
|
+
flex: 1,
|
|
384
|
+
backgroundColor: '#fff',
|
|
385
|
+
},
|
|
386
|
+
header: {
|
|
387
|
+
flexDirection: 'row',
|
|
388
|
+
justifyContent: 'space-between',
|
|
389
|
+
alignItems: 'center',
|
|
390
|
+
padding: 15,
|
|
391
|
+
backgroundColor: '#f5f5f5',
|
|
392
|
+
borderBottomWidth: 1,
|
|
393
|
+
borderBottomColor: '#ddd',
|
|
394
|
+
},
|
|
395
|
+
pageInfo: {
|
|
396
|
+
fontSize: 16,
|
|
397
|
+
fontWeight: 'bold',
|
|
398
|
+
},
|
|
399
|
+
closeButton: {
|
|
400
|
+
backgroundColor: '#FF3B30',
|
|
401
|
+
paddingHorizontal: 15,
|
|
402
|
+
paddingVertical: 8,
|
|
403
|
+
borderRadius: 6,
|
|
404
|
+
},
|
|
405
|
+
closeButtonText: {
|
|
406
|
+
color: 'white',
|
|
407
|
+
fontSize: 14,
|
|
408
|
+
fontWeight: 'bold',
|
|
321
409
|
},
|
|
322
410
|
pdf: {
|
|
323
|
-
flex:1,
|
|
324
|
-
width:Dimensions.get('window').width,
|
|
325
|
-
height:Dimensions.get('window').height,
|
|
411
|
+
flex: 1,
|
|
412
|
+
width: Dimensions.get('window').width,
|
|
413
|
+
height: Dimensions.get('window').height - 100,
|
|
326
414
|
}
|
|
327
415
|
});
|
|
328
416
|
```
|
|
329
417
|
|
|
330
418
|
### 🚀 JSI Enhanced Usage
|
|
331
419
|
|
|
332
|
-
####
|
|
333
|
-
```
|
|
334
|
-
import React from 'react';
|
|
335
|
-
import { View } from 'react-native';
|
|
336
|
-
import { EnhancedPdfView } from 'react-native-pdf-enhanced';
|
|
420
|
+
#### Real-World JSI Integration Pattern
|
|
421
|
+
```jsx
|
|
422
|
+
import React, { useState, useEffect } from 'react';
|
|
423
|
+
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
337
424
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
425
|
+
// Import JSI modules with proper error handling
|
|
426
|
+
let PDFJSI = null;
|
|
427
|
+
let usePDFJSI = null;
|
|
428
|
+
|
|
429
|
+
try {
|
|
430
|
+
// Import JSI functionality with dynamic imports for release mode compatibility
|
|
431
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
432
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
433
|
+
|
|
434
|
+
PDFJSI = PDFJSIModule.default;
|
|
435
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
436
|
+
|
|
437
|
+
console.log(`🔍 PDFJSI found: ${PDFJSI ? '✅' : '❌'} (type: ${typeof PDFJSI})`);
|
|
438
|
+
console.log(`🔍 usePDFJSI found: ${usePDFJSI ? '✅' : '❌'} (type: ${typeof usePDFJSI})`);
|
|
439
|
+
|
|
440
|
+
} catch (error) {
|
|
441
|
+
console.log('📱 JSI: PDFJSI not available, using fallback - Error:', error.message);
|
|
350
442
|
}
|
|
351
|
-
```
|
|
352
443
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
444
|
+
// Create fallback functions for release builds
|
|
445
|
+
if (!PDFJSI || !usePDFJSI) {
|
|
446
|
+
console.log('🛡️ Creating JSI fallback functions for stability');
|
|
447
|
+
|
|
448
|
+
PDFJSI = {
|
|
449
|
+
checkJSIAvailability: async () => false,
|
|
450
|
+
getJSIStats: async () => ({ jsiEnabled: false }),
|
|
451
|
+
// ... other fallback methods
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
usePDFJSI = (options) => ({
|
|
455
|
+
isJSIAvailable: false,
|
|
456
|
+
isInitialized: true,
|
|
457
|
+
renderPage: () => Promise.resolve({ success: false, error: 'JSI not available' }),
|
|
458
|
+
// ... other fallback methods
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export default function EnhancedPDFExample() {
|
|
463
|
+
const [isJSIAvailable, setIsJSIAvailable] = useState(false);
|
|
464
|
+
const [jsiStats, setJsiStats] = useState(null);
|
|
465
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
466
|
+
|
|
467
|
+
// 🚀 JSI Hook Integration with Fallback
|
|
468
|
+
const jsiHookResult = usePDFJSI({
|
|
367
469
|
autoInitialize: true,
|
|
368
|
-
enablePerformanceTracking: true
|
|
470
|
+
enablePerformanceTracking: true,
|
|
471
|
+
enableCaching: true,
|
|
472
|
+
maxCacheSize: 200,
|
|
369
473
|
});
|
|
370
474
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const result = await renderPage('pdf_123', 1, 2.0, 'base64data');
|
|
375
|
-
console.log('🚀 JSI Render result:', result);
|
|
376
|
-
|
|
377
|
-
// Preload pages for faster access
|
|
378
|
-
const preloadSuccess = await preloadPages('pdf_123', 1, 5);
|
|
379
|
-
console.log('🚀 Preload success:', preloadSuccess);
|
|
475
|
+
useEffect(() => {
|
|
476
|
+
initializeJSI();
|
|
477
|
+
}, []);
|
|
380
478
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
479
|
+
const initializeJSI = async () => {
|
|
480
|
+
try {
|
|
481
|
+
if (PDFJSI && typeof PDFJSI.checkJSIAvailability === 'function') {
|
|
482
|
+
const isAvailable = await PDFJSI.checkJSIAvailability();
|
|
483
|
+
setIsJSIAvailable(isAvailable);
|
|
484
|
+
|
|
485
|
+
if (isAvailable) {
|
|
486
|
+
const stats = await PDFJSI.getJSIStats();
|
|
487
|
+
setJsiStats(stats);
|
|
488
|
+
console.log('🚀 JSI Stats:', stats);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
} catch (error) {
|
|
492
|
+
console.log('📱 JSI initialization failed:', error);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
384
495
|
|
|
496
|
+
const handleJSIOperations = async () => {
|
|
497
|
+
try {
|
|
498
|
+
if (jsiHookResult.isJSIAvailable) {
|
|
499
|
+
// High-performance page rendering
|
|
500
|
+
const result = await jsiHookResult.renderPage('pdf_123', 1, 2.0, 'base64data');
|
|
501
|
+
console.log('🚀 JSI Render result:', result);
|
|
502
|
+
|
|
503
|
+
// Preload pages for faster access
|
|
504
|
+
const preloadSuccess = await jsiHookResult.preloadPages('pdf_123', 1, 5);
|
|
505
|
+
console.log('🚀 Preload success:', preloadSuccess);
|
|
506
|
+
|
|
507
|
+
// Get performance metrics
|
|
508
|
+
const metrics = await jsiHookResult.getPerformanceMetrics('pdf_123');
|
|
509
|
+
console.log('🚀 Performance metrics:', metrics);
|
|
510
|
+
} else {
|
|
511
|
+
console.log('📱 JSI not available, using standard methods');
|
|
512
|
+
}
|
|
385
513
|
} catch (error) {
|
|
386
514
|
console.log('JSI operations failed:', error);
|
|
387
515
|
}
|
|
388
516
|
};
|
|
389
517
|
|
|
390
518
|
return (
|
|
391
|
-
<View style={
|
|
392
|
-
<
|
|
393
|
-
|
|
519
|
+
<View style={styles.container}>
|
|
520
|
+
<View style={styles.statusContainer}>
|
|
521
|
+
<Text style={styles.statusText}>
|
|
522
|
+
JSI Status: {isJSIAvailable ? '✅ Available' : '❌ Not Available'}
|
|
523
|
+
</Text>
|
|
524
|
+
{jsiStats && (
|
|
525
|
+
<Text style={styles.statsText}>
|
|
526
|
+
Performance Level: {jsiStats.performanceLevel}
|
|
527
|
+
</Text>
|
|
528
|
+
)}
|
|
529
|
+
</View>
|
|
530
|
+
|
|
531
|
+
<TouchableOpacity
|
|
532
|
+
style={styles.button}
|
|
394
533
|
onPress={handleJSIOperations}
|
|
395
|
-
|
|
534
|
+
>
|
|
535
|
+
<Text style={styles.buttonText}>
|
|
536
|
+
Test JSI Operations
|
|
537
|
+
</Text>
|
|
538
|
+
</TouchableOpacity>
|
|
396
539
|
</View>
|
|
397
540
|
);
|
|
398
541
|
}
|
|
542
|
+
|
|
543
|
+
const styles = StyleSheet.create({
|
|
544
|
+
container: {
|
|
545
|
+
flex: 1,
|
|
546
|
+
padding: 20,
|
|
547
|
+
justifyContent: 'center',
|
|
548
|
+
},
|
|
549
|
+
statusContainer: {
|
|
550
|
+
backgroundColor: '#f5f5f5',
|
|
551
|
+
padding: 15,
|
|
552
|
+
borderRadius: 8,
|
|
553
|
+
marginBottom: 20,
|
|
554
|
+
},
|
|
555
|
+
statusText: {
|
|
556
|
+
fontSize: 16,
|
|
557
|
+
fontWeight: 'bold',
|
|
558
|
+
marginBottom: 5,
|
|
559
|
+
},
|
|
560
|
+
statsText: {
|
|
561
|
+
fontSize: 14,
|
|
562
|
+
color: '#666',
|
|
563
|
+
},
|
|
564
|
+
button: {
|
|
565
|
+
backgroundColor: '#007AFF',
|
|
566
|
+
padding: 15,
|
|
567
|
+
borderRadius: 8,
|
|
568
|
+
alignItems: 'center',
|
|
569
|
+
},
|
|
570
|
+
buttonText: {
|
|
571
|
+
color: 'white',
|
|
572
|
+
fontSize: 16,
|
|
573
|
+
fontWeight: 'bold',
|
|
574
|
+
},
|
|
575
|
+
});
|
|
399
576
|
```
|
|
400
577
|
|
|
401
578
|
#### Advanced JSI Operations
|
|
@@ -466,6 +643,125 @@ export default function AdvancedJSIExample() {
|
|
|
466
643
|
}
|
|
467
644
|
```
|
|
468
645
|
|
|
646
|
+
## 🛡️ **ProGuard Configuration (Required for Production)**
|
|
647
|
+
|
|
648
|
+
**IMPORTANT**: For production builds, you MUST add ProGuard rules to prevent obfuscation of JSI classes. Without these rules, your app will crash in release mode.
|
|
649
|
+
|
|
650
|
+
### **Add to `android/app/proguard-rules.pro`:**
|
|
651
|
+
|
|
652
|
+
```proguard
|
|
653
|
+
# Add project specific ProGuard rules here.
|
|
654
|
+
# By default, the flags in this file are appended to flags specified
|
|
655
|
+
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
|
656
|
+
# You can edit the include path and order by changing the proguardFiles
|
|
657
|
+
# directive in build.gradle.
|
|
658
|
+
#
|
|
659
|
+
# For more details, see
|
|
660
|
+
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
661
|
+
|
|
662
|
+
# Add any project specific keep options here:
|
|
663
|
+
|
|
664
|
+
# 🚀 JSI Module ProGuard Rules - Prevent obfuscation of JSI classes
|
|
665
|
+
# react-native-pdf-jsi package classes
|
|
666
|
+
-keep class org.wonday.pdf.PDFJSIManager { *; }
|
|
667
|
+
-keep class org.wonday.pdf.PDFJSIModule { *; }
|
|
668
|
+
-keep class org.wonday.pdf.EnhancedPdfJSIBridge { *; }
|
|
669
|
+
-keep class org.wonday.pdf.RNPDFPackage { *; }
|
|
670
|
+
-keep class org.wonday.pdf.PdfManager { *; }
|
|
671
|
+
-keep class org.wonday.pdf.PDFNativeCacheManager { *; }
|
|
672
|
+
-keep class org.wonday.pdf.PdfView { *; }
|
|
673
|
+
-keep class org.wonday.pdf.events.TopChangeEvent { *; }
|
|
674
|
+
|
|
675
|
+
# Keep all JSI native methods
|
|
676
|
+
-keepclasseswithmembernames class * {
|
|
677
|
+
native <methods>;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
# Keep JSI bridge methods
|
|
681
|
+
-keepclassmembers class * {
|
|
682
|
+
@com.facebook.react.bridge.ReactMethod <methods>;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
# Keep React Native bridge classes
|
|
686
|
+
-keep class com.facebook.react.bridge.** { *; }
|
|
687
|
+
-keep class com.facebook.react.turbomodule.** { *; }
|
|
688
|
+
|
|
689
|
+
# Keep native library loading
|
|
690
|
+
-keep class com.facebook.soloader.** { *; }
|
|
691
|
+
|
|
692
|
+
# Keep JSI related classes
|
|
693
|
+
-keep class com.facebook.jni.** { *; }
|
|
694
|
+
|
|
695
|
+
# Prevent obfuscation of PDF JSI native methods
|
|
696
|
+
-keepclassmembers class org.wonday.pdf.PDFJSIManager {
|
|
697
|
+
native void nativeInitializeJSI(java.lang.Object);
|
|
698
|
+
native boolean nativeIsJSIAvailable();
|
|
699
|
+
native com.facebook.react.bridge.WritableMap nativeRenderPageDirect(java.lang.String, int, float, java.lang.String);
|
|
700
|
+
native com.facebook.react.bridge.WritableMap nativeGetPageMetrics(java.lang.String, int);
|
|
701
|
+
native boolean nativePreloadPagesDirect(java.lang.String, int, int);
|
|
702
|
+
native com.facebook.react.bridge.WritableMap nativeGetCacheMetrics(java.lang.String);
|
|
703
|
+
native boolean nativeClearCacheDirect(java.lang.String, java.lang.String);
|
|
704
|
+
native boolean nativeOptimizeMemory(java.lang.String);
|
|
705
|
+
native com.facebook.react.bridge.ReadableArray nativeSearchTextDirect(java.lang.String, java.lang.String, int, int);
|
|
706
|
+
native com.facebook.react.bridge.WritableMap nativeGetPerformanceMetrics(java.lang.String);
|
|
707
|
+
native boolean nativeSetRenderQuality(java.lang.String, int);
|
|
708
|
+
native void nativeCleanupJSI();
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
# Keep all PDF related classes
|
|
712
|
+
-keep class org.wonday.pdf.** { *; }
|
|
713
|
+
|
|
714
|
+
# Keep React Native modules
|
|
715
|
+
-keep class * extends com.facebook.react.bridge.ReactContextBaseJavaModule { *; }
|
|
716
|
+
-keep class * extends com.facebook.react.ReactPackage { *; }
|
|
717
|
+
|
|
718
|
+
# Keep native library names
|
|
719
|
+
-keepnames class * {
|
|
720
|
+
native <methods>;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
# Keep crypto-js classes (dependency of react-native-pdf-jsi)
|
|
724
|
+
-keep class com.google.crypto.** { *; }
|
|
725
|
+
-keep class javax.crypto.** { *; }
|
|
726
|
+
|
|
727
|
+
# Keep JSI specific classes and methods
|
|
728
|
+
-keepclassmembers class org.wonday.pdf.** {
|
|
729
|
+
public <methods>;
|
|
730
|
+
protected <methods>;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
# Keep all event classes
|
|
734
|
+
-keep class org.wonday.pdf.events.** { *; }
|
|
735
|
+
|
|
736
|
+
# Keep React Native JSI specific classes
|
|
737
|
+
-keep class com.facebook.jsi.** { *; }
|
|
738
|
+
-keep class com.facebook.hermes.** { *; }
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### **Why These Rules Are Essential:**
|
|
742
|
+
|
|
743
|
+
1. **JSI Class Protection**: Prevents ProGuard from obfuscating JSI-related classes
|
|
744
|
+
2. **Native Method Preservation**: Keeps native method signatures intact
|
|
745
|
+
3. **Bridge Method Safety**: Protects React Native bridge methods
|
|
746
|
+
4. **Event System**: Maintains event handling functionality
|
|
747
|
+
5. **Crypto Dependencies**: Preserves cryptographic functionality
|
|
748
|
+
|
|
749
|
+
### **Build Configuration:**
|
|
750
|
+
|
|
751
|
+
Make sure your `android/app/build.gradle` has ProGuard enabled:
|
|
752
|
+
|
|
753
|
+
```gradle
|
|
754
|
+
android {
|
|
755
|
+
buildTypes {
|
|
756
|
+
release {
|
|
757
|
+
minifyEnabled true
|
|
758
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
759
|
+
// ... other release config
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
```
|
|
764
|
+
|
|
469
765
|
## 🚨 Expo Support
|
|
470
766
|
|
|
471
767
|
This package is not available in the [Expo Go](https://expo.dev/client) app. Learn how you can use this package in [Custom Dev Clients](https://docs.expo.dev/development/getting-started/) via the out-of-tree [Expo Config Plugin](https://github.com/expo/config-plugins/tree/master/packages/react-native-pdf). Example: [`with-pdf`](https://github.com/expo/examples/tree/master/with-pdf).
|
|
@@ -526,27 +822,130 @@ react-native run-ios
|
|
|
526
822
|
|
|
527
823
|
**Q6. How do I enable JSI mode?**
|
|
528
824
|
A6: JSI mode is automatically enabled on Android. Check JSI availability with:
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
|
|
825
|
+
```jsx
|
|
826
|
+
// Import JSI modules
|
|
827
|
+
let PDFJSI = null;
|
|
828
|
+
try {
|
|
829
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
830
|
+
PDFJSI = PDFJSIModule.default;
|
|
831
|
+
} catch (error) {
|
|
832
|
+
console.log('JSI not available');
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Check availability
|
|
836
|
+
const isAvailable = await PDFJSI?.checkJSIAvailability();
|
|
837
|
+
console.log('JSI Available:', isAvailable);
|
|
532
838
|
```
|
|
533
839
|
|
|
534
840
|
**Q7. What if JSI is not available?**
|
|
535
|
-
A7: The package automatically falls back to standard bridge mode.
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
841
|
+
A7: The package automatically falls back to standard bridge mode. Always implement fallbacks:
|
|
842
|
+
```jsx
|
|
843
|
+
// Import with fallback
|
|
844
|
+
let PDFJSI = null;
|
|
845
|
+
let usePDFJSI = null;
|
|
846
|
+
|
|
847
|
+
try {
|
|
848
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
849
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
850
|
+
|
|
851
|
+
PDFJSI = PDFJSIModule.default;
|
|
852
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
853
|
+
} catch (error) {
|
|
854
|
+
console.log('JSI not available, using fallback');
|
|
543
855
|
}
|
|
856
|
+
|
|
857
|
+
// Use with fallback
|
|
858
|
+
const jsiHookResult = usePDFJSI ? usePDFJSI({
|
|
859
|
+
autoInitialize: true,
|
|
860
|
+
enablePerformanceTracking: true,
|
|
861
|
+
}) : { isJSIAvailable: false, isInitialized: true };
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
**Q8. My app crashes in release mode with JSI errors**
|
|
865
|
+
A8: You need to add ProGuard rules. Add the complete ProGuard configuration from the documentation to your `android/app/proguard-rules.pro` file.
|
|
866
|
+
|
|
867
|
+
**Q9. How do I migrate from react-native-pdf?**
|
|
868
|
+
A9: Follow the migration steps in the documentation:
|
|
869
|
+
1. Update package: `npm install react-native-pdf-jsi`
|
|
870
|
+
2. Update imports: Use `require('react-native-pdf-jsi')`
|
|
871
|
+
3. Add ProGuard rules
|
|
872
|
+
4. Update component usage (same API)
|
|
873
|
+
5. Optionally add JSI integration
|
|
874
|
+
|
|
875
|
+
**Q10. The shimmer loader gets stuck and documents don't load**
|
|
876
|
+
A10: This usually means JSI initialization is failing. Ensure:
|
|
877
|
+
- ProGuard rules are properly configured
|
|
878
|
+
- JSI modules are imported correctly with error handling
|
|
879
|
+
- Fallback mechanisms are in place
|
|
880
|
+
- Check console logs for JSI availability status
|
|
881
|
+
|
|
882
|
+
**Q11. TypeError: constructor is not callable**
|
|
883
|
+
A11: This error occurs when the Pdf component is not imported correctly. Use:
|
|
884
|
+
```jsx
|
|
885
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
886
|
+
const Pdf = PdfModule.default;
|
|
887
|
+
// NOT: const Pdf = require('react-native-pdf-jsi');
|
|
544
888
|
```
|
|
545
889
|
</details>
|
|
546
890
|
|
|
547
891
|
## 📝 Changelog
|
|
548
892
|
|
|
549
|
-
### v2.
|
|
893
|
+
### v2.2.1 (2025) - Latest ✅ PRODUCTION READY WITH REAL-WORLD FIXES
|
|
894
|
+
|
|
895
|
+
#### 🚀 **Community Verified Solutions**
|
|
896
|
+
- **GitHub Issue #970 Fixes**: Integrated all solutions from @IsengardZA's successful resolution
|
|
897
|
+
- **Production Testing**: Verified working in Android Studio APK analyzer by real users
|
|
898
|
+
- **NDK r28 Support**: Confirmed compatibility with latest Android development toolchain
|
|
899
|
+
- **Dependency Updates**: All required dependency versions tested and working
|
|
900
|
+
- **16KB Compliance**: Full Google Play policy compliance verified in production apps
|
|
901
|
+
|
|
902
|
+
#### 📊 **Real-World Validation**
|
|
903
|
+
- **APK Analyzer Compatible**: Confirmed working in Android Studio's APK analyzer
|
|
904
|
+
- **Build System Verified**: All build configurations tested in production environments
|
|
905
|
+
- **Release Build Ready**: Verified compatibility with both debug and release builds
|
|
906
|
+
- **Community Approved**: Solutions tested and confirmed by multiple developers
|
|
907
|
+
|
|
908
|
+
### v2.2.0 (2025) - ✅ ENHANCED 16KB COMPLIANCE & DOCUMENTATION
|
|
909
|
+
|
|
910
|
+
#### 🚀 **16KB Page Alignment Enhancements**
|
|
911
|
+
- **Dependency Updates**: Updated `io.legere:pdfiumandroid` from v1.0.24 to v1.0.32 for optimal 16KB support
|
|
912
|
+
- **Gson Update**: Updated `com.google.code.gson:gson` from v2.8.5 to v2.11.0 for compatibility
|
|
913
|
+
- **Build Configuration**: Updated `compileSdkVersion` and `targetSdkVersion` from 34 to 35 for Android 15+ compatibility
|
|
914
|
+
- **CMakeLists Enhancement**: Added missing executable linker flag `-Wl,-z,max-page-size=16384` for complete 16KB page alignment
|
|
915
|
+
- **Dependency Management**: Added exclusion for bundled PdfiumAndroid to prevent conflicts with specific version
|
|
916
|
+
|
|
917
|
+
#### 📚 **Documentation Overhaul**
|
|
918
|
+
- **README Rewrite**: Complete rewrite of README with real-world usage examples from production projects
|
|
919
|
+
- **Import Patterns**: Updated all examples to show correct import patterns using `require('react-native-pdf-jsi')`
|
|
920
|
+
- **Error Handling**: Added comprehensive error handling and fallback mechanisms in all examples
|
|
921
|
+
- **Modal Implementation**: Added complete modal-based PDF viewer example matching production usage
|
|
922
|
+
- **JSI Integration**: Updated JSI usage examples with proper initialization and error handling patterns
|
|
923
|
+
|
|
924
|
+
#### 🛡️ **Production Safety & ProGuard**
|
|
925
|
+
- **ProGuard Rules**: Added comprehensive ProGuard configuration documentation with complete rule set
|
|
926
|
+
- **Release Build Safety**: Added critical warnings about ProGuard rules preventing production crashes
|
|
927
|
+
- **JSI Class Protection**: Documented all necessary ProGuard rules for JSI class preservation
|
|
928
|
+
- **Native Method Safety**: Added rules for preserving native method signatures and React Native bridge methods
|
|
929
|
+
|
|
930
|
+
#### 📖 **Migration & FAQ Enhancement**
|
|
931
|
+
- **Step-by-Step Migration**: Complete migration guide from react-native-pdf with 5 clear steps
|
|
932
|
+
- **Common Issues**: Added solutions for shimmer loader stuck, constructor errors, and JSI initialization failures
|
|
933
|
+
- **Production Troubleshooting**: Added FAQ entries for release build crashes and ProGuard configuration
|
|
934
|
+
- **Error Solutions**: Documented solutions for "TypeError: constructor is not callable" and other common errors
|
|
935
|
+
|
|
936
|
+
#### ⚡ **Performance & Reliability**
|
|
937
|
+
- **JSI Fallback Patterns**: Enhanced JSI integration with robust fallback mechanisms for production stability
|
|
938
|
+
- **Error Handling**: Added comprehensive try-catch patterns for JSI module loading
|
|
939
|
+
- **Release Build Compatibility**: Ensured compatibility with both debug and release builds
|
|
940
|
+
- **Memory Management**: Enhanced memory optimization patterns for large PDF files
|
|
941
|
+
|
|
942
|
+
#### 📊 **Google Play Compliance**
|
|
943
|
+
- **16KB Verification**: Complete implementation of Google Play 16KB page size requirements
|
|
944
|
+
- **Android 15+ Ready**: Full compatibility with Android 15+ requirements
|
|
945
|
+
- **Future-Proof**: Ensures long-term compatibility with Google Play policy changes
|
|
946
|
+
- **Compliance Testing**: Added verification methods for 16KB page size support
|
|
947
|
+
|
|
948
|
+
### v2.0.1 (2025) - ✅ GOOGLE PLAY COMPLIANT
|
|
550
949
|
- 🚨 **Google Play 16KB Compliance**: Added full support for Google Play's 16KB page size requirement
|
|
551
950
|
- 🔧 **NDK r27+ Support**: Updated to NDK version 27.0.12077973 for Android 15+ compatibility
|
|
552
951
|
- 📱 **16KB Page Size Check**: Added `check16KBSupport()` method to verify compliance
|
|
@@ -602,67 +1001,189 @@ if (stats.jsiEnabled) {
|
|
|
602
1001
|
|
|
603
1002
|
## 🔄 Migration from react-native-pdf
|
|
604
1003
|
|
|
605
|
-
|
|
606
|
-
// Old import
|
|
607
|
-
import Pdf from 'react-native-pdf';
|
|
1004
|
+
### **Step 1: Update Package**
|
|
608
1005
|
|
|
609
|
-
|
|
610
|
-
|
|
1006
|
+
```bash
|
|
1007
|
+
# Remove old package
|
|
1008
|
+
npm uninstall react-native-pdf
|
|
611
1009
|
|
|
612
|
-
|
|
613
|
-
|
|
1010
|
+
# Install new package
|
|
1011
|
+
npm install react-native-pdf-jsi react-native-blob-util
|
|
614
1012
|
```
|
|
615
1013
|
|
|
616
|
-
|
|
1014
|
+
### **Step 2: Update Imports**
|
|
617
1015
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
import Pdf from 'react-native-pdf-enhanced';
|
|
1016
|
+
```jsx
|
|
1017
|
+
// ❌ Old import
|
|
1018
|
+
import Pdf from 'react-native-pdf';
|
|
622
1019
|
|
|
623
|
-
//
|
|
624
|
-
|
|
1020
|
+
// ✅ New import
|
|
1021
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
1022
|
+
const Pdf = PdfModule.default;
|
|
1023
|
+
```
|
|
625
1024
|
|
|
626
|
-
|
|
627
|
-
import { usePDFJSI } from 'react-native-pdf-enhanced';
|
|
1025
|
+
### **Step 3: Add ProGuard Rules**
|
|
628
1026
|
|
|
629
|
-
|
|
630
|
-
|
|
1027
|
+
Add the ProGuard rules from the section above to your `android/app/proguard-rules.pro`.
|
|
1028
|
+
|
|
1029
|
+
### **Step 4: Update Component Usage**
|
|
1030
|
+
|
|
1031
|
+
```jsx
|
|
1032
|
+
// ❌ Old usage
|
|
1033
|
+
<Pdf
|
|
1034
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
1035
|
+
/>
|
|
1036
|
+
|
|
1037
|
+
// ✅ New usage (same API, enhanced performance)
|
|
1038
|
+
<Pdf
|
|
1039
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
1040
|
+
style={{ flex: 1 }}
|
|
1041
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
1042
|
+
console.log(`📄 PDF loaded: ${numberOfPages} pages`);
|
|
1043
|
+
}}
|
|
1044
|
+
onPageChanged={(page, numberOfPages) => {
|
|
1045
|
+
console.log(`📄 Current page: ${page}`);
|
|
1046
|
+
}}
|
|
1047
|
+
trustAllCerts={false}
|
|
1048
|
+
/>
|
|
631
1049
|
```
|
|
632
1050
|
|
|
633
|
-
###
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
1051
|
+
### **Step 5: Add JSI Integration (Optional)**
|
|
1052
|
+
|
|
1053
|
+
For enhanced performance, add JSI integration:
|
|
1054
|
+
|
|
1055
|
+
```jsx
|
|
1056
|
+
// Import JSI modules with error handling
|
|
1057
|
+
let PDFJSI = null;
|
|
1058
|
+
let usePDFJSI = null;
|
|
1059
|
+
|
|
1060
|
+
try {
|
|
1061
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
1062
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
1063
|
+
|
|
1064
|
+
PDFJSI = PDFJSIModule.default;
|
|
1065
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
1066
|
+
} catch (error) {
|
|
1067
|
+
console.log('JSI not available, using fallback');
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
// Use JSI hook
|
|
1071
|
+
const jsiHookResult = usePDFJSI ? usePDFJSI({
|
|
1072
|
+
autoInitialize: true,
|
|
1073
|
+
enablePerformanceTracking: true,
|
|
1074
|
+
}) : { isJSIAvailable: false };
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
### **Migration Benefits:**
|
|
1078
|
+
|
|
1079
|
+
- ✅ **Same API**: No code changes required for basic usage
|
|
1080
|
+
- ✅ **Enhanced Performance**: Up to 80x faster on Android
|
|
1081
|
+
- ✅ **Google Play Compliant**: 16KB page size support
|
|
1082
|
+
- ✅ **Future-Proof**: Built with latest NDK and modern toolchain
|
|
1083
|
+
- ✅ **Better Caching**: Advanced persistent cache system
|
|
1084
|
+
|
|
1085
|
+
## 📦 Available Exports
|
|
1086
|
+
|
|
1087
|
+
### **Core Components**
|
|
1088
|
+
```jsx
|
|
1089
|
+
// Standard PDF component (enhanced with JSI)
|
|
1090
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
1091
|
+
const Pdf = PdfModule.default;
|
|
1092
|
+
|
|
1093
|
+
// Usage
|
|
1094
|
+
<Pdf
|
|
1095
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
1096
|
+
style={{ flex: 1 }}
|
|
1097
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
1098
|
+
console.log(`📄 PDF loaded: ${numberOfPages} pages`);
|
|
1099
|
+
}}
|
|
1100
|
+
trustAllCerts={false}
|
|
1101
|
+
/>
|
|
1102
|
+
```
|
|
654
1103
|
|
|
655
|
-
|
|
656
|
-
|
|
1104
|
+
### **JSI Modules (Advanced Usage)**
|
|
1105
|
+
```jsx
|
|
1106
|
+
// Import JSI functionality with error handling
|
|
1107
|
+
let PDFJSI = null;
|
|
1108
|
+
let usePDFJSI = null;
|
|
1109
|
+
|
|
1110
|
+
try {
|
|
1111
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
1112
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
1113
|
+
|
|
1114
|
+
PDFJSI = PDFJSIModule.default;
|
|
1115
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
console.log('JSI not available, using fallback');
|
|
1118
|
+
}
|
|
657
1119
|
|
|
658
|
-
//
|
|
659
|
-
const
|
|
1120
|
+
// Use JSI hook for enhanced operations
|
|
1121
|
+
const jsiHookResult = usePDFJSI ? usePDFJSI({
|
|
1122
|
+
autoInitialize: true,
|
|
1123
|
+
enablePerformanceTracking: true,
|
|
1124
|
+
enableCaching: true,
|
|
1125
|
+
maxCacheSize: 200,
|
|
1126
|
+
}) : {
|
|
1127
|
+
isJSIAvailable: false,
|
|
1128
|
+
isInitialized: true
|
|
1129
|
+
};
|
|
1130
|
+
```
|
|
660
1131
|
|
|
661
|
-
|
|
662
|
-
|
|
1132
|
+
### **JSI Methods Available**
|
|
1133
|
+
```jsx
|
|
1134
|
+
// When JSI is available, these methods provide enhanced performance:
|
|
1135
|
+
const methods = {
|
|
1136
|
+
// High-performance page rendering
|
|
1137
|
+
renderPage: (pdfId, pageNumber, scale, base64Data) => Promise,
|
|
1138
|
+
|
|
1139
|
+
// Get page metrics
|
|
1140
|
+
getPageMetrics: (pdfId, pageNumber) => Promise,
|
|
1141
|
+
|
|
1142
|
+
// Preload pages for faster access
|
|
1143
|
+
preloadPages: (pdfId, startPage, endPage) => Promise,
|
|
1144
|
+
|
|
1145
|
+
// Cache management
|
|
1146
|
+
getCacheMetrics: (pdfId) => Promise,
|
|
1147
|
+
clearCache: (pdfId, cacheType) => Promise,
|
|
1148
|
+
|
|
1149
|
+
// Memory optimization
|
|
1150
|
+
optimizeMemory: (pdfId) => Promise,
|
|
1151
|
+
|
|
1152
|
+
// Text search
|
|
1153
|
+
searchText: (pdfId, query, startPage, endPage) => Promise,
|
|
1154
|
+
|
|
1155
|
+
// Performance monitoring
|
|
1156
|
+
getPerformanceMetrics: (pdfId) => Promise,
|
|
1157
|
+
|
|
1158
|
+
// Render quality control
|
|
1159
|
+
setRenderQuality: (pdfId, quality) => Promise,
|
|
1160
|
+
|
|
1161
|
+
// JSI availability check
|
|
1162
|
+
checkJSIAvailability: () => Promise,
|
|
1163
|
+
|
|
1164
|
+
// Get JSI statistics
|
|
1165
|
+
getJSIStats: () => Promise
|
|
1166
|
+
};
|
|
1167
|
+
```
|
|
663
1168
|
|
|
664
|
-
|
|
665
|
-
|
|
1169
|
+
### **Error Handling Pattern**
|
|
1170
|
+
```jsx
|
|
1171
|
+
// Always wrap JSI operations in try-catch with fallbacks
|
|
1172
|
+
const handleJSIOperation = async () => {
|
|
1173
|
+
try {
|
|
1174
|
+
if (PDFJSI && jsiHookResult.isJSIAvailable) {
|
|
1175
|
+
// Use JSI for enhanced performance
|
|
1176
|
+
const result = await PDFJSI.renderPageDirect('pdf_123', 1, 2.0, 'base64data');
|
|
1177
|
+
console.log('🚀 JSI operation successful:', result);
|
|
1178
|
+
} else {
|
|
1179
|
+
// Fallback to standard methods
|
|
1180
|
+
console.log('📱 Using standard PDF methods');
|
|
1181
|
+
}
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
console.log('❌ Operation failed:', error);
|
|
1184
|
+
// Handle error gracefully
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
666
1187
|
```
|
|
667
1188
|
|
|
668
1189
|
### Check Google Play 16KB Compliance
|
|
@@ -937,7 +1458,7 @@ For issues and questions:
|
|
|
937
1458
|
|
|
938
1459
|
*Transform your PDF viewing experience with enterprise-grade performance and reliability.*
|
|
939
1460
|
|
|
940
|
-
**
|
|
1461
|
+
**v2.2.1 - Production Ready with Real-World Fixes**
|
|
941
1462
|
**Copyright (c) 2025-present, Punith M (punithm300@gmail.com). Enhanced PDF JSI Integration. All rights reserved.**
|
|
942
1463
|
|
|
943
1464
|
*Original work Copyright (c) 2017-present, Wonday (@wonday.org). All rights reserved.*
|
package/android/build.gradle
CHANGED
|
@@ -93,14 +93,15 @@ android {
|
|
|
93
93
|
if (agpVersion.tokenize('.')[0].toInteger() >= 7) {
|
|
94
94
|
namespace "org.wonday.pdf"
|
|
95
95
|
}
|
|
96
|
-
compileSdkVersion safeExtGet('compileSdkVersion',
|
|
96
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
97
97
|
|
|
98
98
|
// 🚀 NDK Configuration for 16KB Page Size Support
|
|
99
|
-
|
|
99
|
+
// Use NDK r28 which provides proper 16KB page alignment toolchain
|
|
100
|
+
ndkVersion "28.0.12674087"
|
|
100
101
|
|
|
101
102
|
defaultConfig {
|
|
102
103
|
minSdkVersion safeExtGet('minSdkVersion', 21)
|
|
103
|
-
targetSdkVersion safeExtGet('targetSdkVersion',
|
|
104
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
104
105
|
buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString())
|
|
105
106
|
|
|
106
107
|
// 🚀 JSI Configuration with 16KB Page Support
|
|
@@ -69,6 +69,10 @@ target_compile_options(
|
|
|
69
69
|
-fvisibility=hidden
|
|
70
70
|
)
|
|
71
71
|
|
|
72
|
+
# 16KB page size alignment for shared objects
|
|
73
|
+
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
|
74
|
+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
|
75
|
+
|
|
72
76
|
# Set output directory
|
|
73
77
|
set_target_properties(
|
|
74
78
|
pdfjsi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-pdf-jsi",
|
|
3
|
-
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"summary": "High-performance React Native PDF viewer with JSI acceleration - up to 80x faster than traditional bridge",
|
|
5
5
|
"description": "🚀 Ultra-fast React Native PDF viewer with JSI (JavaScript Interface) integration for maximum performance. Features lazy loading, smart caching, progressive loading, and zero-bridge overhead operations. Perfect for large PDF files with 30-day persistent cache and advanced memory optimization. Google Play 16KB page size compliant for Android 15+. Supports iOS, Android, and Windows platforms.",
|
|
6
6
|
"main": "index.js",
|