1 介绍
ContentProvider(内容提供者):为存储和获取数据提供统一的接口。使用ContentProvider,应用程序可以实现跨进程通信–App间数据共享。Android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)。
图片来源于:Android基础入门教程——4.4.1 ContentProvider初探
2 使用系统提供的ContentProvider
2.1 获取本地视频
public class VideoProvider implements AbstructProvider {
private Context context;
private Map<String, String> nameMap;
public VideoProvider(Context context, Map<String, String> nameMap) {
this.context = context;
this.nameMap = nameMap;
}
@Override
public List<LocalVideo> getList() {
List<LocalVideo> list = null;
if (context != null) {
Cursor cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null,
null, null);
if (cursor != null) {
list = new ArrayList<LocalVideo>();
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
String title = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
String album = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.ALBUM));
String artist = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.ARTIST));
String displayName = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME));
String mimeType = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE));
String path = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
long duration = cursor
.getInt(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));
long size = cursor
.getLong(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
String resolution = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.RESOLUTION));
String[] split = path.split("/");
String folderName = split[split.length - 2];
if (nameMap.containsKey(folderName)) {
folderName = nameMap.get(folderName);
}
int lastIndex = path.lastIndexOf("/") + 1;
String folderPath = path.substring(0, lastIndex);
LocalVideo video = new LocalVideo(id, title, album, artist, displayName, mimeType, path, size, duration, resolution, folderName, folderPath);
if (size > 1024) {
list.add(video);
}
}
cursor.close();
}
}
return list;
}
}
2.2 简单的读取收件箱信息
<uses-permission android:name="android.permission.READ_SMS"/>
private void getMsgs(){
Uri uri = Uri.parse("content://sms/");
ContentResolver resolver = getContentResolver();
//获取的是哪些列的信息
Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);
while(cursor.moveToNext())
{
String address = cursor.getString(0);
String date = cursor.getString(1);
String type = cursor.getString(2);
String body = cursor.getString(3);
System.out.println("地址:" + address);
System.out.println("时间:" + date);
System.out.println("类型:" + type);
System.out.println("内容:" + body);
System.out.println("======================");
}
cursor.close();
}
3 自定义ContentProvider
3.1 流程图
3.2 创建一个数据库创建类-DBOpenHelper
public class DBOpenHelper extends SQLiteOpenHelper {
final String CREATE_SQL = "CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT,name)";
public DBOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
3.3 自定义ContentProvider类-NameContentProvider
public class NameContentProvider extends ContentProvider {
//初始化一些常量
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private DBOpenHelper dbOpenHelper;
//为了方便直接使用UriMatcher,这里addURI,下面再调用Matcher进行匹配
static{
matcher.addURI("com.jay.example.providers.myprovider", "test", 1);
}
@Override
public boolean onCreate() {
dbOpenHelper = new DBOpenHelper(this.getContext(), "test.db", null, 1);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
switch(matcher.match(uri)) {
//把数据库打开放到里面是想证明uri匹配完成
case 1:
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
long rowId = db.insert("test", null, values);
if(rowId > 0)
{
//在前面已有的Uri后面追加ID
Uri nameUri = ContentUris.withAppendedId(uri, rowId);
//通知数据已经发生改变
getContext().getContentResolver().notifyChange(nameUri, null);
return nameUri;
}
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}
}
3.4 AndroidManifest.xml中为ContentProvider进行注册
<!--属性依次为:全限定类名,用于匹配的URI,是否共享数据 -->
<provider android:name="com.jay.example.bean.NameContentProvider"
android:authorities="com.jay.example.providers.myprovider"
android:exported="true" />
3.5 MainActivity
public class MainActivity extends Activity {
private Button btninsert;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btninsert = (Button) findViewById(R.id.btninsert);
//读取contentprovider 数据
final ContentResolver resolver = this.getContentResolver();
btninsert.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ContentValues values = new ContentValues();
values.put("name", "测试");
Uri uri = Uri.parse("content://com.jay.example.providers.myprovider/test");
resolver.insert(uri, values);
Toast.makeText(getApplicationContext(), "数据插入成功", Toast.LENGTH_SHORT).show();
}
});
}
}
3.6 如何使用
具体使用和检索本地视频或短信类似,配置自定义的Uri即可。
4 通过ContentObserver监听ContentProvider的数据变化
4.1 概念
ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器。
4.2 应用
当用户在云图App上截图时,观察存储图片的变化,获取最新的图片路径。