四大组件之一 ContentProvider
作者:互联网
ContentProvider
前言
本文记录四大组件之一contentprovider学习,从官方文档 .中学习,从创建数据库SQLiteOpenHelper,到利用提供者分享数据,监听内容变化,只记录简单的方法的使用和一些小事例,
ContentProvider的概述
内容提供程序有助于应用管理其自身和其他应用所存储数据的访问,并提供与其他应用共享数据的方法。它们会封装数据,并提供用于定义数据安全性的机制。内容提供程序是一种标准接口,可将一个进程中的数据与另一个进程中运行的代码进行连。最重要的是,通过配置内容提供程序,您可以使其他应用安全地访问和修改您的应用数据。
简而言之:则是提供一个标准接口,给外部应用操作自己应用的数据库。
数据库的创建
- 继承SQLiteOpenHelper类 创建数据库
- 构造方法 初始化数据库 (上下文,数据库名,游标卡尺,版本号)cursor用于查询数据的箭头默认指向第一个数据。版本号
- oncreate方法 创建数据库用的 一般通过sql语句 一般用到的类型是integer和varchar
- onupdate方法 用于版本升级,当数据库需扩展时,通过sql语句来扩展,最新版本号必须大于等于应用版本号 不然报错
- 创建Dao类操作数据库
- 操作数据库需持有SQLiteOpenHelper帮助类,通过帮助类来进行增删改查方法。
- 增:可以通过sql语句或者api来进行,api ,使用帮助类的insert方法 (表名,null,contentvalues) null表示当插入数据为空所填数值,数据通过contentvalues的键值对方式put该方法成功返回1,错误返回-1
- 删: 可以通过sql语句或者api来进行,api ,使用帮助类的delete方法 (表名,null,null) 第一个null表示: whereClause条件,第二个null表示whereArgs条件下的值,该方法成功返回删除数据个数,错误返回-1
- 改:可以通过sql语句或者api来进行,api ,使用帮助类的update方法 (表名,contentvalues,null,null 第一个null表示: whereClause条件,第二个null表示whereArgs条件下的值
- 查: 可以通过sql语句或者api来进行,api ,使用帮助类的query方法
(表名,列表数columns,查询那列selection,查询那列的条件值selectionArgs,groupBy,having,orderBy)
- 创建Bean类 封装数据
ContentProvider 的使用
- 继承ContentProvider
- 这里有暴露给外部应用的操作数据库的方法 增删改查方法 getType方法 onCreate方法
- onCreate方法 创建SQLiteOpenHelper帮助类操作数据库
- 增删改查方法应用操作帮助类的方法,和Uri ,它是用来匹配外部应用是否使用改数据库的校验。所以需要new UriMatcher(UriMatcher.NO_MATCH)对象 和静态代码块初始化Uri地址(静态的在内存中运行) UriMatcher的addURI方法(校验号,path,校验返回码)校验号返回码。 在增删改查方法,通过外部app传入的url和static代码中校验号/path进行比对放回。
- 清单文件权限在清单文件中注册provider android:name=继承类 ,android:authorities=静态代码块注册的校验号,android:exported=true
- 在外部应用中,通过getContentResolver获取ContentResolver对象 来操作数据库
内容观察者
-
在外部应用中利用ContentResolver对象调用增删改查方法。来操作应用中的数据库。该对象的增删改查方法的参数对应着所写 ContentProvider类中的参数。
-
在外部应用中利用ContentResolver对象注册内容观察者来监听该数据库中数据变化。registerContentObserver(Uri,true,new ContentObserver(new Handler)) true:表示uri 不管后面是否有path都能返回, 内容观察者是当内容发生改变,你要监听的信息。
日历事件的运用
日历提供者
一键插入事件,通过ContentResolver对象 insert方法
以下是插入新事件的规则:
- 您必须加入 CALENDAR_ID 和 DTSTART。
- 您必须加入 EVENT_TIMEZONE。如需获取系统中已安装时区 ID 的列表,请使用 getAvailableIDs()。请注意,如果您按使用 Intent 插入事件中所述通过 INSERT Intent 插入事件,则此规则不适用 — 在该情形下,系统会提供默认时区。
- 对于非重复事件,您必须加入 DTEND。
- 对于重复事件,您必须加入 DURATION,以及 RRULE 或 RDATE。请注意,如果您按使用 Intent 插入事件中所述通过 INSERT Intent 插入事件,则此规则不适用 — 在该情形下,您可以将 RRULE 与 DTSTART 和 DTEND 结合使用,日历应用会自动将其转换为持续时间。
//1:事件表 2.应用weibo相关信息表 3:联系人生日表
long calID = 1;
long startMillis = 0;
long endMillis = 0;
Calendar beginTime = Calendar.getInstance();
beginTime.set(2021, 10, 11, 0, 0);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2021, 10, 11, 23, 59);
endMillis = endTime.getTimeInMillis();
String timeZone= TimeZone.getDefault().getID();
Log.d(TAG,timeZone);
ContentResolver cr = getContentResolver();
ContentValues eventValues = new ContentValues();
eventValues.put(CalendarContract.Events.DTSTART, startMillis);
eventValues.put(CalendarContract.Events.DTEND, endMillis);
eventValues.put(CalendarContract.Events.TITLE, "双十一购物狂欢节开抢");
eventValues.put(CalendarContract.Events.DESCRIPTION, "尽情买买买!!");
eventValues.put(CalendarContract.Events.CALENDAR_ID, calID);
eventValues.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone);
Uri resultUri = cr.insert(CalendarContract.Events.CONTENT_URI, eventValues);
Log.d(TAG,"返回结果"+resultUri);
String eventID = resultUri.getLastPathSegment();
Log.d(TAG,eventID);
ContentValues reminderValues = new ContentValues();
reminderValues.put(CalendarContract.Reminders.MINUTES, 15);
reminderValues.put(CalendarContract.Reminders.EVENT_ID, eventID);
reminderValues.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri uri1 = cr.insert(CalendarContract.Reminders.CONTENT_URI, reminderValues);
联系人提供者
ContentResolver cr = getContentResolver();
Uri rawUri = Uri.parse("content://"+ContactsContract.AUTHORITY+"/raw_contacts");
Cursor rawCursor = cr.query(rawUri, new String[]{"contact_id","display_name"}, null, null, null);
String[] columnNames = rawCursor.getColumnNames();
List<UserInfo> userInfos=new ArrayList<>();
while (rawCursor.moveToNext()) {
UserInfo userInfo=new UserInfo();
userInfo.setId(rawCursor.getString(rawCursor.getColumnIndex("contact_id")));
userInfo.setDisplayName(rawCursor.getString(rawCursor.getColumnIndex("display_name")));
userInfos.add(userInfo);
for (String columnName : columnNames) {
Log.d(TAG,columnName+" ======= "+rawCursor.getString(rawCursor.getColumnIndex(columnName)));
}
}
rawCursor.close();
Uri phoneUri = Uri.parse("content://"+ContactsContract.AUTHORITY+"/data/phones");
for (UserInfo userInfo : userInfos) {
Cursor phoneCursor = cr.query(phoneUri, new String[]{"data1"}, "raw_contact_id=?", new String[]{userInfo.getId()}, null);
if (phoneCursor.moveToNext()) {
userInfo.setPhoneNumber(phoneCursor.getString(0).replace("-",""));
}
Log.d(TAG,"userInfo ===>"+userInfo);
phoneCursor.close();
}
/*for (UserInfo userInfo : userInfos) {
Cursor phoneCursor = cr.query(phoneUri, null, "raw_contact_id=?", new String[]{userInfo.getId()}, null);
String[] columnNames1 = phoneCursor.getColumnNames();
while (phoneCursor.moveToNext()) {
for (String columnName : columnNames1) {
Log.d(TAG, columnName + " ======= " + phoneCursor.getString(phoneCursor.getColumnIndex(columnName)));
}
}
phoneCursor.close();
}*/
这里只能读到手机的联系人手机号,sd卡上无法读取。但能看到联系人的名字,可能得通过另一个数据库去查询。
消息提供者
ContentResolver contentResolver = getContentResolver();
Uri uri=Uri.parse("content://sms");
Cursor cursor = contentResolver.query(uri, null, null, null, null);
String[] columnNames = cursor.getColumnNames();
while (cursor.moveToNext()) {
for (String columnName : columnNames) {
Log.d(TAG,columnName+" ==== "+cursor.getString(cursor.getColumnIndex(columnName)));
}
}
cursor.close();
通过registerContentObserver 内容观察者来获取消息的实时验证吗
- 通过监听sms的数据库变化,获取数据变化的Uri
- 通过Uri查询数据库的短信
- 对短信进行正则化表达式过滤获取 验证码
获取媒体库提供者形成9宫图返回
- LoadManager获取数据库信息
- 如果图片很多时,由于访问数据库耗时操作很多,所以需要在子线程中运行,所以运用LoadManager
- LoadManager.getInstance()获取LoadManager对象
- 调用LoadManager的init方法(load_id,args,Callback) 通过Callback的onCreatLoader方法根据load_id,创建返回的Cursor对象,return new CursorLoad(context,uri,projection,selection,selectionArgs,sortOrder);
- Callback的onLoadFinished方法中得到cursor对象,通过query方法查询需要的信息"_data",“display_name”,“date_added” 并将数据封装到ArrayList当中。
- 将数据库信息加载到RecyclerView的适配器中
- 创建RecyclerView(1.找到控件2.设置LayoutManager3.设置Adapter)
- 将封装好的数据ArrayList对象数据设置Adapter(1.私有化数据2.清空3.重新添加防止数据错乱)
- 加载布局到RecyclerView当中
- onCreateViewHolder的创建复用itemView的Holder对象(1.通过获取WindowManager对象 2.itemView设置LayoutParams 3等分)
- onBindViewHolder绑定数据(数据改变的调用)初始化控件,控件点击事件(imageview,checkbox,view(背景色))
- 控件点击事件设计
- imageview的点击
- 点击一下选择,再点击取消。
- 创建被选择的ArrayList,根据是否包含被选择,如果选择,点击remove的条目,checkbox的setChecked,setButtonDrawable和view变setVisibility(View.GONE)。如果没选择,则相反。
- imageview的点击
- 将选择的数据通过接口返回到Activity中
- 创建Config,设置回调接口set方法和get方法,回调接口返回选择的图片item对象,设置最大图片数的get和set方法。
- 防止泄漏设置成单例模式,由于线程无关,设置成饿汉式
- 在选择图片界面finish的 set回调接口 是否判断接口为空,返回接口
- 在返回界面get回调接口
标签:ContentProvider,数据库,CalendarContract,Uri,四大,组件,new,null,方法 来源: https://blog.csdn.net/sumjim234/article/details/113585684