1. Home
  2. Foxit PDF SDK for Android
  3. Developer Guide for Foxit PDF SDK for Android

Developer Guide for Foxit PDF SDK for Android

Introduction to Foxit PDF SDK

Foxit PDF SDK provides high-performance libraries to help any software developer add robust PDF functionality to their enterprise, mobile and cloud applications across all platforms (includes Windows, Mac, Linux, Web, Android, iOS, and UWP), using the most popular development languages and environments.

Application developers who use Foxit PDF SDK can leverage Foxit’s powerful, standard compliant PDF technology to securely display, create, edit, annotate, format, organize, print, share, secure, search documents as well as to fill PDF forms. Additionally, Foxit PDF SDK includes a built-in, embeddable PDF Viewer, making the development process easier and faster. For more detailed information, please visit the website https://developers.foxitsoftware.com/pdfsdk/. In this guide, we focus on the introduction of Foxit PDF SDK for Android platform.

Foxit PDF SDK for Android

Have you ever worried about the complexity of the PDF specification? Or have you ever felt lost when asked to build a full-featured PDF app within a limited time-frame? If your answer is “Yes”, then congratulations! You have just found the best solution in the industry for rapidly integrating PDF functionality into your apps.

Foxit PDF SDK for Android focuses on helping developers easily integrate powerful Foxit PDF technology into their own mobile apps. With this SDK, even developers with a limited knowledge of PDF can quickly build a professional PDF viewer with just a few lines of code on Android platform.

Why Foxit PDF SDK for Android is your choice

Foxit is an Amazon-invested leading software provider of solutions for reading, editing, creating, organizing, and securing PDF documents. Foxit PDF SDK libraries have been used in many of today’s leading apps, and they are proven, robust, and battle-tested to provide the quality, performance, and features that the industry’s largest apps demand.

Foxit PDF SDK for Android provides quick PDF viewing and manipulation support for Android Devices.Customers choose it for the following reasons:

  • Easy to integrate
    Developers can seamlessly integrate Foxit PDF SDK for Android into their own apps with just a few lines of code.
  • Perfectly designed
    Foxit PDF SDK for Android is designed with a simple, clean, and friendly style, which provides the best user experience.
  • Flexible customization
    Foxit PDF SDK for Android provides the source code for the user interface which lets the developers have full control of the functionality and appearance of their apps.
  • Robust performance on mobile platforms
    Foxit PDF SDK for Android provides an OOM (out-of-memory) recovery mechanism to ensure the app has high robust performance when running the app on a mobile device which offers limited memory.
  • Powered by Foxit’s high fidelity rendering PDF engine
    The core technology of Foxit PDF SDK for Android is based on Foxit’s PDF engine, which is trusted by a large number of the world’s largest and well-known companies. Foxit’s powerful engine makes the app fast on parsing, rendering, and makes document viewing consistent on a variety of devices.
  • Premium World-side Support
    Foxit offers premium support for its developer products because when you are developing mission critical products you need the best support. Foxit has one of the PDF industry’s largest team of support engineers. Updates are released on a regular basis to improve user experience by adding new features and enhancements.

Main Frame of Foxit PDF SDK for Android

Foxit PDF SDK for Android consists of three elements as shown in the following picture. This structure is shared between all mobile platform versions of Foxit PDF SDK, which makes it easier to integrate and support multiple mobile operating systems and frameworks in your apps.

The three elements for Foxit PDF SDK for Android

  • PDF Core API
    The PDF Core API is the heart of this SDK and is built on Foxit’s powerful underlying technology. It provides the functionality for basic PDF operation features, and is utilized by the PDF View Control 0.and UI Extensions Component, which ensures the apps can achieve high performance and efficiency. The Core API can be used independently for document rendering, analysis, text extraction, text search, form filling, digital signatures, Pressure Sensitive Ink, certificate and password security,
    annotation creation and manipulation and much more.
  • PDF View Control
    The PDF View Control is a utility class that provides the functionality for developers to interact with rendering PDF documents per their requirements. With Foxit’s renowned and widely used PDF rendering technology at its core, the View Control provides fast and high quality rendering, zooming, scrolling and page navigation features. The View Control derives from platform related viewer classes (e.g. Android.View.ViewGroup on Android) and allows for extension to accommodate specific user needs.
  • UI Extensions Component
    The UI Extensions Component is an open source library that provides a customizable user interface with built-in support for text selection, markup annotation, outline navigation, reading bookmarks, full-text searching, form filling, text reflow, attachment, digital/handwritten signature, reflow, document editing and password encryption. These features in the UI Extensions Component are implemented using the PDF Core API and PDF View Control. Developers can utilize these ready-to-use UI implementations to build a PDF viewer quickly with the added benefit of complete flexibility and control to customize the UI design as desired.

From version 4.0, Foxit PDF SDK for Android makes a big change and optimization for the UI Extensions Component. Now, it wraps the basic UI implementations to PDFReader class, such as panel controller, toolbar settings, and alert view, etc. Building a full-featured PDF Reader is getting simpler and easier. Furthermore, users can flexibly customize the features they want through a configuration file.

From version 5.0, every element in the built-in UI can be configurable through an API. Foxit PDF SDK for Android provides more advanced APIs in PDFReader class for developers to further customize the UI elements, such as adding/removing a button to/from the toolbar, showing/hiding a specific menu/function panel, and etc.

From version 6.0, Foxit PDF SDK for Android removed the PDFReader class and moved the wrapped APIs in PDFReader class to UI Extensions Component.

UI Extensions Component Overview

The UI Extensions Component uses “module” mechanism which refines each feature into a module. All of the modules except LocalModule (used for file management) will be loaded by default if you add UIExtension. Users can customize module through implementing Module interface class, and then call UIExtensionsManager#registerModule to register the custom module to current UIExtensions manager. When not in use, you can call UIExtensionsManager#unregisterModule to unregister it from current UIExtensions manager.

UIExtensionsManager contains the main-frame UI, such as top/bottom bar, and other UI components which are shared between each module. Meanwhile, through UIExtensionsManager, each feature module can also be loaded separately. And when loaded, the feature module will adapt and adjust the main-frame UI, as well as establish the connection of message event response. Each feature module may contain its module-specific UI components, and have its self-contained message event handling logic. UIExtensionsManager will also be responsible for distributing messages and events received from View Control component to each feature module. The following figure shows the detailed relationship between UIExtensionsManager and modules.

The relationship between UIExtensionsManager and modules

Tool handler and annotation handler will process the events from touch screen or gestures of PDFViewCtrl. When the touch screen and gestures occur, PDFViewCtrl will send the corresponding events to UIExtensionsManager:

  1. If a tool handler exists currently, UIExtensionsManager will send the corresponding events to the current tool handler, and then event-handing process ends.
  2. If an annotation is selected currently, UIExtensionsManager will send the corresponding events to the annotation handler corresponding to the currently selected annotation, and then event-handing process ends.
  3. If currently no tool handler exists and no annotation is selected, UIExtensionsManager will send the corresponding events to selection tool handler. Text Selection tool is used for processing the related events for text selection. For example, select a piece of text, and add Highlight annotation. Blank Selection tool is used for processing the related events for blank space. For example, add a Note annotation on the blank space.
  4. Note: Tool Handler and Annotation Handler will not respond the events at the same time. Tool Handler is primarily used for annotation creation (currently, the creation of link annotation is not supported), signature creation and text selection. Annotation Handler is mainly used for annotation editing and form filling. The following figure shows the event response flow chart between Tool Handler and Annotation Handler.

    The event response flow chart between Tool Handler and Annotation Handler

    Key Features of Foxit PDF SDK for Android

    Foxit PDF SDK for Android has several main features which help app developers quickly implement the functions that they really need and reduce the development cost.

    Features

    PDF Document: Open and close files, set and get metadata.

    PDF Page: Parse, render, read, and edit PDF pages.

    Render: Graphics engine created on a bitmap for platform graphics device.

    Reflow: Rearrange page content.

    Crop: Crop PDF pages for better reading.

    Text Select: Select text in a PDF document.

    Text Search: Search text in a PDF document.

    Outline: Directly locate and link to point of interest within a document.

    Reading Bookmark: Mark progress and interesting passages as users read.

    Annotation: Create, edit and remove annotations.

    Layers: Add, edit and remove optional content groups.

    Attachments: Add, edit and remove document level attachments.

    Form: Fill form with JavaScript support, export and import form data by XFDF/FDF/XML file.

    Signature: Sign a PDF document, verify a signature, add or delete a signature field. Add and verify third-party digital signature.

    Security: Protect PDFs with password or certificate.

    Pan and Zoom: Adjust the magnification and position of the view area to match the area in an adjustable rectangle in the Pan & Zoom window’s thumbnail view of the page.

    Print: Print PDF document.

    Out of Memory: Recover from an OOM condition.

    Note: Outline is the technical term used in the PDF specification for what is commonly known as bookmarks in traditional desktop PDF viewers. Reading bookmarks are commonly used on mobile and tablet PDF viewers to mark progress and interesting passages as users read but are not technically outline and are stored at app level rather than within the PDF itself.

    Support robust PDF applications with Foxit PDF SDK for Android

    Development of robust PDF applications is challenging on mobile platforms which has limited memory. When memory allocation fails, applications may crash or exit unexpectedly. To deal with this issue, Foxit PDF SDK for Android provides an out-of-memory (OOM) mechanism to support applications.

    OOM is an evolved feature in Foxit PDF SDK for Android because of its complexity. The key of OOM mechanism is that Foxit PDF SDK for Android will monitor the usage of memory and take recovery operations automatically once OOM is detected. During the recovery process, Foxit PDF SDK for Android reloads the document and page automatically and restores the status to the original before OOM. It means the current reading page and location, as well as page view mode (single or continuous page) can be recovered. However, the data generated from editing will be lost.

    Foxit PDF SDK for Android provides the property “shouldRecover” in FSPDFViewCtrl class. By default, the value of “shouldRecover”” is “YES”. If you do not want to enable the auto-recovery when OOM is detected, you can set “shouldRecover” to “false” as follows:

    PDFViewCtrl pdfViewerCtrl = new PDFViewCtrl(getActivity().getApplicationContext());
    pdfViewerCtrl.shouldRecover = false;

    At that time, the application will throw an exception, and may crash or exit unexpectedly.

    Evaluation

    Foxit PDF SDK for Android allows users to download trial version to evaluate SDK. The trial version has no difference from the standard licensed version except for the free 21-day trial limitation and the trial watermarks in the generated pages. After the evaluation period expires, customers should contact the Foxit sales team and purchase licenses to continue using Foxit PDF SDK for Android.

    License

    Developers should purchase licenses to use Foxit PDF SDK for Android in their solutions. Licenses grant developers permission to release their apps which utilize Foxit PDF SDK for Android. However, users are prohibited to distribute any documents, sample code, or source code in the released package of Foxit PDF SDK for Android to any third party without written permission from Foxit Software Incorporated.

    About this Guide

    This guide is intended for developers who need to integrate Foxit PDF SDK for Android into their own apps. It aims at introducing the following sections:

    • Introduction to Foxit PDF SDK: gives an introduction of Foxit PDF SDK for Android.
    • Getting Started: illustrates the package structure, running demo, and adding PDF SDK into app.
    • Rapidly Building a full-featured PDF Reader: describes how to quickly create a full-featured PDF Reader.
    • Customizing the UI Implementation: introduces how to customize the UI implementation.
    • Creating a Custom Tool: shows how to create a custom tool.
    • Technical Support: provides support information.

    Note:

    • In section 2, it shows you how to call Foxit PDF SDK for Adnroid APIs to realize some specific features, which does not use the default reader provided in version 5.0. In this case, you should take a lot of effort to design the app’s UI and implement related functions.
    • In section 3, it shows you how to quickly build a full-featured PDF Reader with the default reader provided in version 5.0. In this case, you do not need to take much time to design the UI of your app, and you can flexibly customize the features you want through a configuration file.

    Getting Started

    It is very easy to setup Foxit PDF SDK for Android and see it in action! It takes just a few minutes and we will show you how to use it on the Android platform. The following sections introduce the structure of the installation package, how to run a demo, and how to create your own project in Android Studio.

    Note: The following section 2.4 will show you how to make an Android app using Foxit PDF SDK for Android. It helps you to quickly get started to call the APIs to realize some specific features, which does not use the default reader provided in version 4.0. If you want to quickly build a full-featured PDF Reader, please see section Rapidly Building a full-featured PDF Reader directly.

    System Requirements

    Android device’s requirements:

    • Android 4.1 (API 16) or higher
    • 32/64-bit ARM (armeabi-v7a/arm64-v8a) or 32-bit Intel x86 CPU

    Android 4.1 or higher (Support AAR based build system: Gradle 2.1.0 or later)

    The runtime environment for our demos:

    • Android Studio 3.1
    • JDK 1.8
    • Gradle Version 4.4
    • Gradle Build Tool 3.1

    What’s in the package

    Download “foxitpdfsdk_6_1_android.zip” package, and extract it to a new directory like “foxitpdfsdk_6_1_android” as shown in Figure 2-1. The package contains:

    • docs: A folder containing API references, developer guide, and upgrade warnings.
    • libs: A folder containing license files, .so libraries, Jar, AAR files, and UI Extensions Component source code.
    • samples: A folder containing Android sample projects.
    • getting_started_android.pdf: A quick guide for Foxit PDF SDK for Android.
    • legal.txt: Legal and copyright information.
    • release_notes.txt: Release information.

    Figure 2-1

    In the “libs” folder as shown in Figure 2-2, there are items that make up the core components of Foxit PDF SDK for Android.

    Figure 2-2

    • uiextensions_src project – found in the “libs” folder. It is an open source library that contains some ready-to-use UI module implementations, which can help developers rapidly embed a fully functional PDF reader into their Android app. Of course, developers are not forced to use the default UI, they can freely customize and design the UI for their specific apps through the “uiextensions_src” project.
    • FoxitRDK.aar – contains JAR package which includes all the Java APIs of Foxit PDF SD Kfor Android, as well as the underlying “.so” libraries. The “.so” library is the heart of the SDK including the core functionalities of Foxit PDF SDK for Android. It is built separately for each architecture, and currently available for armeabi-v7a, arm64-v8a, x86, and x86_64.
    • FoxitRDKUIExtensions.aar – generated by the “uiextensions_src” project found in the “libs” folder. It includes the FoxitRDK.jar, built-in UI implementation, and resource files that are needed for the built-in UI implementations, such as images, strings, color values, layout files, and other Android UI resources.

    Note: In order to reduce the size of FoxitRDKUIExtensions.aar, Foxit PDF SDK for Android uses shrink-code the uiextensions_src project. If you do not want to use shrink-code when you build the uiextensions_src project, you can disable it by setting “minifyEnabled” to “false” in the App’s build.gradle. For shrink-code, you can refer to https://developer.android.com/studio/build/shrink-code.html.

    At this point you should just be getting a feel for what Foxit PDF SDK for Android package looks like, we’re going to cover everything in detail in a bit.

    How to run a demo

    Download and install Android Studio IDE (https://developer.android.com/studio/index.html).

    Note: In this guide, we do not cover the installation of Android Studio, Android SDK, and JDK. You can refer to Android Studio’s developer site if you haven’t installed it already.

    Foxit PDF SDK for Android provides four useful demos for developers to learn how to call the SDK as shown in Figure 2-3.

    Figure 2-3

    Function demo

    The function demo is provided to show how to use Foxit PDF SDK for Android to realize some specific features related to PDF with PDF core API. This demo includes the following features:

    • pdf2txt: extract text from a PDF document to a TXT file.
    • outline: edit outline (aka bookmark) appearances and titles.
    • annotation: add annotations to a PDF page.
    • docinfo: export document information of a PDF to a TXT file.
    • render: render a specified page to Bitmap.
    • signature: add a signature to PDF, sign PDF and verify the signature.

    To run it in Android Studio, follow the steps below:

    a) Load the demo in Android Studio through “File ->; New ->; Import Project…” or “File ->; Open…”, and then navigate to where the function_demo project is stored and select the function_demo folder. Continue with “OK”.

    b) Launch an Android device or an emulator (AVD). In this section, an AVD targeting 8.1 will be used as an example.The test files in the “samples/test_files” that are needed for the demos will be copied to the emulator’s storage card automatically when running the demos.

    c) Click on “Run -> Run ‘app'”to run the demo. After installing the APK on the emulator, tap Allow on the pop-up windows to allow the demo to access files on the device. Then you can see the features are listed like Figure 2-4.

    Figure 2-4

    d) Click the feature buttons in the above picture to perform the corresponding actions. For example, click “pdf2txt”, and then a message box will be popped up as shown in Figure 2-6. It shows where the text file was saved to. Just run the demo and try the features.

    Figure 2-5

    Viewer control demo

    The viewer control demo demonstrates how to implement the features related to the View Control feature level, such as performing annotations (note, highlight, underline, strikeout, squiggly, etc.), changing layout, text search, outline, and page thumbnail. The logical structure of the code is quite clear and simple so that developers can quickly find the detailed implementation of features which are used widely in PDF apps, such as a PDF viewer. With this demo, developers can take a closer look at the APIs provided in Foxit PDF SDK for Android.

    To run the demo in Android Studio, please refer to the setup steps outlined in the Function demo.

    Viewer control demo will not copy the test file to the Android device or emulator automatically. It will use the “Sample.pdf” (found in the “samples/test_files” folder) as the test file, please make sure you have pushed this file into the created folder “input_files” of Android device or emulator before running this demo.

    Figure 2-6 shows what the demo looks like after it was built successfully. Here, an AVD targeting 4.4.2 will be used as an example to run the demo.

    Figure 2-6

    Click anywhere in the page, then the Contextual Action bar will appear, you can click at the actions items menu button:And see more action items as shown in Figure 2-7.

    Figure 2-7

    Now we can choose one item to perform the action and see the result. For example, click “Outline”, then you will see the outline (outline is the technical term for bookmark in the PDF specification) of the document as shown in Figure 2-8. Try using the other features to see it in action.

    Figure 2-8

    Complete PDF viewer demo

    The complete PDF viewer demo demonstrates how to use Foxit PDF SDK for Android to realize a completely full-featured PDF viewer which is almost ready-to-use as a real world mobile PDF reader. This demo utilizes all of the features and built-in UI implementations which are provided in Foxit PDF SDK for Android.

    To run the demo in Android Studio, please refer to the setup steps outlined in the Function demo. Here, an AVD targeting 8.1 will also be used as an example to run the demo. After building the demo successfully, on the start screen, it lists the “complete_pdf_viewer_guide_android.pdf” and “Sample.pdf” documents (see Figure 2-9).

    Note: The “complete_pdf_viewer_guide_android.pdf” and “Sample.pdf” documents will be automatically deployed to your device so that you don’t need to push them into the device manually. But if you want to use some other PDF files to test this demo, you should push them into the device’s SD card.

    Figure 2-9

    Click the “complete_pdf_viewer_guide_android.pdf” document, and then it will be opened and displayed as shown in Figure 2-10.

    Figure 2-10

    This demo realizes a completely full-featured PDF viewer, please feel free to run it and try it.

    For example, it provides the page thumbnail feature. You can click the View menu, choose the Thumbnail as shown in Figure 2-11, and then the thumbnail of the document will be displayed as shown in Figure 2-12.

     

    Figure 2-11

    Figure 2-12

    Foxit PDF SDK for Android wrapped all of the UI implementations including the basic UI for app and ready-to-use UI feature modules to UI Extensions Component, so that developers can easily and rapidly build a full-featured PDF Reader with just a few lines of code. This section will help you to quickly get started with using Foxit PDF SDK for Android to make a full-featured PDF Reader app in Android platform with step-by-step instructions provided.This section will help you to quickly make an Android app using Foxit PDF SDK for Android. It includes the following steps:

    a) Create a new Android project
    b) Integrate Foxit PDF SDK for Android into your apps
    c) Apply the license key
    d) Display a PDF document
    e) Build a full-featured PDF Reader with UI Extensions Component

    Create a new Android project

    In this guide, we use Android Studio 3.1.3, along with Android API revision 27.

    Open Android Studio, choose File -> New -> New Project… to start the Create Android Project wizard, and then fill the New Project dialog as shown in Figure 3.1. After filling, click Next.

    Figure 3-1

    In the Target Android Devices dialog, set the Minimum SDK to API 16, which is shown in Figure 3-2. Then, click Next.

    Figure 3-2

    In the Add an activity to Mobile dialog, select “Empty Activity” (for some other Android Studio versions, it might be “Blank Activity”) as shown in Figure 3-3, and then click Next.

    Figure 3-3

    In the Configure Activity dialog, customize your activity as desired. Here, we use the default setting as shown in Figure 3-4, and then click Finish.

    Figure 3-4

    Integrate Foxit PDF SDK for Android

    Note: We will use the default built-in UI implementation including the UI design of the app to create a PDF Reader. So, just use FoxitRDKUIExtensions.aar file for simplicity.

    • FoxitRDK.aar – contains JAR package which includes all the Java APIs of Foxit PDF SDK for Android, as well as the underlying “.so” libraries. The “.so” library is the heart of the SDK including the core functionalities of Foxit PDF SDK for Android. It is built separately for each architecture, and currently available for armeabi-v7a, arm64-v8a, x86, and x86_64
    • FoxitRDKUIExtensions.aar – generated by the “uiextensions_src” project found in the “libs”folder. It includes the FoxitRDK.jar, built-in UI implementations, and resource files that are needed for the built-in UI implementations, such as images, strings, color values, layout files, and other Android UI resources.

    Tip: The UI Extensions Component (FoxitRDKUIExtensions.aar) are not required for the following two sections”Initialize Foxit PDF SDK for Android”and “Display a PDF document using PDFViewCtrl”, so you can just add FoxitRDK.aar to the project at first. Then, add FoxitRDKUIExtensions.aar when you need to use the UI Extensions Component, such like the project described in the section “Build a full-featured PDF Reader with UI Extensions Component”.

    To add the above two AAR files into PDFReader project, please switch to the “Project” view panel and then follow the steps below:

    a) Copy and paste the “FoxitRDK.aar” and FoxitRDKUIExtensions.aar files from the “libs” folder of the download package to “PDFReaer\app\libs” folder.

    Synchronize PDFReader ProjectThen, the project should look like Figure 3-5.

    Figure 3-5

    b) Defin the “libs” directory as a repository. Inside the app’s “build.gradle” file, add the following configuration:

    build.gradle:

    repositories {
            flatDir {
                dirs 'libs'
        }
    }

    d) Include Foxit PDF SDK for Android as a dependency in the project. Inside the app’s “build.gradle””, add “FoxitRDK.aar” and “FoxitRDKUIExtensions.aar” to the dependencies. For simplicity, update the dependencies as follows:

    dependencies {
    implementation(name: 'FoxitRDK', ext: 'aar')
        implementation(name: 'FoxitRDKUIExtensions', ext: 'aar')
        implementation 'com.android.support:design:27.1.1'
        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        testImplementation 'junit:junit:4.12'
    }

    Note: Foxit PDF SDK for Android has a dependency on recyclerview support library, so you should add it to the dependencies. Here, we add ‘com.android.support:design:27.1.1’ which has already included the recyclerview package. Or you can add “implementation ‘com.android.support:recyclerview-v7:27.1.1’” directly.

    After setting the app’s “build.gradle” file, sync it, then the “FoxitRDK.aar”, “FoxitRDKUIExtensions” and “recyclerview” pacakges will appear in External Libraries as shown in Figure 3-6.

    Figure 3-6

    The following code shows “build.gradle” in its entirety.

    build.gradle:

    apply plugin: 'com.android.application'
     
    apply plugin: 'com.android.application'
     
    android {
        compileSdkVersion 27
        defaultConfig {
            applicationId "com.foxit.pdfreader"
            minSdkVersion 16
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
     
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
     
    dependencies {
        implementation(name: 'FoxitRDK', ext: 'aar')
        implementation(name: 'FoxitRDKUIExtensions', ext: 'aar')
        implementation 'com.android.support:design:27.1.1'
        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        testImplementation 'junit:junit:4.12'
    }

     

    Note: So far, we set the compileSdkVersion and targetSdkVersion to API 27. If you also want to use API 27, please make sure you have already installed the SDK Platform Android 8.1, API 27. If you have not already done this, open the Android SDK Manager to download and install it first.

    Initialize Foxit PDF SDK for Android

    It is necessary for apps to initialize and unlock Foxit PDF SDK for Android using a license before calling any APIs. The function Library.init (sn, key) is provided to initialize Foxit PDF SDK for Android. The trial license files can be found in the “libs” folder of the download package. After the evaluation period expires, you should purchase an official license to continue using it. Below you can see an example of how to unlock the SDK library. The next section will show where to include this code in the PDFReader project.

    import com.foxit.sdk.common.Library;
    import com.foxit.sdk.common.Constants;
    import com.foxit.sdk.common.Library;
    ...
     
    int errorCode = Library.initialize("sn", "key");
    if (errorCode != Constants.e_ErrSuccess)
        return;

    Note: The parameter “sn” can be found in the “rdk_sn.txt” (the string after “SN=”) and the “key” can be found in the “rdk_key.txt” (the string after “Sign=”).

    Display a PDF document using PDFViewCtrl

    So far, we have added Foxit PDF SDK for Android libraries to the PDFReader project, and finished the initialization of the Foxit PDF SDK. Now, let’s start displaying a PDF document using PDFViewCtrl with just a few lines of code.

    Note: The UI Extensions Component is not required if you only want to display a PDF document.

    To display a PDF document, follow the steps below:

    a) Instantiate a PDFViewCtrl object to show an existing document.

    In MainActivity.java, instantiate a PDFViewCtrl object, and call PDFViewCtrl.openDoc function to open and render the PDF document.

    Update activity_main.xml as follows:

    import com.foxit.sdk.PDFViewCtrl;
    ...
    private PDFViewCtrl pdfViewCtrl = null;
    ...
    pdfViewCtrl = new PDFViewCtrl(this);
     
    String path = "/mnt/sdcard/input_files/Sample.pdf";
    pdfViewCtrl.openDoc(path, null);
     
    SetContentView(pdfViewCtrl);

    In the “MainActivity.java”, instantiate a PDFDoc object to load an existing PDF document (“/mnt/sdcard/input_files/Sample.pdf“); and instantiate a PDFViewCtrl object to show the document.

    Note: Please make sure you have pushed the “Sample.pdf” document into the created folder “input_files” of the Android device or emulator that will be used to run this project.

    Update MainActivity.java as follows:

    package com.foxit.pdfreader;
     
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
     
    import com.foxit.sdk.PDFViewCtrl;
    import com.foxit.sdk.common.Constants;
    import com.foxit.sdk.common.Library;
     
    public class MainActivity extends AppCompatActivity {
     
        private PDFViewCtrl pdfViewCtrl = null;
     
        // The value of "sn" can be found in the "rdk_sn.txt".
        // The value of "key" can be found in the "rdk_key.txt".
        private static String sn = " ";
        private static String key = " ";
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
     
            // initialize the library.
            int errorCode = Library.initialize(sn, key);
            if (errorCode != Constants.e_ErrSuccess)
                return;
     
            pdfViewCtrl = new PDFViewCtrl(this);
            String path = "/mnt/sdcard/input_files/Sample.pdf";
            pdfViewCtrl.openDoc(path, null);
     
            setContentView(pdfViewCtrl);
        }
    }

    b) Set permissions to write and read the SD card of the Android devices or emulators.

    Note: If you want to run this project on an Android 6.0 (API 23) or higher devices/emulators, you can do one of the following:
    1. Change the targetSdkVersion in app’s “build.gradle” from 27 to the SDK version that is just less than 23, such as 21.
    2. Write some additional code to require the authorization of runtime permissions

    1. Change the targetSdkVersion in app’s “build.gradle” from 27 to 21.
    In this case, set the “users-permission” in the “AndroidManifest.xml” found in the “app/src/main” to give the project permission to write and read the SD card of the Android devices or emulators.

    Update the AndroidManifest.xml as follows:

     
    < ?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.foxit.pdfreader">
     
        <uses -permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses>
        <uses -permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses>
     
        <application android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent -filter>
                    <action android:name="android.intent.action.MAIN"></action>
     
                    <category android:name="android.intent.category.LAUNCHER"></category>
                </intent>
            </activity>
        </application>
     
    </manifest>

    2. Write additional code to require the authorization of runtime permissions.
    In the MainActivity.java file, add the following code to require the authorization of runtime permissions:

    import android.content.pm.PackageManager;
    import android.os.Build;
    import android.support.annotation.NonNull;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    ...
     
    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static final String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    ...
     
    // Require the authorization of runtime permissions.
     if (Build.VERSION.SDK_INT >= 23) {
        int permission = ContextCompat.checkSelfPermission(this.getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            return;
        }
    }
    ...
     
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Open and Reader a PDF document.
            String path = "/mnt/sdcard/input_files/Sample.pdf";
            pdfViewCtrl.openDoc(path, null);
            setContentView(pdfViewCtrl);
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    Then, the whole contents of MainActivity.java will be as follows:

    package com.foxit.pdfreader;
     
    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.os.Build;
    import android.support.annotation.NonNull;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
     
    import com.foxit.sdk.PDFViewCtrl;
    import com.foxit.sdk.common.Constants;
    import com.foxit.sdk.common.Library;
    public class MainActivity extends AppCompatActivity {
     
        private PDFViewCtrl pdfViewCtrl = null;
     
        private static final int REQUEST_EXTERNAL_STORAGE = 1;
        private static final String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
     
        // The value of "sn" can be found in the "rdk_sn.txt".
        // The value of "key" can be found in the "rdk_key.txt".
        private static String sn = " ";
        private static String key = " ";
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
     
            // initialize the library.
            int errorCode = Library.initialize(sn, key);
            if (errorCode != Constants.e_ErrSuccess)
                return;
     
            // Instantiate a PDFViewCtrl object.
            pdfViewCtrl = new PDFViewCtrl(this);
     
            // Require the authorization of runtime permissions.
            if (Build.VERSION.SDK_INT >= 23) {
                int permission = ContextCompat.checkSelfPermission(this.getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
                if (permission != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
                    return;
                }
            }
     
            // Open and Reader a PDF document.
            String path = "/mnt/sdcard/input_files/Sample.pdf";
            pdfViewCtrl.openDoc(path, null);
            setContentView(pdfViewCtrl);
        }
     
        @Override
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Open and Reader a PDF document.
                String path = "/mnt/sdcard/input_files/Sample.pdf";
                pdfViewCtrl.openDoc(path, null);
                setContentView(pdfViewCtrl);
            } else {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    }

    In this section, we build and run the project on an AVD targeting 8.1 (API 27), and use the second method (require authorization of runtime permissions) to get the permissions to write and read the SD card of the emulator.

    Now, we have finished building a simple Android app which uses Foxit PDF SDK for Android to display a PDF document with just a few lines of code. The next step is to run the project.

    After building the project and installing APK on the emulator, tap Allow on the pop-up windows to allow the demo to access files on the device, and then you will see that the “Sample.pdf” document is displayed as shown in Figure 3 7. Now, this sample app has some basic PDF features, such as zooming in/out and page turning. Just have a try!

    Figure 3-7

    Foxit PDF SDK for Android comes with built-in UI design including the basic UI for app and the feature modules UI, which are implemented using Foxit PDF SDK for Android and are shipped in the UI Extensions Component. Hence, building a full-featured PDF Reader is getting simpler and easier. All you need to do is to instantiate a UIExtensionsManager object, and then set it to PDFViewCtrl.

    Instantiate a UIExtensionsManager object and set it to PDFViewCtrl

    In “MainActivity.java” file, we are now going to add the code necessary for including the UIExtensionsManager. The required code additions are shown below and further down you will find a full example of what the “MainActivity.java” file should look like.

    a) Set the system theme to “No Title” mode and set the window to Fullscreen.

    Note: The UI Extensions Component has customized the user interface, so you need to set the system theme to “No Title” mode and set the window to Fullscreen. Otherwise, the layout of the built-in features might be affected.

    import android.view.Window;
    import android.view.WindowManager;
    ...
     
    // Turn off the title at the top of the screen.
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
     
    // Set the window to Fullscreen.
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    b) Add code to instantiate a UIExtensionsManager object and set it to PDFViewCtrl.

    import com.foxit.uiextensions.UIExtensionsManager;
    ...
    private UIExtensionsManager uiExtensionsManager = null;
    ...
    uiExtensionsManager = new UIExtensionsManager(this.getApplicationContext(), pdfViewCtrl);
    uiExtensionsManager.setAttachedActivity(this);
    uiExtensionsManager.onCreate(this, pdfViewCtrl, savedInstanceState);
    pdfViewCtrl.setUIExtensionsManager(uiExtensionsManager);

    c) Open and reader a PDF document, and set the content view.

    Call UIExtensionsManager.openDocument() function to open and reader a PDF document instead of calling PDFViewCtrl.openDoc() function.

    import com.foxit.uiextensions.UIExtensionsManager;
    ...
    String path = "/mnt/sdcard/input_files/Sample.pdf";
    uiExtensionsManager.openDocument(path, null);
    setContentView(uiExtensionsManager.getContentView());

    Update MainActivity.java as follows:

    Note: The Activity Lifecycle Events should be handled as below, otherwise some features may not work correctly.

    package com.foxit.pdfreader;
     
    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.content.res.Configuration;
    import android.os.Build;
    import android.support.annotation.NonNull;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.KeyEvent;
     
    import com.foxit.sdk.PDFViewCtrl;
    import com.foxit.sdk.common.Constants;
    import com.foxit.sdk.common.Library;
    import com.foxit.uiextensions.UIExtensionsManager;
     
    public class MainActivity extends AppCompatActivity {
     
        private PDFViewCtrl pdfViewCtrl = null;
        private UIExtensionsManager uiextensionsManager = null;
     
    private static final int REQUEST_EXTERNAL_STORAGE = 1;
        private static final String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
     
        // The value of "sn" can be found in the "rdk_sn.txt".
        // The value of "key" can be found in the "rdk_key.txt".
        private static String sn = " ";
        private static String key = " ";
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
     
            // initialize the library.
            int errorCode = Library.initialize(sn, key);
            if (errorCode != Constants.e_ErrSuccess)
                return;
     
            // Instantiate a PDFViewCtrl object.
            pdfViewCtrl = new PDFViewCtrl(this);
     
            // Initialize a UIExtensionManager object and set it to PDFViewCtrl.
            uiExtensionsManager = new UIExtensionsManager(this.getApplicationContext(), pdfViewCtrl);
            uiExtensionsManager.setAttachedActivity(this);
            uiExtensionsManager.onCreate(this, pdfViewCtrl, savedInstanceState);
            pdfViewCtrl.setUIExtensionsManager(uiExtensionsManager);
     
            // Require the authorization of runtime permissions.
            if (Build.VERSION.SDK_INT >= 23) {
                int permission = ContextCompat.checkSelfPermission(this.getApplicationContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE);
                if (permission != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
                    return;
                }
            }
     
            // Open and Reader a PDF document.
            String path = "/mnt/sdcard/input_files/Sample.pdf";
            uiExtensionsManager.openDocument(path, null);
            setContentView(uiExtensionsManager.getContentView());
        }
     
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Open and Reader a PDF document.
                String path = "/mnt/sdcard/input_files/Sample.pdf";
                uiExtensionsManager.openDocument(path, null);
                setContentView(uiExtensionsManager.getContentView());
            } else {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
     
        @Override
        public void onStart() {
            if (uiExtensionsManager != null) {
                uiExtensionsManager.onStart(this);
            }
            super.onStart();
        }
     
        @Override
        public void onStop() {
            if (uiExtensionsManager != null) {
                uiExtensionsManager.onStop(this);
            }
            super.onStop();
        }
     
        @Override
        public void onPause() {
            if (uiExtensionsManager != null) {
                uiExtensionsManager.onPause(this);
            }
            super.onPause();
        }
     
        @Override
        public void onResume() {
            if (uiExtensionsManager != null) {
                uiExtensionsManager.onResume(this);
            }
            super.onResume();
        }
     
        @Override
        protected void onDestroy() {
            if (uiExtensionsManager != null) {
                uiExtensionsManager.onDestroy(this);
            }
            super.onDestroy();
        }
     
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            if (uiExtensionsManager != null) {
                uiExtensionsManager.onConfigurationChanged(this, newConfig);
            }
        }
     
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (uiExtensionsManager != null && uiExtensionsManager.onKeyDown(this, keyCode, event))
                return true;
            return super.onKeyDown(keyCode, event);
        }
    }

    Update AndroidManifest.xml
    Add

    "<uses -permission android:name="android.permission.CAMERA"></uses>"

    to grant the project permissions to access the camera.
    Add

    "android:configChanges="keyboardHidden|orientation|locale|layoutDirection|screenSize">"

    property to make sure that the project will only execute the onConfigurationChanged() function without recalling the activity lifecycle when rotating the screen. If you do not add this property, the signature feature will not work correctly.

    Add

    <uses -permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses>

    and

    "<service android:name="com.foxit.uiextensions.modules.panzoom.floatwindow.service.FloatWindowService"></service>"

    , which grants your phone the floating window permissions. If you do not add this permission and service, the Pan and Zoom feature will not be able to work.

    Update AndroidManifest.xml as follows:

    < ?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.foxit.pdfreader">
     
        <uses -permission android:name="android.permission.CAMERA"></uses>
        <uses -permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses>
     
        <application android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity"
             android:configChanges="keyboardHidden|orientation|locale|layoutDirection|screenSize">
                <intent -filter>
                    <action android:name="android.intent.action.MAIN"></action>
     
                    <category android:name="android.intent.category.LAUNCHER"></category>
                </intent>
            </activity>
            <service android:name="com.foxit.uiextensions.modules.panzoom.floatwindow.service.FloatWindowService"></service>
        </application>
     
    </manifest>

    Run the project
    In this section, we build and run the project on an AVD targeting Android 8.1 (API 27). After building the project and installing APK on the emulator, tap Allow on the pop-up windows to allow the demo to access files on the device, and then you will see that the “Sample.pdf” document is displayed as shown in Figure 3 8. Up to now, it is a full-featured PDF Reader which includes all of the features in Complete PDF viewer demo. Feel free to try it.

    Figure 3-8

    Customizing the UI

    Foxit PDF SDK for Android provides a simple, clean and friendly user interface for developers to quickly build a full-featured PDF app without needing to take much time on the design. Furthermore, customizing the user interface is straightforward. Foxit PDF SDK for Android provides the source code of the UI Extensions Component that contains ready-to-use UI module implementations, which lets the developers have full control of styling the appearance as desired.

    From version 4.0, developers can flexibly customize the features they want through a configuration file.

    From version 5.0, every element in the built-in UI can be configurable. More advanced APIs and more powerful configuration file are provided for developers to further customize the UI elements, such as showing or hiding a specific panel, top/bottom bar, the items in the top bar, and the items in the View setting bar and More Menu view.

    The following section will introduce how to customize the feature modules in your project and how to customize the UI elements and implementations through a configuration file, or APIs, or the source code.

    About configuration file

    From version 4.0, Foxit PDF SDK for Android provided a more convenient way to flexibly control and customize the features through a configuration file. Developers can easily choose the features that they want without needing to write any additional code or redesign the app’s UI.

    Two formats of the configuration file

    The configuration file can be provided as a JSON file or implemented directly in code. It controls which feature modules are enabled. Now, we will introduce the two formats of the configuration file respectively.

    The first format, use a JSON file (e.g. name “uiextensions_config.json”) which looks like as follows:

    {
        "modules": {
            "readingbookmark": true,
            "outline": true,
            "annotations": true,
            "thumbnail" : true,
            "attachment": true,
            "signature": true,
            "search": true,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption" : true
        }
    }

    Note: For a full-featured PDF Reader, all of the items in “modules” should be set to “true”, which ensures that all of the features are enabled.

    Assume that you have put the JSON configuration file to “PDFReader\app\src\main\res\raw” (note that you need to create the “raw” folder by yourself).

    Then, use the following code to get the configuration file:

    import java.io.InputStream;
    ...
    InputStream stream = this.getApplicationContext().getResources().openRawResource(R.raw.uiextensions_config);

    The second format, implement it in the code instead of a JSON file as follows:

    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    import java.nio.charset.Charset;
    ...
    String UIExtensionsConfig = "{\n" +
            "    \"modules\": {\n" +
            "        \"readingbookmark\": true,\n" +
            "        \"outline\": true,\n" +
            "        \"annotations\": true,\n" +
            "        \"thumbnail\" : true,\n" +
            "        \"attachment\": true,\n" +
            "        \"signature\": true,\n" +
            "        \"search\": true,\n" +
            "        \"pageNavigation\": true,\n" +
            "        \"form\": true,\n" +
            "        \"selection\": true,\n" +
            "        \"encryption\" : true\n" +
            "    }\n" +
            "}\n";
    InputStream stream = new ByteArrayInputStream(UIExtensionsConfig.getBytes(Charset.forName("UTF-8")));

    In this guide, we will use the first format (JSON file) to present the configuraton file.

    Notice items of configuration file

    The JSON configuration file can be written by yourself. There are some situations needed to notice when you are writing the configuraton file. Following lists some typical examples:

    1) All of the items in “modules” are set to “true”, in this case, all of the feature modules will be enabled.

    {
        "modules": {
            "readingbookmark": true,
            "outline": true,
            "annotations": true,
            "thumbnail" : true,
            "attachment": true,
            "signature": true,
            "search": true,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption": true
        }
    }

    2) Some items in “modules” are set to “false”. For example, “annotations” and “thumbnail” modules are set to “false”, in this case, only the “annotations” and “thumbnail” feature modules are disabled, the others are all enabled.

    {
        "modules": {
            "readingbookmark": true,
            "outline": true,
            "annotations": false,
            "thumbnail" : false,
            "attachment": true,
            "signature": true,
            "search": true,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption": true
        }
    }

    3) Some items in “modules” are not set. For example, “annotations” and “thumbnail” modules are not set in the configuration file, in this case, the “annotations” and “thumbnail” feature modules are enabled, because the default settings are “true”. It means if some features modules are not in the configuration file, they will also be available.

    {
        "modules": {
            "readingbookmark": true,
            "outline": true,
            "attachment": true,
            "signature": true,
            "search": true,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption": true
        }
    }

    From version 5.0, Foxit PDF SDK for Android supported customizing the annotations in the built-in Annotation setting bar through a configuration file, so that developers can choose the annotations that they want without needing to write any additional code. Rewrite the JSON file as follows:

    {
        "modules": {
            "readingbookmark": true,
            "outline": true,
    //        "annotations":true,
            "annotations": {
                "highlight": true,
                "underline": true,
                "squiggly": true,
                "strikeout": true,
                "inserttext": true,
                "replacetext": true,
                "line": true,
                "rectangle": true,
                "oval": true,
                "arrow": true,
                "pencil": true,
                "eraser": true,
                "typewriter": true,
                "textbox": true,
                "callout": true,
                "note": true,
                "stamp": true,
                "polygon": true,
                "cloud":true,
                "polyline":true,
                "distance":true,
                "image":true
            },
            "thumbnail" : true,
            "attachment": true,
            "signature": true,
            "search": true,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption" : true
        }
    }

    Please comment out “”annotations”: true,”, and set the types of annotations that you want to “true”. If you want to remove a specific type of the annotations, just set it to “false”.

    Note: If some types of annotations are not in the configuration file, they are also enabled, because the default setting is “true”. For example, if you comment out “”highlight”: true,”, it is still available.

    Instantiate a UIExtensionsManager object with the configuration file

    We have already introduced how to initialize UIExtensionsManager, and in this way all the built-in UI framework would be loaded by default. In this section, we will provide another method to initialize UIExtensionsManager that uses the configuration file, so that developers can easily customize the feature modules or annotations as desired.

    Please refer to the following code to instantiate a UIExtensionsManager object with the configuration file.

    Note: Here, we assume that you have already put a JSON file named “uiextensions_config.json” to “PDFReader\app\src\main\res\raw” (note that you need to create the “raw” folder by yourself).

    In “MainActivity.java”:

    private PDFViewCtrl pdfViewCtrl = null;
    private UIExtensionsManager uiExtensionsManager = null;
    // Initialize a PDFViewCtrl object.
     pdfViewCtrl = new PDFViewCtrl(this);
     
    // Get the config file, and set it to UIExtensionsManager.
     InputStream stream = this.getApplicationContext().getResources().openRawResource(R.raw.uiextensions_config);
     UIExtensionsManager.Config config = new UIExtensionsManager.Config(stream);
     
     // Initialize a UIExtensionManager object with Configuration file, and set it to PDFViewCtrl.
     uiExtensionsManager = new UIExtensionsManager(this.getApplicationContext(), pdfViewCtrl,config);
     pdfViewCtrl.setUIExtensionsManager(uiExtensionsManager);
     uiExtensionsManager.setAttachedActivity(this);
     uiExtensionsManager.onCreate(this, pdfViewCtrl, savedInstanceState);

    Note: Here, we use a configuration file to initialize the UIExtensions. If you do not want to use configuration file, please refer to the section “Build a full-featured PDF Reader with UI Extensions Component”. If you want to implement the configuration file in code directly instead of a JSON file, please see section “Notice items of configuration file”.

    Customize feature modules and annotations through a configuration file

    From version 4.0, Foxit PDF SDK for Android provided a more convenient way to flexibly control and customize the features through a configuration file. Developers can easily choose the features that they want without needing to write any additional code or redesign the app’s UI.

    From version 5.0, Foxit PDF SDK for Android supported customizing the Annotations tools (except Attachment tool) in the built-in Annotation setting bar (See Figure 4-1) through a configuration file. For more details about the configuration file, you can see section “About configuration file”.
    Note: To find the Annotation setting bar, just click Comment at the bottom bar, and then click the menu button:

    Figure 4-1

    The above picture does not display all of the annotation tools. You can swipe left on the setting bar to see the other annotation tools.

    The configuration file looks like as follows:

    {
        "modules": {
            "readingbookmark": true,
            "outline": true,
    //        "annotations":true,
            "annotations": {
                "highlight": true,
                "underline": true,
                "squiggly": true,
                "strikeout": true,
                "inserttext": true,
                "replacetext": true,
                "line": true,
                "rectangle": true,
                "oval": true,
                "arrow": true,
                "pencil": true,
                "eraser": true,
                "typewriter": true,
                "textbox": true,
                "callout": true,
                "note": true,
                "stamp": true,
                "polygon": true,
                "cloud":true,
                "polyline":true,
                "distance":true,
                "image":true
            },
            "thumbnail" : true,
            "attachment": true,
            "signature": true,
            "search": true,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption" : true
        }
    }

    Please note that only the attachement annotation in the Annotation setting bar is not controlled by the subitems in “annotations”. “”attachment”: true,” controls the attachments panel and attachment annotation. If you set it to “false”, both of them will be disabled. If you want to hide “Comment” in the bottom bar, you should set both “annotations” and “attachment” to “false”.

    To customize the UI elements in the Annotation setting bar, please make sure to comment out “”annotations”: true,”. Then set the types of annotations that you want to “true”, if you want to remove a specific type of the annotations, just set it to “false”.

    Note: If all types of the annotations in the configuration file are set to “false”, it is equal to “”annotations”: false,”. If some types of annotations are not in the configuration file, they are also enabled, because the default setting is “true”. For example, if you comment out “”highlight”: true,”, it is still available.

    In this section, we will show you how to customize feature modules and annotations in your project. You will find it is extremely easy! You only need to modify the configuration file. Below you can see an example of how to do it.

    Note: For your convenience, we will try it in the “complete_pdf_viewer” demo found in the “samples” folder.

    Load the “complete_pdf_viewer” demo in Android Studio. Find the configuration file “uiextensions_config.json” under “complete_pdf_viewer\app\src\main\res\raw”.

    Example: Remove “readingbookmark” and “search” feature modules, as well as the “highlight” and “stamp” annotations.

    Change the JSON file as follows:

    {
        "modules": {
            "readingbookmark": false,
            "outline": true,
    //        "annotations":true,
            "annotations": {
                "highlight": false,
                "underline": true,
                "squiggly": true,
                "strikeout": true,
                "inserttext": true,
                "replacetext": true,
                "line": true,
                "rectangle": true,
                "oval": true,
                "arrow": true,
                "pencil": true,
                "eraser": true,
                "typewriter": true,
                "textbox": true,
                "callout": true,
                "note": true,
                "stamp": false,
                "polygon": true,
                "cloud":true,
                "polyline":true,
                "distance":true,
                "image":true
            },
            "thumbnail" : true,
            "attachment": true,
            "signature": true,
            "search": false,
            "pageNavigation": true,
            "form": true,
            "selection": true,
            "encryption" : true
        }
    }

    Then, rebuild and run the demo to see the result. Following lists the comparison diagrams:

    Before:

    After:

    The “readingbookmark” and “search” feature modules are removed.

    Click Comment at the bottom bar, and then click at the menu button:


    The “highlight” and “stamp” annotations are removed.

    Customize UI Elements through API

    In version 4.0, Foxit PDF SDK for Android supported customizing to show or hide the whole top or bottom bar, and from version 5.0, it provided APIs to customize to show or hide a specific panel, the items in the top bar, View setting bar and More Menu view, which is convenient for developers to modify the UI elements in the context of the built-in UI framework.

    Note:complete_pdf_viewer” demo found in the “samples” folder.We assume that you have not modified the “uiextensions_config.json” file in the demos, which means that all of the built-in UI in the UI Extensions Component are enabled.

    Customizing top/bottom bar

    In the top/bottom bar, you can do the following operations:

  1. Show or hide the top/bottom bar.
  2. Add a custom item at any position
  3. Remove a specific item
  4. Remove all of the items in the toolbar
  5. Show or hide a specific item
  6. Add a custom toolbar
  7. Remove a specific toolbar
  8. Set background color for the toolbar
  9. Get the number of the items in a specific location of the toolbar.

Table 4-1 lists the related APIs which are used to customize the top/bottom bar

void enableTopToolbar(boolean isEnabled)Enable or disable top toolbar.
void enableBottomToolbar(boolean isEnabled)Enable or disable bottom toolbar.
boolean addItem(BarName barName,BaseBar.TB_Position gravity, BaseItem item, int index);Add a custom item to the toolbar. The item will be inserted before any previous element at the specified location.
boolean addItem(BarName barName, BaseBar.TB_Position gravity, int textId, int resId, int index, IItemClickListener clickListener);
Add a default item to the toolbar. The item is inserted before any previous element at the specified location.
int getItemsCount(BarName barName, BaseBar.TB_Position gravity);Get the items count by IBarsHandler.BarName and BaseBar.TB_Position.
boolean removeItem(BarName barName, BaseBar.TB_Position gravity, int index);Remove the item by IBarsHandler.BarName, BaseBar.TB_Position and the specified index.
boolean removeItem(BarName barName, BaseBar.TB_Position gravity, BaseItem item);Removes the item by IBarsHandler.BarName, BaseBar.TB_Position and the specified item.
void removeAllItems(BarName barName); Remove all items from the toolbar.
boolean addCustomToolBar(BarName barName, View view);Add custom toolbar by BarName.
boolean removeToolBar(BarName barName); Remove toolbar by BarName.
void setBackgroundColor(BarName barName, int color);
Set background color for the toolbar.
void setBackgroundResource(BarName barName, int resid);Set background to a given resource.
BaseItem getItem(BarName barName, BaseBar.TB_Position gravity, int tag);Get the item by tag, but if you remove this item before you get it, it will return null.

There are two important enumerations which are defined to locate the position that you want to add a new item or remove an existing item.

enum BarName { 
    TOP_BAR, 
    BOTTOM_BAR; 
} 
 
enum TB_Position { 
    Position_LT, 
    Position_CENTER, 
    Position_RB; 
}

Note:

  1. The top bar or bottom bar can only add up to 7 items.
  2. To add an item to the top bar, please set the BaseBar.TB_Position to Position_LT or Position_RB. To add an item to the bottom bar, please set the BaseBar.TB_Position to Position_CENTER. Otherwise, the items may overlap.
  3. The bottom bar is only one part, and the top bar is divided into two parts, so that there are three parts for the toolbar, and each part has a separate index.(See Figure 4-1)
  4. The top bar can only display a maximum of 15 characters, and the bottom bar can only display a maximum of 8 characters. So, it’s better to set the character number of the text within the maximum number. Please note that the character length does not distinguish between Chinese and English.

Figure 4-2

In the following examples, we will show you how to customize the top/bottom bar through APIs in the “complete_pdf_viewer” demo found in the “samples” folder.

Load the “complete_pdf_viewer” demo in Android Studio. Add the sample code to the “PDFReaderFragment.java” file (after the code “mUIExtensionsManager = new UIExtensionsManager(getActivity().getApplicationContext(), pdfViewerCtrl, config);”).

Example 1: Hide the whole top bar.

mUiExtensionsManager.enableTopToolbar(false);

Before

After:

Example 1: Hide the whole bottom bar.

mUiExtensionsManager.enableBottomToolbar(false);

Before

After:

Example 3: Add an item in the left top bar at the second position.

BaseItemImpl mTopItem1 = new BaseItemImpl(getContext());
mTopItem1.setImageResource(R.drawable.rd_annot_item_delete_selector);
mTopItem1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        UIToast.getInstance(getActivity()).show("Add an item in the left top bar at the second position.");
    }
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, mTopItem1, 1);

The result after running the demo:

 

 

Example 4: Add an item in the right top bar at the first position.

BaseItemImpl mTopItem2 = new BaseItemImpl(getContext());
mTopItem2.setImageResource(R.drawable.annot_fileattachment_selector);
mTopItem2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        UIToast.getInstance(getActivity()).show("Add an item in the right top bar at the first position");
    }
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, mTopItem2, 0);

The result after running the demo:

 

 

Example 5: Add an item to the bottom bar at the first position.

mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.BOTTOM_BAR, BaseBar.TB_Position.Position_CENTER,
        R.string.action_more, R.drawable.rd_bar_more_selector, 0, new IBarsHandler.IItemClickListener() {
            @Override
            public void onClick(View v) {
                UIToast.getInstance(getActivity()).show("Add an item to the bottom bar at the first position.");
            }
        });

The result after running the demo:

 

 

Example 6: Add an item with custom style to the bottom bar at the second position.

int circleResId = R.drawable.rd_bar_circle_bg_selector;
int textSize = getResources().getDimensionPixelSize(R.dimen.ux_text_height_toolbar);
int textColorResId = R.color.ux_text_color_button_colour;
int interval = getResources().getDimensionPixelSize(R.dimen.ux_toolbar_button_icon_text_vert_interval);
CircleItemImpl mSettingBtn = new CircleItemImpl(this.getContext());
mSettingBtn.setImageResource(R.drawable.rd_annot_create_ok_selector);
mSettingBtn.setText("style");
mSettingBtn.setRelation(BaseItemImpl.RELATION_BELOW);
mSettingBtn.setCircleRes(circleResId);
mSettingBtn.setInterval(interval);
mSettingBtn.setTextSize(AppDisplay.getInstance(getContext()).px2dp(textSize));
mSettingBtn.setTextColorResource(textColorResId);
mSettingBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        UIToast.getInstance(getActivity()).show("Add an item with custom style to the bottom bar at the second position.");
    }
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.BOTTOM_BAR, BaseBar.TB_Position.Position_CENTER, mSettingBtn, 1);

The result after running the demo:

 

 

Example 7: Remove an item by index (remove the first item in the bottom bar).

mUiExtensionsManager.getBarManager().removeItem(IBarsHandler.BarName.BOTTOM_BAR, BaseBar.TB_Position.Position_CENTER,0);

The result after running the demo:

 

 

Example 8: Remove an item by BaseItem object (remove a custom item from the top bar that you added before).

mUiExtensionsManager.getBarManager().removeItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, mTopItem1);

Before: (See Example 1)

 

 

After:

 

 

Example 9: Remove all the items in the bottom bar.

mUiExtensionsManager.getBarManager().removeAllItems(IBarsHandler.BarName.BOTTOM_BAR);

Before:

 

 

After:

 

 

Example 10: Add two items in the left top bar to control to show and hide the “more menu” item.

// Get and save the item that you want to show or hide.
BaseBarManager baseBarManager = (BaseBarManager) mUiExtensionsManager.getBarManager();
final BaseItemImpl moreItem = (BaseItemImpl) baseBarManager.getItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, ToolbarItemConfig.ITEM_TOPBAR_MORE_TAG);
 
// Add a buttom in the left top bar to hide the "moreItem" item.
BaseItemImpl mTopItem = new BaseItemImpl(getContext());
mTopItem.setImageResource(R.drawable.rd_annot_item_delete_selector);
mTopItem.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Hide the "moreItem" item.
        mUiExtensionsManager.getBarManager().removeItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, moreItem);
    }
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, mTopItem, 1);
 
// Add a buttom in the left top bar to show the "moreItem" item.
BaseItemImpl mTopItem2 = new BaseItemImpl(getContext());
mTopItem2.setImageResource(R.drawable.annot_reply_item_add_selector);
mTopItem2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Show the "moreItem" item.
        mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, moreItem ,2);
    }
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, mTopItem2, 2);

The result after running the demo, the top bar will look like as follows:

 

 

Click on the trash icon,and the “more menu” will be hidden as follows:

 

 

Click on the plus icon,

and the “more menu” will appear as follows:

 

 

Example 11: Remove the whole bottom bar

mUiExtensionsManager.getBarManager().removeToolBar(IBarsHandler.BarName.BOTTOM_BAR);

Example 12: Add a custom toolbar. (add a custom layout file “test_top_layout”)

View topView = View.inflate(getContext(), R.layout.test_top_layout, null);
mUiExtensionsManager.getBarManager().addCustomToolBar(IBarsHandler.BarName.TOP_BAR, topView);

Customizing to show/hide a specific Panel

To show or hide a specific panel (See Figure 4-2, includes “Reading Bookmarks”, “Outline”, “Annotations” and “Attachments” panels, just clicks List at the bottom bar to find it), you can use the following APIs listed in the Table 4-2.

Table 4-2

public void setPanelHidden(boolean isHidden, PanelSpec.PanelType panelType)
To show or hide a panel according to the
PanelType
public boolean isHiddenPanel(PanelSpec.PanelType panelType) RReturn the current value in setPanelHidden.

Figure 4-2

Note: To show or hide a specific panel through APIs, please mark sure the corresponding features in the configuration file is set to “true“. Otherwise, the API settings will not have any effect.

In this section, we only give an example to show you how to show or hide a specific panel through APIs in the “complete_pdf_viewer” demo found in the “samples” folder. Just take the “Outline” panel as an example, and for others panels, you only need to change the PanelType. The corresponding relation between panels and PanelType are as follows:

PanelPanelType
Reading Bookmarks PanelSpec.PanelType.ReadingBookmarks
OutlinePanelSpec.PanelType.Outline
AnnotationsPanelSpec.PanelType.Annotations
Attachments PanelSpec.PanelType.Attachments

Load the “complete_pdf_viewer” demo in Android Studio. Add the sample code to the “PDFReaderFragment.java” file (after the code “mUiExtensionsManager = new UIExtensionsManager(getActivity().getApplicationContext(), pdfViewerCtrl, config);”).

Example: Add an item in the left top bar at the second position to control whether to show or hide the “Outline” panel.

BaseItemImpl mTopItem = new BaseItemImpl(getActivity());
mTopItem.setImageResource(R.drawable.rd_annot_item_delete_selector);
mTopItem.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mUiExtensionsManager.isHiddenPanel(PanelSpec.PanelType.Outline)){
            mUiExtensionsManager.setPanelHidden(false, PanelSpec.PanelType.Outline);
            UIToast.getInstance(getActivity()).show("show Outline");
        } else {
            mUiExtensionsManager.setPanelHidden(true, PanelSpec.PanelType.Outline);
            UIToast.getInstance(getActivity()).show("hide outline");
        }
    }
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, mTopItem, 1);

Here, we add a button in the top bar to try this function. Click the button, if the “Outline” panel exists, then hides it, otherwise shows it.

After running the demo, click the “delete” button, it will pop up “hide Outline” as follows:

Then, tap List in the bottom bar, and you will see the “Outline” panel has been hidden (See Figure 4-4 ).

Figure 4-4

For Reading Bookmarks, Annotations, and Attachments panels, you only need to change the PanelType. Just try it.

Customizing to show/hide the UI elements in the View seting bar

To show or hide the UI elements in the View setting bar (See Figure 4-5, just clicks View at the bottom bar to find it), you only need to use the following API:

public void setVisibility(int type, int visibility)

Figure 4-5

The value of the parameter “type” can be set as follows, which maps the items in the View setting bar

typeinteger
IMultiLineBar.TYPE_LIGHT1
IMultiLineBar.TYPE_DAYNIGHT2
IMultiLineBar.TYPE_SYSLIGHT4
IMultiLineBar.TYPE_SINGLEPAGE8
IMultiLineBar.TYPE_CONTINUOUSPAGE16
IMultiLineBar.TYPE_THUMBNAIL32
IMultiLineBar.TYPE_LOCKSCREEN64
IMultiLineBar.TYPE_REFLOW 128
IMultiLineBar.TYPE_CROP 256
IMultiLineBar.TYPE_FACING_MODE288
IMultiLineBar.TYPE_COVER_MODE320
IMultiLineBar.TYPE_PANZOOM384

The value of the parameter “visibility” can be set as follows:

visibilityintegerdescription
View.VISIBLE0The view is visible.
View.INVISIBLE4This view is invisible, but it still takes up space for layout purposes.
View.GONE 8This view is invisible, and it doesn't take any space for layout

In this section, we only take “Reflow” item as an example to show you how to show or hide the UI elements in the View setting bar through APIs in the “complete_pdf_viewer” demo found in the “samples” folder. For other UI elements, you only need to change the type.

Load the “complete_pdf_viewer” demo in Android Studio. Add the sample code to the “PDFReaderFragment.java” file file (after the code “mUiExtensionsManager = new UIExtensionsManager(getActivity().getApplicationContext(), pdfViewerCtrl, config);”).

Example 1: To hide the Reflow item in the View setting bar without changing the layout.

mUiExtensionsManager.getSettingBar().setVisibility(IMultiLineBar.TYPE_REFLOW, View.INVISIBLE);

Before:

After:

Example 2: To hide the Reflow item in the View setting bar with changing the layout.

mUiExtensionsManager.getSettingBar().setVisibility(IMultiLineBar.TYPE_REFLOW, View.GONE);

Before:

After:

For other items in the View setting bar, you can refer to the above example, and just need to change the value of the parameter “type” in setVisibility interface.

To show one of the UI elements in the View setting bar, just set the value of the parameter “visibility” in setVisibility interface to “View.VISIBLE“.

Customizing to show/hide the UI elements in the More Menu view

To show or hide the More Menu item, please see “Customizing top/bottom bar” (see example 10).

To show or hide the UI elements in the More Menu view (See Figure 4-6, just click at the menu icon at the right top bar to find it), you can use the following APIs listed in the Table 4-3.

Table 4-3

void setGroupVisibility(int visibility, int tag)Set the enabled state of group according to "tag".
void setItemVisibility(int visibility, int groupTag, int itemTag);Set the enabled state of item according to "groupTag" and "itemTag".

Figure 4-6

The value of the parameter “tag” in the setGroupVisibility interface or the “groupTag” in the setItemVisibility interface can be set as follows:

taginteger
GROUP_FILE100
GROUP_PROTECT101
GROUP_FORM102
GROUP_PRINT103

The value of the parameter “itemTag” in the setItemVisibility interface can be set as follows:

groupTagitemTaginteger
GROUP_FILEITEM_DOCINFO0
GROUP_FILEITEM_REDUCE_FILE_SIZE 1
GROUP_PROTECTITEM_PASSWORD0
GROUP_PROTECTITEM_REMOVESECURITY_PASSWORD 4
GROUP_FORMITEM_RESET_FORM0
GROUP_FORMITEM_IMPORT_FORM1
GROUP_FORMITEM_EXPORT_FORM2
GROUP_PRINTITEM_PRINT_FILE0

The value of the parameter “visibility” in the setGroupVisibility and setItemVisibility interfaces can be set as follows:

visibilityintegerdescription
View.VISIBLE0The view is visible.
View.INVISIBLE4This view is invisible, but it still takes up space for layout purposes.
View.GONE 8This view is invisible, and it doesn't take any space for layout

Note: For setItemVisibility interface, if you want to show or hide an itemTag, please make sure the corresponding groupTag has been set to “View.VISIBLE“. Otherwise, the settings will not have any effect.

In this section, we only take “GROUP_FILE” (File in the view) and “ITEM_DOCINFO” (Properties in the view) as an example to show you how to show or hide the UI elements in the More Menu view through APIs in the “complete_pdf_viewer” demo found in the “samples” folder. For other UI elements, you can refer to the following examples and only need to change the parameter value in the setGroupVisibility and setItemVisibility interfaces.

Load the “complete_pdf_viewer” demo in Android Studio. Add the sample code to the “PDFReaderFragment.java” file file (after the code “mUiExtensionsManager = new UIExtensionsManager(getActivity().getApplicationContext(), pdfViewerCtrl, config);”).

Example 1: Hide the “File” in the More Menu view without changing the layout.

// Get MenuViewImpl from MoreMenuModule.
MoreMenuModule moreMenuModule = (MoreMenuModule) mUiExtensionsManager.getModuleByName(Module.MODULE_MORE_MENU);
MenuViewImpl menuView = (MenuViewImpl) moreMenuModule.getMenuView();
 
menuView.setGroupVisibility(View.INVISIBLE, MoreMenuConfig.GROUP_FILE);

Before:

After:

Example 2: Hide the “File” in the More Menu view with changing the layout.

// Get MenuViewImpl from MoreMenuModule.
MoreMenuModule moreMenuModule = (MoreMenuModule) mUiExtensionsManager.getModuleByName(Module.MODULE_MORE_MENU);
MenuViewImpl menuView = (MenuViewImpl) moreMenuModule.getMenuView();
 
menuView.setGroupVisibility(View.GONE, MoreMenuConfig.GROUP_FILE);

Before:

After:

Example 3: Hide the “Properties” in the More Menu view without changing the layout.

// Get MenuViewImpl from MoreMenuModule.
MoreMenuModule moreMenuModule = (MoreMenuModule) mUiExtensionsManager.getModuleByName(Module.MODULE_MORE_MENU);
MenuViewImpl menuView = (MenuViewImpl) moreMenuModule.getMenuView();
 
menuView.setItemVisibility(View.INVISIBLE, MoreMenuConfig.GROUP_FILE, MoreMenuConfig.ITEM_DOCINFO);

Before:

After:

Example 4: Hide the “Properties” in the More Menu view with changing the layout.

// Get MenuViewImpl from MoreMenuModule.
MoreMenuModule moreMenuModule = (MoreMenuModule) mUiExtensionsManager.getModuleByName(Module.MODULE_MORE_MENU);
MenuViewImpl menuView = (MenuViewImpl) moreMenuModule.getMenuView();
 
menuView.setItemVisibility(View.GONE, MoreMenuConfig.GROUP_FILE, MoreMenuConfig.ITEM_DOCINFO);

Before:

After:

For other items in the More Menu view, you can refer to the above examples, and just need to change the parameter value in the setGroupVisibility and setItemVisibility interfaces.

To show one of the UI elements in the More Menu view, just set the value of the parameter “visibility” in setVisibility and setItemVisibility interfaces to “View.VISIBLE“.

Customize UI implementation through source code

In the previous sections, we have introduced how to customize the UI elements through APIs or configuration file or APIs in detail. Those changes are in the context of the built-in UI framework of Foxit PDF SDK for Android. If you do not want to use the ready-made UI framework, you can redesign it through modifying the source code of the UI Extensions Component.

To customize the UI implementation through source code, you need to follow these steps:

First, add the following files into your app. They are all found in the “libs” folder.

  • uiextensions_src project – It is an open source library that contains some ready-to-use UI module implementations, which can help developers rapidly embed a fully functional PDF reader into their Android app. Of course, developers are not forced to use the default UI, they can freely customize and design the UI for their specific apps through the “uiextensions_src” project.
  • FoxitRDK.aar – contains JAR package which includes all the Java APIs of Foxit PDF SDK for Android, as well as the underlying “.so” libraries. The “.so” library is the heart of the SDK including the core functionalities of Foxit PDF SDK for Android. It is built separately for each architecture, and currently available for armeabi-v7a, arm64-v8a, x86, and x86_64.

Note: The uiextensions_src project has a dependency on FoxitRDK.aar. It is best to put them in the same directory. If they are not in the same directory, you will need to modify the reference path in the “build.gradle” file of the uiextensions_src project manually.

Second, find the specific layout XML files that you want to customize in the uiextensions_src project, then modify them based on your requirements.

Now, for your convenience, we will show you how to customize the UI implementation in the “viewer_ctrl_demo” project found in the “samples” folder.

UI Customization Example

Step 1:

Add the uiextensions_src project into the demo making sure that it is in the same folder as the FoxitRDK.jar file. This folder should already be in the right location if you have not changed the default folder hierarchy.

Note: The demo already includes references to the FoxitRDK.aar files, so we just need to add the uiextensions_src project through configuring the “settings.gradle” file. When to include the uiextensions_src project as a dependency, the reference to the FoxitRDKUIExtensions.aar needs to be removed.

Load the “viewer_ctrl_demo” in Android Studio. Then, follow the steps below:

a) In the “settings.gradle” file, add the following code to include the uiextensions_src project.

settings.gradle:

include ':app'
include ':uiextensions_src'
project(':uiextensions_src').projectDir = new File('../../libs/uiextensions_src/')

Rebuild the gradle, then the uiextensions_src project will be added as shown in Figure 4-7.

Figure 4-7

b) Include the uiextensions_src project as a dependency into the demo. Inside the app’s “build.gradle” file, add the compile project(“:uiextensions_src”) line and comment out the compile(name:’FoxitRDKUIExtensions’, ext:’aar’) line as follows:

dependencies {
    implementation 'com.google.android:multidex:0.1'
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    implementation (name: 'FoxitRDK', ext: 'aar')
    implementation project(":uiextensions_src")
    // implementation(name:'FoxitRDKUIExtensions', ext:'aar')
}

After making the change, rebuild this gradle. Then, select “File -> Project Structure…” to open the Project Structure dialog. In the dialog click “Modules -> app“, and select the Dependencies option, then you can see that the demo has a dependency on the uiextensions_src project as shown in Figure 4-8.

Figure 4-8

Congratulations! You have completed the first step.
Step 2:
Find and modify the layout files related to the UI that you want to customize.

Now we will show you a simple example that changes one button’s icon in the search panel as shown in Figure 4-9.

Figure 4-9

To replace the icon we only need to find the place which stores the icon for this button, then use another icon with the same name to replace it.

In the project, click “uiextensions_src -> src -> main -> res -> layout” as shown in Figure 4-10.

Figure 4-10

In the layout list, find the “search_layout.xml” file, and double-click it. Find the button in the Preview window, and click it to navigate to the related code as shown in Figure 4-11.

Figure 4-11

After finishing the three steps described in the above picture, go to “search_result_selector.xml” as shown in Figure 4-12. We can see that the icon is stored in the “drawable-xxx” folder with the name of “search_result.png” by holding Ctrl and left-clicking on “search_result”. Just replace it with your own icon.

Note: Foxit PDF SDK for Android provides three sets of icons for devices with different DPI requirements to make sure that your apps can run smoothly on every device.

Figure 4-12

For example, we use the icon of the search next button (“search_next.png” stored in the same folder with “search_result.png”) to replace it. Then, rerun the demo, try the search feature and we can see that the icon of the bottom search button has changed as shown in Figure 4-13.

Figure 4-13

This is just a simple example to show how to customize the UI implementation. You can refer to it and feel free to customize and design the UI for your specific apps through the uiextensions_src project.

Creating a custom tool

With Foxit PDF SDK for Android, creating a custom tool is a simple process. There are several tools implemented in the UI Extensions Component already. These tools can be used as a base for developers to build upon or use as a reference to create a new tool. In order to create your own tool quickly, we suggest you take a look at the uiextensions_src project found in the “libs” folder.

To create a new tool, the most important step is to create a Java class that implements the “ToolHandler.java” interface.

In this section, we will make a Regional Screenshot Tool to show how to create a custom tool with Foxit PDF SDK for Android. This tool can help the users who only want to select an area in a PDF page to capture, and then save it as an image. Now, let’s do it.

For convenience, we will build this tool based on the “viewer_ctrl_demo” project found in the “samples” folder. Steps required for implementing this tool are as follows:

  • Create a Java class named ScreenCaptureToolHandler that implements the “ToolHandler.java” interface.
  • Handle the onTouchEvent and onDraw events.
  • Instantiate a ScreenCaptureToolHandler object, and then register it to the tool manager.
  • Set the ScreenCaptureToolHandler object as the current tool handler.

Step 1:
Create a Java class named ScreenCaptureToolHandler that implements the “ToolHandler.java” interface.

a) Load the “viewer_ctrl_demo” project in Android Studio. Create a Java class named “ScreenCaptureToolHandler” in the “com.foxit.pdf.viewctrl” package.

b) Let the ScreenCaptureToolHandler.java class implement the ToolHandler interface as shown in Figure 5-1.

Figure 5-1

Step 2:
Handle the onTouchEvent and onDraw events.

Update ScreenCaptureToolHandler.java as follows:

package com.foxit.pdf.pdfviewer;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.widget.Toast;
 
import com.foxit.sdk.PDFViewCtrl;
import com.foxit.sdk.PDFException;
import com.foxit.sdk.common.Progressive;
import com.foxit.sdk.common.fxcrt.Matrix2D;
import com.foxit.sdk.pdf.PDFPage;
import com.foxit.sdk.common.Renderer;
import com.foxit.uiextensions.ToolHandler;
import com.foxit.uiextensions.UIExtensionsManager;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class ScreenCaptureToolHandler implements ToolHandler {
 
    private Context mContext;
    private PDFViewCtrl mPdfViewCtrl;
 
    public ScreenCaptureToolHandler(Context context, PDFViewCtrl pdfViewCtrl) {
        mPdfViewCtrl = pdfViewCtrl;
        mContext = context;
    }
 
    @Override
    public String getType() {
        return "";
    }
 
    @Override
    public void onActivate() {
 
    }
 
    @Override
    public void onDeactivate() {
 
    }
 
    private PointF mStartPoint = new PointF(0, 0);
    private PointF mEndPoint = new PointF(0, 0);
    private PointF mDownPoint = new PointF(0, 0);
    private Rect mRect = new Rect(0, 0, 0, 0);
    private RectF mNowRect = new RectF(0, 0, 0, 0);
    private int mLastPageIndex = -1;
 
    // Handle OnTouch event
    @Override
    public boolean onTouchEvent(int pageIndex, MotionEvent motionEvent) {
 
        // Get the display view point in device coordinate system
        PointF devPt = new PointF(motionEvent.getX(), motionEvent.getY());
        PointF point = new PointF();
        // Convert display view point to page view point.
        mPdfViewCtrl.convertDisplayViewPtToPageViewPt(devPt, point, pageIndex);
        float x = point.x;
        float y = point.y;
 
        switch (motionEvent.getAction()) {
            // Handle ACTION_DOWN event: get the coordinates of the StartPoint.
            case MotionEvent.ACTION_DOWN:
                if (mLastPageIndex == -1 || mLastPageIndex == pageIndex) {
                    mStartPoint.x = x;
                    mStartPoint.y = y;
                    mEndPoint.x = x;
                    mEndPoint.y = y;
                    mDownPoint.set(x, y);
                    if (mLastPageIndex == -1) {
                        mLastPageIndex = pageIndex;
                    }
                }
                return true;
 
            // Handle ACTION_Move event.
            case MotionEvent.ACTION_MOVE:
                if (mLastPageIndex != pageIndex)
                    break;
                if (!mDownPoint.equals(x, y)) {
                    mEndPoint.x = x;
                    mEndPoint.y = y;
 
                    // Get the coordinates of the Rect.
                    getDrawRect(mStartPoint.x, mStartPoint.y, mEndPoint.x, mEndPoint.y);
 
                    // Convert the coordinates of the Rect from float to integer.
                    mRect.set((int) mNowRect.left, (int) mNowRect.top, (int) mNowRect.right, (int) mNowRect.bottom);
 
                    // Refresh the PdfViewCtrl, then the onDraw event will be triggered.
                    mPdfViewCtrl.refresh(pageIndex, mRect);
                    mDownPoint.set(x, y);
                }
                return true;
 
            // Save the selected area as a bitmap.
            case MotionEvent.ACTION_UP:
                if (mLastPageIndex != pageIndex)
                    break;
                if (!mStartPoint.equals(mEndPoint.x, mEndPoint.y)) {
                    renderToBmp(pageIndex, "/mnt/sdcard/ScreenCapture.bmp");
                    Toast.makeText(mContext, "The selected area was saved as a bitmap stored in the /mnt/sdcard/ScreenCapture.bmp", Toast.LENGTH_LONG).show();
                }
                mDownPoint.set(0, 0);
                mLastPageIndex = -1;
                return true;
            default:
                return true;
        }
        return true;
    }
 
    // Save a bimap to a specified path.
    public static void saveBitmap(Bitmap bm, String outPath) throws IOException {
        File file = new File(outPath);
        file.createNewFile();
 
        FileOutputStream fileout = null;
        try {
            fileout = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
 
        bm.compress(Bitmap.CompressFormat.JPEG, 100, fileout);
        try {
            fileout.flush();
            fileout.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    // Render the selected area to a bitmap.
    private void renderToBmp(int pageIndex, String filePath) {
        try {
            PDFPage page = mPdfViewCtrl.getDoc().getPage(pageIndex);
 
            mPdfViewCtrl.convertPageViewRectToPdfRect(mNowRect, mNowRect, pageIndex);
            int width = (int) page.getWidth();
            int height = (int) page.getHeight();
 
            Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            bmp.eraseColor(Color.WHITE);
 
            // Create a Renderer object
            Renderer renderer = new Renderer(bmp, true);
 
            // Get the display matrix.
            Matrix2D matrix = page.getDisplayMatrix(0, 0, width, height, 0);
            Progressive progress = renderer.startRender(page, matrix, null);
            int state = Progressive.e_ToBeContinued;
            while (state == Progressive.e_ToBeContinued) {
                state = progress.resume();
            }
 
            // Create a bitmap with the size of the selected area.
            bmp = Bitmap.createBitmap(bmp, (int) mNowRect.left, (int) (height - mNowRect.top), (int) mNowRect.width(), (int) Math.abs(mNowRect.height()));
            try {
                saveBitmap(bmp, filePath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (PDFException e) {
            e.printStackTrace();
        }
    }
 
    //Get the coordinates of a Rect.
    private void getDrawRect(float x1, float y1, float x2, float y2) {
        float minx = Math.min(x1, x2);
        float miny = Math.min(y1, y2);
        float maxx = Math.max(x1, x2);
        float maxy = Math.max(y1, y2);
 
        mNowRect.left = minx;
        mNowRect.top = miny;
        mNowRect.right = maxx;
        mNowRect.bottom = maxy;
    }
 
    @Override
    public boolean onLongPress(int i, MotionEvent motionEvent) {
        return false;
    }
 
    @Override
    public boolean onSingleTapConfirmed(int i, MotionEvent motionEvent) {
        return false;
    }
 
    //Handle the drawing event.
    @Override
    public void onDraw(int pageIndex, Canvas canvas) {
        if (((UIExtensionsManager) mPdfViewCtrl.getUIExtensionsManager()).getCurrentToolHandler() != this)
            return;
        if (mLastPageIndex != pageIndex) {
            return;
        }
        canvas.save();
        Paint mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.BLUE);
        mPaint.setAlpha(200);
        mPaint.setStrokeWidth(3);
        canvas.drawRect(mNowRect, mPaint);
        canvas.restore();
    }
}

Step 3:
Instantiate a ScreenCaptureToolHandler object and then register it to the UIExtensionsManager.

private ScreenCaptureToolHandler screenCapture = null;
...
screenCapture = new ScreenCaptureToolHandler(mContext, parent, pdfViewCtrl);
uiExtensionsManager.registerToolHandler(screenCapture);

Step 4:

Set the ScreenCaptureToolHandler object as the current tool handler.

uiExtensionsManager.setCurrentToolHandler(screenCapture);

Now, we have really finished creating a custom tool. In order to see what the tool looks like, we need to make it run. Just add an action item and add the code referred in Step 3 and Step 4 to MainActivity.java.

First, add an action item in Main.xml found in “app/src/main/res/menu” as follows.

<item android:id="@+id/ScreenCapture"
   android:title="@string/screencapture"></item>

In “app/src/main/res/values/strings.xml”, add the following string:

<string name="screencapture">ScreenCapture</string>

Then, add the following code to the onActionItemClicked() function in MainActivity.java.

if (itemId == R.id.ScreenCapture) {
    if (screenCapture == null) {
        screenCapture = new ScreenCaptureToolHandler(mContext, parent, pdfViewCtrl);
        uiExtensionsManager.registerToolHandler(screenCapture);
    }
    uiExtensionsManager.setCurrentToolHandler(screenCapture);
}

Please remember to instantiate a ScreenCaptureToolHandler object at first, like (private ScreenCaptureToolHandler screenCapture = null;).

After finishing all of the above work, build and run the demo.

Note Here, we run the demo on an AVD targeting 8.1. Please make sure you have pushed the “Sample.pdf” document into the created folder “input_files” of the emulator’s SD card.

After building the demo and installing the APK on the emulator successfully, tap Allow on the pop-up windows to allow the demo to access files on the device. Click anywhere on the opened document to display the Contextual Action bar, and click the overflow button(top-right of the screen) to find the ScreenCapture action button as shown in Figure 5 2.

And find the ScreenCapture action button as shown in Figure 5-2.

Figure 5-2

Click ScreenCapture, long press and select a rectangular area, and then a message box will be popped up as shown in Figure 5-3. It shows where the bitmap (selected area) was saved to.

Figure 5-3

In order to verify whether the tool captures the selected area successfully, we need to find the screenshot. Open the Android Device Monitor, we can see the screenshot named “ScreenCapture.bmp” in the SD card as shown in Figure 5-4.

Figure 5-4

Pull the ScreenCapture.bmp from the emulator, we can see the image as shown in Figure 5-5.

Figure 5-5

As you can see we have successfully created a Regional Screenshot Tool. This is just an example to show how to create a custom tool with Foxit PDF SDK for Android. You can refer to it or our demos to develop the tools you want.

Technical Support

Reporting Problems

Foxit offers 24/7 support for its products and are fully supported by the PDF industry’s largest development team of support engineers. If you encounter any technical questions or bug issues when using Foxit PDF SDK for Android, please submit the problem report to the Foxit support team at http://tickets.foxitsoftware.com/create.php. In order to better help you solve the problem, please provide the following information:

  • Contact details
  • Foxit PDF SDK for Android product and version
  • Your Operating System and IDE version
  • Detailed description of the problem
  • Any other related information, such as log file or error screenshot

Contact Information

You can contact Foxit directly, please use the contact information as follows:

Foxit Support:

Sales Contact:

  • Phone: 1-866-680-3668
  •  Email: sales@foxitsoftware.com

Support & General Contact:

  • Phone: 1-866-MYFOXIT or 1-866-693-6948
  • Email: support@foxitsoftware.com
Updated on August 22, 2018

Was this article helpful?

Related Articles