Android 系统内建的 ContentProvider
大多时候,我们使用 ContentProvider
并不是自己暴露自己的数据,而是通过 ContentResolver
来读取其它应用的信息,比如读取系统 APP,信息,联系人,多媒体信息
Android 系统内建的 ContentProvider
Android 系统提供了大量的内建 ContentProvider
,如果你想调用某个,就需要自己去查了
为什么我不一一列出?
是因为不同的版本,可能对应着不同的 URL,根本没法列
这里只提供如何获取 URL
与对应的数据库表的字段的方法
我们拿最常用的联系人为例
-
系统源码文件下:
all-src.rar -> TeleponeProvider -> AndroidManifest.xml
查找对应 API -
打开模拟器的
file exploer/data/data/com.android.providers.contacts/databases/contact2.db
-
导出后使用 SQLite 图形工具查看,三个核心的表:
raw_contact
表 ,data
表 ,mimetypes
表
从内建的 ContentProvider 中读取数据
我们写一个 demo
从常用的 ContentProvider
中读取数据
首先创建一个 空的 Android 项目 cn.twle.android.SystemProvider
简单的读取收件箱信息
-
修改
MainActivity.java
读取收件箱信息package cn.twle.android.systemprovider; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getMsgs(); } 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(); } }
-
然后修改
AndroidManifest.xml
加入读取收件箱的权限<uses-permission android:name="android.permission.READ_SMS"/>
运行后截图如下
往收件箱里插入一条信息
-
修改
MainActivity.java
往收件箱里插入一条信息package cn.twle.android.systemprovider; import android.content.ContentResolver; import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); insertMsg(); } private void insertMsg() { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://sms/"); ContentValues conValues = new ContentValues(); conValues.put("address", "123456789"); conValues.put("type", 1); conValues.put("date", System.currentTimeMillis()); conValues.put("body", "简单教程,简单编程"); resolver.insert(uri, conValues); Toast.makeText(MainActivity.this,"短信插入完毕~",Toast.LENGTH_LONG).show(); } }
-
然后修改
AndroidManifest.xml
加入写入收件箱的权限<uses-permission android:name="android.permission.WRITE_SMS" />
运行效果图如下
注意:
在 Android 4.4 以下都可以实现写入短信的功能,而 5.0上 有可能无法写入
从 5.0 开始,默认短信应用外的软件不能以写入短信数据库的形式发短信
读取手机联系人
-
修改
MainActivity.java
读取手机联系人package cn.twle.android.systemprovider; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getContacts(); } private void getContacts(){ // 1. 查询 raw_contacts 表获得联系人的 id ContentResolver resolver = getContentResolver(); Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; //查询联系人数据 Cursor cursor = resolver.query(uri, null, null, null, null); while(cursor.moveToNext()) { //获取联系人姓名,手机号码 String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); System.out.println("姓名:" + cName + " 号码:" + cNum); } cursor.close(); } }
-
然后修改
AndroidManifest.xml
加入读联系人的权限<uses-permission android:name="android.permission.READ_CONTACTS"/>
运行后截图如下
不用怀疑,我的确只有一个中国移动的联系人...
查询指定电话的联系人信息
-
修改
MainActivity.java
查询指定电话的联系人信息package cn.twle.android.systemprovider; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 你需要修改要查询的电话号码,因为你那里不一定保留了 中国移动 queryContact("10086"); } private void queryContact(String number){ Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number); ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null); if (cursor.moveToFirst()) { String name = cursor.getString(0); System.out.println(number + " 对应的联系人名称 :" + name); } cursor.close(); } }
-
然后修改
AndroidManifest.xml
加入读联系人的权限<uses-permission android:name="android.permission.READ_CONTACTS"/>
运行后截图如下
添加一个新的联系人
-
修改
activity_main.xml
添加一个按钮<?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" > <Button android:text="添加联系人" android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
-
修改
MainActivity.java
添加一个新的联系人package cn.twle.android.systemprovider; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.OperationApplicationException; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; import android.widget.Button; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_add = findViewById(R.id.btn_add); btn_add.setOnClickListener(new View.OnClickListener(){ @Override public void onClick( View view ) { try { AddContact(); } catch (Exception e){} } }); } private void AddContact() throws RemoteException, OperationApplicationException { //使用事务添加联系人 Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); Uri dataUri = Uri.parse("content://com.android.contacts/data"); ContentResolver resolver = getContentResolver(); ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri) .withValue("account_name", null) .build(); operations.add(op1); //依次是姓名,号码,邮编 ContentProviderOperation op2 = ContentProviderOperation.newInsert(dataUri) .withValueBackReference("raw_contact_id", 0) .withValue("mimetype", "vnd.android.cursor.item/name") .withValue("data2", "中国联通") .build(); operations.add(op2); ContentProviderOperation op3 = ContentProviderOperation.newInsert(dataUri) .withValueBackReference("raw_contact_id", 0) .withValue("mimetype", "vnd.android.cursor.item/phone_v2") .withValue("data1", "100010") .withValue("data2", "2") .build(); operations.add(op3); ContentProviderOperation op4 = ContentProviderOperation.newInsert(dataUri) .withValueBackReference("raw_contact_id", 0) .withValue("mimetype", "vnd.android.cursor.item/email_v2") .withValue("data1", "kf@10010.com") .withValue("data2", "2") .build(); operations.add(op4); //将上述内容添加到手机联系人中~ resolver.applyBatch("com.android.contacts", operations); Toast.makeText(getApplicationContext(), "添加成功", Toast.LENGTH_SHORT).show(); } }
-
修改
AndroidManifest.xml
加入读写联系人信息权限<uses-permission android:name="android.permission.WRITE_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_PROFILE"/>
运行效果如下