网站制作论文,网站开发项目挣钱吗,商家免费入驻平台,已经有域名 怎么修改网站在Android 应用程序之间数据共享—-ContentResolver中#xff0c;已经说明了Android是如何实现应用程序之间数据共享的#xff0c;并详细解析了如何获取其他应用程序共享的数据。ContentProviders存储和检索数据#xff0c;通过它可以让所有的应用程序访问到#xff0c;这也… 在Android 应用程序之间数据共享—-ContentResolver中已经说明了Android是如何实现应用程序之间数据共享的并详细解析了如何获取其他应用程序共享的数据。ContentProviders存储和检索数据通过它可以让所有的应用程序访问到这也是应用程序之间唯一共享数据的方法。那么如何将应用程序的数据暴露出去 通过以前文章的学习知道ContentResolver是通过ContentProvider来获取其他与应用程序共享的数据那么ContentResolver与ContentProvider的接口应该差不多的。 其中ContentProvider负责
组织应用程序的数据向其他应用程序提供数据 ContentResolver则负责
获取ContentProvider提供的数据修改/添加/删除更新数据等 ContentProvider 是如何向外界提供数据的 Android提供了ContentProvider一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去而且ContentProviders是以类似数据库中表的方式将数据暴露也就是说ContentProvider就像一个“数据库”。那么外界获取其提供的数据也就应该与从数据库中获取数据的操作基本一样只不过是采用URI来表示外界需要访问的“数据库”。至于如何从URI中识别出外界需要的是哪个“数据库”这就是Android底层需要做的事情了不在此详细说。简要分析下ContentProvider向外界提供数据操作的接口 query(Uri, String[], String, String[], String) insert(Uri, ContentValues) update(Uri, ContentValues, String, String[]) delete(Uri, String, String[]) 这些操作与数据库的操作基本上完全一样在此不详细说具体的解析可以参考Android Sqlite解析篇中的详细说明。需要特殊说明的地方是URI 在URI的D部分可能包含一个_ID 这个应该出现在SQL语句中的可以以种特殊的方式出现这就要求我们在提供数据的时候需要来额外关注这个特殊的信息。Android SDK推荐的方法是在提供数据表字段中包含一个ID在创建表时INTEGER PRIMARY KEY AUTOINCREMENT标识此ID字段。 ContentProvider 是如何组织数据的 组织数据主要包括存储数据读取数据以数据库的方式暴露数据。数据的存储需要根据设计的需求选择合适的存储结构首选数据库当然也可以选择本地其他文件甚至可以是网络上的数据。数据的读取以数据库的方式暴露数据这就要求无论数据是如何存储的数据最后必须以数据的方式访问。 可能还有2个问题是需要关注的。
ContentProvider是什么时候创建的是谁创建的访问某个应用程序共享的数据是否需要启动这个应用程序这个问题在Android SDK中没有明确说明但是从数据共享的角度出发ContentProvider应该是Android在系统启动时就创建了否则就谈不上数据共享了。这就要求在AndroidManifest.XML中使用provider元素明确定义。可能会有多个程序同时通过ContentResolver访问一个ContentProvider会不会导致像数据库那样的“脏数据”这个问题一方面需要数据库访问的同步尤其是数据写入的同步在AndroidManifest.XML中定义ContentProvider的时候需要考虑是provider元素multiprocess属性的值另外一方面Android在ContentResolver中提供了notifyChange()接口在数据改变时会通知其他ContentObserver这个地方应该使用了观察者模式在ContentResolver中应该有一些类似registerunregister的接口。 至此已经对ContentProvider提供了比较全面的分析至于如何创建ContentProvider可通过2种方法创建一个属于你自己的ContentProvider或者将你的数据添加到一个已经存在的ContentProvider中当然前提是有相同数据类型并且有写入Content provider的权限。在Android SDK的sample中提供的Notepad具体实例中去看源代码 使用 ContentProvider共享数据 当应用继承 ContentProvider类并重写该类用于提供数据和存储数据的方法就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据但数据访问方式会因数据存储的方式而不同如采用文件方式对外共享数据需要进行文件操作读写数据采用 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使用provider对该ContentProvider进行配置为了能让其他应用找到该ContentProvider ContentProvider 采用了authorities主机名/域名对它进行唯一标识你可以把ContentProvider看作是一个网站想想网站也是提供数据者authorities 就是他的域名 manifest .... application android:icondrawable/icon android:labelstring/app_name provider android:name.PersonContentProvider android:authoritiescn.itcast.provider.personprovider/ /application /manifest 注意一旦应用继承了 ContentProvider类后面我们就会把这个应用称为 ContentProvider 内容提供者。 l Uri介绍 Uri代表了要操作的数据 Uri主要包含了两部分信息 1》需要操作的ContentProvider 2》对ContentProvider中 的什么数据进行操作一个 Uri由以下几部分组成 l 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文件中 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使用 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.provider.personprovider/person/10”)那么将会对主机名为 cn.itcast.provider.personprovider的 ContentProvider进行操作操作的数据为 person表中 id为 10的记录 l使用 ContentResolver操作 ContentProvider中的数据 使用 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); [java] view plain copy public class PersonContentProvider extends ContentProvider{ private DataBaseOpenHelper dataBaseOpenHelper; private static final int ALLPERSON1; private static final int PERSON2; private static final UriMatcher uriMatchernew UriMatcher(UriMatcher.NO_MATCH); static{ uriMatcher.addURI(com.gao.provider.personprovider, person, ALLPERSON); uriMatcher.addURI(com.gao.provider.personprovider, person/#, PERSON); } Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase databasedataBaseOpenHelper.getWritableDatabase(); int count0; switch (uriMatcher.match(uri)) { case ALLPERSON://content://com.gao.provider.personprovider/person countdatabase.delete(person, selection, selectionArgs); break; case PERSON://content://com.gao.provider.personprovider/person/100 long idContentUris.parseId(uri); String whereTextUtils.isEmpty(selection)?personid?:selectionand personid?; String[] paramsnew String[]{String.valueOf(id)}; if (!TextUtils.isEmpty(selection)selectionArgs!null) { paramsnew String[selectionArgs.length1]; for (int i 0; i selectionArgs.length; i) { params[i]selectionArgs[i]; } params[selectionArgs.length1]String.valueOf(id); } countdatabase.delete(person, where, selectionArgs); break; default: throw new IllegalArgumentException(Unkonw uri:uri); } return count; } Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case ALLPERSON: return vnd.android.cursor.dir/personprovider.person; case PERSON: return vnd.android.cursor.item/personprovider.person; default: break; } return null; } Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase databasedataBaseOpenHelper.getWritableDatabase(); long id0; switch (uriMatcher.match(uri)) { case ALLPERSON://content://com.gao.provider.personprovider/person iddatabase.insert(person, name, values);//返回记录的行号主键是int实际上就是主键值 return ContentUris.withAppendedId(uri, id); case PERSON://content://com.gao.provider.personprovider/person/100 iddatabase.insert(person, name, values); String pathuri.toString(); return Uri.parse(path.substring(0, path.lastIndexOf(/))id); default: throw new IllegalArgumentException(Unkonw uri:uri); } } Override public boolean onCreate() { dataBaseOpenHelpernew DataBaseOpenHelper(this.getContext()); return false; } Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase databasedataBaseOpenHelper.getReadableDatabase(); switch (uriMatcher.match(uri)) { case ALLPERSON: database.query(person, projection, selection, selectionArgs, null, null, sortOrder); break; case PERSON: long idContentUris.parseId(uri); String whereTextUtils.isEmpty(selection)?personid?:selectionand personid?; String[] paramsnew String[]{String.valueOf(id)}; if (!TextUtils.isEmpty(selection)selectionArgs!null) { paramsnew String[selectionArgs.length1]; for (int i 0; i selectionArgs.length; i) { params[i]selectionArgs[i]; } params[selectionArgs.length1]String.valueOf(id); } database.query(person, projection, where, params, null, null, sortOrder); break; default: break; } return null; } //update(content://com.gao.provider.personprovider/person/100,values,name like ? and ...,new String[]{%gao%}); Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase databasedataBaseOpenHelper.getWritableDatabase(); int count0; switch (uriMatcher.match(uri)) { case ALLPERSON://content://com.gao.provider.personprovider/person countdatabase.update(person, values, selection,selectionArgs); break; case PERSON://content://com.gao.provider.personprovider/person/100 long idContentUris.parseId(uri); String whereTextUtils.isEmpty(selection)?personid?:selectionand personid?; String[] paramsnew String[]{String.valueOf(id)}; if (!TextUtils.isEmpty(selection)selectionArgs!null) { paramsnew String[selectionArgs.length1]; for (int i 0; i selectionArgs.length; i) { params[i]selectionArgs[i]; } params[selectionArgs.length1]String.valueOf(id); } countdatabase.update(person, values, where,params); break; default: throw new IllegalArgumentException(Unkonw uri:uri); } return count; } } AndroidManifest.xml provider android:namePersonContentProvider android:authoritiescom.gao.provider.personprovider / 在另一个程序ContentProviderUser中使用上面的内容提供者 [java] view plain copy public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ContentResolver contentResolverthis.getContentResolver(); Uri allUriUri.parse(content://com.gao.provider.personprovider/person); ContentValues valuesnew ContentValues(); values.put(name, GGGGG); values.put(age, 19); contentResolver.insert(uri, values); values.put(name, CCCCCC); values.put(age, 100); Uri uriUri.parse(content://com.gao.provider.personprovider/person/9); // contentResolver.update(uri, values, null, null); //contentResolver.delete(uri, null, null); Cursor cursorcontentResolver.query(uri, new String[]{personid,name,age}, null, null, personid desc); while (cursor.moveToNext()) { Log.i(TAG, psrsonid:cursor.getInt(0),name:cursor.getString(1),agecursor.getInt(2)); } cursor.close();