rn553
)Android | iOS |
---|---|
If using yarn, do: yarn global add react-native-cli
First, follow the official getting started guide on setting up the React Native environment, setting up the iOS and Android environment, and creating a React Native project, the following steps will assume your app is created through react-native init MyApp
.
In MyApp
folder, install react-native-pdftron
by calling:
yarn add github:PDFTron/pdftron-react-native
yarn add @react-native-community/cli --dev
yarn add @react-native-community/cli-platform-android --dev
yarn add @react-native-community/cli-platform-ios --dev
yarn install
or
npm install github:PDFTron/pdftron-react-native --save
npm install @react-native-community/cli --save-dev
npm install @react-native-community/cli-platform-android --save-dev
npm install @react-native-community/cli-platform-ios --save-dev
Add the following in your android/app/build.gradle
file:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.reactnativesample"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
+ multiDexEnabled true
+ manifestPlaceholders = [pdftronLicenseKey:PDFTRON_LICENSE_KEY]
}
dependencies {
+ implementation "androidx.multidex:multidex:2.0.1"
}
...
}
Add the following to your android/build.gradle
file:
buildscript {
ext {
buildToolsVersion = "28.0.3"
+ minSdkVersion = 21
compileSdkVersion = 28
targetSdkVersion = 28
}
// ...
}
In your android/gradle.properties
file. Add the following line to it:
# Add the PDFTRON_LICENSE_KEY variable here.
# For trial purposes leave it blank.
# For production add a valid commercial license key.
PDFTRON_LICENSE_KEY=
Add the following to your android/app/src/main/AndroidManifest.xml
file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp">
<uses-permission android:name="android.permission.INTERNET" />
<!-- Required to read and write documents from device storage -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Required if you want to record audio annotations -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
...
+ android:largeHeap="true"
+ android:usesCleartextTraffic="true">
<!-- Add license key in meta-data tag here. This should be inside the application tag. -->
+ <meta-data
+ android:name="pdftron_license_key"
+ android:value="${pdftronLicenseKey}"/>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
- android:windowSoftInputMode="adjustResize"
+ android:windowSoftInputMode="adjustPan"
+ android:theme="@style/CustomAppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
In your android\app\src\main\java\com\myapp\MainApplication.java
file, change Application
to MultiDexApplication
:
- import android.app.Application;
+ import androidx.multidex.MultiDexApplication;
...
- public class MainApplication extends Application implements ReactApplication {
+ public class MainApplication extends MultiDexApplication implements ReactApplication {
Replace App.js
with what is shown here
Finally in the root project directory, run react-native run-android
.
Open Podfile
in the ios
folder, add the 3 middle lines to the target 'MyApp' do / end
block:
target 'MyApp' do
use_frameworks!
pod 'PDFNet', podspec: 'https://www.pdftron.com/downloads/ios/cocoapods/pdfnet/latest.podspec'
pod 'RNPdftron', :path => '../node_modules/react-native-pdftron'
end
and remove or comment out the Flipper section:
# use_flipper!
# post_install do |installer|
# flipper_post_install(installer)
# end
In the ios
folder, run pod install
.
(Optional) If you need a close button icon, you will need to add the PNG resources to MyApp
as well, i.e. ic_close_black_24px
.
Replace App.js
with what is shown here.
Finally in the root project directory, run react-native run-ios
.
Replace App.js
with the following:
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
PermissionsAndroid,
BackHandler,
NativeModules,
Alert
} from 'react-native';
import { DocumentView, RNPdftron } from 'react-native-pdftron';
type Props = {};
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
permissionGranted: Platform.OS === 'ios' ? true : false
};
RNPdftron.initialize("Insert commercial license key here after purchase");
RNPdftron.enableJavaScript(true);
}
componentDidMount() {
if (Platform.OS === 'android') {
this.requestStoragePermission();
}
}
async requestStoragePermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this.setState({
permissionGranted: true
});
console.log("Storage permission granted");
} else {
this.setState({
permissionGranted: false
});
console.log("Storage permission denied");
}
} catch (err) {
console.warn(err);
}
}
onLeadingNavButtonPressed = () => {
console.log('leading nav button pressed');
if (Platform.OS === 'ios') {
Alert.alert(
'App',
'onLeadingNavButtonPressed',
[
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{ cancelable: true }
)
} else {
BackHandler.exitApp();
}
}
render() {
if (!this.state.permissionGranted) {
return (
<View style={styles.container}>
<Text>
Storage permission required.
</Text>
</View>
)
}
const path = "https://pdftron.s3.amazonaws.com/downloads/pl/PDFTRON_mobile_about.pdf";
return (
<DocumentView
document={path}
showLeadingNavButton={true}
leadingNavButtonIcon={Platform.OS === 'ios' ? 'ic_close_black_24px.png' : 'ic_arrow_back_white_24dp'}
onLeadingNavButtonPressed={this.onLeadingNavButtonPressed}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
document="sample"
document="file:///storage/emulated/0/Download/sample.pdf"
document="android.resource://mypackagename/raw/sample.pdf"
document="content://..."
initialize(string)
enableJavaScript(bool)
getVersion()
Return a promise with the version of the PDFNet version used.
getPlatformVersion()
Return a promise with the version of current platform (Android/iOS).
encryptDocument(string, string, string)
This function does not lock around the document so be sure to not use it while the document is opened in the viewer.
Return a promise.
Example:
RNPdftron.encryptDocument("/sdcard/Download/new.pdf", "1111", "").then(() => {
console.log("done password");
});
Parameters:
Name | Type | Description |
---|---|---|
file path | string | the local file path to the file |
password | string | the password |
current password | string | the current password, use empty string if no password |
A component for displaying documents of different types such as PDF, docx, pptx, xlsx and various image formats.
string, required
string, optional
string, optional
function, optional
bool, optional
function, optional
function, optional
array of string, optional
array of string, optional
object, optional
bool, optional, default to false
bool, optional, default to true
string, optional
bool, optional
bool, optional, default to true
string, optional
string, optional
number, optional
number, optional
function, optional
function, optional
Perameters:
Name | Type | Description |
---|---|---|
previousPageNumber | int | the previous page number |
pageNumber | int | the current page number |
bool, optional
bool, optional
bool, optional
Whether an unhandled tap in the viewer should toggle the visibility of the top and bottom toolbars. The default value is true
. When false
, the top and bottom toolbar visibility will not be toggled and the page content will fit between the bars, if any.
bool, optional
bool, optional
bool, optional
If true, document
prop will be treated as a base64 string.
When viewing a document initialized with a base64 string (ie a memory buffer), a temporary file is created on Android, and no temporary path is created on iOS.
bool, optional, android only
If true, the viewer will add padding to take account of status bar. Default to false.
bool, optional
array of Config.Tools
string constants, optional
Defines annotation types that will not show the default annotation menu
array of Config.AnnotationMenu
string constants, optional
Defines menu items that can show when an annotation is selected.
array of Config.AnnotationMenu
string constants, optional
Defines menu items that should skip default behavior.
function, optional
Defines what happens on annotation menu press if it is passed in to overrideAnnotationMenuBehavior
Parameters:
Name | Type | Description |
---|---|---|
annotationMenu | string | One of Config.AnnotationMenu string constants |
annotations | array | An array of {id, rect} objects, where id is the annotation identifier and rect={x1, y1, x2, y2} specifies the annotation’s screen rect. |
bool, optional, default to true
If true, the viewer will show the default menu on long press.
array of Config.LongPressMenu
string constants, optional
Defines menu items that can show when long press on text or blank space.
array of Config.LongPressMenu
string constants, optional
Defines menu items that should skip default behavior.
function, optional
Defines what happens on long press menu press if it is passed in to overrideLongPressMenuBehavior
Parameters:
Name | Type | Description |
---|---|---|
longPressMenu | string | One of Config.LongPressMenu string constants |
longPressText | string | the selected text if pressed on text, empty otherwise |
array of Config.Actions
string constants, optional
Defines actions that should skip default behavior, such as external link click.
function, optional
Defines what happens on certain behavior if it is passed in to overrideBehavior
Parameters:
Name | Type | Description |
---|---|---|
action | string | One of Config.Actions string constants |
data | object | A JSON object that varies depending on the action |
data param table:
Action | Param |
---|---|
Config.Actions.linkPress |
key: url , value: the link pressed |
bool, optional, default to true
bool, optional, default to true
If true, stylus will act as a pen in pan mode, otherwise it will act as finger
bool, optional, default to false
If true, signature field will be signed with image stamp. This is useful if you are saving XFDF to remote source.
bool, optional, Android only, default to true
If true, UI will appear in dark color when System is dark mode. Otherwise it will use viewer setting instead.
bool, optional, if set to true then currentUser
must be set as well for collaboration mode to work
string, required if collabEnabled
is set to true
string, optional
function, optional, annotation command will be given on each edit
function, optional
Parameters:
Name | Type | Description |
---|---|---|
annotations | array | array of annotation data in the format {id: string, pageNumber: number, rect: {x1: number, y1: number, x2: number, y2: number}} |
function, optional
Parameters:
Name | Type | Description |
---|---|---|
action | string | the action that occurred (add, delete, modify) |
annotations | array | array of annotation data in the format {id: string, pageNumber: number} |
bool, optional, default to false
If true, annotation’s flags will be taken into account when it is selected, for example, a locked annotation can not be resized or moved.
function, optional
Parameters:
Name | Type | Description |
---|---|---|
fields | array | array of field data in the format {fieldName: string, fieldValue: string} |
function, optional
Defines what happens if a change has been made to bookmarks
Parameters:
Name | Type | Description |
---|---|---|
bookmarkJson | string | the list of current bookmarks in JSON format |
Example:
import { DocumentView, Config } from 'react-native-pdftron';
<DocumentView
ref={(c) => this._viewer = c}
document={path}
showLeadingNavButton={true}
leadingNavButtonIcon={Platform.OS === 'ios' ? 'ic_close_black_24px.png' : 'ic_arrow_back_white_24dp'}
onLeadingNavButtonPressed={() => {}}
onDocumentLoaded={() => {}}
onDocumentError={() => {}}
disabledElements={[Config.Buttons.searchButton, Config.Buttons.shareButton]}
disabledTools={[Config.Tools.annotationCreateLine, Config.Tools.annotationCreateRectangle]}
customHeaders={{Foo: bar}}
initialPageNumber={11}
readOnly={false}
annotationAuthor={'PDFTron'}
continuousAnnotationEditing={true}
fitMode={Config.FitMode.FitPage}
layoutMode={Config.LayoutMode.Continuous}
onPageChanged={({previousPageNumber, pageNumber}) => { console.log('page changed'); }}
onAnnotationChanged={({action, annotations}) => { console.log('annotations changed'); }}
annotationPermissionCheckEnabled={false}
onBookmarkChanged={({bookmarkJson}) => { console.log('bookmark changed'); }}
/>
To set the current tool mode (Config.Tools
constants).
this._viewer.setToolMode(Config.Tools.annotationCreateFreeHand);
Commits the current tool, only available for multi-stroke ink and poly-shape.
Returns a Promise.
this._viewer.commitTool().then((committed) => {
// committed: true if either ink or poly-shape tool is committed, false otherwise
});
To get the current page count of the document.
Returns a Promise.
this._viewer.getPageCount().then((pageCount) => {
console.log('pageCount', pageCount);
});
To import XFDF string to the current document.
Returns a Promise.
const xfdf = '<?xml version="1.0" encoding="UTF-8"?>\n<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">...</xfdf>';
this._viewer.importAnnotations(xfdf);
To extract XFDF from the current document.
Perameters:
Name | Type | Description |
---|---|---|
options | object | key: annotList, type: array |
Returns a Promise.
this._viewer.exportAnnotations().then((xfdf) => {
console.log('xfdf', xfdf);
});
With options:
// annotList is an array of annotation data in the format {id: string, pageNumber: int}
this._viewer.exportAnnotations({annotList: annotations}).then((xfdf) => {
console.log('xfdf for annotations', xfdf);
});
To flatten the forms and (optionally) annotations in the current document. The formsOnly
parameter controls whether only forms are flattened.
Returns a Promise.
// flatten forms and annotations in the current document.
this._viewer.flattenAnnotations(false);
To delete the specified annotations in the current document.
Returns a Promise.
// delete annotations in the current document.
this._viewer.deleteAnnotations([
{
id: 'annotId1',
pageNumber: 1,
},
{
id: 'annotId2',
pageNumber: 2,
}
]);
To save the current document.
Returns a Promise.
this._viewer.saveDocument().then((filePath) => {
console.log('saveDocument:', filePath);
});
Set a field flag value on one or more form fields.
Parameters:
Name | Type | Description |
---|---|---|
fields | array | list of field names for which the flag should be set |
flag | integer | flag to be set (see https://www.pdftron.com/api/ios/Enums/PTFieldFlag.html) |
value | bool | value to set for flag |
Returns a Promise.
this._viewer.setFlagForFields(['First Name', 'Last Name'], Config.FieldFlags.ReadOnly, true);
Set field values on one or more form fields.
Note: the old function setValueForFields
is deprecated. Please use this one.
Parameters:
Name | Type | Description |
---|---|---|
fieldsMap | object | map of field names and values which should be set |
Returns a Promise.
this._viewer.setValuesForFields({
'textField1': 'Test',
'textField2': 1234,
'checkboxField1': true,
'checkboxField2': false,
'radioButton1': 'Yes',
'radioButton2': 'No'
});
Import remote annotation command to local document.
Parameters:
Name | Type | Description |
---|---|---|
xfdfCommand | string | the XFDF command string |
initialLoad | bool | whether this is for initial load |
Returns a Promise.
Android only.
this._viewer.handleBackButton().then((handled) => {
if (!handled) {
BackHandler.exitApp();
}
});
To select the specified annotation in the current document.
Parameters:
Name | Type | Description |
---|---|---|
id | string | the id of the target annotation |
pageNumber | integer | the page number where the targe annotation is located. It is 1-indexed |
Return a Promise.
// select annotation in the current document.
this._viewer.selectAnnotation('annotId1', 1);
To set flags for specified annotations in the current document. The flagValue
controls whether a flag will be set to or removed from the annotation.
Note: the old function setFlagForAnnotations
is deprecated. Please use this one.
Parameters:
Name | Type | Description |
---|---|---|
annotationFlagList | array | A list of annotation flag operations |
Return a Promise.
// Set flag for annotations in the current document.
this._viewer.setFlagsForAnnotations([
{
id: 'annotId1',
pageNumber: 1,
flag: Config.AnnotationFlags.noView,
flagValue: true
},
{
id: 'annotId2',
pageNumber: 5,
flag: Config.AnnotationFlags.lockedContents,
flagValue: false
}
]);
To set properties for specified annotation in the current document, if it is valid.
Note: the old function setPropertyForAnnotation
is deprecated. Please use this one.
Parameters:
Name | Type | Description |
---|---|---|
annotationId | string | the unique id of the annotation |
pageNumber | integer | the page number where annotation is located. It is 1-indexed |
propertyMap | object | an object containing properties to be set. Available properties are listed below |
Properties:
Name | Type | Markup exclusive | Example |
---|---|---|---|
rect | object | no | {x1: 1, y1: 2, x2: 3, y2: 4} |
contents | string | no | “contents” |
subject | string | yes | “subject” |
title | string | yes | “title” |
contentRect | object | yes | {x1: 1, y1: 2, x2: 3, y2: 4} |
Return a promise.
// Set properties for annotation in the current document.
this._viewer.setPropertiesForAnnotation('Pdftron', 1, {
rect: {
x1: 1.1, // left
y1: 3, // bottom
x2: 100.9, // right
y2: 99.8 // top
},
contents: 'Hello World',
subject: 'Sample',
title: 'set-prop-for-annot'
});
Return a JSON object with properties for position (x1
, y1
, x2
and y2
) and size (width
and height
) of the crop box for specified page.
Parameters:
Name | Type | Description |
---|---|---|
pageNumber | integer | the page number for the target crop box. It is 1-indexed |
Return a Promise.
this._viewer.getPageCropBox(1).then((cropBox) => {
console.log('bottom-left coordinate:', cropBox.x1, cropBox.y1);
console.log('top-right coordinate:', cropBox.x2, cropBox.y2);
console.log('width and height:', cropBox.width, cropBox.height);
});
Imports user bookmarks to the document. The input needs to be a valid bookmark JSON format, for example {“0”:“Page 1”}.
Parameters:
Name | Type | Description |
---|---|---|
bookmarkJson | String | needs to be in valid bookmark JSON format, for example {“0”: “Page 1”}. The page numbers are 1-indexed |
Return a Promise.
this._viewer.importBookmarkJson("{\"0\": \"Page 1\", \"3\": \"Page 4\"}");
Set current page of the document.
Parameters:
Name | Type | Description |
---|---|---|
pageNumber | integer | the page number for the target crop box. It is 1-indexed |
Return a Promise (with a boolean that tells whether the setting process is successful).
this._viewer.setCurrentPage(4).then((success) => {
if (success) {
console.log("Current page is set to 4.");
}
});
Return the path of the current document.
Return a Promise.
this._viewer.getDocumentPath().then((path) => {
console.log('The path to current document is: ' + path);
});
See Contributing
Author: PDFTron
Demo: https://www.pdftron.com/
Source Code: https://github.com/PDFTron/pdftron-react-native
#react #react-native #mobile-apps