Android
Fournisseur de contenu
Recherche…
Remarques
Les fournisseurs de contenu gèrent l'accès à un ensemble structuré de données. Ils encapsulent les données et fournissent des mécanismes pour définir la sécurité des données. Les fournisseurs de contenu sont l'interface standard qui connecte les données dans un processus avec du code exécuté dans un autre processus.
Lorsque vous souhaitez accéder aux données d'un fournisseur de contenu, vous utilisez l'objet ContentResolver
dans le Context
votre application pour communiquer avec le fournisseur en tant que client. L'objet ContentResolver
communique avec l'objet fournisseur, une instance d'une classe qui implémente ContentProvider
. L'objet fournisseur reçoit les demandes de données des clients, effectue l'action demandée et renvoie les résultats.
Vous n'avez pas besoin de développer votre propre fournisseur si vous n'avez pas l'intention de partager vos données avec d'autres applications. Cependant, vous avez besoin de votre propre fournisseur pour fournir des suggestions de recherche personnalisées dans votre propre application. Vous avez également besoin de votre propre fournisseur si vous souhaitez copier et coller des données ou des fichiers complexes depuis votre application vers d'autres applications.
Android lui-même comprend des fournisseurs de contenu qui gèrent des données telles que des données audio, vidéo, des images et des informations de contact personnelles. Vous pouvez voir certains d'entre eux répertoriés dans la documentation de référence du package android.provider
. Avec certaines restrictions, ces fournisseurs sont accessibles à toute application Android.
Implémentation d'une classe de fournisseur de contenu de base
1) Créez une classe de contrat
Une classe de contrat définit des constantes qui aident les applications à utiliser les URI de contenu, les noms de colonne, les actions d'intention et les autres fonctionnalités d'un fournisseur de contenu. Les classes de contrat ne sont pas incluses automatiquement avec un fournisseur; le développeur du fournisseur doit les définir et les mettre à la disposition des autres développeurs.
Un fournisseur a généralement une autorité unique, qui sert de nom interne à Android. Pour éviter les conflits avec d'autres fournisseurs, utilisez une autorité de contenu unique. Étant donné que cette recommandation est également vraie pour les noms de package Android, vous pouvez définir votre autorité de fournisseur comme une extension du nom du package contenant le fournisseur. Par exemple, si votre nom de package Android est com.example.appname
, vous devez donner à votre fournisseur l'autorité com.example.appname.provider
.
public class MyContract {
public static final String CONTENT_AUTHORITY = "com.example.myApp";
public static final String PATH_DATATABLE = "dataTable";
public static final String TABLE_NAME = "dataTable";
}
Un URI de contenu est un URI qui identifie des données dans un fournisseur. Les URI de contenu incluent le nom symbolique du fournisseur complet (son autorité) et un nom qui pointe vers une table ou un fichier (un chemin). La partie facultative id pointe sur une ligne individuelle dans une table. Chaque méthode d'accès aux données de ContentProvider a un URI de contenu comme argument; Cela vous permet de déterminer la table, la ligne ou le fichier auquel accéder. Définissez-les dans la classe de contrat.
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_DATATABLE).build();
// define all columns of table and common functions required
2) Créer la classe d'assistance
Une classe d'assistance gère la création de bases de données et la gestion des versions.
public class DatabaseHelper extends SQLiteOpenHelper {
// Increment the version when there is a change in the structure of database
public static final int DATABASE_VERSION = 1;
// The name of the database in the filesystem, you can choose this to be anything
public static final String DATABASE_NAME = "weather.db";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// Called when the database is created for the first time. This is where the
// creation of tables and the initial population of the tables should happen.
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Called when the database needs to be upgraded. The implementation
// should use this method to drop tables, add tables, or do anything else it
// needs to upgrade to the new schema version.
}
}
3) Créer une classe qui étend la classe ContentProvider
public class MyProvider extends ContentProvider {
public DatabaseHelper dbHelper;
public static final UriMatcher matcher = buildUriMatcher();
public static final int DATA_TABLE = 100;
public static final int DATA_TABLE_DATE = 101;
Un UriMatcher mappe une autorité et un chemin d'accès à une valeur entière. La méthode match()
renvoie une valeur entière unique pour un URI (il peut s'agir d'un nombre quelconque, à condition qu'il soit unique). Une instruction de commutateur choisit d'interroger la table entière et d'interroger un seul enregistrement. Notre UriMatcher renvoie 100 si l'URI est l'URI du contenu de la table et 101 si l'URI pointe sur une ligne spécifique de cette table. Vous pouvez utiliser le caractère générique #
pour correspondre à n'importe quel nombre et *
pour correspondre à n'importe quelle chaîne.
public static UriMatcher buildUriMatcher() {
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(CONTENT_AUTHORITY, MyContract.PATH_DATATABLE, DATA_TABLE);
uriMatcher.addURI(CONTENT_AUTHORITY, MyContract.PATH_DATATABLE + "/#", DATA_TABLE_DATE);
return uriMatcher;
}
IMPORTANT: la commande d' addURI()
importante! Le UriMatcher regardera dans l'ordre séquentiel du premier ajouté à la dernière. Comme les caractères génériques tels que #
et *
sont gourmands, vous devez vous assurer que vous avez correctement commandé vos URI. Par exemple:
uriMatcher.addURI(CONTENT_AUTHORITY, "/example", 1);
uriMatcher.addURI(CONTENT_AUTHORITY, "/*", 2);
est le bon ordre, car le matcher cherchera d'abord /example
avant de recourir à la correspondance /*
. Si ces appels de méthode ont été inversés et que vous avez appelé uriMatcher.match("/example")
, le UriMatcher cessera de rechercher des correspondances une fois qu'il rencontrera le chemin /*
et renverra le mauvais résultat!
Vous devrez alors remplacer ces fonctions:
onCreate () : Initialise votre fournisseur. Le système Android appelle cette méthode immédiatement après la création de votre fournisseur. Notez que votre fournisseur n'est pas créé jusqu'à ce qu'un objet ContentResolver tente d'y accéder.
@Override
public boolean onCreate() {
dbhelper = new DatabaseHelper(getContext());
return true;
}
getType () : Retourne le type MIME correspondant à un URI de contenu
@Override
public String getType(Uri uri) {
final int match = matcher.match(uri);
switch (match) {
case DATA_TABLE:
return ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + MyContract.CONTENT_AUTHORITY + "/" + MyContract.PATH_DATATABLE;
case DATA_TABLE_DATE:
return ContentResolver.ANY_CURSOR_ITEM_TYPE + "/" + MyContract.CONTENT_AUTHORITY + "/" + MyContract.PATH_DATATABLE;
default:
throw new UnsupportedOperationException("Unknown Uri: " + uri);
}
}
query () : récupère les données de votre fournisseur. Utilisez les arguments pour sélectionner la table à interroger, les lignes et les colonnes à renvoyer et l'ordre de tri du résultat. Renvoie les données en tant qu'objet Cursor.
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor retCursor = dbHelper.getReadableDatabase().query(
MyContract.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
Insérez une nouvelle ligne dans votre fournisseur. Utilisez les arguments pour sélectionner la table de destination et obtenir les valeurs de colonne à utiliser. Renvoie un URI de contenu pour la ligne nouvellement insérée.
@Override
public Uri insert(Uri uri, ContentValues values)
{
final SQLiteDatabase db = dbHelper.getWritableDatabase();
long id = db.insert(MyContract.TABLE_NAME, null, values);
return ContentUris.withAppendedId(MyContract.CONTENT_URI, ID);
}
delete () : supprime les lignes de votre fournisseur. Utilisez les arguments pour sélectionner la table et les lignes à supprimer. Renvoie le nombre de lignes supprimées.
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int rowsDeleted = db.delete(MyContract.TABLE_NAME, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
update () : Mettez à jour les lignes existantes dans votre fournisseur. Utilisez les arguments pour sélectionner la table et les lignes à mettre à jour et pour obtenir les nouvelles valeurs de colonne. Renvoie le nombre de lignes mises à jour.
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int rowsUpdated = db.update(MyContract.TABLE_NAME, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
4) Mettre à jour le fichier manifeste
<provider
android:authorities="com.example.myApp"
android:name=".DatabaseProvider"/>