Introdução
Provedor de conteúdo, um dos quatro principais componentes do Android, sua principal função é realizar o compartilhamento de dados (entre aplicativos) entre vários aplicativos.
O problema da comunicação do processo está envolvido aqui. Naturalmente, o fichário é usado no Android, mas como a quantidade de dados fornecidos pelo provedor de conteúdo geralmente é relativamente grande, eles não podem ser transmitidos diretamente.
Portanto, o que é usado aqui é um método chamado memória compartilhada anônima para transferência de dados, e apenas um descritor de arquivo precisa ser transferido em diferentes processos.
Tenha uma compreensão mais intuitiva do provedor de conteúdo através da figura a seguir:
ContentProvider fornece um mecanismo para compartilhar dados entre aplicativos.
-
Armazenar e recuperar dados fornece uma interface unificada.
-
Encapsule os dados sem se preocupar com os detalhes de armazenamento de dados.
-
O Android fornece um ContentProvider padrão para alguns dados comuns (incluindo áudio, vídeo, fotos e contatos, etc.).
Então, como o ContentProvider realiza o compartilhamento de dados?
Identificador Uniforme de Recursos (URI)
A URI representa os dados a serem operados, e pode ser utilizada para identificar cada ContentProvider, de forma que você possa encontrar o ContentProvider desejado através da URI especificada, e obter ou modificar dados a partir dele.
O formato de um URI no Android é o seguinte:
URI =
<schema>://<authority>/<path>/<id>
Por exemplo: content://com.jeanboy.provider/User/1
-
tema (esquema)
O prefixo URI do ContentProvider indica um URI de conteúdo do Android, indicando que os dados são controlados pelo ContentProvider. Esta parte é fixa e não pode ser alterada.
-
Informações de autorização (autoridade)
A parte de autorização do URI é um identificador exclusivo usado para localizar o ContentProvider. O formato geralmente é o nome totalmente qualificado da classe ContentProvider customizada, que é necessária para o registro. Tais como: com.jeanboy.provider.TestProvider.
-
nome da tabela (caminho)
O fragmento de caminho, geralmente o nome da tabela, aponta para um nome de tabela no banco de dados.
-
registro (id)
Aponta para um registro específico, como um registro em uma tabela (retorna todos os registros, se não for especificado).
tipo de dados MIME
MIME é especificar um arquivo com uma extensão para abrir com um aplicativo, assim como você usa um navegador para visualizar um arquivo PDF, e o navegador escolherá o aplicativo apropriado para abrir.
A forma como funciona no Android é semelhante ao HTTP, o ContentProvider retornará o tipo MIME de acordo com a URI e o ContentProvider retornará uma string contendo duas partes.
Composição MIME = tipo + subtipo.
texto/aplicativo html/pdf
...
ContentProvider retorna o tipo MIME de acordo com o URI
ContentProvider.geType(uri) ;
O Android segue uma convenção semelhante para definir tipos MIME, e há duas formas de tipos MIME Android para cada tipo de conteúdo: registros múltiplos (coleções) e registros únicos.
-
Vários registros:
vnd.android.cursor.dir/<custom>
-
Registro único:
vnd.android.cursor.item/<custom>
vnd indica que esses tipos e subtipos têm um formulário não padrão e específico do fornecedor. O tipo no Android foi corrigido e não pode ser alterado. Só pode ser distinguido se é uma coleção ou um único registro específico. O conteúdo após o subtipo vnd. pode ser preenchido de acordo com o formato.
Ao usar o Intent, o MIME será usado para abrir a atividade que atende às condições de acordo com o tipo MIME.
<activity android:name=".TestActivity"> <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.dir/jeanboy. primeiro" /> </intent-filter> </activity>
Criar um provedor de conteúdo
Em seguida, aprenda como criar um ContentProvider personalizado por meio de uma demonstração simples. A fonte de dados pode escolher SQLite, a mais usada é essa, claro, você também pode escolher outras, como SharedPreferences.
Primeiro, crie uma classe TestContentProvider, herde ContentProvider e implemente o método.
public class TestContentProvider extends ContentProvider { @Override public boolean onCreate() { // TODO 做一些初始化操作 return false; } @Override public Cursor query(Uri uri, String[] projeção, String selection, String[] selectionArgs, String sortOrder) { // TODO 查询 return null; } @Override public String getType(Uri uri) { // TODO MIME Type return null; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO 插入 return null; } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO 删除 return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO 更新 return 0; } }
Então, ele precisa ser registrado AndroidManifest.xml
com .
<provider android:name=".ui.provider.TestProvider" android:authorities="com.jeanboy.testprovider" />
Usar provedor de conteúdo
Em aplicativos de terceiros, como usamos URI para executar operações em dados compartilhados? Isso é feito usando a classe ContentResolver.
O método para obter uma instância ContentResolver é:
Resolvedor ContentResolver = getContentResolver();
ContentResolver tem as seguintes operações de banco de dados: query, insert, update, delete.
public final Consulta de cursor (Uri uri, projeção String[], seleção String, String[] selectionArgs, String sortOrder) public final Uri insert (Uri url, valores ContentValues) public final int update (Uri uri, valores ContentValues, String where, String [] selectionArgs) public final int delete (Uri url, String where, String[] selectionArgs)
Um exemplo completo é o seguinte:
public class ContentProviderActivity extends BaseActivity { private Uri uriUser = Uri.parse("content://com.jeanboy.testprovider/user"); @Override protected void onCreate(Bundle saveInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content_provider); } public void toInsert(View view) { ContentValues values = new ContentValues(); valores.put("id", 3); values.put("nome", "张三"); Resolvedor ContentResolver = getContentResolver(); resolver.insert(uriUser, valores); } public void toUpdate(Exibir visualização) { Valores de ContentValues = new ContentValues(); valores.put("id", 3); values.put("nome", "张三三"); Resolvedor ContentResolver = getContentResolver(); resolver.update(uriUser, values, "id = ?", new String[]{"3"}); } public void toSelect(View view) { ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(uriUser, new String[]{"id", "nome"}, nulo, nulo, nulo); while (cursor.moveToNext()) { Log.e(TAG, "=========== query :" + cursor.getInt(0) + "==" + cursor.getString(1)) ; } cursor.close(); } public void toDelete(View view) { resolvedor.delete(uriUser, "id = ?", new String[]{"3"}); } }
Permissões do provedor de conteúdo
Há três permissões de parâmetros adicionais, readPermission e writePermission na tag do provedor em AndroidManifest.xml.
Primeiro observe o seguinte código:
<provider android:name=".ui.provider.TestProvider" android:authorities="com.jeanboy.testprovider" android:exported="true" android:readPermission="com.jeanboy.provider.permission.read" android:writePermission ="com.jeanboy.provider.permission.write" android:permission="com.jeanboy.provider.permission"/>
Existem vários parâmetros neste código para prestar atenção especial:
-
exportado
Este atributo é usado para indicar se o serviço pode ser invocado ou interagir com outros componentes de aplicativo do programa; o valor é (verdadeiro | falso).
Se configurado como true, ele pode ser chamado ou interagir, caso contrário, não; quando configurado como false, apenas componentes do mesmo aplicativo ou aplicativos com o mesmo ID do usuário podem iniciar ou ligar o serviço.
-
permissão de leitura
A autoridade necessária para usar a função de consulta do Content Provider, ou seja, a autoridade para usar query()
as funções .
-
permissão de gravação
A autoridade necessária para usar a função de modificação de ContentProvider, ou seja, a autoridade para usar as funções insert()
, update()
e delete()
de ContentProvider.
-
permissão
O nome da permissão necessária para o cliente ler e gravar dados no provedor de conteúdo.
Esta propriedade fornece um atalho para configurar as permissões de leitura e gravação de uma só vez. No entanto, os atributos readPermission e writePermission têm precedência sobre essa configuração.
Se a propriedade readPermission também estiver definida, ela controlará a leitura do provedor de conteúdo. Se o atributo writePermission for definido, ele também controlará a modificação dos dados do provedor de conteúdo.
Ou seja, se apenas a permissão permission for definida, o aplicativo com essa permissão poderá ler e gravar o ContentProvider aqui; se ambos permission e readPermission forem definidos, apenas o aplicativo com permissão readPermission poderá ler e apenas o aplicativo com permissão permissão pode escrever! Ou seja, você não pode ler apenas com a permissão permission, porque a prioridade de readPermission é maior que a de permission; se readPermission, writePermission e permission forem definidos ao mesmo tempo, a permissão será inválida.
Permissão para usar
Após declarar a permissão acima, você precisa registrá-la no diretório no mesmo nível do tag application.
<manifest ...> <permission android:name="com.jeanboy.provider.permission.read" android:label="provider pomission" android:protectionLevel="normal" /> <application ...> ... < /aplicativo> </manifesto>
Desta forma, nossa permissão será cadastrada no sistema e utilizada em aplicativos de terceiros <uses-permission>
para utilização de permissões.
<uses-permission android:name="com.jeanboy.provider.permission.read"/>
ContentObserver
A principal função do ContentObserver é monitorar as alterações do banco de dados no URI especificado.
Primeiro, crie um ContentObserver.
public class DataObserver extends ContentObserver { public DataObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); // TODO escuta alterações de dados } }
Registre um ContentObserver.
public class ContentProviderActivity extends BaseActivity { private Uri uriUser = Uri.parse("content://com.jeanboy.myprovider/user"); privado DataObserver dataObserver; @Substituir string protegida getTAG() { return ContentProviderActivity.class.getSimpleName(); } @Override protected void onCreate(Bundle saveInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content_provider); // Exibe DataObserver dataObserver = new DataObserver(new Handler()); // Mais DataObserver getContentResolver().registerContentObserver(uriUser, true, dataObserver); } @Override void protegido onDestroy() { super.onDestroy(); // Exibe o método getContentResolver().unregisterContentObserver(dataObserver); } }
Por fim, observe o uso da função de ouvinte registerContentObserver()
registrado :
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
-
uri
O URI a ser observado.
-
NotificarParaDescendentes
Se for falso, significa correspondência exata, ou seja, corresponde apenas a este URI; se for verdadeiro, significa que pode corresponder ao mesmo tempo ao seu URI derivado.