android之内容提供者解析

该系统有两个应用,比较繁琐。但是内容提供者是android里非常非常重要的一个内容,我们得好好学习下哦。先看效果图,我们提供了四个按钮,点击按钮便会进行相应的操作。
我们先看内容提供者所在的应用,代码结构:

activity代码:
- package cn.com.contentProvider;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.TextView;
- public class ContentProviderAcitivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- }
MyContentProvider.java代码
- package cn.com.contentProvider;
- import android.content.ContentProvider;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.UriMatcher;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.net.Uri;
- /**
- *
- * @author chenzheng_java
- * @description 自定义的内容提供者.
- * 总结下访问内容提供者的主要步骤:
- * 第一:我们要有一个uri,这就相当于我们的网址,我们有了网址才能去访问具体的网站
- * 第二:我们去系统中寻找该uri中的authority(可以理解为主机地址),
- * 只要我们的内容提供者在manifest.xml文件中注册了,那么系统中就一定存在。
- * 第三:通过内容提供者内部的uriMatcher对请求进行验证(你找到我了,还不行,我还得看看你有没有权限访问我呢)。
- * 第四:验证通过后,就可以调用内容提供者的增删查改方法进行操作了
- */
- public class MyContentProvider extends ContentProvider {
- // 自己实现的数据库操作帮助类
- private MyOpenHelper myOpenHelper;
- // 数据库相关类
- private SQLiteDatabase sqLiteDatabase;
- // uri匹配相关
- private static UriMatcher uriMatcher;
- // 主机名称(这一部分是可以随便取得)
- private static final String authority = "cn.com.chenzheng_java.hello";
- // 注册该内容提供者匹配的uri
- static {
- uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- /*
- * path_chenzheng部分的字符串是随便取得,1代表着如果请求的uri与当前加入
- * 的匹配uri正好吻合,uriMathcher.match()方法返回的值.#代表任意数字,*代表任意字符串
- */
- uriMatcher.addURI(authority, "path_chenzheng", 1);// 代表当前表中的所有的记录
- uriMatcher.addURI(authority, "path_chenzheng/#", 2);// 代表当前表中的某条特定的记录,记录id便是#处得数字
- }
- // 数据表中的列名映射
- private static final String _id = "id";
- private static final String name = "name";
- private static final String age = "age";
- private static final String isMan = "isMan";
- /**
- * @description 当内容提供者第一次创建时执行
- */
- @Override
- public boolean onCreate() {
- try {
- myOpenHelper = new MyOpenHelper(getContext(), DB_Name, null,
- Version_1);
- } catch (Exception e) {
- return false;
- }
- return true;
- }
- /**
- * @description 对数据库进行删除操作的时候执行
- * android.content.ContentUri为我们解析uri相关的内容提供了快捷方便的途径
- */
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- int number = 0;
- sqLiteDatabase = myOpenHelper.getWritableDatabase();
- int code = uriMatcher.match(uri);
- switch (code) {
- case 1:
- number = sqLiteDatabase
- .delete(Table_Name, selection, selectionArgs);
- break;
- case 2:
- long id = ContentUris.parseId(uri);
- /*
- * 拼接where子句用三目运算符是不是特烦人啊? 实际上,我们这里可以用些技巧的.
- * if(selection==null||"".equals(selection.trim())) selection =
- * " 1=1 and "; selection+=_id+"="+id;
- * 拼接where子句中最麻烦的就是and的问题,这里我们通过添加一个1=1这样的恒等式便将问题解决了
- */
- selection = (selection == null || "".equals(selection.trim())) ? _id
- + "=" + id
- : selection + " and " + _id + "=" + id;
- number = sqLiteDatabase
- .delete(Table_Name, selection, selectionArgs);
- break;
- default:
- throw new IllegalArgumentException("异常参数");
- }
- return number;
- }
- /**
- *@description 获取当前内容提供者的MIME类型 集合类型必须添加前缀vnd.android.cursor.dir/(该部分随意)
- * 单条记录类型添加前缀vnd,android.cursor.item/(该部分随意)
- * 定义了该方法之后,系统会在第一次请求时进行验证,验证通过则执行crub方法时不再重复进行验证,
- * 否则如果没有定义该方法或者验证失败,crub方法执行的时候系统会默认的为其添加类型验证代码。
- */
- @Override
- public String getType(Uri uri) {
- int code = uriMatcher.match(uri);
- switch (code) {
- case 1:
- return "vnd.android.cursor.dir/chenzheng_java";
- case 2:
- return "vnd.android.cursor.item/chenzheng_java";
- default:
- throw new IllegalArgumentException("异常参数");
- }
- }
- /**
- * @description 对数据表进行insert时执行该方法
- */
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- sqLiteDatabase = myOpenHelper.getWritableDatabase();
- int code = uriMatcher.match(uri);
- switch (code) {
- case 1:
- sqLiteDatabase.insert(Table_Name, name, values);
- break;
- case 2:
- long id = sqLiteDatabase.insert(Table_Name, name, values);
- // withAppendId将id添加到uri的最后
- ContentUris.withAppendedId(uri, id);
- break;
- default:
- throw new IllegalArgumentException("异常参数");
- }
- return uri;
- }
- /**
- * 当执行查询时调用该方法
- */
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- Cursor cursor = null;
- sqLiteDatabase = myOpenHelper.getReadableDatabase();
- int code = uriMatcher.match(uri);
- switch (code) {
- case 1:
- cursor = sqLiteDatabase.query(Table_Name, projection, selection,
- selectionArgs, null, null, sortOrder);
- break;
- case 2:
- // 从uri中解析出ID
- long id = ContentUris.parseId(uri);
- selection = (selection == null || "".equals(selection.trim())) ? _id
- + "=" + id
- : selection + " and " + _id + "=" + id;
- cursor = sqLiteDatabase.query(Table_Name, projection, selection,
- selectionArgs, null, null, sortOrder);
- break;
- default:
- throw new IllegalArgumentException("参数错误");
- }
- return cursor;
- }
- /**
- * 当执行更新操作的时候执行该方法
- */
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- int num = 0;
- sqLiteDatabase = myOpenHelper.getWritableDatabase();
- int code = uriMatcher.match(uri);
- switch (code) {
- case 1:
- num = sqLiteDatabase.update(Table_Name, values, selection, selectionArgs);
- break;
- case 2:
- long id = ContentUris.parseId(uri);
- selection = (selection == null || "".equals(selection.trim())) ? _id
- + "=" + id
- : selection + " and " + _id + "=" + id;
- num = sqLiteDatabase.update(Table_Name, values, selection, selectionArgs);
- break;
- default:
- break;
- }
- return num;
- }
- // 数据库名称
- private final String DB_Name = "chenzheng_java.db";
- // 数据表名
- private final String Table_Name = "chenzheng_java";
- // 版本号
- private final int Version_1 = 1;
- private class MyOpenHelper extends SQLiteOpenHelper {
- public MyOpenHelper(Context context, String name,
- CursorFactory factory, int version) {
- super(context, name, factory, version);
- }
- /**
- * @description 当数据表无连接时创建新的表
- */
- @Override
- public void onCreate(SQLiteDatabase db) {
- String sql = " create table if not exists " + Table_Name
- + "(id INTEGER,name varchar(20),age integer,isMan boolean)";
- db.execSQL(sql);
- }
- /**
- * @description 当版本更新时触发的方法
- */
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- String sql = " drop table if exists " + Table_Name;
- db.execSQL(sql);
- onCreate(db);
- }
- }
- }
androidManifest.xml代码
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cn.com.contentProvider" android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".ContentProviderAcitivity"
- 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="cn.com.chenzheng_java.hello"
- android:multiprocess="true" android:permission="cn.com.chenzheng_java.permission"></provider>
- </application>
- <!--
- permission中的android:name的值与provider中的android:permission的值是一样的
- android:protectionLevel 则代表了权限等级
- -->
- <permission android:name="cn.com.chenzheng_java.permission"
- android:protectionLevel="normal"></permission>
- </manifest>
main.xml为默认。
----------------------------------------------------------------------------------------------------------------
第二个应用(用于访问内容提供者的应用)

activity代码
- package cn.com.chenzheng_java;
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.TextView;
- /**
- *
- * @author chenzheng_java
- * @description 通过访问内容提供者进行增删查改.注意本程序中为了方便阅读,
- * 在需要数据库列名的地方直接写上了数据库中字段的名称,实际上这是不合理的,
- * 作为内容提供者的使用者,我们不可能在使用这个内容提供者之前先去了解sqlite
- * 中表的结构。比较适宜的做法是,在内容提供者中将愿意提供给外部访问的字段名称(列名)
- * 定义为string final 的常量!
- */
- public class ContentAccessActivity extends Activity {
- private final static String tag = "通知";
- private TextView textView;
- String result = "结果:/n";
- ContentResolver reslover;
- Uri uri;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- /**
- * 这里我们一定要搞清楚,uri的内容到底和内容提供者中哪个地方一一对应
- * 在MyContentProvider中我们有如下片段
- * uriMatcher.addURI(authority, "path_chenzheng", 1);// 代表当前表中的所有的记录
- uriMatcher.addURI(authority, "path_chenzheng/#", 2);// 代表当前表中的某条特定的记录,记录id便是#处得数字
- 其中authority为cn.com.chenzheng_java.hello。
- */
- uri = Uri.parse("content://cn.com.chenzheng_java.hello/path_chenzheng");
- /**
- * 内容提供者是什么?内容提供者相当于一个封装好了增删改查操作的接口,这个接口有一把锁,只有携带钥匙的访问者才能访问。
- * ContentResolver是什么?ContentResolver是一个开锁匠,他携带者钥匙(钥匙上有标签显示他是那个门得钥匙,如path_chenzheng)
- * 去寻找内容提供者,然后访问内容提供者的增删查改方法
- * 我们这里调用contentResolver的增删查改就相当于将任务交给了锁匠,
- * 然后让锁匠去找能打开的内容提供者,并且执行里面相应的方法,并将结果返回.
- * ContentResolver的好处在于,我们可以无视CotentProvider的具体实现,无论contentProvider里面是如何实现的,我想执行
- * 某一个操作时,所要书写的代码都是一样的。
- */
- reslover = this.getContentResolver();
- textView = (TextView) findViewById(R.id.textView);
- Button insertButton = (Button) findViewById(R.id.insertButton);
- insertButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- insert(reslover, uri);
- }
- });
- Button deleteButton = (Button) findViewById(R.id.deleteButton);
- deleteButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- delete(reslover, uri);
- }
- });
- Button updateButton = (Button) findViewById(R.id.updateButton);
- updateButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- update(reslover, uri);
- }
- });
- Button queryButton = (Button) findViewById(R.id.queryButton);
- queryButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- query(reslover, uri);
- }
- });
- }
- private void insert(ContentResolver resolver, Uri uri) {
- ContentValues contentValues = new ContentValues();
- contentValues.put("name", "张小凡");
- contentValues.put("age", 22);
- contentValues.put("isMan", true);
- Uri uri2 = resolver.insert(uri, contentValues);
- Log.i(tag, "插入成功!");
- result += "成功插入了一条记录,uri为" + uri2;
- textView.setText(result);
- result = "";
- }
- private void update(ContentResolver resolver, Uri uri) {
- ContentValues contentValues = new ContentValues();
- contentValues.put("age", 122);
- int number = resolver.update(uri, contentValues, null, null);
- Log.i(tag, "更新成功!");
- result += "成功更新了" + number+"条记录";
- textView.setText(result);
- result = "";
- }
- private void delete(ContentResolver resolver, Uri uri) {
- String where = " 1=1 and isMan=?";
- //这里要注意哦,sqlite数据库中是没有boolean的,true会被转成1存储
- String[] selectionArgs = new String[] { "1" };
- int number = resolver.delete(uri, where, selectionArgs);
- Log.i(tag, "删除成功!");
- textView.setText(result + "成功删除了" + number + "条记录");
- result = "";
- }
- private void query(ContentResolver resolver, Uri uri) {
- String[] projection = new String[] { "id", "name", "age", "isMan" };
- Cursor cursor = resolver.query(uri, projection, null, null, null);
- int count = cursor.getCount();
- Log.i(tag, "总记录数" + count);
- int idIndex = cursor.getColumnIndex("id");
- int nameIndex = cursor.getColumnIndex("name");
- int ageIndex = cursor.getColumnIndex("age");
- int isManIndex = cursor.getColumnIndex("isMan");
- cursor.moveToFirst();
- while (!cursor.isAfterLast()) {
- int id = cursor.getInt(idIndex);
- String name = cursor.getString(nameIndex);
- int age = cursor.getInt(ageIndex);
- int isMan = cursor.getInt(isManIndex);
- Log.i(tag, "id=" + id + " name=" + name + " age=" + age + " isMan="
- + isMan);
- result += "id=" + id + " name=" + name + " age=" + age + " isMan="
- + isMan;
- cursor.moveToNext();
- }
- textView.setText(result);
- result = "";
- }
- }
manifest.xml
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cn.com.chenzheng_java"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".ContentAccessActivity"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- <!-- 添加对内容提供者访问的权限,该权限是有我们自己定义的哦 -->
- <uses-permission android:name="cn.com.chenzheng_java.permission"></uses-permission>
- </manifest>
main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <TextView
- android:id="@+id/textView"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/hello"
- />
- <Button
- android:id="@+id/insertButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="insert"
- ></Button>
- <Button
- android:id="@+id/deleteButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="delete"
- ></Button>
- <Button
- android:id="@+id/updateButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="update"
- ></Button>
- <Button
- android:id="@+id/queryButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="query"
- ></Button>
- </LinearLayout>
--------------------------------------------------------------------------------
想说的话,在代码的注释中已经说的很清晰了。这里再次重复下我们定义和使用内容提供者的步骤吧。
定义内容提供者:
我们定义内容提供者的目的是什么,共享数据,对,定义内容提供者的目的就是让别的应用能够访问当前应用的一些数据,至于到底暴露给外界什么数据,我们可以 在定义内容提供者的时候详细控制!不管如何,我们明确了第一个问题,定义内容提供者的目的----数据共享!
我们平时对数据的操作都有哪些?增删改查!就四个字!这也是为什么我们再定义内容提供者的时候必须要实现相应的方法了。当然如果你要是不想提供相应的操作,你可以在内部进行方法空实现。
是不是所有的应用都可以访问我啊?不可能!我们可不是随便的人,对吧!所以我们要进行验证,验证不通过的直接让它去死就可以了。验证怎么验证啊?通过UriMatcher进行匹配!
现在我们已经提供了访问接口了,我们怎么让系统知道,别的应用可以用我的东西啊?去配置文件中注册!!
使用内容提供者:
如何找到该内容提供者啊?需要Uri和相应的访问权限。相当于地址
如何进行增删查改啊?通过ContentResolver对象的相应方法。
android之内容提供者解析的更多相关文章
- Android 中内容提供者的使用
在Android中内容提供者主要是用于不同程序之间的数据共享.内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序的数据,另一种是创建自己的内容提供器,供其他的程序访问. 使用现 ...
- Android 之内容提供者 内容解析者 内容观察者
contentProvider:ContentProvider在Android中的作用是对外提供数据,除了可以为所在应用提供数据外,还可以共享数据给其他应用,这是Android中解决应用之间数据共享的 ...
- [Android Pro] 内容提供者ContentProvider的基本使用
一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.ContentProvider为存储和获取数据提 ...
- Android中内容提供者ContentProvider的详解
1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不 ...
- Android使用内容提供者实现增删改查操作
Android使用内容提供者实现增删改查操作 这里需要建立两个项目:SiYouShuJuKu(使用内容提供者暴露相关的操作),DQDYGApplication(使用内容解析者对第一个应用进行相关的解析 ...
- Android -- ContentProvider 内容提供者,创建和调用
1. 概述 ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentPr ...
- Android基础内容提供者ContentProvider的使用详解(转)
1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不 ...
- android contentprovider内容提供者
contentprovider内容提供者:让其他app可以访问私有数据库(文件) 1.AndroidManifest.xml 配置provider <?xml version="1.0 ...
- Android之内容提供者ContentProvider的总结
本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 Conte ...
随机推荐
- view加阴影和边框
UIImageView *imgvPhoto = [UIImageView alloc] init]; //添加边框 CALayer *layer = [_imgvPhoto layer]; ...
- 1.2(SQL学习笔记)高级数据过滤
一.AND 通过WHERE可以进行条件过滤,但只限于单个条件. 通过AND就可以连接多个条件,AND代表了和,即AND两边的条件全部满足才会通过筛选. 这就类似编程语言中的&&. 以下 ...
- CentOS 6.9下配置安装KVM
注意:KVM一切安装和运行都是在root用户下完成的,并且只有root才能支持某些软件. 一.准备工作: 1.查看系统版本.内核版本 ##查看系统版本 # cat /etc/redhat-releas ...
- .Net的差评
.NET平台很棒.真的很棒.直到它不再那么棒.我为什么不再用.NET?简单来说,它限制了我们选择的能力(对我来说很重要),转移了我们的注意力,使得我们向内认知它的安全性,替代了帮助我们认知外面广阔世界 ...
- python tkinter 框架开发的收费音乐免费下载工具
使用介绍: 工具下载地址:https://wps-oss.oss-cn-shenzhen.aliyuncs.com/Music2.exe 技术交流和赞助请前往我的咸鱼: https://market. ...
- Delphi 资源文件( .res)
一. 现在的Windows应用程序几乎都使用图标.图片.光标.声音等,我们称它们为资源(Resource).最简单的使用资源的办法是把这些资源的源文件打入软件包,以方便程序需要的时候调用.资源是 ...
- linux(虚拟机中)与windows共享文件两种方法
Windows 下用 SourceInsight 与 Linux 协作编码 习惯了用SourceInsight 读写代码,在Linux下一时没找到类似的工具,vi的操作也不熟,偶尔看看或小 ...
- 2017.12.25 Mybatis物理分页插件PageHelper的使用(二)
参考来自: 官方文档的说明:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md 上篇博客 ...
- Android - Animation(二)
Android - Animation(一) 一文总结了Android中的补间动画(View Animation/Tween Animation)和帧动画(Drawable Animation/Fra ...
- Elasticsearch的javaAPI之query dsl-queries
Elasticsearch的javaAPI之query dsl-queries 和rest query dsl一样,elasticsearch提供了一个完整的Java query dsl. 查询建造者 ...