Android 11 デベロッパー プレビュー 2 が公開されました。ぜひお試しのうえ、フィードバックをお寄せください

カスタム候補の追加

Android の検索ダイアログまたは検索ウィジェットを使用すると、アプリのデータから作成されたカスタム検索候補を表示できます。たとえば辞書アプリでは、その時点で入力されているテキストと一致する単語を辞書から候補として表示できます。これは極めて有用な候補です。ユーザーが求めている結果を効果的に予測して、それに即座にアクセスできるようにすることが可能です。図 1 に、カスタム候補が表示された検索ダイアログの例を示します。

作成したカスタム候補をシステム全体のクイック検索ボックスでも利用できるようにすることで、アプリ外からコンテンツにアクセスできるようになります。

このガイドに沿ってカスタム候補を追加する前に、Android の検索ダイアログまたは検索ウィジェットを実装して、アプリで検索を実行できるようにする必要があります。これらをまだ実装していない場合は、検索インターフェースの作成をご覧ください。また、コンテンツ プロバイダのドキュメントもご覧ください。

基本

図 1. カスタム検索候補が表示された検索ダイアログのスクリーンショット

ユーザーがカスタム候補を選択すると、Android システムによって Intent が検索可能アクティビティに送信されます。通常の検索クエリが ACTION_SEARCH アクションを含むインテントを送信するのに対し、カスタム候補を定義すると、ACTION_VIEW(または他の任意のインテント アクション)を使用できるほか、選択した候補に関連するデータを含めることもできます。辞書の例では、ユーザーが候補を選択すると、辞書で一致する単語を検索する代わりに、その単語の定義をアプリですぐに開くことができます。

カスタム候補を表示するには、以下の操作を行います。

  • 検索インターフェースの作成の説明に沿って、検索可能アクティビティを実装します。
  • カスタム候補を提供するコンテンツ プロバイダに関する情報を使用して検索可能構成を変更します。
  • 候補テーブルを(SQLiteDatabase などで)作成し、必須の列でテーブルをフォーマットします。
  • 候補テーブルにアクセス可能なコンテンツ プロバイダを作成し、マニフェストでそのプロバイダを宣言します。
  • ユーザーが候補(カスタム アクションとカスタムデータを含む)を選択したときに送信する Intent のタイプを宣言します。

Android システムは、検索ダイアログを表示するのと同じように、検索候補も表示します。必要なものは、システムが候補を取得できるコンテンツ プロバイダだけです。コンテンツ プロバイダの作成に慣れていない場合は、先に進む前にコンテンツ プロバイダのデベロッパー ガイドをご覧ください。

アクティビティが検索可能であり、検索候補を表示できることがシステムで確認されると、ユーザーがクエリを入力したときに次の手順が行われます。

  1. システムが検索クエリのテキスト(その時点で入力されているすべてのテキスト)を取得し、候補を管理するコンテンツ プロバイダに対してクエリを実行します。
  2. コンテンツ プロバイダが、検索クエリのテキストに関連するすべての候補を指す Cursor を返します。
  3. Cursor から提供された候補のリストが表示されます。

カスタム候補が表示された後、以下の処理が行われることがあります。

  • ユーザーが別のキーを入力するか、なんらかの方法でクエリを変更した場合、上記の手順が再実行され、必要に応じて候補のリストが更新されます。
  • ユーザーが検索を実行した場合、候補が無視され、通常の ACTION_SEARCH インテントを使用して検索クエリが検索可能アクティビティに渡されます。
  • ユーザーが候補を選択した場合、インテントが検索可能アクティビティに送信され、カスタム アクションとカスタムデータが伝達されます。これにより、アプリで候補のコンテンツを開くことができるようになります。

検索可能構成の変更

カスタム候補に対するサポートを追加するには、検索可能構成ファイルで android:searchSuggestAuthority 属性を <searchable> 要素に追加します。次に例を示します。

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_label"
        android:hint="@string/search_hint"
        android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider">
    </searchable>
    

各候補に関連付けるインテントのタイプや、コンテンツ プロバイダへのクエリのフォーマット方法によっては、追加の属性が必要になることがあります。その他のオプションの属性については、以下のセクションで説明します。

コンテンツ プロバイダの作成

カスタム候補用のコンテンツ プロバイダを作成する場合、コンテンツ プロバイダに関する予備知識が必要になります(コンテンツ プロバイダのデベロッパー ガイドに記載されています)。カスタム候補用のコンテンツ プロバイダのほとんどの部分は、他のコンテンツ プロバイダと同じです。ただし、表示する各候補では、Cursor のそれぞれの行に特定の列を含める必要があります。システムはこの列を理解および使用することで候補をフォーマットします。

ユーザーが検索ダイアログまたは検索ウィジェットへの入力を開始すると、システムが、文字が入力されるたびに query() を呼び出して、コンテンツ プロバイダに対して候補のクエリを実行します。query() の実装では、コンテンツ プロバイダが候補データを検索して、適切な候補と判断した行を指す Cursor を返す必要があります。

カスタム候補用のコンテンツ プロバイダの作成方法について詳しくは、次の 2 つのセクションをご覧ください。

候補のクエリの処理
システムからコンテンツ プロバイダにリクエストを送信する方法とリクエストの処理方法
候補テーブルの作成
各クエリで返される Cursor にシステムが求める列を定義する方法

候補のクエリの処理

システムは、コンテンツ プロバイダに候補をリクエストするときに、コンテンツ プロバイダの query() メソッドを呼び出します。このメソッドの実装では、候補データを検索し、適切と思われる候補を指す Cursor を返すようにする必要があります。

システムが query() メソッドに渡すパラメータの概要を以下に示します(渡す順に記載)。

uri
常に次の形式のコンテンツ Uri です。
    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY
    

デフォルトの動作では、システムがこの URI を渡し、それにクエリテキストを付加します。次に例を示します。

    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY/puppies
    

最後のクエリテキストは URI エンコード ルールを使用してエンコードされるため、検索を実行する前にデコードが必要になる場合があります。

optional.suggest.path の部分は、検索可能構成ファイルで android:searchSuggestPath 属性を使用してこのようなパスを設定した場合にのみ URI に含めます。これが必要になるのは、複数の検索可能アクティビティで同じコンテンツ プロバイダを使用している場合だけです。その場合、候補クエリのソースの曖昧さを解消する必要があります。

注: SUGGEST_URI_PATH_QUERY は、URI で提供されるリテラル文字列ではなく、このパスを参照する必要がある場合に使用する定数です。

projection
常に null です。
selection
検索可能構成ファイルの android:searchSuggestSelection 属性に指定されている値です。android:searchSuggestSelection 属性を宣言していない場合は null です。このパラメータを使用してクエリを取得する方法について詳しくは、以下をご覧ください。
selectionArgs
検索可能構成で android:searchSuggestSelection 属性を宣言した場合、配列の最初の(唯一の)要素として検索クエリが含まれます。android:searchSuggestSelection を宣言していない場合、このパラメータは null になります。このパラメータを使用してクエリを取得する方法について詳しくは、以下をご覧ください。
sortOrder
常に null です。

システムは検索クエリのテキストを 2 つの方法で送信できます。デフォルトの方法は、uri パラメータで渡されるコンテンツ URI の最後のパスとしてクエリテキストを含める方法です。一方、検索可能構成の android:searchSuggestSelection 属性に選択値を含めると、selectionArgs 文字列配列の最初の要素としてクエリテキストが渡されます。両方の方法の概要を以下に示します。

URI でクエリを取得する

デフォルトでは、クエリが uri パラメータ(Uri オブジェクト)の最後のセグメントとして付加されます。この場合にクエリテキストを取得するには、単に getLastPathSegment() を使用します。次に例を示します。

Kotlin

    val query: String = uri.lastPathSegment.toLowerCase()
    

Java

    String query = uri.getLastPathSegment().toLowerCase();
    

これにより、Uri の最後のセグメント(ユーザーが入力したクエリテキスト)が返されます。

選択引数でクエリを取得する

URI を使用する代わりに、query() メソッドで検索の実行に必要な要素をすべて受け取り、selection パラメータと selectionArgs パラメータで適切な値を伝達する方が合理的な場合もあります。そのような場合は、SQLite 選択文字列が設定された android:searchSuggestSelection 属性を検索可能構成に追加します。選択文字列には、実際の検索クエリのプレースホルダとして疑問符(「?」)を含めます。システムは、selection パラメータとして選択文字列を、selectionArgs 配列の最初の要素として検索クエリを使用して query() を呼び出します。

以下に、android:searchSuggestSelection 属性を設定して全文検索ステートメントを作成する方法の例を示します。

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_label"
        android:hint="@string/search_hint"
        android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:searchSuggestSelection="word MATCH ?">
    </searchable>
    

query() メソッドはこの構成を使用して、"word MATCH ?" として selection パラメータを、検索クエリとして selectionArgs パラメータを渡します。これらは、SQLite の query() メソッドにそれぞれの引数として渡すときに合成されます(疑問符がクエリテキストで置き換えられます)。候補クエリをこの方法で受け取るように選択し、ワイルドカードをクエリテキストに追加する必要がある場合は、selectionArgs パラメータの前または後ろ(あるいはその両方)に付加します。これは、この値が引用符で囲まれ、疑問符の箇所に挿入されるためです。

上の例のもう 1 つの新しい属性が android:searchSuggestIntentAction です。この属性では、ユーザーが候補を選択したときに各インテントで送信されるインテント アクションを定義します。この属性について詳しくは、候補用のインテントの宣言をご覧ください。

ヒント: android:searchSuggestSelection 属性で選択句を定義せずに、selectionArgs パラメータでクエリテキストを受け取りたい場合は、android:searchSuggestSelection 属性に null 以外の値を指定します。これにより、クエリが selectionArgs で渡されるため、selection パラメータを無視できます。このように、実際の選択句を下位レベルで定義できるため、コンテンツ プロバイダで選択句を処理する必要がなくなります。

候補テーブルの作成

Cursor でシステムに候補を返す場合、システムは各行に特定の列が含まれていることを期待します。そのため、候補データの保存先がデバイス上の SQLite データベースか、ウェブサーバー上のデータベースか、デバイスまたはウェブ上の別の形式かに関係なく、テーブルの行として候補をフォーマットし、Cursor を使用してそれらを表示する必要があります。

注: 検索候補がシステムで必要な列を使用したテーブル形式(SQLite テーブルなど)で保存されていない場合、一致する候補データを検索し、リクエストごとに必要なテーブルにフォーマットすることができます。そのためには、必要な列名を使用して MatrixCursor を作成し、addRow(Object[]) を使用して各候補の行を追加します。最終結果はコンテンツ プロバイダの query() メソッドから返されます。

システムは複数の列を認識しますが、必要なのはそのうちの次の 2 つだけです。

_ID
各候補の一意の行 ID(整数)。ListView に候補を表示するには、システムでこの ID が必要になります。
SUGGEST_COLUMN_TEXT_1
候補として表示される文字列。

以下の列はすべてオプションです(以降のセクションで詳細を説明します)。

SUGGEST_COLUMN_TEXT_2
文字列。Cursor にこの列が含まれている場合、すべての候補が 2 行の形式で表示されます。この列の文字列は、第二の小さい文字のテキスト行として第一の候補テキストの下に表示されます。第二のテキストを表示しない場合は、null を指定するか、空にします。
SUGGEST_COLUMN_ICON_1
ドローアブル リソース、コンテンツ、またはファイル URI の文字列。Cursor にこの列が含まれている場合、すべての候補がアイコンとテキストの形式で表示されます(ドローアブル アイコンが左側に表示されます)。アイコンを表示しない場合は、この行に null またはゼロを指定します。
SUGGEST_COLUMN_ICON_2
ドローアブル リソース、コンテンツ、またはファイル URI の文字列。Cursor にこの列が含まれている場合、すべての候補がアイコンとテキストの形式で表示されます(アイコンが右側に表示されます)。アイコンを表示しない場合は、この行に null またはゼロを指定します。
SUGGEST_COLUMN_INTENT_ACTION
インテント アクションの文字列。この列が存在し、所定の行に値が含まれている場合、ここで定義したアクションが候補のインテントの設定時に使用されます。この要素が指定されていない場合、検索可能構成の android:searchSuggestIntentAction フィールドからアクションが取得されます。すべての候補のアクションが同じ場合、android:searchSuggestIntentAction を使用してアクションを指定し、この列を省略する方が効率的です。
SUGGEST_COLUMN_INTENT_DATA
データ URI の文字列。この列が存在し、所定の行に値が含まれている場合、候補のインテントの設定時にこのデータが使用されます。この要素が指定されていない場合、検索可能構成の android:searchSuggestIntentData フィールドからデータが取得されます。どちらのソースも指定されていない場合、インテントのデータ フィールドが null になります。すべての候補のデータが同じか、定数部分と特定の ID を使用してデータを記述できる場合は、android:searchSuggestIntentData を使用してデータを指定し、この列を省略する方が効率的です。
SUGGEST_COLUMN_INTENT_DATA_ID
URI パスの文字列。この列が存在し、所定の行に値が含まれている場合は、「/」とこの値がインテントのデータ フィールドに付加されます。この列を使用する必要があるのは、検索可能構成の android:searchSuggestIntentData 属性で指定されたデータ フィールドがすでに適切なベース文字列に設定されている場合だけです。
SUGGEST_COLUMN_INTENT_EXTRA_DATA
任意のデータ。この列が存在し、所定の行に値が含まれている場合、このエクストラ データが候補のインテントの設定時に使用されます。指定されていない場合、インテントのエクストラ データ フィールドが null になります。この列を使用すると、インテントの EXTRA_DATA_KEY キーにエクストラとして含まれる追加データを候補で指定できます。
SUGGEST_COLUMN_QUERY
この列が存在し、所定の行にこの要素が存在する場合、このデータが候補のクエリの設定時に使用され、インテントの QUERY キーにエクストラとして含まれます。候補のアクションが ACTION_SEARCH の場合は必須、それ以外の場合はオプションです。
SUGGEST_COLUMN_SHORTCUT_ID
クイック検索ボックスで候補を表示する場合にのみ使用します。この列は、検索候補をショートカットとして保存するかどうか、および検索候補を検証するかどうかを示します。ショートカットは通常、ユーザーがクイック検索ボックスで候補をクリックしたときに設定されます。この列を設定しないと、結果がショートカットとして保存され、更新されなくなります。SUGGEST_NEVER_MAKE_SHORTCUT に設定すると、結果がショートカットとして保存されません。その他の場合は、SUGGEST_URI_PATH_SHORTCUT を使用して最新の候補を確認するためにショートカット ID が使用されます。
SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
クイック検索ボックスで候補を表示する場合にのみ使用します。この列では、クイック検索ボックス内でこの候補のショートカットを更新している間、SUGGEST_COLUMN_ICON_2 のアイコンの代わりにスピナーを表示することを指定します。

以降のセクションでは、これらの列の一部についてさらに詳しく説明します。

候補用のインテントの宣言

ユーザーが検索ダイアログまたは検索ウィジェットの下に表示されるリストから候補を選択すると、システムによってカスタムの Intent が検索可能アクティビティに送信されます。インテントのアクションとデータはデベロッパーが定義する必要があります。

インテント アクションの宣言

カスタム候補の最も一般的なインテント アクションは ACTION_VIEW です。このアクションは、単語の定義、ユーザーの連絡先情報、ウェブページなど、何かを開きたい場合に適しています。ただし、インテント アクションは他のアクションにすることもでき、候補ごとに異なるアクションを指定することも可能です。

すべての候補で同じインテント アクションを使用するかどうかに応じて、次の 2 つの方法でアクションを定義できます。

  1. すべての候補のアクションを定義するには、検索可能構成ファイルの android:searchSuggestIntentAction 属性を使用します。

    次に例を示します。

        <?xml version="1.0" encoding="utf-8"?>
        <searchable xmlns:android="http://schemas.android.com/apk/res/android"
            android:label="@string/app_label"
            android:hint="@string/search_hint"
            android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
            android:searchSuggestIntentAction="android.intent.action.VIEW" >
        </searchable>
        
  2. 個々の候補のアクションを定義するには、SUGGEST_COLUMN_INTENT_ACTION 列を使用します。

    SUGGEST_COLUMN_INTENT_ACTION 列を候補テーブルに追加し、各候補で使用するアクション("android.intent.action.VIEW" など)を設定します。

この 2 つの方法を組み合わせることも可能です。たとえば、すべての候補で使用するアクションが指定された android:searchSuggestIntentAction 属性をデフォルトで含めて、その後、SUGGEST_COLUMN_INTENT_ACTION 列で別のアクションを宣言することで、一部の候補のアクションをオーバーライドできます。SUGGEST_COLUMN_INTENT_ACTION 列に値を含めないと、android:searchSuggestIntentAction 属性で指定されているインテントが使用されます。

: 検索可能構成に android:searchSuggestIntentAction 属性を含めない場合は、すべての候補の SUGGEST_COLUMN_INTENT_ACTION 列に値を含める必要があります。そうしないと、インテントが失敗します。

インテント データの宣言

ユーザーが候補を選択すると、前のセクションで説明したとおり、定義したアクションを含むインテントが検索可能アクティビティに送信されます。ただし、どの候補が選択されたかをアクティビティで特定するためには、インテントでデータも渡す必要があります。厳密に言えば、データは候補ごとに一意なものである必要があります(SQLite テーブルの候補の行 ID など)。インテントを受け取った後、添付されているデータを取得するには、getData() または getDataString() を使用します。

インテントに含めるデータは、次の 2 つの方法で定義できます。

  1. 候補テーブルの SUGGEST_COLUMN_INTENT_DATA 列内で候補ごとにデータを定義します。

    SUGGEST_COLUMN_INTENT_DATA 列を追加し、各行に一意のデータを設定することで、候補テーブルの各インテントに必要なすべてのデータ情報を指定します。この列のデータは、この列で定義したとおりにインテントに添付されます。これで、getData() または getDataString() を使用してデータを取得できます。

    ヒント: テーブルの行 ID は常に一意であるため、通常はこの ID をインテント データとして使用するのが最も簡単です。そのためには、SUGGEST_COLUMN_INTENT_DATA 列の名前を行 ID 列のエイリアスとして使用します。SQLiteQueryBuilder でエイリアスに対する列名の projection map を作成する例について、検索可能な辞書のサンプルアプリをご覧ください。

  2. データ URI を 2 つの部分(すべての候補に共通の部分と、候補ごとに固有の部分)に分けます。これらをそれぞれ、検索可能構成の android:searchSuggestintentData 属性と、候補テーブルの SUGGEST_COLUMN_INTENT_DATA_ID 列に設定します。

    検索可能構成の android:searchSuggestIntentData 属性で、すべての候補に共通の URI の部分を宣言します。次に例を示します。

        <?xml version="1.0" encoding="utf-8"?>
        <searchable xmlns:android="http://schemas.android.com/apk/res/android"
            android:label="@string/app_label"
            android:hint="@string/search_hint"
            android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
            android:searchSuggestIntentAction="android.intent.action.VIEW"
            android:searchSuggestIntentData="content://com.example/datatable" >
        </searchable>
        

    次に、候補テーブルの SUGGEST_COLUMN_INTENT_DATA_ID 列に各候補の最終パス(固有の部分)を含めます。ユーザーが候補を選択すると、システムが android:searchSuggestIntentData から文字列を取得してスラッシュ(「/」)を付加し、SUGGEST_COLUMN_INTENT_DATA_ID 列のそれぞれの値を追加して完全なコンテンツ URI を構成します。これで、getData() を使用して Uri を取得できます。

データの追加

インテントでさらに多くの情報を表現する必要がある場合、テーブル列 SUGGEST_COLUMN_INTENT_EXTRA_DATA を追加できます。この列に、候補に関する追加情報を保存できます。この列に保存されたデータは、インテントのエクストラ Bundle の EXTRA_DATA_KEY に配置されます。

インテントの処理

カスタム検索候補にカスタム インテントを提供したので、次に、ユーザーが候補を選択したときに、検索可能アクティビティでこれらのインテントを処理する必要があります。これは、検索可能アクティビティですでに行っている ACTION_SEARCH インテントの処理とは別のものです。以下に、アクティビティの onCreate() コールバックでインテントを処理する方法の例を示します。

Kotlin

    when(intent.action) {
        Intent.ACTION_SEARCH -> {
            // Handle the normal search query case
            intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                doSearch(query)
            }
        }
        Intent.ACTION_VIEW -> {
            // Handle a suggestions click (because the suggestions all use ACTION_VIEW)
            showResult(intent.data)
        }
    }
    

Java

    Intent intent = getIntent();
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        // Handle the normal search query case
        String query = intent.getStringExtra(SearchManager.QUERY);
        doSearch(query);
    } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
        // Handle a suggestions click (because the suggestions all use ACTION_VIEW)
        Uri data = intent.getData();
        showResult(data);
    }
    

この例のインテント アクションは ACTION_VIEW で、候補のアイテムを指す、android:searchSuggestIntentData 文字列と SUGGEST_COLUMN_INTENT_DATA_ID 列が合成された完全な URI がデータによって渡されます。その後、URI がローカルの showResult() メソッドに渡されます。このメソッドはコンテンツ プロバイダに対し、URI で指定されたアイテムを照会します。

注: android:searchSuggestIntentAction 属性または SUGGEST_COLUMN_INTENT_ACTION 列で定義したインテント アクション用のインテント フィルタを Android マニフェスト ファイルに追加する必要はありません。システムは検索可能アクティビティを名前で開いて候補のインテントを渡すため、受け取ったアクションをアクティビティで宣言する必要はありません。

クエリテキストの書き換え

ユーザーが方向コントロール(トラックボールや D-pad など)を使用して候補リストをスクロールした場合、デフォルトではクエリテキストは更新されません。ただし、ユーザーのクエリテキストが、現在フォーカスされている候補と一致するクエリとともにテキスト ボックスに表示されている場合、一時的に書き換えることができます。これによりユーザーは、候補になっているクエリを確認し(該当する場合)、検索ボックスを選択して、クエリを検索としてディスパッチする前に編集できます。

クエリテキストは以下の方法で書き換えることができます。

  1. 値 "queryRewriteFromText" が設定された android:searchMode 属性を検索可能構成に追加します。この場合、候補の SUGGEST_COLUMN_TEXT_1 列の内容がクエリテキストの書き換えに使用されます。
  2. 値 "queryRewriteFromData" が設定された android:searchMode 属性を検索可能構成に追加します。この場合、候補の SUGGEST_COLUMN_INTENT_DATA 列の内容がクエリテキストの書き換えに使用されます。これは、ユーザーに表示することを目的とした URI やその他のデータ形式(HTTP URL など)でのみ使用してください。この方法では、クエリの書き換えに内部 URI スキームを使用しないでください。
  3. 候補テーブルの SUGGEST_COLUMN_QUERY 列で、一意のクエリテキスト文字列を指定します。この列が存在し、現在の候補の値が設定されている場合、クエリテキストの書き換え(および以前の実装のいずれかのオーバーライド)に使用されます。

クイック検索ボックスへの検索候補の公開

カスタム検索候補を表示するようにアプリを設定すると、グローバルにアクセス可能なクイック検索ボックスでそれらの候補を表示できるようになります。この操作は、検索可能構成に android:includeInGlobalSearch を追加して "true" に設定するだけです。

追加の作業が必要なシナリオは、コンテンツ プロバイダが読み取り権限を必要とする場合だけです。このシナリオでは、プロバイダ用の特別な <path-permission> 要素を追加して、コンテンツ プロバイダに対する読み取りアクセス権をクイック検索ボックスに付与する必要があります。次に例を示します。

    <provider android:name="MySuggestionProvider"
              android:authorities="com.example.MyCustomSuggestionProvider"
              android:readPermission="com.example.provider.READ_MY_DATA"
              android:writePermission="com.example.provider.WRITE_MY_DATA">
      <path-permission android:pathPrefix="/search_suggest_query"
                       android:readPermission="android.permission.GLOBAL_SEARCH" />
    </provider>
    

この例では、プロバイダがコンテンツに対する読み取りおよび書き込みアクセス権を制限しています。<path-permission> 要素は、"android.permission.GLOBAL_SEARCH" 権限が存在する場合に "/search_suggest_query" パス プレフィックス内のコンテンツに対する読み取りアクセス権を付与することで、制限を修正しています。これにより、クイック検索ボックスにアクセス権が付与され、コンテンツ プロバイダに対して候補を照会できるようになります。

コンテンツ プロバイダに読み取り権限が適用されていなくても、クイック検索ボックスはデフォルトでコンテンツ プロバイダを読み取ることができます。

デバイスでの候補の有効化

クイック検索ボックスに候補を表示するようにアプリが設定されていても、実際には、デフォルトでクイック検索ボックスに候補を表示することはできません。アプリでクイック検索ボックスに候補を含めるかどうかはユーザーが選択します。アプリで検索候補を有効にするには、ユーザーが [検索対象]([設定] > [検索])を開いて、アプリを検索対象として有効にする必要があります。

クイック検索ボックスで使用できる各アプリには、[検索対象] 設定ページにエントリがあります。このエントリには、アプリの名前と、アプリから検索でき、クイック検索ボックス内の候補で使用できるコンテンツの簡単な説明が含まれます。検索可能なアプリの説明のテキストを定義するには、android:searchSettingsDescription 属性を検索可能構成に追加します。次に例を示します。

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_label"
        android:hint="@string/search_hint"
        android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW"
        android:includeInGlobalSearch="true"
        android:searchSettingsDescription="@string/search_description" >
    </searchable>
    

android:searchSettingsDescription の文字列はできるだけ簡潔にし、検索可能なコンテンツについて記述する必要があります。たとえば、音楽アプリの場合は「アーティスト、アルバム、トラック」、NotePad アプリの場合は「保存したメモ」といった具合です。ユーザーはこの説明からどのような候補が表示されているかを理解できるため、この説明は重要です。android:includeInGlobalSearch が "true" の場合は、この属性を含める必要があります。

ユーザーは、検索候補がクイック検索ボックスに表示される前に、設定メニューにアクセスしてアプリの検索候補を有効にする必要があります。そのため、検索がアプリの重要な要素である場合は、そのことをユーザーに伝える方法について検討することをおすすめします。たとえば、ユーザーがアプリを初めて起動したときに、クイック検索ボックスの検索候補を有効にする方法を説明するメモを表示できます。

クイック検索ボックスの候補ショートカットの管理

ユーザーがクイック検索ボックスで選択した候補を自動的にショートカットにすることができます。これらはシステムがコンテンツ プロバイダからコピーした候補であるため、候補にすばやくアクセスできます。コンテンツ プロバイダを再照会する必要もありません。

デフォルトでは、この機能はクイック検索ボックスで取得したすべての候補に対して有効になっていますが、候補データが経時的に変化する場合は、ショートカットを更新するようリクエストできます。たとえば、候補が動的なデータ(連絡先のプレゼンス状態など)を参照する場合、候補ショートカットをユーザーに表示するときに更新するようリクエストする必要があります。そのためには、候補テーブルに SUGGEST_COLUMN_SHORTCUT_ID を含めます。この列を使用して、次のいずれかの方法で各候補のショートカットの動作を設定できます。

  1. クイック検索ボックスで、コンテンツ プロバイダに対して候補ショートカットの最新バージョンを再照会します。

    SUGGEST_COLUMN_SHORTCUT_ID 列で値を指定します。ショートカットが表示されるたびに、候補に対して最新バージョンが再照会されます。更新クエリが返ってくるまでは、最近使用可能になったデータでショートカットが即座に表示され、更新クエリが返ってくると、候補が新しい情報で更新されます。更新クエリは、(SUGGEST_URI_PATH_QUERY ではなく)SUGGEST_URI_PATH_SHORTCUT の URI パスを使用してコンテンツ プロバイダに送信されます。

    返す Cursor には、元の候補と同じ列を使用した候補を 1 つ含める必要があります。あるいは、ショートカットが有効でなくなったことを示す場合は空にする必要があります(この場合、候補が表示されなくなり、ショートカットが削除されます)。

    更新に時間がかかる可能性があるデータを候補が参照する場合(ネットワーク ベースの更新など)、更新が完了するまで右側のアイコンの代わりに進行状況スピナーを表示するために、値が "true" に設定された SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING 列を候補テーブルに追加することもできます。"true" 以外の値が設定されている場合、進行状況スピナーは表示されません。

  2. 候補がショートカットにコピーされないようにします。

    SUGGEST_COLUMN_SHORTCUT_ID 列で、SUGGEST_NEVER_MAKE_SHORTCUT という値を指定します。この場合、候補がショートカットにコピーされることはありません。この操作が必要なのは、以前にコピーした候補を絶対に表示させたくない場合だけです(列で通常の値を指定すると、更新クエリが返ってくるまでの間だけ候補ショートカットが表示されます)。

  3. デフォルトのショートカットの動作を適用できるようにします。

    変更されることがなく、ショートカットとして保存可能な候補の場合は、SUGGEST_COLUMN_SHORTCUT_ID を空のままにします。

どの候補も変更されない場合、SUGGEST_COLUMN_SHORTCUT_ID 列は必要ありません。

: クイック検索ボックスは、これらの値をアプリからの強い要求とみなし、候補のショートカットを作成するかどうかを最終的に決定します。ただし、候補ショートカットに対してリクエストした動作が優先されるとは限りません。

クイック検索ボックスの候補のランキングについて

アプリの検索候補をクイック検索ボックスで表示できるようにすると、特定のクエリに対する候補の表示方法がクイック検索ボックスのランキングによって決まります。この表示方法は、そのクエリに対する結果を保持している他のアプリの数や、ユーザーが結果を選択した頻度(他のアプリとの比較)によって異なる場合があります。候補がどのようにランク付けされるかや、特定のクエリに対してアプリの候補が表示されるかどうかについての保証はありません。一般に、結果の質が高い場合、アプリの候補が目立つ位置に表示される可能性が高くなり、結果の質が低いアプリでは、候補が下位にランク付けされるか、表示されない可能性が高くなります。

カスタム検索候補の完全なデモについては、検索可能な辞書のサンプルアプリをご覧ください。