1、ContentProvider,内容提供者
功能:向其他的应用程序提供数据访问的接口,一般使用在产品线内的多个应用程序,比如QQ和微信之间的数据共享,qq和其他应用程序可以访问手机联系人
2、ContentProvider,负责将数据暴露给其他的应用程序,可以暴露任何资源数据,通常暴露数据库文件
ContentResolver,内容解析器,负责解析ContentProvider暴露的数据
3、URI,统一资源标识符,通过URI可以找到应用程序暴露的数据
http://localhost:8080/web/index.html
content://sms
content://call_log/calls
content://com.android.contacts/raw_contacts
4/短信的数据库
data/data/com.android.provides.telephony/database/mmssms.db
权限:
READ_SMS
WRITE_SMS
Cursor c = resolver.query(Uri.parse(uriStr), new String[] { "_id",
"address", "date", "type", "body" }, null, null, null);
短信类型:1(接收),2(发送),3(草稿)
5、通话记录
data/data/com.android.providers.contacts/database/contacts2.db
权限:READ_CALL_LOG
Cursor c = getContentResolver().query(Uri.parse(uriStr),
new String[] { "_id", "name", "number", "date", "type" }, null,null, null);
通话类型:1(拨入),2(拨出),3(未接)
6、查询联系人
data/data/com.android.providers.contacts/database/contacts2.db
raw_contacts:可以查询联系人总数,联系人的主键(_id),display_name
data:存储联系人的具体信息
7、自定义ContentProvider
a:
创建子类继承ContentProvider,在子类中对数据库进行crud操作
b:
UriMatcher,Uri匹配器
添加Uri
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.qf.mycontentprovider", "query", QUERYCODE);
c:重写crud方法,先判断uri匹配是否成功
if (uriMatcher.match(uri) == QUERYCODE)
d:在清单文件中注册
<!-- 注册自定义ContentProvider
android:name:全类名
android:authorities:授权,权限
android:exported:是否可以被其他应用程序访问,true,向外暴露数据供其他应用程序访问
-->
<provider
android:name="com.example.day16_provider_custom.MyContentProvider"
android:authorities="com.qf.mycontentprovider"
android:exported="true"></provider>
//注意:在访问系统应用程序时,要记得加权限
案例一:
public class MainActivity extends Activity {
private ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
String uriStr = "content://sms";
// 获得内容解析器
ContentResolver resolver = getContentResolver();
// uri:数据库资源的地址
// projection:查询字段的名称
// selection:查询条件子句,可以使用占位符
// selectionArgs:用来替代占位符的数据
// sortOrder:根据某个字段进行排序
Cursor c = resolver.query(Uri.parse(uriStr), new String[] { "_id","address", "date", "type", "body" }, null, null, null);
// SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
// R.layout.item, c, new String[] { "address", "date", "type",
// "body" }, new int[] { R.id.tv_address, R.id.tv_date,
// R.id.tv_type, R.id.tv_body },
// SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
MyCursorAdapter adapter = new MyCursorAdapter(this, c,CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
}
// 创建自定义CursorAdapter
class MyCursorAdapter extends CursorAdapter {
public MyCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
// TODO Auto-generated constructor stub
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// TODO Auto-generated method stub
return LayoutInflater.from(context).inflate(R.layout.item, null);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// TODO Auto-generated method stub
TextView tvAddress = (TextView) view.findViewById(R.id.tv_address);
TextView tvType = (TextView) view.findViewById(R.id.tv_type);
TextView tvDate = (TextView) view.findViewById(R.id.tv_date);
TextView tvBody = (TextView) view.findViewById(R.id.tv_body);
tvAddress
.setText(cursor.getString(cursor.getColumnIndex("address")));
tvBody.setText(cursor.getString(cursor.getColumnIndex("body")));
// 处理时间
long date = cursor.getLong(cursor.getColumnIndex("date"));
tvDate.setText(parseDate(date));
// 处理短信类型
int type = cursor.getInt(cursor.getColumnIndex("type"));
if (type == 1) {
tvType.setText("接收");
} else if (type == 2) {
tvType.setText("发送");
} else {
tvType.setText(type + "");
}
}
}
public String parseDate(long date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
return sdf.format(new Date(date));
}
}
//注意在写自定义contentprovider时要在清单文件中注册,四大组件都要注册
案例二:自定义contentprovider
首先需要写一个databaseHelper类:
然后再写一个MyContentProvider来继承contentprovider:
public class MyContentProvider extends ContentProvider {
private DBHelper helper;
private String table = "person";
// 定义常量,作为uri的匹配吗
private static final int QUERYCODE = 1;
private static final int INSERTCODE = 2;
private static final int UPDATECODE = 3;
private static final int DELETECODE = 4;
// Uri匹配器,或匹配Uri的工具类
private static UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 权限
// 路径
// 返回值
uriMatcher.addURI("com.qf.mycontentprovider", "query", QUERYCODE);
uriMatcher.addURI("com.qf.mycontentprovider", "insert", INSERTCODE);
uriMatcher.addURI("com.qf.mycontentprovider", "update", UPDATECODE);
uriMatcher.addURI("com.qf.mycontentprovider", "delete", DELETECODE);
}
// 当创建ContentProvider时执行,只执行一次
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
helper = new DBHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = null;
if (uriMatcher.match(uri) == QUERYCODE) {
cursor = db.query(table, projection, selection, selectionArgs,
null, null, sortOrder);
}
return cursor;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
if (uriMatcher.match(uri) == INSERTCODE) {
SQLiteDatabase db = helper.getWritableDatabase();
db.insert(table, null, values);
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
int n = 0;
if (uriMatcher.match(uri) == DELETECODE) {
SQLiteDatabase db = helper.getWritableDatabase();
n = db.delete(table, selection, selectionArgs);
}
return n;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
int n = 0;
if (uriMatcher.match(uri) == UPDATECODE) {
SQLiteDatabase db = helper.getWritableDatabase();
n = db.update(table, values, selection, selectionArgs);
}
return n;
}
}
另一个应用程序就可以通过url匹配地址来访问上一个应用程序:
在这个应用程序中有三个按钮,增加,删除,修改,对上一个应用程序的数据库进行访问
public class MainActivity extends Activity {
private String queryStr = "content://com.qf.mycontentprovider/query";
private String insertStr = "content://com.qf.mycontentprovider/insert";
private String updateStr = "content://com.qf.mycontentprovider/update";
private String deleteStr = "content://com.qf.mycontentprovider/delete";
private ContentResolver res = null;
private Cursor cursor;
private ListView lv;
private SimpleCursorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
res = getContentResolver();
select();
adapter = new SimpleCursorAdapter(this, R.layout.item, cursor,new String[] { "name", "age" }, new int{R.id.tv_name,R.id.tv_age },cursorAdaptr.FLAG_REGISTER_CONTENT_OBSERVER);
lv.setAdapter(adapter);
}
public void insert(View v) {
ContentValues values = new ContentValues();
values.put("name", "zhangsan");
values.put("age", 20);
res.insert(Uri.parse(insertStr), values);
select();
adapter.swapCursor(cursor);
}
public void update(View v) {
select();
cursor.moveToFirst();
ContentValues values = new ContentValues();
values.put("age", 21);
res.update(Uri.parse(updateStr), values, "_id=?",
new String[] { cursor.getInt(0) + "" });
select();
adapter.swapCursor(cursor);
}
public void delete(View v) {
select();
cursor.moveToFirst();
res.delete(Uri.parse(deleteStr), "_id=?",
new String[] { cursor.getInt(0) + "" });
select();
adapter.swapCursor(cursor);
}
public void select() {
cursor = res.query(Uri.parse(queryStr), null, null, null, null);
}
}