このレッスンでは、次の方法を使用して、検索文字列の全部または一部にデータが一致する連絡先のリストを取得する方法を説明します。
- 連絡先の名前を照合する
- 検索文字列を連絡先名データのすべてまたは一部と照合して、連絡先のリストを取得します。連絡先プロバイダは同じ名前の複数のインスタンスを許可するため、この方法で一致するもののリストを返すことができます。
- 特定の種類のデータ(電話番号など)を照合する
- 検索文字列をメールアドレスなど、特定の種類の詳細データと照合して、連絡先のリストを取得します。たとえば、メールアドレスが検索文字列と一致する連絡先をすべて一覧表示できます。
- すべての種類のデータを照合する
- 検索文字列を名前、電話番号、住所、メールアドレスなどの任意のタイプの詳細データと照合して、連絡先のリストを取得します。たとえば、この手法では、検索文字列に対して任意のタイプのデータを受け入れ、そのデータが文字列に一致する連絡先をリストできます。
注: このレッスンのすべての例では、CursorLoader
を使用して連絡先プロバイダからデータを取得します。CursorLoader
は、UI スレッドとは別のスレッドでクエリを実行します。これにより、クエリによって UI の応答時間が遅くなったり、ユーザー エクスペリエンスが低下したりすることがなくなります。詳細については、Android トレーニング クラスの
バックグラウンドでのデータの読み込みをご覧ください。
プロバイダの読み取り権限をリクエストする
連絡先プロバイダのあらゆる種類の検索を行うには、アプリに READ_CONTACTS
権限が必要です。これをリクエストするには、この <uses-permission>
要素を <manifest>
の子要素としてマニフェスト ファイルに追加します。
<uses-permission android:name="android.permission.READ_CONTACTS" />
連絡先を名前で照合して結果を一覧表示する
この手法では、検索文字列を、連絡先プロバイダの ContactsContract.Contacts
テーブル内の連絡先の名前と照合します。通常は、結果を ListView
に表示して、一致した連絡先からユーザーが選択できるようにします。
ListView とアイテム レイアウトを定義する
検索結果を ListView
に表示するには、ListView
を含む UI 全体を定義するメイン レイアウト ファイルと、ListView
の 1 行を定義するアイテム レイアウト ファイルが必要です。たとえば、次の XML を使用してメイン レイアウト ファイル res/layout/contacts_list_view.xml
を作成できます。
<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent"/>
この XML は、組み込みの Android ListView
ウィジェット android:id/list
を使用します。
次の XML を使用してアイテム レイアウト ファイル contacts_list_item.xml
を定義します。
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true"/>
この XML は、組み込みの Android TextView
ウィジェット android:text1
を使用します。
注: このレッスンでは、ユーザーから検索文字列を取得するための UI については説明しません。文字列を間接的に取得する場合があるためです。たとえば、受信したテキスト メッセージ内の文字列と名前が一致する連絡先を検索するオプションをユーザーに提供できます。
作成した 2 つのレイアウト ファイルは、ListView
を表示するユーザー インターフェースを定義しています。次のステップでは、この UI を使用して連絡先のリストを表示するコードを記述します。
連絡先のリストを表示するフラグメントを定義する
連絡先のリストを表示するには、まず Activity
によって読み込まれる Fragment
を定義します。Fragment
を使用するほうがより柔軟な手法です。1 つの Fragment
を使用してリストを表示し、2 つ目の Fragment
を使用してユーザーがリストから選択した連絡先の詳細を表示できます。この方法を使用すると、このレッスンで紹介した手法の 1 つと、
連絡先の詳細を取得するで紹介した手法を組み合わせることができます。
Activity
から 1 つ以上の Fragment
オブジェクトを使用する方法については、トレーニング クラスの
フラグメントを使用して動的 UI を作成するをご覧ください。
連絡先プロバイダに対するクエリを作成しやすくするために、Android フレームワークには、プロバイダにアクセスするための便利な定数とメソッドを定義する ContactsContract
というコントラクト クラスが用意されています。このクラスを使用する場合、コンテンツ URI、テーブル名、列用に独自の定数を定義する必要はありません。このクラスを使用するには、次のステートメントを含めます。
Kotlin
import android.provider.ContactsContract
Java
import android.provider.ContactsContract;
コードは CursorLoader
を使用してプロバイダからデータを取得するため、ローダ インターフェース LoaderManager.LoaderCallbacks
を実装するように指定する必要があります。また、ユーザーが検索結果のリストから選択した連絡先を検出できるように、アダプター インターフェース AdapterView.OnItemClickListener
を実装します。次に例を示します。
Kotlin
... import android.support.v4.app.Fragment import android.support.v4.app.LoaderManager import android.widget.AdapterView ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
Java
... import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.widget.AdapterView; ... public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
グローバル変数を定義する
コードの他の部分で使用されるグローバル変数を定義します。
Kotlin
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private val FROM_COLUMNS: Array<String> = arrayOf( if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) { ContactsContract.Contacts.DISPLAY_NAME_PRIMARY } else { ContactsContract.Contacts.DISPLAY_NAME } ) /* * Defines an array that contains resource ids for the layout views * that get the Cursor column contents. The id is pre-defined in * the Android framework, so it is prefaced with "android.R.id" */ private val TO_IDS: IntArray = intArrayOf(android.R.id.text1) ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener { ... // Define global mutable variables // Define a ListView object lateinit var contactsList: ListView // Define variables for the contact the user selects // The contact's _ID value var contactId: Long = 0 // The contact's LOOKUP_KEY var contactKey: String? = null // A content URI for the selected contact var contactUri: Uri? = null // An adapter that binds the result Cursor to the ListView private val cursorAdapter: SimpleCursorAdapter? = null
Java
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private final static String[] FROM_COLUMNS = { Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME }; /* * Defines an array that contains resource ids for the layout views * that get the Cursor column contents. The id is pre-defined in * the Android framework, so it is prefaced with "android.R.id" */ private final static int[] TO_IDS = { android.R.id.text1 }; // Define global mutable variables // Define a ListView object ListView contactsList; // Define variables for the contact the user selects // The contact's _ID value long contactId; // The contact's LOOKUP_KEY String contactKey; // A content URI for the selected contact Uri contactUri; // An adapter that binds the result Cursor to the ListView private SimpleCursorAdapter cursorAdapter; ...
注: Contacts.DISPLAY_NAME_PRIMARY
には Android 3.0(API バージョン 11)以降が必要なため、アプリの minSdkVersion
を 10 以下に設定すると、Android Studio で Android Lint 警告が生成されます。この警告をオフにするには、FROM_COLUMNS
の定義の前にアノテーション @SuppressLint("InlinedApi")
を追加します。
フラグメントを初期化する
Fragment
を初期化します。Android システムで必要な空のパブリック コンストラクタを追加し、コールバック メソッド onCreateView()
で Fragment
オブジェクトの UI をインフレートします。次に例を示します。
Kotlin
// A UI Fragment must inflate its View override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false) }
Java
// Empty public constructor, required by the system public ContactsFragment() {} // A UI Fragment must inflate its View @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false); }
ListView の CursorAdapter を設定する
検索結果を ListView
にバインドする SimpleCursorAdapter
をセットアップします。連絡先を表示する ListView
オブジェクトを取得するには、Fragment
の親アクティビティを使用して Activity.findViewById()
を呼び出す必要があります。setAdapter()
を呼び出すときに、親アクティビティの Context
を使用します。
次に例を示します。
Kotlin
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) ... // Gets the ListView from the View list of the parent activity activity?.also { contactsList = it.findViewById<ListView>(R.id.contact_list_view) // Gets a CursorAdapter cursorAdapter = SimpleCursorAdapter( it, R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0 ) // Sets the adapter for the ListView contactsList.adapter = cursorAdapter } }
Java
public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ... // Gets the ListView from the View list of the parent activity contactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); // Gets a CursorAdapter cursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0); // Sets the adapter for the ListView contactsList.setAdapter(cursorAdapter); }
選択した連絡先リスナーを設定する
通常、検索結果を表示する際に、ユーザーが 1 件の連絡先を選択してさらに処理を進められるようにします。たとえば、ユーザーが連絡先をクリックしたときに、連絡先の住所を地図上に表示できます。この機能を提供するには、連絡先のリストを表示するフラグメントを定義するで示しているように、まず現在の Fragment
をクリック リスナーとして定義し、クラスが AdapterView.OnItemClickListener
を実装することを指定します。
リスナーの設定を続けるには、onActivityCreated()
の setOnItemClickListener()
メソッドを呼び出して、ListView
にバインドします。次に例を示します。
Kotlin
fun onActivityCreated(savedInstanceState:Bundle) { ... // Set the item click listener to be the current fragment. contactsList.onItemClickListener = this ... }
Java
public void onActivityCreated(Bundle savedInstanceState) { ... // Set the item click listener to be the current fragment. contactsList.setOnItemClickListener(this); ... }
現在の Fragment
を ListView
の OnItemClickListener
に指定したため、クリック イベントを処理する必須のメソッド onItemClick()
を実装する必要があります。これについては、次のセクションで説明します。
射影を定義する
クエリから返す列を含む定数を定義します。ListView
の各項目には、連絡先の表示名が表示されます。表示名には、連絡先の名前の主な形式が含まれます。Android 3.0(API バージョン 11)以降では、この列の名前は Contacts.DISPLAY_NAME_PRIMARY
です。それ以前のバージョンでは、Contacts.DISPLAY_NAME
になります。
Contacts._ID
列は SimpleCursorAdapter
バインディング プロセスで使用されます。Contacts._ID
と LOOKUP_KEY
を併用して、ユーザーが選択する連絡先のコンテンツ URI を作成します。
Kotlin
... @SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Contacts.DISPLAY_NAME_PRIMARY else ContactsContract.Contacts.DISPLAY_NAME )
Java
... @SuppressLint("InlinedApi") private static final String[] PROJECTION = { Contacts._ID, Contacts.LOOKUP_KEY, Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME };
Cursor 列のインデックスの定数を定義する
Cursor
の個々の列からデータを取得するには、Cursor
内の列のインデックスが必要です。インデックスは射影の列名の順序と同じであるため、Cursor
列のインデックスの定数を定義できます。次に例を示します。
Kotlin
// The column index for the _ID column private const val CONTACT_ID_INDEX: Int = 0 // The column index for the CONTACT_KEY column private const val CONTACT_KEY_INDEX: Int = 1
Java
// The column index for the _ID column private static final int CONTACT_ID_INDEX = 0; // The column index for the CONTACT_KEY column private static final int CONTACT_KEY_INDEX = 1;
選択基準を指定する
必要なデータを指定するには、テキスト式と変数の組み合わせを作成し、検索するデータ列と検索する値をプロバイダに指示します。
テキスト表現には、検索列をリストする定数を定義します。この式に値を含めることもできますが、「?」プレースホルダで値を表すことをおすすめします。取得時に、プレースホルダは配列の値に置き換えられます。「?」をプレースホルダとして使用すると、検索仕様が SQL コンパイルではなくバインディングによって生成されます。これにより、悪意のある SQL インジェクションの可能性が排除されます。次に例を示します。
Kotlin
// Defines the text expression @SuppressLint("InlinedApi") private val SELECTION: String = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE ?" else "${ContactsContract.Contacts.DISPLAY_NAME} LIKE ?" ... // Defines a variable for the search string private val searchString: String = ... // Defines the array to hold values that replace the ? private val selectionArgs = arrayOf<String>(searchString)
Java
// Defines the text expression @SuppressLint("InlinedApi") private static final String SELECTION = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?" : Contacts.DISPLAY_NAME + " LIKE ?"; // Defines a variable for the search string private String searchString; // Defines the array to hold values that replace the ? private String[] selectionArgs = { searchString };
onItemClick() メソッドを定義する
前のセクションでは、ListView
のアイテム クリック リスナーを設定しました。次に、メソッド AdapterView.OnItemClickListener.onItemClick()
を定義して、リスナー用のアクションを実装します。
Kotlin
override fun onItemClick(parent: AdapterView<*>, view: View?, position: Int, id: Long) { // Get the Cursor val cursor: Cursor? = (parent.adapter as? CursorAdapter)?.cursor?.apply { // Move to the selected contact moveToPosition(position) // Get the _ID value contactId = getLong(CONTACT_ID_INDEX) // Get the selected LOOKUP KEY contactKey = getString(CONTACT_KEY_INDEX) // Create the contact's content Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, mContactKey) /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ } }
Java
@Override public void onItemClick( AdapterView<?> parent, View item, int position, long rowID) { // Get the Cursor Cursor cursor = parent.getAdapter().getCursor(); // Move to the selected contact cursor.moveToPosition(position); // Get the _ID value contactId = cursor.getLong(CONTACT_ID_INDEX); // Get the selected LOOKUP KEY contactKey = cursor.getString(CONTACT_KEY_INDEX); // Create the contact's content Uri contactUri = Contacts.getLookupUri(contactId, mContactKey); /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ }
ローダを初期化する
CursorLoader
を使用してデータを取得するため、非同期の取得を制御するバックグラウンド スレッドとその他の変数を初期化する必要があります。次の例に示すように、onCreate()
で初期化を行います。
Kotlin
class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { // Always call the super method first super.onCreate(savedInstanceState) ... // Initializes the loader loaderManager.initLoader(0, null, this)
Java
public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Called just before the Fragment displays its UI @Override public void onCreate(Bundle savedInstanceState) { // Always call the super method first super.onCreate(savedInstanceState); ... // Initializes the loader getLoaderManager().initLoader(0, null, this);
onCreateLoader() を実装する
onCreateLoader()
メソッドを実装します。このメソッドは、initLoader()
を呼び出した直後にローダー フレームワークによって呼び出されます。
onCreateLoader()
で検索文字列パターンを設定します。文字列をパターンに変換するには、「%」(パーセント)文字を挿入して 0 個以上の文字を示すか、「_」(アンダースコア)を挿入して 1 文字を示すか、またはその両方を表します。たとえば、パターン「%Jefferson%」は、「Thomas Jefferson」と「Jefferson Davis」の両方に一致します。
メソッドから新しい CursorLoader
を返します。コンテンツ URI には、Contacts.CONTENT_URI
を使用します。この URI は、次の例に示すように、テーブル全体を参照します。
Kotlin
... override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%$mSearchString%" // Starts the query return activity?.let { return CursorLoader( it, ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
... @Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%" + searchString + "%"; // Starts the query return new CursorLoader( getActivity(), ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
onLoadFinished() と onLoaderReset() を実装する
onLoadFinished()
メソッドを実装します。連絡先プロバイダがクエリの結果を返すと、ローダー フレームワークは onLoadFinished()
を呼び出します。このメソッドで、結果の Cursor
を SimpleCursorAdapter
に入れます。これにより、ListView
が検索結果で自動的に更新されます。
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter?.swapCursor(cursor) }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter.swapCursor(cursor); }
メソッド onLoaderReset()
は、結果 Cursor
に古いデータが含まれていることをローダー フレームワークが検出したときに呼び出されます。既存の Cursor
への SimpleCursorAdapter
参照を削除します。そうしないと、ローダー フレームワークは Cursor
をリサイクルせず、メモリリークの原因になります。次に例を示します。
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { // Delete the reference to the existing Cursor cursorAdapter?.swapCursor(null) }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { // Delete the reference to the existing Cursor cursorAdapter.swapCursor(null); }
これで、検索文字列を連絡先名と照合し、結果を ListView
に返すアプリの主要なピースができました。ユーザーは連絡先名をクリックして選択できます。
これによりリスナーがトリガーされ、連絡先のデータをさらに操作できます。たとえば、連絡先の詳細を取得できます。これを行う方法については、次のレッスンの連絡先の詳細を取得するに進んでください。
検索ユーザー インターフェースの詳細については、API ガイドの検索インターフェースを作成するをご覧ください。
このレッスンの残りのセクションでは、連絡先プロバイダで連絡先を見つけるその他の方法について説明します。
特定の種類のデータで連絡先を照合する
この手法では、照合するデータの種類を指定できます。名前による取得は、このタイプのクエリの具体例ですが、連絡先に関連付けられたどのタイプの詳細データに対しても行うことができます。たとえば、特定の郵便番号を持つ連絡先を取得できます。この場合、検索文字列は郵便番号行に格納されているデータと一致する必要があります。
このタイプの取得を実装するには、前のセクションで説明したように、まず次のコードを実装します。
- プロバイダを読み取る権限をリクエストします。
- ListView とアイテム レイアウトを定義します。
- 連絡先のリストを表示するフラグメントを定義します。
- グローバル変数を定義します。
- Fragment を初期化する。
- ListView の CursorAdapter を設定します。
- 選択した連絡先リスナーを設定します。
-
Cursor 列インデックスの定数を定義します。
別のテーブルからデータを取得しても、射影の列の順序は同じであるため、Cursor に同じインデックスを使用できます。
- onItemClick() メソッドを定義します。
- ローダーを初期化します。
- onLoadFinished() と onLoaderReset() を実装します。
次の手順では、検索文字列を特定の種類の詳細データと照合して結果を表示するために必要な追加コードを示します。
データの種類とテーブルを選択する
特定の種類の詳細データを検索するには、そのデータ型のカスタム MIME タイプの値が必要です。各データ型には、データ型に関連付けられた ContactsContract.CommonDataKinds
のサブクラス内の定数 CONTENT_ITEM_TYPE
によって定義される一意の MIME タイプ値があります。サブクラスには、データタイプを示す名前があります。たとえば、メールデータのサブクラスは ContactsContract.CommonDataKinds.Email
で、メールデータのカスタム MIME タイプは定数 Email.CONTENT_ITEM_TYPE
で定義されます。
検索には ContactsContract.Data
テーブルを使用します。射影、選択句、並べ替え順に必要なすべての定数は、このテーブルで定義されるか、継承されます。
射影を定義する
射影を定義するには、ContactsContract.Data
で定義されている列、またはそれを継承するクラスを 1 つ以上選択します。連絡先プロバイダは、行を返す前に ContactsContract.Data
と他のテーブルを暗黙的に結合します。次に例を示します。
Kotlin
@SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Data.DISPLAY_NAME_PRIMARY else ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY )
Java
@SuppressLint("InlinedApi") private static final String[] PROJECTION = { /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Data.DISPLAY_NAME_PRIMARY : ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY // A permanent link to the contact };
検索条件を定義する
特定のタイプのデータから文字列を検索するには、以下から選択句を作成します。
-
検索文字列を含む列の名前。この名前はデータ型によって異なるため、データ型に対応する
ContactsContract.CommonDataKinds
のサブクラスを見つけて、そのサブクラスから列名を選択する必要があります。たとえば、メールアドレスを検索するには、Email.ADDRESS
列を使用します。 - 選択句で「?」文字として表される検索文字列自体。
-
カスタム MIME タイプの値を含む列の名前。この名前は常に
Data.MIMETYPE
です。 -
データの種類のカスタム MIME タイプの値。前述のとおり、これは
ContactsContract.CommonDataKinds
サブクラス内の定数CONTENT_ITEM_TYPE
です。たとえば、メールデータの MIME タイプの値はEmail.CONTENT_ITEM_TYPE
です。定数の先頭と末尾に「'
」(一重引用符)を連結して、値を一重引用符で囲みます。そうしないと、プロバイダは値を文字列値ではなく変数名として解釈します。 ユーザー指定の値ではなく定数を使用しているため、この値にプレースホルダを使用する必要はありません。
次に例を示します。
Kotlin
/* * Constructs search criteria from the search string * and email MIME type */ private val SELECTION: String = /* * Searches for an email address * that matches the search string */ "${Email.ADDRESS} LIKE ? AND " + /* * Searches for a MIME type that matches * the value of the constant * Email.CONTENT_ITEM_TYPE. Note the * single quotes surrounding Email.CONTENT_ITEM_TYPE. */ "${ContactsContract.Data.MIMETYPE } = '${Email.CONTENT_ITEM_TYPE}'"
Java
/* * Constructs search criteria from the search string * and email MIME type */ private static final String SELECTION = /* * Searches for an email address * that matches the search string */ Email.ADDRESS + " LIKE ? " + "AND " + /* * Searches for a MIME type that matches * the value of the constant * Email.CONTENT_ITEM_TYPE. Note the * single quotes surrounding Email.CONTENT_ITEM_TYPE. */ ContactsContract.Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'";
次に、選択引数を含む変数を定義します。
Kotlin
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
Java
String searchString; String[] selectionArgs = { "" };
onCreateLoader() を実装する
必要なデータとその検索方法を指定したら、onCreateLoader()
の実装でクエリを定義します。投影、選択テキスト式、選択配列を引数として使用して、このメソッドから新しい CursorLoader
を返します。コンテンツ URI には、Data.CONTENT_URI
を使用します。次に例を示します。
Kotlin
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { // OPTIONAL: Makes search string into pattern searchString = "%$mSearchString%" searchString?.also { // Puts the search string into the selection criteria selectionArgs[0] = it } // Starts the query return activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // OPTIONAL: Makes search string into pattern searchString = "%" + searchString + "%"; // Puts the search string into the selection criteria selectionArgs[0] = searchString; // Starts the query return new CursorLoader( getActivity(), Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
これらのコード スニペットは、特定のタイプの詳細データに基づく単純な逆引きに基づいています。これは、アプリがメールなどの特定の種類のデータに焦点を当てており、ユーザーがデータに関連付けられた名前を取得できるようにする場合に使用するのに最適な方法です。
すべての種類のデータで連絡先を照合する
あらゆる種類のデータに基づいて連絡先を取得すると、名前、メールアドレス、住所、電話番号などのデータのいずれかが検索文字列に一致する場合、連絡先が返されます。これにより、幅広い検索結果が得られます。たとえば、検索文字列が「Doe」の場合、任意のデータ型を検索すると「John Doe」という連絡先が返されます。また、「Doe Street」に住んでいる連絡先も返されます。
このタイプの取得を実装するには、前のセクションで説明したように、まず次のコードを実装します。
- プロバイダを読み取る権限をリクエストします。
- ListView とアイテム レイアウトを定義します。
- 連絡先のリストを表示するフラグメントを定義します。
- グローバル変数を定義します。
- Fragment を初期化する。
- ListView の CursorAdapter を設定します。
- 選択した連絡先リスナーを設定します。
- 投影を定義します。
-
Cursor 列インデックスの定数を定義します。
このタイプの取得では、名前で連絡先を照合して結果を一覧表示するで使用したものと同じテーブルを使用します。同じ列インデックスも使用します。
- onItemClick() メソッドを定義します。
- ローダーを初期化します。
- onLoadFinished() と onLoaderReset() を実装します。
次の手順では、検索文字列をあらゆるタイプのデータと照合して結果を表示するために必要な追加コードを示します。
選択基準を削除する
SELECTION
定数または mSelectionArgs
変数は定義しないでください。これらは、このタイプの取得では使用されません。
onCreateLoader() を実装する
onCreateLoader()
メソッドを実装して、新しい CursorLoader
を返します。検索文字列をパターンに変換する必要はありません。これは、連絡先プロバイダによって自動的に行われます。Contacts.CONTENT_FILTER_URI
をベース URI として使用し、Uri.withAppendedPath()
を呼び出して検索文字列を追加します。この URI を使用すると、任意のデータ型の検索が自動的にトリガーされます。次の例をご覧ください。
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ val contentUri: Uri = Uri.withAppendedPath( ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(searchString) ) // Starts the query return activity?.let { CursorLoader( it, contentUri, PROJECTION2, null, null, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ Uri contentUri = Uri.withAppendedPath( Contacts.CONTENT_FILTER_URI, Uri.encode(searchString)); // Starts the query return new CursorLoader( getActivity(), contentUri, PROJECTION, null, null, null ); }
これらのコード スニペットは、連絡先プロバイダの幅広い検索を行うアプリのベースです。この手法は、連絡帳アプリの連絡先リスト画面に似た機能を実装するアプリで役立ちます。