Android - Fournisseurs de contenu
Un composant fournisseur de contenu fournit des données d'une application à d'autres sur demande. Ces demandes sont gérées par les méthodes de la classe ContentResolver. Un fournisseur de contenu peut utiliser différentes méthodes pour stocker ses données et les données peuvent être stockées dans une base de données, dans des fichiers ou même sur un réseau.
Fournisseur de contenu
sometimes it is required to share data across applications. This is where content providers become very useful.
Les fournisseurs de contenu vous permettent de centraliser le contenu en un seul endroit et de permettre à de nombreuses applications d'y accéder selon les besoins. Un fournisseur de contenu se comporte très comme une base de données dans laquelle vous pouvez l'interroger, modifier son contenu, ainsi qu'ajouter ou supprimer du contenu à l'aide des méthodes insert (), update (), delete () et query (). Dans la plupart des cas, ces données sont stockées dans unSQlite base de données.
Un fournisseur de contenu est implémenté en tant que sous-classe de ContentProvider classe et doit implémenter un ensemble standard d'API permettant à d'autres applications d'effectuer des transactions.
public class My Application extends ContentProvider {
}
URI de contenu
Pour interroger un fournisseur de contenu, vous spécifiez la chaîne de requête sous la forme d'un URI au format suivant:
<prefix>://<authority>/<data_type>/<id>
Voici le détail des différentes parties de l'URI -
Sr. Non | Pièce et description |
---|---|
1 | prefix Ceci est toujours défini sur content: // |
2 | authority Cela spécifie le nom du fournisseur de contenu, par exemple les contacts , le navigateur, etc. Pour les fournisseurs de contenu tiers, il peut s'agir du nom complet, tel que com.tutorialspoint.statusprovider |
3 | data_type Cela indique le type de données que ce fournisseur particulier fournit. Par exemple, si vous obtenez tous les contacts du fournisseur de contenu Contacts , le chemin des données serait les personnes et l'URI ressemblerait à ce contenu: // contacts / personnes |
4 | id Ceci spécifie l'enregistrement spécifique demandé. Par exemple, si vous recherchez le numéro de contact 5 dans le fournisseur de contenu Contacts, l'URI ressemblerait à ce contenu: // contacts / people / 5 . |
Créer un fournisseur de contenu
Cela implique un certain nombre d'étapes simples pour créer votre propre fournisseur de contenu.
Tout d'abord, vous devez créer une classe Content Provider qui étend la ContentProviderbaseclass.
Deuxièmement, vous devez définir l'adresse URI de votre fournisseur de contenu qui sera utilisée pour accéder au contenu.
Ensuite, vous devrez créer votre propre base de données pour conserver le contenu. Habituellement, Android utilise la base de données SQLite et le framework doit remplacer la méthode onCreate () qui utilisera la méthode SQLite Open Helper pour créer ou ouvrir la base de données du fournisseur. Lorsque votre application est lancée, le gestionnaire onCreate () de chacun de ses fournisseurs de contenu est appelé sur le thread d'application principal.
Ensuite, vous devrez implémenter des requêtes de fournisseur de contenu pour effectuer différentes opérations spécifiques à la base de données.
Enfin, enregistrez votre fournisseur de contenu dans votre fichier d'activité à l'aide de la balise <provider>.
Voici la liste des méthodes que vous devez remplacer dans la classe Content Provider pour que votre fournisseur de contenu fonctionne -
Fournisseur de contenu
onCreate() Cette méthode est appelée au démarrage du fournisseur.
query()Cette méthode reçoit une demande d'un client. Le résultat est renvoyé sous la forme d'un objet Cursor.
insert()Cette méthode insère un nouvel enregistrement dans le fournisseur de contenu.
delete() Cette méthode supprime un enregistrement existant du fournisseur de contenu.
update() Cette méthode met à jour un enregistrement existant du fournisseur de contenu.
getType() Cette méthode renvoie le type MIME des données à l'URI donné.
Exemple
Cet exemple vous explique comment créer votre propre ContentProvider . Alors, suivons les étapes suivantes pour ressembler à ce que nous avons suivi lors de la création de Hello World Exemple -
Étape | La description |
---|---|
1 | Vous utiliserez Android StudioIDE pour créer une application Android et la nommerez My Application sous un package com.example.MyApplication , avec une activité vide. |
2 | Modifiez le fichier d'activité principal MainActivity.java pour ajouter deux nouvelles méthodes onClickAddName () et onClickRetrieveStudents () . |
3 | Créez un nouveau fichier java appelé StudentsProvider.java sous le package com.example.MyApplication pour définir votre fournisseur réel et les méthodes associées. |
4 | Enregistrez votre fournisseur de contenu dans votre fichier AndroidManifest.xml à l'aide de la balise <provider ... /> |
5 | Modifiez le contenu par défaut du fichier res / layout / activity_main.xml pour inclure une petite interface graphique pour ajouter des enregistrements d'étudiants. |
6 | Pas besoin de changer string.xml.Android studio s'occupe du fichier string.xml. |
sept | Exécutez l'application pour lancer l'émulateur Android et vérifier le résultat des modifications effectuées dans l'application. |
Voici le contenu du fichier d'activité principal modifié src/com.example.MyApplication/MainActivity.java. Ce fichier peut inclure chacune des méthodes fondamentales du cycle de vie. Nous avons ajouté deux nouvelles méthodes onClickAddName () et onClickRetrieveStudents () pour gérer l'interaction de l'utilisateur avec l'application.
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());
}
}
}
Créez un nouveau fichier StudentsProvider.java sous le package com.example.MyApplication et voici le contenu 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);
}
}
}
Voici le contenu modifié du fichier AndroidManifest.xml . Ici, nous avons ajouté la balise <provider ... /> pour inclure notre fournisseur de contenu:
<?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>
Voici le contenu de res/layout/activity_main.xml fichier−
<?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>
Assurez-vous d'avoir le contenu suivant de res/values/strings.xml fichier:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
</resources>;
Essayons d'exécuter notre modifié My Applicationapplication que nous venons de créer. Je suppose que vous avez créé votreAVDlors de la configuration de l'environnement. Pour exécuter l'application à partir de l'IDE Android Studio, ouvrez l'un des fichiers d'activité de votre projet et cliquez sur l'
Maintenant, entrons étudiant Name et Grade et enfin cliquez sur Add Name, cela ajoutera un enregistrement d'étudiant dans la base de données et fera clignoter un message en bas indiquant l'URI ContentProvider avec le numéro d'enregistrement ajouté dans la base de données. Cette opération utilise notreinsert()méthode. Répétons ce processus pour ajouter quelques étudiants supplémentaires dans la base de données de notre fournisseur de contenu.
Une fois que vous avez terminé d'ajouter des enregistrements dans la base de données, il est maintenant temps de demander à ContentProvider de nous rendre ces enregistrements, alors cliquons sur Retrieve Students bouton qui récupérera et affichera tous les enregistrements un par un, conformément à notre mise en œuvre de notre query() méthode.
Vous pouvez écrire des activités par rapport aux opérations de mise à jour et de suppression en fournissant des fonctions de rappel dans MainActivity.java puis modifiez l'interface utilisateur pour avoir des boutons pour les opérations de mise à jour et de suppression de la même manière que nous l'avons fait pour les opérations d'ajout et de lecture.
De cette façon, vous pouvez utiliser un fournisseur de contenu existant tel que Carnet d'adresses ou vous pouvez utiliser le concept de fournisseur de contenu pour développer de jolies applications orientées base de données où vous pouvez effectuer toutes sortes d'opérations de base de données telles que lire, écrire, mettre à jour et supprimer comme expliqué ci-dessus dans l'exemple.