Android - Provedores de conteúdo
Um componente de provedor de conteúdo fornece dados de um aplicativo para outros, mediante solicitação. Essas solicitações são tratadas pelos métodos da classe ContentResolver. Um provedor de conteúdo pode usar diferentes maneiras de armazenar seus dados e os dados podem ser armazenados em um banco de dados, em arquivos ou até mesmo em uma rede.
Provedor de conteúdos
sometimes it is required to share data across applications. This is where content providers become very useful.
Os provedores de conteúdo permitem que você centralize o conteúdo em um local e tenha muitos aplicativos diferentes acessando-o conforme necessário. Um provedor de conteúdo se comporta de maneira muito semelhante a um banco de dados onde você pode consultá-lo, editar seu conteúdo, bem como adicionar ou excluir conteúdo usando os métodos insert (), update (), delete () e query (). Na maioria dos casos, esses dados são armazenados em umSQlite base de dados.
Um provedor de conteúdo é implementado como uma subclasse de ContentProvider classe e deve implementar um conjunto padrão de APIs que permitem que outros aplicativos executem transações.
public class My Application extends ContentProvider {
}
URIs de conteúdo
Para consultar um provedor de conteúdo, você especifica a string de consulta na forma de um URI que tem o seguinte formato -
<prefix>://<authority>/<data_type>/<id>
Aqui está o detalhe de várias partes do URI -
Sr. Não | Descrição parcial |
---|---|
1 | prefix Isso é sempre definido como content: // |
2 | authority Isso especifica o nome do provedor de conteúdo, por exemplo , contatos , navegador , etc. Para provedores de conteúdo de terceiros, pode ser o nome totalmente qualificado, como com.tutorialspoint.statusprovider |
3 | data_type Isso indica o tipo de dados que esse provedor específico fornece. Por exemplo, se você estiver obtendo todos os contatos do provedor de conteúdo de Contatos , o caminho de dados seria pessoas e o URI seria semelhante a este conteúdo: // contatos / pessoas |
4 | id Isso especifica o registro específico solicitado. Por exemplo, se você estiver procurando pelo contato número 5 no provedor de conteúdo de Contatos, o URI será semelhante a este conteúdo: // contatos / pessoas / 5 . |
Criar provedor de conteúdo
Isso envolve uma série de etapas simples para criar seu próprio provedor de conteúdo.
Em primeiro lugar, você precisa criar uma classe de provedor de conteúdo que estenda a classe ContentProviderbaseclass.
Em segundo lugar, você precisa definir o endereço URI do seu provedor de conteúdo, que será usado para acessar o conteúdo.
Em seguida, você precisará criar seu próprio banco de dados para manter o conteúdo. Normalmente, o Android usa o banco de dados SQLite e a estrutura precisa substituir o método onCreate () , que usará o método SQLite Open Helper para criar ou abrir o banco de dados do provedor. Quando seu aplicativo é iniciado, o manipulador onCreate () de cada um de seus Provedores de Conteúdo é chamado no thread principal do aplicativo.
Em seguida, você terá que implementar consultas do provedor de conteúdo para realizar diferentes operações específicas do banco de dados.
Por fim, registre seu provedor de conteúdo em seu arquivo de atividade usando a tag <provider>.
Aqui está a lista de métodos que você precisa substituir na classe do Provedor de Conteúdo para que seu Provedor de Conteúdo funcione -
Provedor de conteúdos
onCreate() Este método é chamado quando o provedor é iniciado.
query()Este método recebe uma solicitação de um cliente. O resultado é retornado como um objeto Cursor.
insert()Este método insere um novo registro no provedor de conteúdo.
delete() Este método exclui um registro existente do provedor de conteúdo.
update() Este método atualiza um registro existente do provedor de conteúdo.
getType() Este método retorna o tipo MIME dos dados no URI fornecido.
Exemplo
Este exemplo irá explicar como criar seu próprio ContentProvider . Então, vamos seguir as etapas a seguir para se assemelhar ao que seguimos durante a criação do Exemplo Hello World -
Degrau | Descrição |
---|---|
1 | Você usará o Android StudioIDE para criar um aplicativo Android e nomeá-lo como My Application em um pacote com.example.MyApplication , com Activity em branco. |
2 | Modifique o arquivo de atividade principal MainActivity.java para adicionar dois novos métodos onClickAddName () e onClickRetrieveStudents () . |
3 | Crie um novo arquivo java chamado StudentsProvider.java no pacote com.example.MyApplication para definir seu provedor real e métodos associados. |
4 | Registre seu provedor de conteúdo em seu arquivo AndroidManifest.xml usando a tag <provider ... /> |
5 | Modifique o conteúdo padrão do arquivo res / layout / activity_main.xml para incluir uma pequena GUI para adicionar registros de alunos. |
6 | Não há necessidade de alterar string.xml. O Android Studio cuida do arquivo string.xml. |
7 | Execute o aplicativo para iniciar o emulador Android e verifique o resultado das alterações feitas no aplicativo. |
A seguir está o conteúdo do arquivo de atividade principal modificado src/com.example.MyApplication/MainActivity.java. Este arquivo pode incluir cada um dos métodos fundamentais do ciclo de vida. Adicionamos dois novos métodos onClickAddName () e onClickRetrieveStudents () para lidar com a interação do usuário com o aplicativo.
package com.example.MyApplication;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClickAddName(View view) {
// Add a new student record
ContentValues values = new ContentValues();
values.put(StudentsProvider.NAME,
((EditText)findViewById(R.id.editText2)).getText().toString());
values.put(StudentsProvider.GRADE,
((EditText)findViewById(R.id.editText3)).getText().toString());
Uri uri = getContentResolver().insert(
StudentsProvider.CONTENT_URI, values);
Toast.makeText(getBaseContext(),
uri.toString(), Toast.LENGTH_LONG).show();
}
public void onClickRetrieveStudents(View view) {
// Retrieve student records
String URL = "content://com.example.MyApplication.StudentsProvider";
Uri students = Uri.parse(URL);
Cursor c = managedQuery(students, null, null, null, "name");
if (c.moveToFirst()) {
do{
Toast.makeText(this,
c.getString(c.getColumnIndex(StudentsProvider._ID)) +
", " + c.getString(c.getColumnIndex( StudentsProvider.NAME)) +
", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)),
Toast.LENGTH_SHORT).show();
} while (c.moveToNext());
}
}
}
Crie um novo arquivo StudentsProvider.java sob o pacote com.example.MyApplication e a seguir está o conteúdo desrc/com.example.MyApplication/StudentsProvider.java -
package com.example.MyApplication;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
public class StudentsProvider extends ContentProvider {
static final String PROVIDER_NAME = "com.example.MyApplication.StudentsProvider";
static final String URL = "content://" + PROVIDER_NAME + "/students";
static final Uri CONTENT_URI = Uri.parse(URL);
static final String _ID = "_id";
static final String NAME = "name";
static final String GRADE = "grade";
private static HashMap<String, String> STUDENTS_PROJECTION_MAP;
static final int STUDENTS = 1;
static final int STUDENT_ID = 2;
static final UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);
uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);
}
/**
* Database specific constant declarations
*/
private SQLiteDatabase db;
static final String DATABASE_NAME = "College";
static final String STUDENTS_TABLE_NAME = "students";
static final int DATABASE_VERSION = 1;
static final String CREATE_DB_TABLE =
" CREATE TABLE " + STUDENTS_TABLE_NAME +
" (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" name TEXT NOT NULL, " +
" grade TEXT NOT NULL);";
/**
* Helper class that actually creates and manages
* the provider's underlying data repository.
*/
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DB_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + STUDENTS_TABLE_NAME);
onCreate(db);
}
}
@Override
public boolean onCreate() {
Context context = getContext();
DatabaseHelper dbHelper = new DatabaseHelper(context);
/**
* Create a write able database which will trigger its
* creation if it doesn't already exist.
*/
db = dbHelper.getWritableDatabase();
return (db == null)? false:true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
/**
* Add a new student record
*/
long rowID = db.insert( STUDENTS_TABLE_NAME, "", values);
/**
* If record is added successfully
*/
if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to add a record into " + uri);
}
@Override
public Cursor query(Uri uri, String[] projection,
String selection,String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(STUDENTS_TABLE_NAME);
switch (uriMatcher.match(uri)) {
case STUDENTS:
qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
break;
case STUDENT_ID:
qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));
break;
default:
}
if (sortOrder == null || sortOrder == ""){
/**
* By default sort on student names
*/
sortOrder = NAME;
}
Cursor c = qb.query(db, projection, selection,
selectionArgs,null, null, sortOrder);
/**
* register to watch a content URI for changes
*/
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)){
case STUDENTS:
count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs);
break;
case STUDENT_ID:
String id = uri.getPathSegments().get(1);
count = db.delete( STUDENTS_TABLE_NAME, _ID + " = " + id +
(!TextUtils.isEmpty(selection) ? "
AND (" + selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case STUDENTS:
count = db.update(STUDENTS_TABLE_NAME, values, selection, selectionArgs);
break;
case STUDENT_ID:
count = db.update(STUDENTS_TABLE_NAME, values,
_ID + " = " + uri.getPathSegments().get(1) +
(!TextUtils.isEmpty(selection) ? "
AND (" +selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri );
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)){
/**
* Get all student records
*/
case STUDENTS:
return "vnd.android.cursor.dir/vnd.example.students";
/**
* Get a particular student
*/
case STUDENT_ID:
return "vnd.android.cursor.item/vnd.example.students";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
}
A seguir, o conteúdo modificado do arquivo AndroidManifest.xml . Aqui, adicionamos a tag <provider ... /> para incluir nosso provedor de conteúdo:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.MyApplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:name="StudentsProvider"
android:authorities="com.example.MyApplication.StudentsProvider"/>
</application>
</manifest>
A seguir estará o conteúdo de res/layout/activity_main.xml arquivo−
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.MyApplication.MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Content provider"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textSize="30dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tutorials point "
android:textColor="#ff87ff09"
android:textSize="30dp"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton"
android:src="@drawable/abc"
android:layout_below="@+id/textView2"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="Add Name"
android:layout_below="@+id/editText3"
android:layout_alignRight="@+id/textView2"
android:layout_alignEnd="@+id/textView2"
android:layout_alignLeft="@+id/textView2"
android:layout_alignStart="@+id/textView2"
android:onClick="onClickAddName"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_below="@+id/imageButton"
android:layout_alignRight="@+id/imageButton"
android:layout_alignEnd="@+id/imageButton" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText2"
android:layout_alignTop="@+id/editText"
android:layout_alignLeft="@+id/textView1"
android:layout_alignStart="@+id/textView1"
android:layout_alignRight="@+id/textView1"
android:layout_alignEnd="@+id/textView1"
android:hint="Name"
android:textColorHint="@android:color/holo_blue_light" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText3"
android:layout_below="@+id/editText"
android:layout_alignLeft="@+id/editText2"
android:layout_alignStart="@+id/editText2"
android:layout_alignRight="@+id/editText2"
android:layout_alignEnd="@+id/editText2"
android:hint="Grade"
android:textColorHint="@android:color/holo_blue_bright" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Retrive student"
android:id="@+id/button"
android:layout_below="@+id/button2"
android:layout_alignRight="@+id/editText3"
android:layout_alignEnd="@+id/editText3"
android:layout_alignLeft="@+id/button2"
android:layout_alignStart="@+id/button2"
android:onClick="onClickRetrieveStudents"/>
</RelativeLayout>
Certifique-se de ter o seguinte conteúdo de res/values/strings.xml Arquivo:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
</resources>;
Vamos tentar executar nosso modificado My Applicationaplicativo que acabamos de criar. Suponho que você tenha criado o seuAVDao fazer a configuração do ambiente. Para executar o aplicativo a partir do Android Studio IDE, abra um dos arquivos de atividade do seu projeto e clique no ícone Executar na barra de ferramentas. O Android Studio instala o aplicativo em seu AVD e o inicia e se tudo estiver bem com sua configuração e aplicativo, ele será exibido na janela do emulador seguinte, tenha paciência porque pode levar algum tempo com base na velocidade do seu computador -
Agora vamos entrar aluno Name e Grade e finalmente clique em Add Namebotão, isso adicionará o registro do aluno no banco de dados e piscará uma mensagem na parte inferior mostrando o URI do ContentProvider junto com o número do registro adicionado no banco de dados. Esta operação faz uso de nossoinsert()método. Vamos repetir esse processo para adicionar mais alguns alunos ao banco de dados de nosso provedor de conteúdo.
Quando terminar de adicionar registros no banco de dados, agora é hora de pedir a ContentProvider para nos devolver esses registros, então vamos clicar Retrieve Students botão que irá buscar e exibir todos os registros, um por um, que está de acordo com a implementação de nosso query() método.
Você pode escrever atividades em relação às operações de atualização e exclusão, fornecendo funções de retorno de chamada em MainActivity.java e, em seguida, modifique a interface do usuário para ter botões para atualizar e excluir operações da mesma forma que fizemos para adicionar e ler as operações.
Desta forma, você pode usar o Provedor de Conteúdo existente, como o Catálogo de Endereços, ou pode usar o conceito do Provedor de Conteúdo no desenvolvimento de bons aplicativos orientados a banco de dados, onde você pode realizar todos os tipos de operações de banco de dados como ler, gravar, atualizar e excluir conforme explicado acima no exemplo.