l 使用 ContentProvider (内容提供者)共享数据
/* ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider 对你应用中的数据进行添删改查。关于数据共享,以前我们学习过文件操作模式,知道通过指定文件的操作模式为Context.MODE_WORLD_READABLE 或Context.MODE_WORLD_WRITEABLE同样也可以对外共享数据。那么,这里为何要使用ContentProvider 对外共享数据呢?是这样的,如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据。 使用ContentProvider对外共享数据的好处是统一了数据的访问方式。 当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并重写下面方法: public class PersonContentProvider extends ContentProvider{ public boolean onCreate() public Uri insert(Uri uri, ContentValues values) public int delete(Uri uri, String selection, String[] selectionArgs) public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) public String getType(Uri uri)} 第二步需要在AndroidManifest.xml使用对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider , ContentProvider 采用了authorities(主机名/域名)对它进行唯一标识,你可以把 ContentProvider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名: */

l Uri 介绍 Uri 代表了要操作的数据 Uri 主要包含了两部分信息: 1 》需要操作的 ContentProvider 2 》对 ContentProvider 的什么数据进行操作,一个 Uri 由以下几部分组成:



ContentProvider (内容提供者)的 scheme 已经由 Android 所规定, scheme 为: content:// 主机名(或叫 Authority )用于唯一标识这个 ContentProvider ,外部调用者可以根据这个标识来找到它。 路径( path )可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下 : 要操作 person 表中 id 10 的记录,可以构建这样的路径 :/person/10 要操作 person 表中 id 10 的记录的 name 字段, person/10/name 要操作 person 表中的所有记录,可以构建这样的路径 :/person 要操作 xxx 表中的记录,可以构建这样的路径 :/xxx 当然要操作的数据不一定来自数据库,也可以是文件、 xml 或网络等其他存储方式,如下 : 要操作 xml 文件中 person 节点下的 name 节点,可以构建这样的路径: /person/name 如果要把一个字符串转换成 Uri ,可以使用 Uri 类中的 parse() 方法,如下: Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

l UriMatcher 类使用介绍
因为 Uri 代表了要操作的数据,所以我们经常需要解析 Uri ,并从 Uri 中获取数据。 Android 系统提供了两个用于操作 Uri 的工具类,分别为 UriMatcher ContentUris 。掌握它们的使用,会便于我们的开发工作。 UriMatcher 类用于匹配 Uri ,它的用法如下: 首先第一步把你需要匹配 Uri 路径全部给注册上,如下: // 常量 UriMatcher.NO_MATCH 表示不匹配任何路径的返回码 UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH); // 如果 match() 方法匹配 content://cn.itcast.provider.personprovider/person 路径,返回匹配码为 1 sMatcher.addURI( cn.itcast.provider.personprovider , person , 1);// 添加需要匹配 uri ,如果匹配就会返回匹配码 // 如果 match() 方法匹配 content://cn.itcast.provider.personprovider/person/230 路径,返回匹配码为 2 sMatcher.addURI(“cn.itcast.provider.personprovider”, “person/#”, 2); //# 号为通配符 switch ( sMatcher.match( Uri.parse("content://cn.itcast.provider.personprovider/person/10" ) )) {    case 1     break;    case 2     break;    default:// 不匹配     break; } 注册完需要匹配的 Uri 后,就可以使用 sMatcher.match(uri) 方法对输入的 Uri 进行匹配,如果匹配就返回匹配码, 匹配码是调用 addURI() 方法传入的第三个参数,假设匹配 content://cn.itcast.provider.personprovider/person 路径,返回的匹配码为 1
l ContentUris 类使用介绍 ContentUris 类用于获取 Uri 路径后面的 ID 部分,它有两个比较实用的方法: withAppendedId(uri, id) 用于为路径加上 ID 部分: Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person") Uri resultUri = ContentUris.withAppendedId(uri, 10); // 生成后的 Uri 为: content://cn.itcast.provider.personprovider/person/10 parseId(uri) 方法用于从路径中获取 ID 部分: Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10") long personid = ContentUris.parseId(uri);// 获取的结果为 :10
l 使用 ContentProvider 共享数据 ContentProvider 类主要方法的作用: public boolean onCreate() 该方法在 ContentProvider 创建后就会被调用, Android 开机后, ContentProvider 在其它应用第一次访问它时才 会被创建。 public Uri insert(Uri uri, ContentValues values) 该方法用于供外部应用往 ContentProvider 添加数据。 public int delete(Uri uri, String selection, String[] selectionArgs) 该方法用于供外部应用从 ContentProvider 删除数据。 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 该方法用于供外部应用更新 ContentProvider 中的数据。 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 该方法用于供外部应用从 ContentProvider 中获取数据。 public String getType(Uri uri) 该方法用于返回当前 Url 所代表数据的 MIME 类型。如果操作的数据属于集合类型,那么 MIME 类型字符串应该以 vnd.android.cursor.dir/ 开头,例如:要得到所有 person 记录的 Uri content://cn.itcast.provider.personprovider/person ,那么返回的 MIME 类型字符串应该为: vnd.android.cursor.dir/person 。如果要操作的数据属于非集合类型数据,那么 MIME 类型字符串应该以 vnd.android.cursor.item/ 开头,例如:得到 id 10 person 记录, Uri content://cn.itcast.provider.personprovider/person/10 ,那么返回的 MIME 类型字符串应该为: vnd.android.cursor.item/person l l l l l ContentResolver 操作 ContentProvider 中数据 当外部应用需要对 ContentProvider 中的数据进行添加、删除、修改和查询操作时,可以使用 ContentResolver 来完成,要获取 ContentResolver 对象,可以使用 Activity 提供的 getContentResolver() 方法。 ContentResolver 类提供了与 ContentProvider 类相同签名的四个方法: public Uri insert(Uri uri, ContentValues values) 该方法用于往 ContentProvider 添加数据。 public int delete(Uri uri, String selection, String[] selectionArgs) 该方法用于从 ContentProvider 删除数据。 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 该方法用于更新 ContentProvider 中的数据。 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 该方法用于从 ContentProvider 中获取数据。 这些方法的第一个参数为 Uri ,代表要操作的 ContentProvider 和对其中的什么数据进行操作,假设给定的是: Uri.parse(“content://cn.itcast.providers.personprovider/person/10”) ,那么将会对主机名为 cn.itcast.providers.personprovider ContentProvider 进行操作,操作的数据为 person 表中 id 10 的记录。
使用 ContentResolver ContentProvider 中的数据进行添加、删除、修改和查询操作: ContentResolver resolver =  getContentResolver(); Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person"); // 添加一条记录 ContentValues values = new ContentValues(); values.put("name", "itcast"); values.put("age", 25); resolver.insert(uri, values); // 获取 person 表中所有记录 Cursor cursor = resolver.query(uri, null, null, null, "personid desc"); while(cursor.moveToNext()){ Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1)); } // id 1 的记录的 name 字段值更改新为 liming ContentValues updateValues = new ContentValues(); updateValues.put("name", "liming"); Uri updateIdUri = ContentUris.withAppendedId(uri, 2); resolver.update(updateIdUri, updateValues, null, null); // 删除 id 2 的记录 Uri deleteIdUri = ContentUris.withAppendedId(uri, 2); resolver.delete(deleteIdUri, null, null);


package com.zyq.service; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBOpenHelper extends SQLiteOpenHelper { /** * 如果想额外的增加一个字段(需求) * 可以把版本号更改掉 但必须 >=1 * 更改版本号之后 会根据版本号判断是不是上次创建的时候 (目前的版本号和传入的版本号是否一致 ) * 如果不是会执行 onUpgrade() 方法 * @param context */ public DBOpenHelper(Context context) { super(context, "zyq.db", null, 5); } /** * 在数据库创建的时候第一个调用的方法 * 适合创建表结构 */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE person (personid integer primary key autoincrement, name varchar(20),phone VARCHAR(12) NULL)");//创建表 } /** * 更新表结构 在数据库版本号发生改变的时候调用 * 应用升级 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("ALTER TABLE person ADD amount integer"); //往表中增加一列 } }
package com.zyq.voo; public class Person { public Integer getAmount() { return amount; } public void setAmount(Integer amount) { this.amount = amount; } private Integer id; private String name; private String phone; private Integer amount; public Person(int personid, String name, String phone) { this.id=personid; this.name=name; this.phone=phone; } public Person(String name, String phone) { this.name = name; this.phone = phone; } public String toString() { return "Person [id=" + id + ", name=" + name + ", phone=" + phone + "]"; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
package com.zyq.main; import java.util.List; import android.test.AndroidTestCase; import android.util.Log; import com.zyq.service.DBOpenHelper; import com.zyq.service.PersonService; import com.zyq.voo.Person; /** * 测试方法 通过Junit 单元测试 * 1.>实例化测试类 * 2.>把与应用有关的上下文信息传入到测试类实例 * 3.>运行测试方法 * @author Administrator * */ public class PersonServiceTest extends AndroidTestCase { private final static String TAG="PersonServiceTest"; /** * 测试创建数据库 * @throws Throwable */ public void testCreateDB() throws Throwable { DBOpenHelper dbOpenHelper=new DBOpenHelper(this.getContext()); dbOpenHelper.getReadableDatabase(); //Create and/or open a database. } /** * 测试新增一条记录 * @throws Throwable */ public void testSave() throws Throwable { PersonService personService=new PersonService(this.getContext()); personService.save(new Person("","1360215320")); personService.save(new Person("lisi","13563985632")); personService.save(new Person("lili","232")); personService.save(new Person("wangda","123123")); personService.save(new Person("laozhu","234532")); } /** * 查找一条记录 * @throws Throwable */ public void testFind() throws Throwable { PersonService personService=new PersonService(this.getContext()); Person person=personService.find(1); Log.i(TAG,person.toString()); } /** * 测试更新一条记录 * @throws Throwable */ public void testUpdate() throws Throwable { PersonService personService=new PersonService(this.getContext()); Person person=personService.find(1); person.setName("lisi"); personService.update(person); } /** * 测试得到所有记录数 * @throws Throwable */ public void testGetCount() throws Throwable { PersonService personService=new PersonService(this.getContext()); Log.i(TAG, personService.getCount()+"********"); } /** * 测试分页 * @throws Throwable */ public void testScroll() throws Throwable { PersonService personService=new PersonService(this.getContext()); List persons=personService.getScrollData(0, 30); for(Person person:persons) { Log.i(TAG, person.toString()); } } /** * 测试删除一条记录 * @throws Throwable */ public void testDelete() throws Throwable { PersonService personService=new PersonService(this.getContext()); personService.delete(5); } }
package com.zyq.main; import com.zyq.service.DBOpenHelper; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; public class PersonProvider extends ContentProvider { private static final UriMatcher MATCHER=new UriMatcher(UriMatcher.NO_MATCH); private static final int PERSONS=1; private static final int PERSON=2; private DBOpenHelper helper; static { MATCHER.addURI("com.zyq.providers.personprovider", "person", PERSONS); MATCHER.addURI("com.zyq.providers.personprovider", "person/#", PERSON); } /** * 完成数据的初始化工作 */ public boolean onCreate() { helper=new DBOpenHelper(this.getContext()); return true; } /** * 查询PERSON数据库数据 * /person 代表查询所有的数据 * /person/# 代表查询person表指定ID的数据 */ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db=helper.getWritableDatabase(); switch (MATCHER.match(uri)) { case PERSONS: return db.query("person", projection, selection, selectionArgs, null, null, sortOrder); case PERSON: long id=ContentUris.parseId(uri); String where="personid="+id; if(selection!=null && !"".equals(selection.trim())) { where=where+" and "+selection; } return db.query("person", projection, where, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unknown Uri:" +uri); } } /** * */ public String getType(Uri uri) { switch (MATCHER.match(uri)) { case PERSONS: return "vnd.android.cursor.dir/person"; case PERSON: return "vnd.android.cursor.item/person"; default: throw new IllegalArgumentException("Unknown Uri:" +uri); } } /** * 往PERSON表添加数据 * /person 为URI */ public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db=helper.getWritableDatabase(); Log.i("*********", MATCHER.match(uri)+""); switch (MATCHER.match(uri)) { case PERSONS: long rowid=db.insert("person", "personid", values);// return ContentUris.withAppendedId(uri, rowid); default: throw new IllegalArgumentException("Unknown Uri:" +uri); } } /** * 删除PERSON表中的数据 * /person 代表删除所有的数据 * /person/# 代表删除某一条数据 */ public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db=helper.getWritableDatabase(); int num=0; switch (MATCHER.match(uri)) { case PERSONS: num=db.delete("person", selection, selectionArgs); break; case PERSON: long id=ContentUris.parseId(uri); String where="personid="+id; if(selection!=null && !"".equals(selection.trim())) { where=where+" and "+selection; } num=db.delete("person", where, selectionArgs); break; default: throw new IllegalArgumentException("Unknown Uri:" +uri); } return num; } /** * 更新PERSON表中的数据 * /person 代表更新所有的数据 * /person/# 代表更新person表指定ID的数据 */ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db=helper.getWritableDatabase(); int num=0; switch (MATCHER.match(uri)) { case PERSONS: num=db.update("person", values, selection, selectionArgs); break; case PERSON: long id=ContentUris.parseId(uri); String where="personid="+id; if(selection!=null && !"".equals(selection.trim())) { where=where+" and "+selection; } num=db.update("person", values, where, selectionArgs); break; default: throw new IllegalArgumentException("Unknown Uri:" +uri); } return num; } }
package com.zyq.service; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.zyq.voo.Person; public class PersonService { private DBOpenHelper helper; public PersonService(Context context) { helper=new DBOpenHelper(context); } /** * 新增一条记录 * @param person */ public void save(Person person) { SQLiteDatabase db=helper.getWritableDatabase();//Create and/or open a database that will be used for reading and writing db.execSQL("INSERT INTO person(name,phone) values(?,?)",new Object[]{person.getName().trim(),person.getPhone().trim()});//使用占位符进行转译 // db.close(); 不关数据库连接 。可以提高性能 因为创建数据库的时候的操作模式是私有的。 // 代表此数据库,只能被本应用所访问 单用户的,可以维持长久的链接 } /** * 更新某一条记录 * @param person */ public void update(Person person) { SQLiteDatabase db=helper.getWritableDatabase(); db.execSQL("update person set phone=?,name=? where personid=?", new Object[]{person.getPhone().trim(),person.getName().trim(),person.getId()}); } /** * 根据ID查询某条记录 * @param id * @return */ public Person find(Integer id) { SQLiteDatabase db=helper.getReadableDatabase(); Cursor cursor=db.rawQuery("select * from person where personid=?", new String[]{id.toString()});//Cursor 游标和 ResultSet 很像 if(cursor.moveToFirst())//Move the cursor to the first row. This method will return false if the cursor is empty. { int personid=cursor.getInt(cursor.getColumnIndex("personid")); String name=cursor.getString(cursor.getColumnIndex("name")); String phone=cursor.getString(cursor.getColumnIndex("phone")); return new Person(personid,name,phone); } return null; } /** * 删除某一条记录 * @param id */ public void delete(Integer id) { SQLiteDatabase db=helper.getWritableDatabase(); db.execSQL("delete from person where personid=?", new Object[]{id}); } /** * 得到记录数 * @return */ public long getCount() { SQLiteDatabase db=helper.getReadableDatabase(); Cursor cursor=db.rawQuery("select count(*) from person", null); cursor.moveToFirst(); return cursor.getLong(0); } /** * 分页查询方法 SQL语句跟MySQL的语法一样 * @return */ public List getScrollData(int offset,int maxResult) { List persons=new ArrayList(); SQLiteDatabase db=helper.getReadableDatabase(); Cursor cursor=db.rawQuery("select * from person limit ?,?", new String[]{String.valueOf(offset),String.valueOf(maxResult)}); while (cursor.moveToNext()) { int personid=cursor.getInt(cursor.getColumnIndex("personid")); String name=cursor.getString(cursor.getColumnIndex("name")); String phone=cursor.getString(cursor.getColumnIndex("phone")); persons.add(new Person(personid,name,phone)); } return persons; } } <?xml version="1.0" encoding="utf-8"?>
这是另外一个项目 测试得类
package com.zyq.junit; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.test.AndroidTestCase; import android.util.Log; import android.webkit.WebChromeClient.CustomViewCallback; public class AccessContentProvider extends AndroidTestCase { private static final String TAG="AccessContentProvider"; /** * 测试内容提供者的 添加数据方法 * @throws Throwable */ public void testInsert() throws Throwable { ContentResolver resolver=this.getContext().getContentResolver(); Uri uri=Uri.parse("content://com.zyq.providers.personprovider/person"); ContentValues values = new ContentValues(); values.put("name", "朱元璋"); values.put("phone", "1356398546"); values.put("amount", 50); resolver.insert(uri, values); } /** * 测试内容提供者的 查找数据方法 * @throws Throwable */ public void testFind() throws Throwable { ContentResolver resolver=this.getContext().getContentResolver(); Uri uri=Uri.parse("content://com.zyq.providers.personprovider/person/1"); Cursor cursor=resolver.query(uri, null, null, null, null); if(cursor.moveToFirst()) { String name=cursor.getString(cursor.getColumnIndex("name")); Log.i(TAG, name+"*******"); } } /** * 测试内容提供者的更新数据方法 * @throws Throwable */ public void testUpdate() throws Throwable { ContentResolver resolver=this.getContext().getContentResolver(); Uri uri=Uri.parse("content://com.zyq.providers.personprovider/person/1"); ContentValues values = new ContentValues(); values.put("name", "中国"); resolver.update(uri, values, null, null); } /** * 测试内容提供者的删除数据方法 * @throws Throwable */ public void testDelete() throws Throwable { ContentResolver resolver=this.getContext().getContentResolver(); Uri uri=Uri.parse("content://com.zyq.providers.personprovider/person/6"); resolver.delete(uri, null, null); } }

 先运行好数据库 定义好 ContentProdvider  用 单元测试 来 测试数据  !
 信息全打印在控制台中


l

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. 一句话锁定MySQL数据占用元凶
  3. Android以太网卡配置启动流程和双网卡同时支持的实现
  4. Preference 使用详解
  5. Android数据库(SQLite)的简单使用——增、删、查改功能的简单实现
  6. IPC 机制(上)
  7. Ionic Cordova实现软键盘的监听 以及操作大全
  8. android根目录获取
  9. 关于android双屏异显的一些总结和卡死的一些解决方法

随机推荐

  1. Android中的软件安全和逆向分析[一]—apk
  2. Android(安卓)App的设计架构:MVC,MVP,MVVM
  3. Android窗口管理服务WindowManagerServic
  4. Android自动解析html带图片,实现图文混排
  5. Android系列之如何成为Android编程高手第
  6. Motorola Droid 4 现踪迹,将支持 LTE 移动
  7. android屏幕适配计算方式及适配values文
  8. Dell Streak 5 从美国网站静静地消失了,呜
  9. [Android]如何做一个崩溃率少于千分之三
  10. Android(安卓)Activity背景半透明设置方