Skip to content
ComPDF
DemoSampleAPI ReferenceFAQ
Guides

Configure Document State and Error Callbacks

After the basic CPDFReaderView integration is complete, viewer pages usually still need to handle these events:

  • document loading, load completion, and load failure
  • errors that occur during reading operations
  • viewer mode and gesture mode changes
  • tapping, scrolling, and page navigation events

This page groups the most commonly used callback types in the Android viewer so that page state and interaction logic can be organized more clearly.

Identify the callback type that matches the task

Callback typeWhat it solvesWhen to use it
IDocumentStatusCallbackWhether the document is loading, loaded, or failed to loadWhen the screen needs loading, empty, or error states
IPDFErrorMessageCallbackWhy a viewer action failed internallyWhen the screen needs unified error prompts or logging
OnViewModeChangedListenerWhether the current viewer working mode changedWhen toolbars and feature entry points must stay in sync
OnTouchModeChangedListenerWhether the current gesture interaction mode changedWhen drawing, screenshot, or browse-state UI must update
IReaderViewCallbackReading actions such as tapping, scrolling, and jumping pagesWhen page indicators, toolbars, or reading position must stay in sync

Register callbacks before opening the document

It is usually best to register callbacks right after CPDFReaderView is initialized and before the document is opened and bound. This ensures that:

  • loading state changes are captured from the start of the open flow
  • first-screen failures are not missed
  • mode changes and reading behavior can be handled from one consistent entry point

Listen to the document loading lifecycle

IDocumentStatusCallback is used to track the document loading flow. It is suitable for driving loading indicators, failure states, and post-load UI transitions.

java
readerView.setDocumentStatusCallback(new IDocumentStatusCallback() {
    @Override
    public void onLoading() {
        // Document is loading
    }

    @Override
    public void onLoadFailed() {
        // Document failed to load
    }

    @Override
    public void onLoadComplete() {
        // Document loading completed
        // This callback is also triggered when reloadPages() is called.
    }
});
kotlin
readerView.setDocumentStatusCallback(object : IDocumentStatusCallback {
    override fun onLoading() {
        // Document is loading
    }

    override fun onLoadFailed() {
        // Document failed to load
    }

    override fun onLoadComplete() {
        // Document loading completed
        // This callback is also triggered when reloadPages() is called.
    }
})

This callback is commonly used for page-level state transitions, for example:

  • show loading in onLoading()
  • show a retry state in onLoadFailed()
  • hide loading and reveal the viewer in onLoadComplete()

Handle viewer errors in one place

IPDFErrorMessageCallback is used to receive internal viewer errors. It is different from the return value of document.open(...).

  • document.open(...) is primarily about whether the document was opened successfully.
  • IPDFErrorMessageCallback is primarily about why an operation failed during the reading flow.

Actions such as copying content, opening links, or entering editing operations may all trigger this callback when the current conditions are not valid.

Identify common error types

Error enumDescriptionCommon scenario
NO_EMAIL_APPNo email app availableSharing a PDF to email
NO_BROWSE_APPNo browser app availableOpening a link from a PDF
NO_CONTENT_TO_PASTENothing is available to pastePaste actions
INVALID_LINKThe link is invalidThe link cannot be opened
NO_TEXT_ON_PAGEThe page has no text contentText selection or copy actions
CANNOT_EDITThe document cannot be editedThe document is permission-restricted
CANNOT_EDIT_ANNOTThe annotation cannot be editedAnnotation editing is restricted
CANNOT_EDIT_FORMThe form cannot be editedForm editing is restricted
CANNOT_ADD_ANNOTAn annotation cannot be addedThe document blocks annotation creation
CANNOT_ADD_FORMA form cannot be addedThe document blocks form creation
NOT_IN_PDFEDIT_MODEThe viewer is not in PDF edit modeContent editing is triggered in the wrong mode

Register the error callback

java
readerView.setPdfErrorMessageCallback(new IPDFErrorMessageCallback() {
    @Override
    public void onError(ErrorId errorId) {
        switch (errorId) {
            case NO_EMAIL_APP:
                Log.e("ComPDF", "No email app available");
                break;
            case NO_BROWSE_APP:
                Log.e("ComPDF", "No browser app available");
                break;
            case NO_CONTENT_TO_PASTE:
                Log.e("ComPDF", "Nothing to paste");
                break;
            case INVALID_LINK:
                Log.e("ComPDF", "Invalid link");
                break;
            case NO_TEXT_ON_PAGE:
                Log.e("ComPDF", "No text on page");
                break;
            case CANNOT_EDIT:
                Log.e("ComPDF", "Document cannot be edited");
                break;
            case CANNOT_EDIT_ANNOT:
                Log.e("ComPDF", "Annotation cannot be edited");
                break;
            case CANNOT_EDIT_FORM:
                Log.e("ComPDF", "Form cannot be edited");
                break;
            case CANNOT_ADD_ANNOT:
                Log.e("ComPDF", "Cannot add annotation");
                break;
            case CANNOT_ADD_FORM:
                Log.e("ComPDF", "Cannot add form");
                break;
            case NOT_IN_PDFEDIT_MODE:
                Log.e("ComPDF", "Not in PDF edit mode");
                break;
        }
    }
});
kotlin
readerView.setPdfErrorMessageCallback(object : IPDFErrorMessageCallback {
    override fun onError(errorId: ErrorId) {
        val message = when (errorId) {
            ErrorId.NO_EMAIL_APP -> "No email app available"
            ErrorId.NO_BROWSE_APP -> "No browser app available"
            ErrorId.NO_CONTENT_TO_PASTE -> "Nothing to paste"
            ErrorId.INVALID_LINK -> "Invalid link"
            ErrorId.NO_TEXT_ON_PAGE -> "No text on page"
            ErrorId.CANNOT_EDIT -> "Document cannot be edited"
            ErrorId.CANNOT_EDIT_ANNOT -> "Annotation cannot be edited"
            ErrorId.CANNOT_EDIT_FORM -> "Form cannot be edited"
            ErrorId.CANNOT_ADD_ANNOT -> "Cannot add annotations"
            ErrorId.CANNOT_ADD_FORM -> "Cannot add forms"
            ErrorId.NOT_IN_PDFEDIT_MODE -> "Not in PDF edit mode"
        }
        Log.e("ComPDF", message)
    }
})

If the screen already has a unified toast, snackbar, or dialog system, this callback is the right place to map error enums to a consistent UI message layer.

Distinguish ViewMode from TouchMode

ViewMode and TouchMode both affect viewer behavior, but they represent different levels of state.

Use ViewMode to track the working mode

ViewMode is a capability-level state. It indicates whether the current screen is in reading, annotation editing, form editing, or content editing mode.

When toolbars, bottom bars, or feature panels must follow the current working mode, OnViewModeChangedListener is the relevant callback.

java
readerView.setOnViewModeChangedListener(new OnViewModeChangedListener() {
    @Override
    public void onViewModeChange(ViewMode viewMode) {
        Log.d("ComPDF", "ViewMode changed: " + viewMode);
    }
});
kotlin
readerView.setOnViewModeChangedListener(object : OnViewModeChangedListener {
    override fun onViewModeChange(viewMode: ViewMode) {
        Log.d("ComPDF", "ViewMode changed: $viewMode")
    }
})

Use TouchMode to track the interaction mode

TouchMode is an interaction-level state. It indicates whether the current gesture behavior is browsing, adding annotations, taking screenshots, or erasing ink.

When the screen needs to update button states, toolbar labels, or interaction entry points based on gesture behavior, OnTouchModeChangedListener is the right callback.

Common enum values include:

Enum valueDescriptionCommon scenario
BROWSEBrowse modeDefault reading, scrolling, and zooming
ADD_ANNOTAdd annotation modeAfter annotation tools are selected
EDITEdit modeEditing text, images, or forms
SCREENSHOTScreenshot modeFull-page or partial capture
ERASE_INKErase ink modeRemoving handwritten ink
java
readerView.setOnTouchModeChangedListener(new OnTouchModeChangedListener() {
    @Override
    public void onTouchModeChanged(TouchMode touchMode) {
        Log.d("ComPDF", "TouchMode changed: " + touchMode);
    }
});
kotlin
readerView.setOnTouchModeChangedListener(object : OnTouchModeChangedListener {
    override fun onTouchModeChanged(touchMode: TouchMode) {
        Log.d("ComPDF", "TouchMode changed: $touchMode")
    }
})

Listen to reader interaction events

IReaderViewCallback is used to receive interaction events such as tapping, scrolling, and page jumps. It is suitable for synchronizing page indicators, toolbar visibility, and reading position.

MethodDescriptionTypical use
onTapMainDocArea()Tap the main document areaHide or show toolbars
onMoveToChild(int pageIndex)A page jump occursUpdate the current page indicator
onEndScroll()Scrolling endsRefresh UI or record the current position
onScrolling()Scrolling is in progressUpdate a progress state
onRecordLastJumpPageNum(int pageIndex)Record the last jumped pageRestore the last reading position
java
readerView.setReaderViewCallback(new IReaderViewCallback() {
    @Override
    public void onTapMainDocArea() {
        Log.d("ComPDF", "Tap main document area");
    }

    @Override
    public void onMoveToChild(int pageIndex) {
        Log.d("ComPDF", "Move to page: " + pageIndex);
    }

    @Override
    public void onEndScroll() {
        Log.d("ComPDF", "Scroll ended");
    }

    @Override
    public void onScrolling() {
        Log.d("ComPDF", "Scrolling");
    }

    @Override
    public void onRecordLastJumpPageNum(int pageIndex) {
        Log.d("ComPDF", "Last jump page: " + pageIndex);
    }
});
kotlin
readerView.setReaderViewCallback(object : IReaderViewCallback {
    override fun onTapMainDocArea() {
        Log.d("ComPDF", "Tap main document area")
    }

    override fun onMoveToChild(pageIndex: Int) {
        Log.d("ComPDF", "Move to page: $pageIndex")
    }

    override fun onEndScroll() {
        Log.d("ComPDF", "Scroll ended")
    }

    override fun onScrolling() {
        Log.d("ComPDF", "Scrolling")
    }

    override fun onRecordLastJumpPageNum(pageIndex: Int) {
        Log.d("ComPDF", "Last jump page: $pageIndex")
    }
})

If the main concern is page jumps and reading position synchronization, see Page Navigation.

Start with a minimal callback combination

For a standard reading screen, these three callbacks are usually enough as a first step:

  1. IDocumentStatusCallback
  2. IPDFErrorMessageCallback
  3. IReaderViewCallback

Together, they cover most viewer pages that need loading state, error handling, and interaction synchronization.

Continue reading