ContentProvider
1. ContentProvider 简介
是Android四大组件之一,为存储和获取数据提供统一的接口.可以在不同的应用程序之间共享数据.对于
ContentProvider而言,无论数据的来源是什么,他都认为是中表,然后把数据组织成表格
Content Providers 管理访问结构化的数据集。它们可以封装这些数据,并且为定义
安全的数据提供机制。Content providers 是标准的接口,它能将一个线程中的数据
与其他线程中的运行的代码进行连接。也就是说 Content providers 支持跨应用间
的访问。
2. ContentProvider 的使用场景
当你想要在 Content provider[内容提供者] 中访问数据,你要在你的应用程序的
Context 中使用 ContentResolver[内容解析者] 对象与 provider 进行连接作为客
户端[通过 Cotext 中 getContentResolver()方法] 。这个 ContentResolver 会与
provider 对象进行连接,provider 它是一个继承 Content provider 的类的实例。
provide 这个对象会接受从客户端请求的数据,执行请求动作,返回结果。
如果你不打算将自己的数据分享给其他应用程序,就不必要开发自己的 内容提供者
[提供者], 然而你想要在你的应用程序中提供自定义的搜索建议你需要开发内容提供
者,如果你想要复制数据或者文件到其它应用程序,你就需要拥有自己的 provider 。
Android 自己提供了一个 content providers 来管理数据,如果 音频,视频,或
者个人信息等。你可以在 android.provider 包中查看,这些提供者可以给任何应用
程序所访问题
ContentProvider配置
1.继承ContentProvider类,实现要求的方法
package com.example.administrator.myapplication; 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.net.Uri; import android.util.Log; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import static android.content.ContentValues.TAG; public class MyContentProvider extends ContentProvider { private SQLiteDatabase db; private UriMatcher matcher; // Context context; public MyContentProvider() { // this.context = context; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Implement this to handle requests to delete one or more rows. return db.delete("info_stu", selection, selectionArgs); } @Override public String getType(Uri uri) { // TODO: Implement this to handle requests for the MIME type of the data // at the given URI. throw new UnsupportedOperationException("Not yet implemented"); } @Override public Uri insert(Uri uri, ContentValues values) { // TODO: Implement this to handle requests to insert a new row. long id = 0; if (values.size()>0){ id = db.insert("info_stu", null, values); }else { //获取主机名 String Authority = uri.getAuthority(); //获取路径名 String path = uri.getPath(); //获取整个参数 uri中 ? 后面的所有内容 String qury = uri.getQuery(); //分别获取对应的参数 String name = uri.getQueryParameter("name"); String age = uri.getQueryParameter("age"); String sex = uri.getQueryParameter("sex"); values.put("name",name); values.put("age",age); values.put("sex",sex); id = db.insert("info_stu",null,values); } //将id追加到uri return ContentUris.withAppendedId(uri, id); } //在ContentProvider创建时调用,数据初始化操作 @Override public boolean onCreate() { // TODO: Implement this to initialize your content provider on startup. SQLiteOpenHelper helper = new SQLiteOpenHelper(getContext(), "content.db", null, 2) { @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { String sql = "create table info_stu(_id integer primary key autoincrement, " + "name text,age integer,sex varchar(2))"; sqLiteDatabase.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }; db = helper.getReadableDatabase(); //URi解析 参数代表无法匹配 matcher = new UriMatcher(UriMatcher.NO_MATCH); //参数1 主机名(配置文件中) 参数2 路径 参数3 匹配码 matcher.addURI("com.hejun", "search", 9999); matcher.addURI("com.hejun","search/name",10010); /* //匹配该路径下任意数字的路径 matcher.addURI("com.hejun","search/name/#",10011); //匹配该路径下任意字符的路径 matcher.addURI("com.hejun","search/name/*",10012);*/ //记得返回true,才能被加载 return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.e(TAG, "query: "+"执行了" ); //解析匹配码 int code = matcher.match(uri); Cursor cursor; //升序 asc 降序 desc switch (code){ case 9999: Log.e(TAG, "insert: " + "9999"); cursor = db.query("info_stu", projection, selection, selectionArgs, null, null, sortOrder); break; case 10010: Log.e(TAG, "insert: " + "10010"); cursor = db.query("info_stu", projection, selection, selectionArgs, null, null, sortOrder); break; default: cursor = db.query("info_stu", null, null, null, null, null, null); break; } return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO: Implement this to handle requests to update one or more rows. return db.update("info_stu", values, selection, selectionArgs); } }
配置完成之后,不要忘记在manifests中进行注册
<provider android:name=".MyContentProvider" android:authorities="com.hejun" android:enabled="true" android:exported="true"></provider>
使用注册的contentprovider,对数据进行增删改查的基本操作
并对不同uri进行解析,对应不同操作
package com.example.content_provider; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.CursorAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.RadioGroup; import android.widget.SimpleCursorAdapter; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private ContentResolver contentResolver; EditText name,age,id; RadioGroup radioGroup; String sex = "男"; private ListView listView; private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); name = findViewById(R.id.et_name); age = findViewById(R.id.et_age); id = findViewById(R.id.et_id); listView = findViewById(R.id.listView); radioGroup = findViewById(R.id.rg_sex); radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { if (i == R.id.rb_woman){ sex = "女"; }else{ sex = "男"; } } }); //获取ContentResolver对象 contentResolver = this.getContentResolver(); } public void onButtonClick(View view) { Uri uri = Uri.parse("content://com.hejun"); Uri uriMatch = Uri.parse("content://com.hejun/search"); Uri uriMatch2 = Uri.parse("content://com.hejun/search/name"); String name1 = name.getText().toString(); String age1 = age.getText().toString(); String id1 = id.getText().toString(); switch (view.getId()){ case R.id.in_button: //参数1 URI 统一资源定位符 参数2 ContentValues ContentValues values = new ContentValues(); values.put("name",name1); values.put("age",age1); values.put("sex",sex); //该方法返回的Uri是insert方法中返回的uri,在通过ContentUris.parseId(uri)将id解析出来 // 就可以获得当前所添加数据的id Uri uri2 = contentResolver.insert(uri,values); Toast.makeText(this, "添加成功,新学生的学号:" + ContentUris.parseId(uri2),Toast.LENGTH_SHORT).show(); break; case R.id.sea_button: Cursor cursor = contentResolver.query(uri,null,null,null,null); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.listview_item,cursor, new String[]{"_id","name","age","sex"}, new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.sex_item}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); listView.setAdapter(adapter); break; case R.id.del_button: int i = contentResolver.delete(uri,"_id = ?",new String[]{id1}); if (i > 0){ Toast.makeText(this, "删除成功,删除了" + i + "条数据" ,Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "删除失败" ,Toast.LENGTH_SHORT).show(); } break; case R.id.upl_button: ContentValues values1 = new ContentValues(); values1.put("name",name1); values1.put("age",age1); values1.put("sex",sex); int i1 = contentResolver.update(uri,values1,"_id = ?",new String[]{id1}); if (i1 > 0){ Toast.makeText(this, "修改成功,修改了" + i1+ "条数据" ,Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "修改失败" ,Toast.LENGTH_SHORT).show(); } break; case R.id.search: Cursor cursor1 = contentResolver.query(uriMatch,null,"_id = ?",new String[]{id1},null); SimpleCursorAdapter adapter1 = new SimpleCursorAdapter(this,R.layout.listview_item,cursor1, new String[]{"_id","name","age","sex"}, new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.sex_item}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); Log.e(TAG, "onButtonClick: "+ adapter1.isEmpty()); listView.setAdapter(adapter1); break; case R.id.search2: Cursor cursor2 = contentResolver.query(uriMatch2,null,"name = ?",new String[]{name1},null); SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,R.layout.listview_item,cursor2, new String[]{"_id","name","age","sex"}, new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.sex_item}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); Log.e(TAG, "onButtonClick: "+ adapter2.isEmpty()); listView.setAdapter(adapter2); break; case R.id.uri_button: Uri uri1 = contentResolver.insert(Uri.parse("content://com.hejun?name=heyong&age=15&sex=男"),new ContentValues()); Toast.makeText(this, "添加成功,新学生的学号:" + ContentUris.parseId(uri1),Toast.LENGTH_SHORT).show(); break; } } }
通过contentprovider获取系统 短信和联系人
package com.example.content_provider_phone; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.SimpleAdapter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; public class MainActivity extends AppCompatActivity { private ListView listView; private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = findViewById(R.id.listView); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // getsms(); // getContact(); addContact(); } }); } //读取短信信息 public void getsms(){ /** * content://sms 全部短信息内容 * content://sms/sent 发件箱 * content://sms//inbox 收件箱 * content://sms/draft 草稿箱 * * 不同的路径会做出不同处理 */ Uri uri = Uri.parse("content://sms"); //查询所有短信息 Cursor cursor = getContentResolver().query(uri,null,null,null,"date desc"); List<String> list = new ArrayList<>(); //解析Cursor if (cursor!=null){ while (cursor.moveToNext()){ String address = cursor.getString(cursor.getColumnIndex("address"));//手机号码 String body = cursor.getString(cursor.getColumnIndex("body"));//信息内容 long data = cursor.getLong(cursor.getColumnIndex("date"));//日期 String type = cursor.getString(cursor.getColumnIndex("type"));//状态 1 接收 2 发送 3 草稿 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String date = simpleDateFormat.format(new Date(data)); list.add("手机号码:‘" + address + " " + "内容:" + body + " "+ "日期:" + date + " " + "状态:" + type + " "); } } Log.e(TAG, "getsms: " + list.size() ); ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this,R.layout.item,R.id.text1,list); listView.setAdapter(arrayAdapter); } //查询联系人 public void getContact(){ /** * 由于 联系人的 姓名 和 电话号码 存放在不同的表中 * 通过主键_id 进行关联 */ Uri uri = ContactsContract.Contacts.CONTENT_URI; Cursor cursor = getContentResolver().query(uri,null,null,null,null); List<String> list = new ArrayList<>(); if (cursor!=null){ while (cursor.moveToNext()){ String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "= ?"; Cursor cursor1 = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,selection,new String[]{id},null); if (cursor1!=null){ while (cursor1.moveToNext()){ String number = cursor1.getString(cursor1.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); list.add("联系人姓名:" + name + "电话号码:" + number); } } } } Log.e(TAG, "getContact: " + list.size() ); ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this,R.layout.item,R.id.text1,list); listView.setAdapter(arrayAdapter); } //添加联系人 public void addContact(){ /** * 先添加一个空联系人,获取对应的id */ ContentValues values = new ContentValues(); Uri uri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI,values); //通过ContentUris解析uri的id long id = ContentUris.parseId(uri); //插入姓名 //指定姓名列的内容 values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,"王家园"); //指定指定和姓名关联的编号列的内容 values.put(ContactsContract.Data.RAW_CONTACT_ID,id); //指定改行数据类型 values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); getContentResolver().insert(ContactsContract.Data.CONTENT_URI,values); //插入电话号码 //清空ContentValues对象 values.clear(); //指定电话号码列的内容 values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "15573401421198"); //指定和电话号码关联的编号列的内容 values.put(ContactsContract.Data.RAW_CONTACT_ID,id); //指定该行数据的类型 values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); //指定联系方式的类型 values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); getContentResolver().insert(ContactsContract.Data.CONTENT_URI,values); } }