Android四大组件之Content Provider
ContentProvider:内容提供者
1、为存储和读取数据提供了统一的接口
2、使用ContentProvider,应用程序可以实现数据共享
3、android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)
4、当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。
先来了解一下Uri:
Uri,即通用资源标识符
1、Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示
2、Uri一般由三部分组成:访问资源的命名机制;存放资源的主机名; 资源自身的名称,由路径表示。
Android的Uri由以下三部分组成: "content://"+数据的路径+标示ID(可选)、
如:所有联系人的Uri: content://contacts/people
某个联系人的Uri: content://contacts/people/5 //联系人中id为5的联系人
3、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.archer.ContentProvider")
ContentResolver:
在android中,每个应用程序是可以实现数据共享的,对于每一个应用程序程序都拥有一个ContentProvider实例进行存储,
而ContentResolver则是用于管理所有程序的ContentProvider实例,通过ContentRescolver可以对数据进行添加、删除、修改和查询操作
通过getContentRescolver()获取实例
下面通过创建一个Content Provider,并使用 SQLLite数据库实现数据共享
首先,定义ContentProvider的CONTENT_URI,并且是public static final的Uri类型的类变量
必须为其制定一个唯一的字符串值,一般用类的全名称命名
package com.ContentProviderDemo.Archer; import android.net.Uri; import android.provider.BaseColumns; public class MyUsers { public static final String AUTHORITY = "com.archer.ContentProvider"; //BaseColumn类中已经包含了 _id 字段 public static final class User implements BaseColumns{ public static final Uri CONTENT_URI = Uri.parse("content://com.archer.ContentProvider"); //表数据列 public static final String USER_NAME = "USER_NAME"; } }
之后创建一个类继承ContentProvider
package com.ContentProviderDemo.Archer; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; 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; public class MyContentProvider extends ContentProvider{ /** * 定义一个SQLiteDatabase变量 * Android提供了一个名为SQLiteDatabase的类,它封装了一些操作数据库的API。 * 使用它能实现基本的CRUD(插入、查询、更新、删除)操作,通过getWritableDatabase()和getReadableDatabase()可以获取数据库实例 */ 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";//表名 /** * 首先需要创建数据库(定义一个内部类,继承SQLiteOpenHelper类,重写其方法) * SQliteOpenHelper是一个抽象类,来管理数据库的创建和版本的管理。 * 要使用它必须实现它的onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int)方法 * onCreate:当数据库第一次被建立的时候被执行,例如创建表,初始化数据等。 * onUpgrade:当数据库需要被更新的时候执行,例如删除旧表,创建新表。 * @author Administrator */ private static class DatabaseHelper extends SQLiteOpenHelper{ /** * 创建数据库的构造方法 * name 数据库的名字 * factory 查询数据库的游标工厂一般情况下用sdk默认的 * version 数据库的版本一般大于0 */ public DatabaseHelper(Context context){ super(context,DATABASE_NAME,null,DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { String sq1 = "Create table " + TABLE_NAME + "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);"; //创建表的sql语句 db.execSQL(sq1); //创建表 } /** * 更新数据的时候调用的方法,如新增表、修改数据 */ @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[] arg2) { return 0; } @Override public String getType(Uri arg0) { return null; } /** * 插入数据 * ContentValues类负责存储一些名值对,的名是一个String类型,而值都是基本类型。 */ @Override public Uri insert(Uri uri, ContentValues contentValues) { //以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,就会打开失败 sqlDB = dbHelper.getWritableDatabase(); //插入一条新的纪录,如果插入成功则会返回这条记录的id,如果插入失败会返回-1 long rowId = sqlDB.insert(TABLE_NAME, "", contentValues); if(rowId > 0){ // ContentUris 类用于获取Uri路径后面的ID部分 //appendId:为该Uri加上ID Uri rowUri = ContentUris.appendId(MyUsers.User.CONTENT_URI.buildUpon(), rowId).build(); // getContextResolver().notifyChange():获得一个ContextResolver对象并且更新里面的内容。 getContext().getContentResolver().notifyChange(rowUri, null); return rowUri; } throw new SQLException("Fail 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 是一个构造SQL查询语句的辅助类。 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); //getReadableDatabase():先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库 SQLiteDatabase db = dbHelper.getReadableDatabase(); qb.setTables(TABLE_NAME); /** * Cursor 是每行的集合 * 在Android中 查询数据是通过Cursor 类来实现的。当我们使用 SQLiteDatabase.query()方法时,就会得到Cursor对象, * Cursor所指向的就是每一条数据 */ Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { return 0; } }
在AndroidManifest.xml中进行注册:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".MyContentProvider" android:authorities="com.archer.ContentProvider"> </provider> <!-- android:authorities属性配置的就是该ContentProvider的名字,是它在Android系统中的名字,我们是通过这个名字去找对应的ContentProvider对象的--> </application>
最后,创建一个新的工程(测试用)
package com.ContentProviderDemo.Archer; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; /** * 在另一个工程中访问创建的数据库,不用再注册provider,否则会保存 * @author Administrator * */ public class MainActivity extends Activity { public static final String AUTHORITY = "com.archer.ContentProvider"; private Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); insertRecord("record1"); displayRecords(); } //插入数据 private void insertRecord(String userName) { ContentValues values = new ContentValues(); values.put("USER_NAME", userName); getContentResolver().insert(CONTENT_URI, values); } //查询数据 private void displayRecords() { // 该数组中包含了所有要返回的字段 String columns[] = new String[] { "_id", "USER_NAME" }; Uri myUri = CONTENT_URI; Cursor cur = getContentResolver().query(myUri, columns, null, null,null); if (cur.moveToFirst()) { String id = null; String userName = null; do { id = cur.getString(cur.getColumnIndex("_id")); userName = cur.getString(cur.getColumnIndex("USER_NAME")); Log.e("TAG", "id:" + id + ";" + "userName:" + userName); } while (cur.moveToNext()); } cur.close(); // 关闭Cursor对象 } }
这样,就是先不同应用程序间的数据共享了
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。