> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/android/search/text.md).

# Text search

Learn how to add text search functionality to your Android viewer with this comprehensive guide. Implement UI components and API for efficient text searching. The Apryse Android SDK streamlines secure

There are two parts to text searching. First is the UI component that is presented to the user. Second is an API guide to perform the text search functionality.

{% tabs %}
{% tab title="UI component" %}

## Add text search to Android viewer

Text search functionality can be added to your viewer using the text search UI component. Alternatively, you can programmatically perform text search in PDFViewCtrl.

## Prerequisites

* Set up [PDFViewCtrl](/android/open-save-document/open/view.md) and [ToolManager](/android/annotation/toolmanager-config.md) in your activity.

## Add text search using UI component

Apryse provides [`SearchToolbar`](https://sdk.apryse.com/api/android/javadoc/reference/com/pdftron/pdf/controls/SearchToolbar.html) and [`FindTextOverlay`](https://sdk.apryse.com/api/android/javadoc/reference/com/pdftron/pdf/controls/FindTextOverlay.html) as utility classes for implementing text search in your document viewer. Here is a short guide on adding text search to your activity:

1. Add the search controls to your layout, a simple example will be something like:

{% code lineNumbers="true" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

        <com.pdftron.pdf.controls.SearchToolbar android:id="@+id/searchtoolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" android:visibility="gone" app:contentInsetStart="@dimen/second_keyline" app:navigationIcon="@drawable/ic_arrow_back_white_24dp" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

        <com.pdftron.pdf.PDFViewCtrl android:id="@+id/pdfviewctrl" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:scrollbars="vertical|horizontal" />
    </LinearLayout>

    <com.pdftron.pdf.controls.FindTextOverlay android:id="@+id/find_text_view" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" />
</RelativeLayout>
```

{% endcode %}

1. In `onCreate` of your activity, set up your `SearchToolbar` and `FindTextOverlay`:

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
private PDFViewCtrl mPdfViewCtrl;
// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    // Set up the search controls in our activity
    final SearchToolbar searchToolbar = findViewById(R.id.searchtoolbar);
    final FindTextOverlay searchOverlay = findViewById(R.id.find_text_view);
    searchOverlay.setPdfViewCtrl(mPdfViewCtrl);
    searchToolbar.setSearchToolbarListener(new SearchToolbar.SearchToolbarListener() {
        @Override
        public void onExitSearch() {
            searchToolbar.setVisibility(View.GONE);
            searchOverlay.setVisibility(View.GONE);
            searchOverlay.exitSearchMode();
        }

        @Override
        public void onClearSearchQuery() {
            searchOverlay.cancelFindText();
        }

        @Override
        public void onSearchQuerySubmit(String s) {
            searchOverlay.queryTextSubmit(s);
        }

        @Override
        public void onSearchQueryChange(String s) {
            searchOverlay.setSearchQuery(s);
        }

        @Override
        public void onSearchOptionsItemSelected(MenuItem menuItem, String s) {
            int id = menuItem.getItemId();
            if (id == R.id.action_match_case) {
                boolean isChecked = menuItem.isChecked();
                searchOverlay.setSearchMatchCase(!isChecked);
                searchOverlay.resetFullTextResults();
                menuItem.setChecked(!isChecked);
            } else if (id == R.id.action_whole_word) {
                boolean isChecked = menuItem.isChecked();
                searchOverlay.setSearchWholeWord(!isChecked);
                searchOverlay.resetFullTextResults();
                menuItem.setChecked(!isChecked);
            }
        }
    });
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
private var mPdfViewCtrl: PDFViewCtrl? = null
// ...
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...
    // Set up the search controls in our activity
    val searchToolbar: SearchToolbar = findViewById(R.id.searchToolbar)
    val searchOverlay: FindTextOverlay = findViewById(R.id.find_text_view)
    searchOverlay.setPdfViewCtrl(mPdfViewCtrl!!)
    searchToolbar.setSearchToolbarListener(object : SearchToolbar.SearchToolbarListener {
    override fun onExitSearch() {
        searchToolbar.visibility = View.GONE
        searchOverlay.visibility = View.GONE
        searchOverlay.exitSearchMode()
    }

    override fun onClearSearchQuery() {
        searchOverlay.cancelFindText()
    }

    override fun onSearchQuerySubmit(s: String) {
        searchOverlay.queryTextSubmit(s)
    }

    override fun onSearchQueryChange(s: String) {
        searchOverlay.setSearchQuery(s)
    }

    override fun onSearchOptionsItemSelected(menuItem: MenuItem, s: String) {
        val id = menuItem.itemId
        if (id == R.id.action_match_case) {
        val isChecked = menuItem.isChecked
        searchOverlay.setSearchMatchCase(!isChecked)
        searchOverlay.resetFullTextResults()
        menuItem.isChecked = !isChecked
        } else if (id == R.id.action_whole_word) {
        val isChecked = menuItem.isChecked
        searchOverlay.setSearchWholeWord(!isChecked)
        searchOverlay.resetFullTextResults()
        menuItem.isChecked = !isChecked
        }
    }
    })
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

1. Show the layout

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
searchToolbar.setVisibility(View.VISIBLE);
searchOverlay.setVisibility(View.VISIBLE);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
searchToolbar.visibility = View.VISIBLE
searchOverlay.visibility = View.VISIBLE
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now when running the app, you will see a toolbar that allows you to enter search terms as well as an overlay on top of the PDFViewCtrl that navigates among search results.

![](https://226546913-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0QItsdFBmuuL9ezHimHy%2Fuploads%2Fgit-blob-458a76a40e34fcc6632629846962476e9ba5c017%2Fe03209a7fd9601c73d1ea180eea01fc2f0df581b-600x1200.gif?alt=media)

## Search results view

[`SearchResultsView`](https://sdk.apryse.com/api/android/javadoc/reference/com/pdftron/pdf/controls/SearchResultsView.html) class enables users to easily search for a query and see the results.

![](https://226546913-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0QItsdFBmuuL9ezHimHy%2Fuploads%2Fgit-blob-dbe944bce12238ddbb39e44e9942d70cfc8c9ec9%2F26e5ab9a7adb9084eddbb524fa44c1ec790c62eb-1080x2160.png?alt=media)

To set up your layout for a `SearchResultsView`, add an element to your XML layout as follows:

{% code lineNumbers="true" %}

```xml
<com.pdftron.pdf.controls.SearchResultsView android:id="@+id/searchResultsView" android:layout_width="match_parent" android:layout_height="wrap_content" />
```

{% endcode %}

Then, you need to set [`SearchResultsListener`](https://sdk.apryse.com/api/android/javadoc/reference/com/pdftron/pdf/controls/SearchResultsView.SearchResultsListener.html) to receive a callback when

* An item from the search results is clicked
* A full-text search is started and result has not yet been ready
* A search is found

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
SearchResultsView searchResultsView = view.findViewById(R.id.searchResultsView);
searchResultsView.setPdfViewCtrl(mPdfViewCtrl);
searchResultsView.setListener(searchResultsListener);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val searchResultsView = view.findViewById(R.id.searchResultsView)
searchResultsView.setPdfViewCtrl(mPdfViewCtrl)
searchResultsView.setListener(searchResultsListener)
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="API guide" %}

## Text search API for Android

To search for text in a PDF using regular expression and then apply a link annotation on the highlighted result.

{% hint style="info" %}
In this example, we add a link annotation but any other types of annotations can be applied here such as redaction annotations in the case of a search and redact workflow.
{% endhint %}

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
PDFDoc doc = new PDFDoc(filename);
TextSearch txt_search = new TextSearch();
int mode = TextSearch.e_whole_word | TextSearch.e_page_stop;
String pattern = "";

//use regular expression to find credit card number
mode |= TextSearch.e_reg_expression | TextSearch.e_highlight;
txt_search.setMode(mode);
String new_pattern = "\\d{4}-\\d{4}-\\d{4}-\\d{4}"; //or "(\\d{4}-){3}\\d{4}"
txt_search.setPattern(new_pattern);

//call Begin() method to initialize the text search.
txt_search.begin(doc, pattern, mode, -1, -1);
TextSearchResult result = txt_search.run();

if (result.getCode() == TextSearchResult.e_found) {
  //add a link annotation based on the location of the found instance
  Highlights hlts = result.getHighlights();
  hlts.begin(doc);
  while (hlts.hasNext()) {
    Page cur_page = doc.getPage(hlts.getCurrentPageNumber());
    double[] q = hlts.getCurrentQuads();
    int quad_count = q.length / 8;
    for (int i = 0; i < quad_count; ++i) {
      //assume each quad is an axis-aligned rectangle
      int offset = 8 * i;
      double x1 = Math.min(Math.min(Math.min(q[offset + 0], q[offset + 2]), q[offset + 4]), q[offset + 6]);
      double x2 = Math.max(Math.max(Math.max(q[offset + 0], q[offset + 2]), q[offset + 4]), q[offset + 6]);
      double y1 = Math.min(Math.min(Math.min(q[offset + 1], q[offset + 3]), q[offset + 5]), q[offset + 7]);
      double y2 = Math.max(Math.max(Math.max(q[offset + 1], q[offset + 3]), q[offset + 5]), q[offset + 7]);
      annots.Link hyper_link = annots.Link.create(doc, new Rect(x1, y1, x2, y2), Action.createURI(doc, "http://www.apryse.com"));
      cur_page.annotPushBack(hyper_link);
    }
    hlts.next();
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val doc = PDFDoc(filename)
val txt_search = TextSearch()
var mode = TextSearch.e_whole_word or TextSearch.e_page_stop
val pattern = ""

//use regular expression to find credit card number
mode = mode or (TextSearch.e_reg_expression or TextSearch.e_highlight)
txt_search.mode = mode
val new_pattern = "\\d{4}-\\d{4}-\\d{4}-\\d{4}" //or "(\\d{4}-){3}\\d{4}"
txt_search.setPattern(new_pattern)

//call Begin() method to initialize the text search.
txt_search.begin(doc, pattern, mode, -1, -1)
val result = txt_search.run()

if (result.code == TextSearchResult.e_found) {
  //add a link annotation based on the location of the found instance
  val hlts = result.highlights
  hlts.begin(doc)
  while (hlts.hasNext()) {
    val cur_page = doc.getPage(hlts.currentPageNumber)
    val q = hlts.currentQuads
    val quad_count = q.size / 8
    for (i in 0 until quad_count) {
      //assume each quad is an axis-aligned rectangle
      val offset = 8 * i
      val x1 = Math.min(Math.min(Math.min(q[offset + 0], q[offset + 2]), q[offset + 4]), q[offset + 6])
      val x2 = Math.max(Math.max(Math.max(q[offset + 0], q[offset + 2]), q[offset + 4]), q[offset + 6])
      val y1 = Math.min(Math.min(Math.min(q[offset + 1], q[offset + 3]), q[offset + 5]), q[offset + 7])
      val y2 = Math.max(Math.max(Math.max(q[offset + 1], q[offset + 3]), q[offset + 5]), q[offset + 7])
      val hyper_link = com.pdftron.pdf.annots.Link.create(doc, Rect(x1, y1, x2, y2), Action.createURI(doc, "http://www.apryse.com"))
      cur_page.annotPushBack(hyper_link)
    }
    hlts.next()
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

[Search PDF files for text](/android/get-started/samples.md#textsearch) Full code sample which shows how to use TextSearch to search text on PDF pages using regular expressions.
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/android/search/text.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
