Search

Searching using keywords

Here are the invocation attributes that you use to search with keywords:

Attribute Value

Target ID

sys.search

Action

bb.action.OPEN

MIME type

All supported files

URI

search://?term=<keywords>, where keywords are free-form text

Integrating your app with the Search app

If your app includes data that users can search for, you can integrate it with the Search app on a device. There are two ways that your app can appear in the Search app:

Extended search
When a user types a search term in the Search app, the user can extend the search to other apps on the device (for example, Help, Maps, BlackBerry World, and so on). The Search app invokes the app that the user chooses (the target app) and passes the search term to the app in the invocation request. The target app is responsible for displaying the search results. The list of target apps appears in the Extend Search section at the bottom of the Search app, and you can register your app to be part of this list.
Active search
As a user types a search term in the Search app, search results are displayed dynamically. When the user taps a result, a card is displayed or an app is started based on the result that the user tapped. These active search results are categorized in sections that describe the type of result, such as Browser, Messages, and Places. You can register your app to be part of the list of active search results.

In later releases of the BlackBerry 10 OS, the Search app is also known as BlackBerry Assistant.

Registering for extended search

To register your app as an invocation target for extended search, here's how you can specify your app in the config.xml file:

<invoke-target id="com.blackberry.search.extended.test1">
   <invoke-target-type>APPLICATION</invoke-target-type>
   <filter>
      <action>bb.action.SEARCH.EXTENDED</action>
      <mime-type>application/vnd.bb.search.criteria</mime-type>
   </filter>
</invoke-target>

When your app is registered, the Search app displays your app in the Extend Search section using your app’s name and icon. Your app receives any search requests as invocation requests. The search string is delivered in the data attribute of the request as an in-band transfer.

Registering for active search

To register your app as an invocation target for active search, here's how you can specify your app in the config.xml file:

<invoke-target id="com.blackberry.search.asyoutype.test1">
   <invoke-target-type>APPLICATION</invoke-target-type>
   <filter>
      <action>bb.action.SEARCH.SOURCE</action>
      <mime-type>application/vnd.bb.search.db.criteria</mime-type>
   </filter>
</invoke-target>

When your app is registered, the Search app displays your app in one of the active search categories using your app’s name and icon. The Search app discovers and displays your app dynamically as a data source or category (for example, alongside the Messages or Calendar apps). When the user types a search term, the Search app queries a database in your app for results and displays the results in the appropriate category. When the user taps a search result, an invocation request is sent to your app so that it can display the details of that result.

When you register your app for active search, your app must provide searchable data for the Search app to access. The BlackBerry 10 OS includes the /sharewith/search/ folder for an app to share its search data (for example, /accounts/1000/appdata/myapp/sharewith/search/). The Search app has read-only access to this folder, and your app must provide a searchable database in this folder to let the Search app perform queries.

For more information about folders in the BlackBerry 10 OS, see File system access.

Requirements for the search database

There are a few rules that you must follow when you create the search database:

  • The database must be an SQLite3 database and the database file name must be search.db (for example, /accounts/1000/appdata/myapp/sharewith/search/search.db).

  • The search.db database file must include two tables:
    • search: This table is a full-text search (FTS) table that contains the search data.
    • search_info: This table contains information that isn't searchable but is required by the Search app to render, view, or sort the search results. For example, this table might provide a timestamp, an icon, and an invocation URI for each result.
    You can include other tables in the search.db file, but they are optional and depend on the features of your app.

  • The search table must meet the following criteria:
    • It must be an FTS table, which provides the Search app with behavior and search results that are consistent with other data sources.
    • It must include the title and description columns to store searchable data. The Search app uses the data in these columns to display the search results. You should keep the data in these columns small enough to be displayed correctly, but large enough to provide useful information to users.
    • It must use TOKENIZE=icu instead of the default simple tokenizer. This tokenizer provides consistency across data sources and helps to improve the quality of search results in certain languages, such as Chinese.
    • It can have as many other columns as are required to support the features in your app.

    Here's an example of an SQL creation script that you can use to create the search table:

    CREATE VIRTUAL TABLE search USING fts4 (
        title, description,
        <optional app-specific columns>,
        TOKENIZE=icu);
  • The search_info table can optionally include the following columns:

    icon_path
    This column contains a relative path to an image in the app sandbox folder. If this value is empty, then the Search app displays an image of the app in the search result. Icons must be configured as public assets in the bar-descriptor.xml file so that they're stored in the /app/public/ folder on the device. For example, a valid icon path is /app/public/search_icon.png.
    uri
    This column contains an unbound URI that can be used to invoke a specific result. If no URI is provided, the app is invoked with a result ID as the in-band data, which is discussed in Handling an invocation request from active search below.
    timestamp
    This column contains a timestamp in Epoch format. This timestamp is localized and displayed in a common format, depending on the locale of the device. This column can be empty if it's not applicable in your app.
    group_id
    This column allows your app to control how search results are grouped and displayed in the Search app.

    Here's an example of an SQL creation script that you can use to create the search_info table:

    CREATE TABLE search_info (
        icon_path VARCHAR(128),
        uri VARCHAR(128),
        timestamp INTEGER NOT NULL DEFAULT 0,
        group_id INTEGER NOT NULL DEFAULT 0);
  • The search and search_info tables should be organized so that the docid column in the search table has a 1:1 relationship with the rowid column in the search_info table. For more information about how to structure these tables for your apps, see Examples.

The search.db database file that you share with the Search app can include other tables that your app uses. The Search app reads only the search and search_info tables, and the Search app is the only part of the BlackBerry 10 OS that has read-only access to the /sharewith/search/ folder. Your app is the only component that has read-write access to the data that it provides.

Handling an invocation request from active search

When your app is invoked from an active search result, the data attribute contains a result ID as an in-band transfer. Your app can use the result ID to check the search.db database file and find the corresponding record. The result ID is one of the rowid values in the search_info table.

Your app can handle the invocation as an application or a card.

Examples

The following examples show you how you can structure the search and search_info tables to provide active search results from your app.

Searching by title and description

This example shows how you can provide titles and descriptions that are searchable and displayed in active search results. It also demonstrates how your app can have additional custom columns that are also searchable. The example includes the address, phone_number, and mobile_number columns, as well as the required title and description columns.

DROP TABLE IF EXISTS search_info;
DROP TABLE IF EXISTS search;

CREATE TABLE search_info (icon_path VARCHAR(128),
                          uri VARCHAR(128),
                          timestamp INTEGER NOT NULL DEFAULT 0,
                          group_id INTEGER NOT NULL DEFAULT 0);
CREATE INDEX search_info_timestamp_index ON search_info(timestamp);
CREATE INDEX search_info_groupid_index ON search_info(group_id);

CREATE VIRTUAL TABLE search USING fts4 (title, description, address,
                                        phone_number, mobile_number,
                                        TOKENIZE=icu);

INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
    VALUES(1, "", "http://www.example.com", 0, 1);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
    VALUES(2, "app/public/test1.jpg", "", 0, 2);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
    VALUES(3, "", "", 0, 3);

INSERT INTO search(docid, title, description, address, phone_number,
                   mobile_number)
    VALUES(1, "Westlee Barichak", "BlackBerry", "4701 Tahoe Blvd.",
           "519-555-0100", "519-555-0167");

INSERT INTO search(docid, title, description, address, phone_number,
                   mobile_number)
    VALUES(2, "Karla Tetzel", "BlackBerry", "619 Kumpf Dr.",
           "519-555-0123", "519-555-0184");

INSERT INTO search(docid, title, description, address, phone_number,
                   mobile_number)
    VALUES(3, "Denise Marshall", "BlackBerry", "1001 Farrar Road",
           "519-555-0128", "519-555-0189");

Here's an example of active search results for this data:

rowid title description icon_path uri timestamp group_id
3 Denise Marshall BlackBerry     0 3
1 Westlee Barichak BlackBerry   http://www.example.com 0 1

Grouping search results

This example shows how you can group active search results from your app. Grouping is usually required for instant messaging searches. For example, BBM uses this type of grouping; you can search for content inside any message in a conversation, but the active search results display only the last message of the conversation. You can control this logic in your own app by using the same group_id value for each entry in the search_info table.

DROP TABLE IF EXISTS search_info;
DROP TABLE IF EXISTS search;

CREATE TABLE search_info (icon_path VARCHAR(128),
                          uri VARCHAR(128),
                          timestamp INTEGER NOT NULL DEFAULT 0,
                          group_id INTEGER NOT NULL DEFAULT 0);
CREATE INDEX search_info_timestamp_index ON search_info(timestamp);
CREATE INDEX search_info_groupid_index ON search_info(group_id);

CREATE VIRTUAL TABLE search USING fts4 (title, description,
                                        TOKENIZE=icu);

INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(1, "app/public/con1.jpg", "", 1365403000, 1);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(2, "app/public/con1.jpg", "", 1365303001, 1);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(3, "app/public/con2.jpg", "", 1365203002, 2);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(4, "app/public/con2.jpg", "", 1365103003, 2);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(5, "app/public/con2.jpg", "", 1365003004, 2);

INSERT INTO search(docid, title, description)
   VALUES(1, "IM conversation 1", "Test message 1, conversation 1");
INSERT INTO search(docid, title, description)
   VALUES(2, "IM conversation 1", "Test message 2, conversation 1");
INSERT INTO search(docid, title, description)
   VALUES(3, "IM conversation 2", "Test message 1, conversation 2");
INSERT INTO search(docid, title, description)
   VALUES(4, "IM conversation 2", "Test message 2, conversation 2");
INSERT INTO search(docid, title, description)
   VALUES(5, "IM conversation 2", "Test message 3, conversation 2");

Here's an example of active search results for this data:

rowid title description icon_path uri timestamp group_id
2 IM conversation 1 Test message 2, conversation 1 app/public/con1.jpg   1365303001 1
5 IM conversation 2 Test message 3, conversation 2 app/public/con2.jpg   1365003004 2

Controlling grouping manually

This example illustrates how the Search app doesn't force apps to group their active search results. If you use the same data from the Grouping search results example above but use unique values for each group_id, then the Search app displays multiple results even if they are in the same conversation. This behavior allows you to control how search results are grouped and displayed.

DROP TABLE IF EXISTS search_info;
DROP TABLE IF EXISTS search;

CREATE TABLE search_info (icon_path VARCHAR(128),
                          uri VARCHAR(128),
                          timestamp INTEGER NOT NULL DEFAULT 0,
                          group_id INTEGER NOT NULL DEFAULT 0);
CREATE INDEX search_info_timestamp_index ON search_info(timestamp);
CREATE INDEX search_info_groupid_index ON search_info(group_id);

CREATE VIRTUAL TABLE search USING fts4 (title, description,
                                        TOKENIZE=icu);

INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(1, "app/public/msg1.jpg", "", 1365403000, 1);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(2, "app/public/msg2.jpg", "", 1365403001, 2);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(3, "app/public/msg3.jpg", "", 1365403002, 3);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(4, "app/public/msg4.jpg", "", 1365403003, 4);
INSERT INTO search_info(rowid, icon_path, uri, timestamp, group_id)
   VALUES(5, "app/public/msg5.jpg", "", 1365403004, 5);

INSERT INTO search(docid, title, description)
   VALUES(1, "IM conversation 1", "Test message 1, conversation 1");
INSERT INTO search(docid, title, description)
   VALUES(2, "IM conversation 1", "Test message 2, conversation 1");
INSERT INTO search(docid, title, description)
   VALUES(3, "IM conversation 2", "Test message 1, conversation 2");
INSERT INTO search(docid, title, description)
   VALUES(4, "IM conversation 2", "Test message 2, conversation 2");
INSERT INTO search(docid, title, description)
   VALUES(5, "IM conversation 2", "Test message 3, conversation 2");

Here's an example of active search results for this data:

rowid title description icon_path uri timestamp group_id
5 IM conversation 2 Test message 3, conversation 2 app/public/msg5.jpg   1365403004 5
4 IM conversation 2 Test message 2, conversation 2 app/public/msg4.jpg   1365403003 4
3 IM conversation 2 Test message 1, conversation 2 app/public/msg3.jpg   1365403002 3
2 IM conversation 1 Test message 2, conversation 1 app/public/msg2.jpg   1365403001 2
1 IM conversation 1 Test message 1, conversation 1 app/public/msg1.jpg   1365403000 1

Last modified: 2014-12-04



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus