内容提供器的用法一般有两种,一种是使用现有的内容来读取和操作相应程序中的数据,另一种是创建自己的内容提供器给我们程序的数据提供外部访问接口。首先,我们来学习第一种。
如果一个应用通过内容提供器对自己的数据提供了外部访问的接口,那么其他的应用程序都可以对这部分数据进行访问。Android系统自带的电话簿、短信、媒体库等程序都提供了类似的外部接口,这就使得第三方的应用程序可以充分的利用这部分数据来实现更好的功能。
1.ContentResolver的基本用法
对一个每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContextResolver类,可以通过Context类中的getContentResolver()方法来获取ContentResolver类的对象。ContentResolver类中提供了一些类似于数据库的操作。
不同于SQLiteDataBase,ContentResolver中的增删改查方法都不是接收表名的参数,而是使用一个Uri参数来代替,这个参数被称为内容URI。
内容URI给内容提供器中的数据提供了唯一的标识符,它主要有两部分组成:authority和path。authority是用于对不同的应用程序做区分的,一般为了冲突,都会采用应用程序的包名的方式来进行命名。比如某个程序的包名是com.example.demo,那么该程序对应的authority就可以命名为com.example.demo.provider。path则是用于对同一个应用程序中不同的表做区分的,通常会添加到authority的后面。比如某一个应用程序的数据中有两张表:table1、table2,这时就可以将path命名为/table1和/table2,然后再将authority和path进行组合,内容URI变成了com.example.demo.provider/table1和com.example.demo.provider/table2。不过目前还很难的辨认出这两个字符串就是两个内容URI,所以我们还需要在字符串的头部加上协议声明。因此,内容URI最标准的格式为:
content://com.example.demo.provider/table1
在得到了内容URI字符串之后,我们还需要将它解析成URI对象才可以作为参数传入。我们可以通过Uri中parse方法来进行解析
Uri uri = Uri.parse("content://com.example.demo.provider/table1");
(1).查询数据
现在我们就可以使用这个对象对table1表中的数据进行查询
Cursor cursor = getContentResolver().query(final Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)
1.uri,指定查询某一个程序下的某一张表
2.projection,指定查询的列名
3.selection,指定查询条件,相当于sql语句中where后面的条件
4.selectionArgs,给selection中的占位符提供具体的值
5.orderBy,指定查询结果排序方式
6.cancellationSignal,取消正在进行操作的信号量
(2).插入数据
ContentValues values = new ContentValues();
values.put();
getContentResolver.insert(uri,values);
(3).更新数据
ContentValues values = new ContentValues();
values.put();
getContentResolver.update(uri, values, "column1 = ? and column2 = ?", new String[]{"text", "1"});
注意上面使用了selection和selectionArgs参数来对想要更新的数据进行了约束,以防止所有的行都会影响。
(4).删除数据
getContentResolver().delete(uri, "column2 = ?", new String[]{"1"});
2.读取联系人
现在我们使用之前的知识来做一个小demo,来读取手机电话薄的联系人
1 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 2 private Button buttonCall = null; 3 private RecyclerView myRecyclerView = null; 4 private MyAdapter myAdapter = null; 5 private List<Bean> datas = null; 6 7 @Override 8 protected void onCreate(@Nullable Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_main); 11 initView(); 12 } 13 14 private void initView() { 15 buttonCall = (Button) findViewById(R.id.id_button_readContacts); 16 buttonCall.setOnClickListener(this); 17 myRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerView); 18 datas = new ArrayList<>(); 19 myAdapter = new MyAdapter(this, datas); 20 myRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); 21 myRecyclerView.setAdapter(myAdapter); 22 } 23 24 @Override 25 public void onClick(View v) { 26 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { 27 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1); 28 } 29 else 30 { 31 readContacts(); 32 } 33 } 34 35 @Override 36 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 37 if (requestCode == 1) { 38 if (permissions.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 39 readContacts(); 40 } else { 41 Toast.makeText(this, "权限不允许!", Toast.LENGTH_SHORT).show(); 42 } 43 } 44 } 45 46 private void readContacts() { 47 Cursor cursor = null; 48 try { 49 cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); 50 if(cursor != null) 51 { 52 while(cursor.moveToNext()) 53 { 54 String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 55 String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 56 Bean bean = new Bean(name, phoneNumber); 57 datas.add(bean); 58 } 59 } 60 Log.i("main", "size = " + datas.size()); 61 myAdapter.notifyDataSetChanged(); 62 } 63 catch(Exception e) 64 { 65 e.printStackTrace(); 66 }finally{ 67 if(cursor != null) 68 { 69 cursor.close(); 70 } 71 } 72 } 73 }
布局文件代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:gravity="center" 6 android:orientation="vertical"> 7 <android.support.v7.widget.RecyclerView 8 android:id="@+id/id_recyclerView" 9 android:layout_weight="10" 10 android:layout_width="match_parent" 11 android:layout_height="0dp"></android.support.v7.widget.RecyclerView> 12 <Button 13 android:layout_weight="1" 14 android:id="@+id/id_button_readContacts" 15 android:text="读取" 16 android:textSize="20sp" 17 android:layout_width="wrap_content" 18 android:layout_height="0dp" /> 19 </LinearLayout>
效果展示: