ContentProvider 内容提供器
来源:互联网 发布:手机网络渗透 编辑:程序博客网 时间:2024/04/18 08:14
ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。ContentProvider分为系统的和自定义的,系统的也就是例如联系人,图片等数据。
内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中的数据,另一种是创建自己的内容提供器给我们程序的数据提供外部访问接口。
如果一个应用程序通过内容提供器对数据提供了外部访问接口,那么任何其他的应用程序就都可以对这部分数据进行访问。Android 系统中自带的电话薄, 短信,媒体库等程序都提供了类似的访问接口,这就使的第三方应用程序可以充分地利用这部分数据来实现更好的功能。
ContentProvider
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。
ContentResolver cr = getContentResolver();
ContentResolver提供的方法和ContentProvider提供的方法对应的有以下几个方法。
public Uri insert(Uri uri, ContentValues values) 用于添加数据到指定Uri的ContentProvider中。
public int delete(Uri uri, String selection, String[] selectionArgs) 用于从指定Uri的ContentProvider中删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用于更新指定Uri的ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用于查询指定Uri的ContentProvider。
android系统管理联系人的URI如下:ContactsContract.Contacts.CONTENT_URI 管理联系人的UriContactsContract.CommonDataKinds.Phone.CONTENT_URI 管理联系人的电话的UriContactsContract.CommonDataKinds.Email.CONTENT_URI 管理联系人的Email的UriContacts有两个表,分别是rawContact和DatarawContact记录了用户的id和name:其中id栏名称为:ContactsContract.Contacts._ID name名称栏为ContactContract.Contracts.DISPLAY_NAME电话信息表的外键id为ContactsContract.CommonDataKinds.Phone.CONTACT_ID电话号码栏名称为:ContactsContract.CommonDataKinds.Phone.NUMBERdata表中Email地址栏名称为:ContactsContract.CommonDataKinds.Email.DATA其外键栏为:ContactsContract.CommonDataKinds.Email.CONTACT_IDandroid为多媒体提供的ContentProvider的Uri如下:MediaStore.Audio.Media.EXTERNAL_CONTENT_URI 存储在sd卡上的音频文件MediaStore.Audio.Media.INTERNAL_CONTENT_URI 存储在手机内部存储器上的音频文件MediaStore.Audio.Images.EXTERNAL_CONTENT_URI SD卡上的图片文件内容MediaStore.Audio.Images.INTERNAL_CONTENT_URI 手机内部存储器上的图片MediaStore.Audio.Video.EXTERNAL_CONTENT_URI SD卡上的视频MediaStore.Audio.Video.INTERNAL_CONTENT_URI 手机内部存储器上的视频
访问通讯录
public class MainActivity extends AppCompatActivity { ArrayAdapter<String> adapter; List<String> contactsList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView contactsView = (ListView) findViewById(R.id.contacts_view); adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,contactsList); contactsView.setAdapter(adapter); if(ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS},1); }else{ readContacts(); } } private void readContacts(){ Cursor cursor = null; try{ //ContactsContract.CommonDataKinds.Phone.CONTENT_URI 管理联系人的电话的Uri。系统已经封装好了 cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,null); if(cursor != null){ while (cursor.moveToNext()){ //获取联系人姓名 String displayName = cursor.getString(cursor.getColumnIndex (ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); //获取联系人手机号 String number = cursor.getString(cursor.getColumnIndex (ContactsContract.CommonDataKinds.Phone.NUMBER)); contactsList.add(displayName + "\n" + number); } //更新 adapter.notifyDataSetChanged(); } }catch (Exception e){ e.printStackTrace(); } finally { if(cursor != null){ cursor.close(); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode){ case 1: if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ readContacts(); } else { Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show(); } break; default: break; } }}
Uri
Uri代表了要操作的Uri指定了将要操作的ContentProvider的数据。它由两部分组成:authority 和 path。
ContentProvider的scheme已经由Android所规定, scheme为:content://
authority:是用于对不同的应用程序作区分,一般为了避免冲突,都会采用程序包名来进行命名。
path:路径。
id:通常定义URI时使用”#”号占位符代替, 使用时替换成对应的数字
content://com.jxn.provider/person/# #代表任意长度的数字
content://com.jxn.provider/person/* *来匹配任意长度的字符
content://com.example.app.provider/table1 表1
content://com.example.app.provider/table2 表2
要操作table1表中id为10的记录,可以构建这样的路径:/table1/10
content://com.example.app.provider/table1/10
Android系统提供了两个用于操作Uri的工具类:UriMatcher 和 ContentUris
UriMatcher
UriMatcher 类主要用于匹配Uri。UtiMatcher中提供了一个addURI()方法,这个方法接受3个参数,可以分别把authority,path,和一个自定义码传进去。这样,当调用UriMatcher的math()方法时,就可以将一个 Uri 对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期望访问的是哪张表的数据了。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.example.app.provider","table1",0); uriMatcher.addURI("com.example.app.provider","table1/#",1);
Uri是content://com.example.databasetest.provider/book
使用uriMatcher.math(uri)得到的是匹配码是0。
Uri是content://com.example.databasetest.provider/book/#
使用uriMatcher.math(uri)得到的是匹配码是1。
ContentUris类用于为路径加上ID和获取路径的ID
Uri resultUri = ContentUris.withAppendedId(uri, id)//给Uri加上id
long id = ContentUris.parseId(uri) //获取id
创建自己的内容提供器
public class MyProvider extends ContentProvider { @Override public boolean onCreate() { return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public String getType(Uri uri) { return null; }}
onCreate()
初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供其才会被初始化。query()
从内容提供器中查询数据。使用uri参数来确定查询哪张表, projection参数用于确定查询那些列, selection 和 selectionArgs 参数用于约束查询哪些行, sortOrder 参数用于对结果进行排序, 查询的结果存放在Cursor对象中返回。insert()
向内容提供器中添加一条数据。使用 uri 参数来确定要添加到的表, 待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URL。update()
更新内容提供器中已有的数据。使用 uri 参数来确定更新哪一张表中的数据,新数据保存在values 参数中, selection 和 selectionArgs 参数用于约束更新哪些行,受影响的行数将作为返回值返回。
5.delete()
从内容提供器中删除数据。 使用 uri 参数来确定删除哪一张表中的数据,selection 和 selectionArgs 参数用于约束删除那些行,别删除的行数将作为返回值返回。
- getType()
根据传入的内容URI来返回相应的MIME类型。
实例
创建DatabaseTest工程
MyDatabaseHelper.class
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table Book ("+ "id integer primary key autoincrement, "+ "author text, "+ "price real, "+ "pages integer, "+ "name text)"; private Context mContext; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } public MyDatabaseHelper(Context context, String name) { super(context, name, null,1); } @Override public void onCreate(SQLiteDatabase db) { //执行建表语句 db.execSQL(CREATE_BOOK); } //如果想要这个方法执行,就必须更新数据库的版本号 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //如果已经存在这个表则删除 db.execSQL("drop table if exists Book"); //重新创建 onCreate(db); }}
创建一个内容提供器
DatabaseProvider.class
public class DatabaseProvider extends ContentProvider { public static final int BOOK_DIR = 0; public static final int BOOK_ITEM = 1; public static final String AUTHORITY = "com.example.databasetest.provider"; private static UriMatcher uriMatcher; private MyDatabaseHelper dbHelper; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR); uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM); } @Override public boolean onCreate() { dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // 查询数据 SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = null; switch (uriMatcher.match(uri)) { case BOOK_DIR: cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder); break; case BOOK_ITEM: String bookId = uri.getPathSegments().get(1); cursor = db.query("Book", projection, "id = ?", new String[] { bookId }, null, null, sortOrder); break; default: break; } return cursor; } @Override public Uri insert(Uri uri, ContentValues values) { // 添加数据 SQLiteDatabase db = dbHelper.getWritableDatabase(); Uri uriReturn = null; switch (uriMatcher.match(uri)) { case BOOK_DIR: case BOOK_ITEM: long newBookId = db.insert("Book", null, values); uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId); break; default: break; } return uriReturn; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // 更新数据 SQLiteDatabase db = dbHelper.getWritableDatabase(); int updatedRows = 0; switch (uriMatcher.match(uri)) { case BOOK_DIR: updatedRows = db.update("Book", values, selection, selectionArgs); break; case BOOK_ITEM: String bookId = uri.getPathSegments().get(1); updatedRows = db.update("Book", values, "id = ?", new String[] { bookId }); break; default: break; } return updatedRows; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // 删除数据 SQLiteDatabase db = dbHelper.getWritableDatabase(); int deletedRows = 0; switch (uriMatcher.match(uri)) { case BOOK_DIR: deletedRows = db.delete("Book", selection, selectionArgs); break; case BOOK_ITEM: String bookId = uri.getPathSegments().get(1); deletedRows = db.delete("Book", "id = ?", new String[] { bookId }); break; default: break; } return deletedRows; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case BOOK_DIR: return "vnd.android.cursor.dir/vnd.com.example.databasetest. provider.book"; case BOOK_ITEM: return "vnd.android.cursor.item/vnd.com.example.databasetest. provider.book"; } return null; }
AndroidMainfest.xml
<provider android:name=".DatabaseProvider" android:authorities="com.example.databasetest.provider" android:enabled="true" android:exported="true"> </provider>
创建ProviderTest工程
activity_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="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/add_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add To Book"/> <Button android:id="@+id/query_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Query From Book"/> <Button android:id="@+id/update_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Update Book"/> <Button android:id="@+id/delete_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Delete From Book"/></LinearLayout>
MainActivity.class
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private String newId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button addData = (Button) findViewById(R.id.add_data); Button queryData = (Button) findViewById(R.id.query_data); Button updateData = (Button) findViewById(R.id.update_data); Button deleteData = (Button) findViewById(R.id.delete_data); addData.setOnClickListener(this); queryData.setOnClickListener(this); updateData.setOnClickListener(this); deleteData.setOnClickListener(this); } @Override public void onClick(View view) { Uri uri = null; ContentValues values = new ContentValues(); switch (view.getId()){ case R.id.add_data: // 添加数据 uri = Uri.parse("content://com.example.databasetest.provider/book"); values.clear(); values.put("name", "A Clash of Kings"); values.put("author", "George Martin"); values.put("pages", 1040); values.put("price", 60); Uri newUri = getContentResolver().insert(uri, values); newId = newUri.getPathSegments().get(1); break; case R.id.query_data: // 查询数据 uri = Uri.parse("content://com.example.databasetest.provider/book"); values.clear(); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { String name = cursor.getString(cursor. getColumnIndex("name")); String author = cursor.getString(cursor. getColumnIndex("author")); int pages = cursor.getInt(cursor.getColumnIndex ("pages")); double price = cursor.getDouble(cursor. getColumnIndex("price")); Log.d("MainActivity", "book name is " + name); Log.d("MainActivity", "book author is " + author); Log.d("MainActivity", "book pages is " + pages); Log.d("MainActivity", "book price is " + price); } cursor.close(); } break; case R.id.update_data: // 更新数据 uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId); values.clear(); values.put("name", "A Storm of Swords"); values.put("pages", 1216); values.put("price", 30); getContentResolver().update(uri, values, null, null); break; case R.id.delete_data: // 删除数据 uri = Uri.parse("content://com.example.databasetest.provider/book/" + newId); values.clear(); getContentResolver().delete(uri, null, null); break; default: break; } }}
- ContentProvider ---内容提供器
- ContentProvider内容提供器
- ContentProvider(内容提供器)
- ContentProvider 内容提供器
- Android 内容提供器 ContentProvider
- ContentProvider--------详解内容提供器
- 跨程序内容提供器ContentProvider
- 创建自己的内容提供器ContentProvider
- ContentProvider内容提供器学习笔记
- Android 组件ContentProvider(一)内容提供器
- [Android四大组件] ContentProvider 内容提供器
- Android内容提供器——ContentProvider
- 访问内容提供器(ContentProvider)提供的数据
- Android ContentProvider(内容提供器运用一)
- Android之内容提供器ContentProvider的简单表示
- Android之ContentProvider(一):内容提供器的用法
- Android 内容提供器---创建内容提供器(实现ContentProvider类)
- Android 内容提供器---创建内容提供器(实现ContentProvider的MIME类型)
- 会说话的PPT,从开发者角度十分钟理解区块链
- LeetCode算法问题4 —— Longest Palindromic Substring
- Android Studio导入第三方库
- 使用python利器selenium工具模拟浏览器运行并爬取淘宝商品信息
- 2017_9_9
- ContentProvider 内容提供器
- 最长公共子序列
- 1019. General Palindromic Number (20)
- 二分查找应用-旋转数组
- Rails 十日谈
- Hibernate笔记
- Kotlin 第九章:可见性修饰词
- 创建mysql数据库
- Servlet如何编写以及写Servlet注意事项