Esta lição mostra como recuperar uma lista de contatos cujos dados correspondem a toda ou a parte de uma string de pesquisa, usando as seguintes técnicas:
- Correspondência com nomes de contatos
- Recuperar uma lista de contatos fazendo a correspondência da string de pesquisa com todo o contato ou parte dele. dados de nome. O Provedor de contatos permite várias instâncias do mesmo nome, então esse pode retornar uma lista de correspondências.
- Correspondência com um tipo específico de dados, por exemplo, um número de telefone
- Recuperar uma lista de contatos pela correspondência da string de pesquisa a um tipo específico de detalhe. como um endereço de e-mail. Por exemplo, essa técnica permite listar todos os contatos cujo endereço de e-mail corresponda à string de pesquisa.
- Correspondência com qualquer tipo de dados
- Recuperar uma lista de contatos pela correspondência da string de pesquisa a qualquer tipo de dados detalhados. incluindo nome, número de telefone, endereço, endereço de e-mail e assim por diante. Por exemplo, essa técnica permite aceitar qualquer tipo de dados para uma string de pesquisa e listar os contatos com dados que correspondem à string.
Observação: todos os exemplos desta lição usam uma
CursorLoader
para recuperar dados dos contatos
Provedor. Um CursorLoader
executa a consulta em um
linha de execução separada da linha de execução de IU. Isso garante que a consulta não atrase o tempo de resposta da IU
e cause uma experiência ruim para o usuário. Para saber mais, consulte a classe de treinamento
do Android
Como carregar dados em segundo plano.
Solicitar permissão para ler o provedor
Para fazer qualquer tipo de pesquisa do Provedor de contatos, seu app precisa ter
a permissão READ_CONTACTS
.
Para solicitar isso, adicione o elemento
<uses-permission>
ao arquivo de manifesto como um elemento filho de
<manifest>
:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Fazer a correspondência de um contato por nome e listar os resultados
Essa técnica tenta associar uma string de pesquisa ao nome de um contato ou contatos na
tabela ContactsContract.Contacts
do Provedor de contatos. Normalmente, você quer
para mostrar os resultados em uma ListView
, permitindo que o usuário escolha entre
os contatos correspondentes.
Definir ListView e layouts de item
Para mostrar os resultados da pesquisa em uma ListView
, é necessário um arquivo de layout principal
que define toda a interface, incluindo o ListView
e um layout de item
que define uma linha do ListView
. Por exemplo, você pode criar
o arquivo de layout principal res/layout/contacts_list_view.xml
com
este 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"/>
Esse XML usa o widget ListView
integrado do Android
android:id/list
.
Defina o arquivo de layout do item contacts_list_item.xml
com o seguinte 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"/>
Esse XML usa o widget TextView
integrado do Android
android:text1
.
Observação: esta lição não descreve a interface para receber uma string de pesquisa do user, porque é possível receber a string indiretamente. Por exemplo, você pode dar ao usuário uma opção para procurar contatos cujo nome corresponda a uma string em uma mensagem de texto recebida.
Os dois arquivos de layout que você escreveu definem uma interface de usuário que mostra uma
ListView
: A próxima etapa é escrever o código que usa essa interface para mostrar uma
lista de contatos.
Definir um fragmento que exiba a lista de contatos
Para mostrar a lista de contatos, defina um Fragment
que é carregado por uma Activity
. O uso de um
Fragment
é uma técnica mais flexível, porque você pode usar
um Fragment
para exibir a lista e um segundo
Fragment
para mostrar os detalhes de um contato que o usuário
escolhe na lista. Usando essa abordagem, você pode combinar uma das técnicas apresentadas em
esta lição com uma da lição
Recuperar detalhes de um contato.
Para aprender a usar um ou mais objetos Fragment
de uma
Activity
, leia a aula de treinamento
Criar uma interface dinâmica com fragmentos.
Para ajudar você a escrever consultas no Provedor de contatos, a estrutura do Android fornece um
de contratos da classe chamada ContactsContract
, que define
constantes e métodos para acessar o provedor. Quando você usa essa classe, não precisa
definir suas próprias constantes para URIs de conteúdo, nomes de tabelas ou colunas. Para usar essa classe,
inclua a seguinte instrução:
Kotlin
import android.provider.ContactsContract
Java
import android.provider.ContactsContract;
Como o código usa um CursorLoader
para extrair dados
do provedor, você deve especificar que ele implementa a interface do carregador
LoaderManager.LoaderCallbacks
. Além disso, para ajudar a detectar qual contato
o usuário seleciona na lista de resultados da pesquisa, implemente a interface do adaptador
AdapterView.OnItemClickListener
: Exemplo:
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 {
Definir variáveis globais
Defina variáveis globais usadas em outras partes do código:
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; ...
Observação: como
O Contacts.DISPLAY_NAME_PRIMARY
exige o Android 3.0 (API de nível 11) ou mais recente. A configuração do
a versão 10 ou minSdkVersion
do app gera um aviso do Android Lint
Android Studio Para desativar esse aviso, adicione a anotação
@SuppressLint("InlinedApi")
antes da definição de FROM_COLUMNS
.
Inicializar o fragmento
Inicialize o Fragment
: Adicione o construtor público vazio
exigido pelo sistema Android e infle a IU do objeto
Fragment
no método de callback onCreateView()
.
Exemplo:
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); }
Configurar o CursorAdapter para a ListView
Configure o SimpleCursorAdapter
que vincula os resultados do
para o ListView
. Para acessar o objeto ListView
que mostra os contatos, é necessário chamar Activity.findViewById()
usando a atividade pai do
Fragment
. Use o Context
do
atividade pai quando você chama setAdapter()
.
Exemplo:
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); }
Definir o listener do contato selecionado
Ao exibir os resultados de uma pesquisa, você geralmente quer permitir que o usuário selecione um
um único contato para processamento adicional. Por exemplo, quando o usuário clica em um contato, você pode
mostrar o endereço do contato em um mapa. Para fornecer esse recurso, primeiro você definiu o
Fragment
como o listener de clique, especificando que a classe
implementa AdapterView.OnItemClickListener
, conforme mostrado na seção
Definir um fragmento para exibir a lista de contatos.
Para continuar configurando o listener, vincule-o à ListView
chamando
o método setOnItemClickListener()
em onActivityCreated()
. Exemplo:
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); ... }
Como você especificou que o Fragment
atual é o
OnItemClickListener
para o
ListView
, agora é preciso implementar o método necessário
onItemClick()
, que
processa o evento de clique. Isso é descrito em uma seção a seguir.
Definir uma projeção
Defina uma constante que contenha as colunas que você quer que sejam retornadas da sua consulta. Cada item em
ListView
mostra o nome de exibição do contato.
que contém a forma principal do nome do contato. No Android 3.0 (API de nível 11) e versões mais recentes,
o nome dessa coluna é
Contacts.DISPLAY_NAME_PRIMARY
. Nas versões anteriores, o nome é
Contacts.DISPLAY_NAME
.
A coluna Contacts._ID
é usada pelo
Processo de vinculação de SimpleCursorAdapter
.
Contacts._ID
e
LOOKUP_KEY
são usados juntos para
construir um URI de conteúdo para o contato que o usuário seleciona.
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 };
Definir constantes para os índices da coluna do Cursor
Para conferir os dados de uma coluna individual em um Cursor
, você precisa
do índice da coluna dentro do Cursor
. É possível definir constantes
para os índices das colunas Cursor
, porque os índices são
igual à ordem dos nomes das colunas na sua projeção. Exemplo:
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;
Especificar os critérios de seleção
Para especificar os dados desejados, crie uma combinação de expressões e variáveis de texto que informam ao provedor as colunas de dados a serem pesquisadas e os valores a serem encontrados.
Para a expressão de texto, defina uma constante que liste as colunas de pesquisa. Embora essa expressão possa conter valores também, a prática recomendada é representar os valores com um marcador de posição "?". Durante a recuperação, o marcador é substituído pelos valores de uma matriz. O uso de "?" como marcador garante que a especificação de pesquisa seja gerada por vinculação e não por compilação SQL. Essa prática elimina a possibilidade de SQL malicioso por injeção. Exemplo:
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 };
Definir o método onItemClick()
Na seção anterior, você definiu o listener de clique do item para a ListView
.
Agora, implemente a ação para o listener, definindo o método
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. */ }
Inicializar o carregador
Como você está usando um CursorLoader
para recuperar dados,
é necessário inicializar a linha de execução em segundo plano e outras variáveis que controlam a recuperação
assíncrona. Faça a inicialização em
onCreate()
como
como mostrado no exemplo a seguir:
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);
Implementar onCreateLoader()
Implementar o método
onCreateLoader()
,
que é chamado pelo framework do carregador imediatamente após a chamada
initLoader()
.
Em onCreateLoader()
,
configure o padrão de string de pesquisa. Para transformar uma string em um padrão, insira caracteres "%"
(porcentagem) para representar uma sequência de zero ou mais caracteres, ou caracteres "_"
(sublinhado) para representar um único caractere, ou ambos. Por exemplo, o padrão "%Jefferson%"
corresponderia a "Thomas Jefferson" e "Jefferson Davis".
Retorne um novo CursorLoader
do método. Para o URI de
conteúdo, use Contacts.CONTENT_URI
.
Esse URI refere-se à tabela inteira, conforme mostrado no exemplo a seguir:
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 ); }
Implementar onLoadFinished() e onLoaderReset()
Implementar o
onLoadFinished()
. O framework do carregador chama
onLoadFinished()
quando o Provedor de contatos retorna os resultados da consulta. Neste método, coloque o
resultado Cursor
no
SimpleCursorAdapter
. Isso atualiza automaticamente a
ListView
com os resultados da pesquisa:
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); }
O método onLoaderReset()
é invocado quando o framework do carregador detecta que o
o resultado Cursor
contém dados desatualizados. Exclua o
Referência do SimpleCursorAdapter
ao arquivo
Cursor
. Caso contrário, o framework do carregador não
Reciclar Cursor
, o que causa um vazamento de memória. Exemplo:
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); }
Agora você tem as principais partes de um app que faz a correspondência de uma string de pesquisa a nomes de contatos e retorna
o resultado em uma ListView
. O usuário pode clicar no nome de um contato para selecioná-lo.
Isso aciona um listener, em que você pode trabalhar mais com os dados do contato. Por exemplo,
você pode recuperar os detalhes do contato. Para saber como fazer isso, continue na próxima
aula, Recuperar detalhes de um contato.
Para saber mais sobre interfaces de usuário de pesquisa, leia o guia da API Criar uma interface de pesquisa.
As seções restantes desta lição demonstram outras formas de encontrar contatos no Provedor de contatos.
Fazer a correspondência de um contato por um tipo específico de dados
Essa técnica permite especificar o tipo de dados que você quer na correspondência. Recuperando por nome é um exemplo específico desse tipo de consulta, mas também pode ser usado para qualquer tipo de dados detalhados associados a um contato. Por exemplo, você pode recuperar contatos que tenham um CEP específico que, nesse caso, a sequência de pesquisa deve corresponder aos dados armazenados em um código postal linha de comando.
Para implementar esse tipo de recuperação, primeiro implemente o seguinte código, conforme listado nas seções anteriores:
- Solicitar permissão para ler o provedor
- Definir ListView e layouts de item
- Definir um fragmento que exiba a lista de contatos
- Definir variáveis globais
- Inicializar o fragmento
- Configurar o CursorAdapter para a ListView
- Definir o listener do contato selecionado
-
Definir constantes para os índices da coluna do Cursor
Embora você esteja recuperando dados de uma tabela diferente, a ordem das colunas no a projeção é a mesma, então você pode usar os mesmos índices para o Cursor.
- Definir o método onItemClick()
- Inicializar o carregador
- Implementar onLoadFinished() e onLoaderReset()
As etapas a seguir mostram o código adicional que você precisa para corresponder uma string de pesquisa a um tipo específico de dados detalhados e exibir os resultados.
Escolher o tipo de dados e a tabela
Para pesquisar um tipo específico de dados detalhados, você precisa saber o valor do tipo MIME personalizado
para o tipo de dados. Cada tipo de dados tem um valor exclusivo de tipo MIME
definido por uma constante CONTENT_ITEM_TYPE
na subclasse de
ContactsContract.CommonDataKinds
associada ao tipo de dados.
As subclasses têm nomes que indicam o tipo de dados. Por exemplo, a subclasse de dados de e-mail é ContactsContract.CommonDataKinds.Email
, e o tipo MIME personalizado para dados de e-mail é definido pela constante Email.CONTENT_ITEM_TYPE
.
Use a tabela ContactsContract.Data
para a pesquisa. Todas as
constantes necessárias para sua projeção, cláusula de seleção e ordem de classificação são definidas em ou
herdadas por esta tabela.
Definir uma projeção
Para definir uma projeção, escolha uma ou mais colunas definidas em
ContactsContract.Data
ou as classes de que ela é herdada. O
Provedor de contatos faz uma mesclagem implícita entre ContactsContract.Data
e outras tabelas antes de retornar linhas. Exemplo:
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 };
Definir critérios de pesquisa
Para procurar uma string em um tipo específico de dados, construa uma cláusula de seleção a partir de o seguinte:
-
O nome da coluna que contém sua string de pesquisa. Esse nome varia de acordo com o tipo de dados.
Portanto, você precisa encontrar a subclasse de
ContactsContract.CommonDataKinds
que corresponde ao tipo de dados e escolher o nome da coluna dessa subclasse. Por exemplo, para procurar endereços de e-mail, use a colunaEmail.ADDRESS
. - A própria string de pesquisa, representada como o caractere "?" na cláusula de seleção.
-
O nome da coluna que contém o valor do tipo MIME personalizado. Esse nome é sempre
Data.MIMETYPE
: -
O valor do tipo MIME personalizado para o tipo de dados. Como descrito anteriormente, esta é a constante
CONTENT_ITEM_TYPE
noContactsContract.CommonDataKinds
. Por exemplo, o valor do tipo MIME para dados de e-mail éEmail.CONTENT_ITEM_TYPE
. Coloque o valor entre aspas simples, concatenando um "'
" (aspas simples) no início e no final da constante. caso contrário, o provedor interpreta o valor como um nome de variável, e não como um valor de string. Você não precisa usar um marcador para esse valor, porque está usando um valor constante em vez de um valor fornecido pelo usuário.
Exemplo:
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 + "'";
Em seguida, defina variáveis para conter o argumento de seleção:
Kotlin
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
Java
String searchString; String[] selectionArgs = { "" };
Implementar onCreateLoader()
Agora que você especificou os dados desejados e como encontrá-los, defina uma consulta na sua
implementação de onCreateLoader()
.
Retornar um novo CursorLoader
deste
usando sua projeção, expressão de texto de seleção e matriz de seleção como
. Para um URI de conteúdo, use
Data.CONTENT_URI
. Exemplo:
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 ); }
Esses snippets de código são a base de uma pesquisa inversa simples com base em um tipo específico de dados detalhados. Essa é a melhor técnica a ser usada se o app se concentra em um tipo específico de dados, por exemplo, e-mails, e você quer que os usuários vejam os nomes associados a um dado.
Fazer a correspondência de um contato por qualquer tipo de dados
A recuperação de um contato com base em qualquer tipo de dados retornará contatos se um deles corresponder à string de caracteres de pesquisa, incluindo nome, endereço de e-mail, endereço postal, número de telefone e assim por diante. Isso resulta em um conjunto grande de resultados de pesquisa. Por exemplo, se a string de pesquisa for "Doe", a pesquisa de qualquer tipo de dados retornará o contato "John Doe"; também retornará contatos que moram na "Doe Street".
Para implementar esse tipo de recuperação, primeiro implemente o código a seguir, conforme listado em seções anteriores:
- Solicitar permissão para ler o provedor
- Definir ListView e layouts de item
- Definir um fragmento que exiba a lista de contatos
- Definir variáveis globais
- Inicializar o fragmento
- Configurar o CursorAdapter para a ListView
- Definir o listener do contato selecionado
- Definir uma projeção
-
Definir constantes para os índices da coluna do Cursor
Para esse tipo de recuperação, você está usando a mesma tabela usada na seção Faça a correspondência de um contato por nome e liste os resultados. Use os mesmos índices de coluna também.
- Definir o método onItemClick()
- Inicializar o carregador
- Implementar onLoadFinished() e onLoaderReset()
As etapas a seguir mostram o código adicional que você precisa para corresponder uma string de pesquisa a qualquer tipo de dados e exibir os resultados.
Remover critérios de seleção
Não defina as constantes SELECTION
ou a variável mSelectionArgs
.
Elas não são usadas nesse tipo de recuperação.
Implementar onCreateLoader()
Implemente o método onCreateLoader()
,
retornando um novo CursorLoader
.
Você não precisa converter a string de pesquisa em um padrão, porque o Provedor de contatos
isso automaticamente. Use
Contacts.CONTENT_FILTER_URI
como o URI base e anexe sua string de pesquisa a ele chamando
Uri.withAppendedPath()
. O uso desse URI
aciona automaticamente a pesquisa de qualquer tipo de dados, conforme mostrado no exemplo a seguir:
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 ); }
Esses snippets de código são a base de um app que faz uma pesquisa ampla no Provedor de contatos. A técnica é útil para aplicativos que desejam implementar uma funcionalidade semelhante à Tela da lista de contatos do app People.