1. Scénarios applicables
1) ContentProvider fournit une interface unifiée pour le stockage et la lecture des données
2) Grâce à ContentProvider, les applications peuvent réaliser le partage de données
3) De nombreuses données intégrées à Android sont utilisées. que les développeurs peuvent appeler (comme la vidéo, l'audio, les images, les carnets d'adresses, etc.)
2. Introduction aux concepts associés
1) Introduction à ContentProvider
Lorsqu'une application hérite de la classe ContentProvider et réécrit cette classe Méthodes pour fournir des données et stocker des données afin qu'elles puissent être partagées avec d'autres applications. Bien que les données puissent être partagées en externe à l'aide d'autres méthodes, la méthode d'accès aux données diffère selon la manière dont les données sont stockées. Par exemple, si vous utilisez le mode fichier pour partager des données en externe, vous devez effectuer des opérations sur les fichiers pour lire et écrire des données ; si vous utilisez sharedpreferences pour partager des données, vous devez utiliser l'API sharedpreferences pour lire et écrire des données. L'avantage d'utiliser ContentProvider pour partager des données est d'unifier la méthode d'accès aux données.
2) Introduction à la classe Uri
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
La chaîne de requête utilisée dans le fournisseur de contenu est différente de la chaîne standard Requête SQL. Nous utilisons un URI spécial pour effectuer de nombreuses opérations telles que sélectionner, ajouter, supprimer, modifier, etc. Cet URI se compose de trois parties, "content://", qui représente le chemin des données, et une donnée d'identification facultative. . Voici quelques exemples d'URI :
content://media/internal/images 这个URI将返回设备上存储的所有图片 content://contacts/people/ 这个URI将返回设备上的所有联系人信息 content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)
Bien que ce format de chaîne de requête soit courant, il peut encore paraître un peu déroutant. À cette fin, Android fournit une série de classes d'aide (sous le package android.provider), qui contiennent de nombreuses chaînes de requête données sous forme de variables de classe. Cette méthode nous facilite la compréhension, comme indiqué ci-dessus : /. /contacts/people/45 Cet URI peut être écrit sous la forme suivante :
Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45);
Exécutez ensuite la requête de données :
Curseur cur = géréQuery( person, null, null, null);
Cette requête renvoie un curseur contenant tous les champs de données. Nous pouvons obtenir toutes les données en itérant ce curseur :
package com.wissen.testApp; public class ContentProviderDemo extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); displayRecords(); } private void displayRecords() { //该数组中包含了所有要返回的字段 String columns[] = new String[] { People.NAME, People.NUMBER }; Uri mContacts = People.CONTENT_URI; Cursor cur = managedQuery( mContacts, columns, // 要返回的数据字段 null, // WHERE子句 null, // WHERE 子句的参数 null // Order-by子句 ); if (cur.moveToFirst()) { String name = null; String phoneNo = null; do { // 获取字段的值 name = cur.getString(cur.getColumnIndex(People.NAME)); phoneNo = cur.getString(cur.getColumnIndex(People.NUMBER)); Toast.makeText(this, name + ” ” + phoneNo, Toast.LENGTH_LONG).show(); } while (cur.moveToNext()); } } }
L'exemple ci-dessus montre comment lire. séquence Obtenez le nom et le numéro de la colonne de données spécifiés dans le tableau des informations de contact.
Modifier les enregistrements :
Nous pouvons utiliser la méthode ContentResolver.update() pour modifier les données. Écrivons une méthode pour modifier les données :
private void updateRecord(int recNo, String name) { Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recNo); ContentValues values = new ContentValues(); values.put(People.NAME, name); getContentResolver().update(uri, values, null, null); }
Vous pouvez maintenant appeler la méthode ci-dessus pour mettre à jour les enregistrements. spécifié Record :
updateRecord(10, ”XYZ”); //Changez la valeur du champ de nom du 10ème enregistrement en “XYZ”
Ajouter un enregistrement :
Pour ajouter un enregistrement, nous pouvons appeler ContentResolver.insert (), cette méthode accepte un URI cible de l'enregistrement à ajouter et un objet Map contenant la nouvelle valeur d'enregistrement. La valeur de retour après l'appel est l'URI du nouvel enregistrement, y compris le numéro d'enregistrement.
Dans les exemples ci-dessus, nous sommes tous basés sur le fournisseur de contenu standard du carnet d'informations de contact. Nous continuons maintenant à créer une méthode insertRecord() pour ajouter des données au carnet d'informations de contact :
private void insertRecords(String name, String phoneNo) { ContentValues values = new ContentValues(); values.put(People.NAME, name); Uri uri = getContentResolver().insert(People.CONTENT_URI, values); Log.d(”ANDROID”, uri.toString()); Uri numberUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY); values.clear(); values.put(Contacts.Phones.TYPE, People.Phones.TYPE_MOBILE); values.put(People.NUMBER, phoneNo); getContentResolver().insert(numberUri, values); }De cette façon, nous pouvons appeler insertRecords(name, phoneNo) pour ajouter le nom et le numéro de téléphone du contact au carnet d'informations de contact.
Supprimer des enregistrements :
La méthode getContextResolver.delete() du fournisseur de contenu peut être utilisée pour supprimer des enregistrements. Les enregistrements suivants sont utilisés pour supprimer toutes les informations de contact sur l'appareil :
private void deleteRecords() { Uri uri = People.CONTENT_URI; getContentResolver().delete(uri, null, null); }
你也可以指定WHERE条件语句来删除特定的记录:
getContentResolver().delete(uri, “NAME=” + “‘XYZ XYZ'”, null);
这将会删除name为‘XYZ XYZ'的记录。
3. 创建ContentProvider
要创建我们自己的Content Provider的话,我们需要遵循以下几步:
a. 创建一个继承了ContentProvider父类的类
b. 定义一个名为CONTENT_URI,并且是public static final的Uri类型的类变量,你必须为其指定一个唯一的字符串值,最好的方案是以类的全名称, 如:
public static final Uri CONTENT_URI = Uri.parse( “content://com.google.android.MyContentProvider”);
c. 定义你要返回给客户端的数据列名。如果你正在使用Android数据库,必须为其定义一个叫_id的列,它用来表示每条记录的唯一性。
d. 创建你的数据存储系统。大多数Content Provider使用Android文件系统或SQLite数据库来保持数据,但是你也可以以任何你想要的方式来存储。
e. 如果你要存储字节型数据,比如位图文件等,数据列其实是一个表示实际保存文件的URI字符串,通过它来读取对应的文件数据。处理这种数据类型的Content Provider需要实现一个名为_data的字段,_data字段列出了该文件在Android文件系统上的精确路径。这个字段不仅是供客户端使用,而且也可以供ContentResolver使用。客户端可以调用ContentResolver.openOutputStream()方法来处理该URI指向的文件资源;如果是ContentResolver本身的话,由于其持有的权限比客户端要高,所以它能直接访问该数据文件。
f. 声明public static String型的变量,用于指定要从游标处返回的数据列。
g. 查询返回一个Cursor类型的对象。所有执行写操作的方法如insert(), update() 以及delete()都将被监听。我们可以通过使用ContentResover().notifyChange()方法来通知监听器关于数据更新的信息。
h. 在AndroidMenifest.xml中使用245134590f76a973a830651cacc0946c标签来设置Content Provider。
i. 如果你要处理的数据类型是一种比较新的类型,你就必须先定义一个新的MIME类型,以供ContentProvider.geType(url)来返回。MIME类型有两种形式:一种是为指定的单个记录的,还有一种是为多条记录的。这里给出一种常用的格式:
vnd.android.cursor.item/vnd.yourcompanyname.contenttype (单个记录的MIME类型) 比如, 一个请求列车信息的URI如content://com.example.transportationprovider/trains/122 可能就会返回typevnd.android.cursor.item/vnd.example.rail这样一个MIME类型。 vnd.android.cursor.dir/vnd.yourcompanyname.contenttype (多个记录的MIME类型) 比如, 一个请求所有列车信息的URI如content://com.example.transportationprovider/trains 可能就会返回vnd.android.cursor.dir/vnd.example.rail这样一个MIME 类型。
下列代码将创建一个Content Provider,它仅仅是存储用户名称并显示所有的用户名称(使用 SQLLite数据库存储这些数据):
public class MyUsers { public static final String AUTHORITY = “com.wissen.MyContentProvider”; // BaseColumn类中已经包含了 _id字段 public static final class User implements BaseColumns { public static final Uri CONTENT_URI = Uri.parse(”content://com.wissen.MyContentProvider”); // 表数据列 public static final String USER_NAME = “USER_NAME”; } }
上面的类中定义了Content Provider的CONTENT_URI,以及数据列。下面我们将定义基于上面的类来定义实际的Content Provider类:
public class MyContentProvider extends ContentProvider { private SQLiteDatabase sqlDB; private DatabaseHelper dbHelper; private static final String DATABASE_NAME = “Users.db”; private static final int DATABASE_VERSION= 1; private static final String TABLE_NAME= “User”; private static final String TAG = “MyContentProvider”; 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 table ” + TABLE_NAME + “( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);”); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(”DROP TABLE IF EXISTS ” + TABLE_NAME); onCreate(db); } } @Override public int delete(Uri uri, String s, String[] as) { return 0; } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues contentvalues) { sqlDB = dbHelper.getWritableDatabase(); long rowId = sqlDB.insert(TABLE_NAME, “”, contentvalues); if (rowId > 0) { Uri rowUri = ContentUris.appendId(MyUsers.User.CONTENT_URI.buildUpon(), rowId).build(); getContext().getContentResolver().notifyChange(rowUri, null); return rowUri; } throw new SQLException(”Failed to insert row into ” + uri); } @Override public boolean onCreate() { dbHelper = new DatabaseHelper(getContext()); return (dbHelper == null) ? false : true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); SQLiteDatabase db = dbHelper.getReadableDatabase(); qb.setTables(TABLE_NAME); Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int update(Uri uri, ContentValues contentvalues, String s, String[] as) { return 0; } }一个名为MyContentProvider的Content Provider创建完成了,它用于从Sqlite数据库中添加和读取记录。
Content Provider的入口需要在AndroidManifest.xml中配置:
<provider android:name=”MyContentProvider” android:authorities=”com.wissen.MyContentProvider” />
之后,让我们来使用这个定义好的Content Provider:
1)为应用程序添加ContentProvider的访问权限。
2)通过getContentResolver()方法得到ContentResolver对象。
3)调用ContentResolver类的query()方法查询数据,该方法会返回一个Cursor对象。
4)对得到的Cursor对象进行分析,得到需要的数据。
5)调用Cursor类的close()方法将Cursor对象关闭。
public class MyContentDemo extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); insertRecord(”MyUser”); displayRecords(); } private void insertRecord(String userName) { ContentValues values = new ContentValues(); values.put(MyUsers.User.USER_NAME, userName); getContentResolver().insert(MyUsers.User.CONTENT_URI, values); } private void displayRecords() { String columns[] = new String[] { MyUsers.User._ID, MyUsers.User.USER_NAME }; Uri myUri = MyUsers.User.CONTENT_URI; Cursor cur = managedQuery(myUri, columns,null, null, null ); if (cur.moveToFirst()) { String id = null; String userName = null; do { id = cur.getString(cur.getColumnIndex(MyUsers.User._ID)); userName = cur.getString(cur.getColumnIndex(MyUsers.User.USER_NAME)); Toast.makeText(this, id + ” ” + userName, Toast.LENGTH_LONG).show(); } while (cur.moveToNext()); } } }
更多基于Android ContentProvider的总结详解相关文章请关注PHP中文网!