安卓基础总结 内容提供者
2015-04-13 00:26
357 查看
1.使用内容提供者读写短信信息
(1)将短信内容读出并写入XML文件
API
ContentResolver contentResolver = getContentResolver(); //getContentResolver();是上下文中携带的方法,用于处理内容提供者提供的访问方式。
寻找哪个内容提供者需要用通过uri,uri路径分文 "主机名"+"具体要操作的数据" 其中"主机名"在提供数据库程序的清单文件中定义,"具体要操作的数据"在这个程序的源码中(一般文件名有provide字样), 我们可以通过查找"UriMatcher"函数搜索相关的信息。
读取短信例程
提供权限 读写短信 操作SD卡: <uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.WRITE_SMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v) { ContentResolver contentResolver = getContentResolver(); //通过查找TelephonyProvider程序的清单文件和源码可知,主机名为"sms" 后面为空则对应SMS_ALL Uri uri = Uri.parse("content://sms/"); //使用ContentResolver提供的查询方法,查找短信相关信息 Cursor cursor = contentResolver.query(uri, new String[]{"address", "body"}, null, null, null); //将cursor指向的内容封装到xml文件中 OutputStream os; try { os = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/msmInfo.xml"); XmlSerializer serializer = Xml.newSerializer(); serializer.setOutput(os, "utf-8"); serializer.startDocument("utf-8", true); serializer.startTag(null, "info"); while(cursor.moveToNext()) { serializer.startTag(null, "sms"); serializer.startTag(null, "address"); String address = cursor.getString(0); serializer.text(address); serializer.endTag(null, "address"); serializer.startTag(null, "body"); String body = cursor.getString(1); serializer.text(body); serializer.endTag(null, "body"); serializer.endTag(null, "sms"); } serializer.endTag(null, "info"); serializer.endDocument(); } catch (Exception e) { e.printStackTrace(); } } }
(2)将自定义信息写入短信程序下的数据库中
写入短信例程
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v) { ContentResolver contentResolver = getContentResolver(); Uri uri = Uri.parse("content://sms/"); //写入列名及其对应的值 ContentValues values = new ContentValues(); values.put("address", "110"); values.put("body", "hello chenchen"); contentResolver.insert(uri, values); } }
2.使用内容提供者读写联系人信息
背景知识
1.data表中存储联系人的所有信息 2.通过mimetype 来区分信息对应的类型 3.通过raw_contact_id(即联系人的id)来区分不同信息对应的联系人
1.读取联系人信息模板 例程
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v) { ContentResolver contentResolver = getContentResolver(); //用于处理raw_contacts表格的uri Uri uri_raw = Uri.parse("content://com.android.contacts/raw_contacts"); //用于处理data表格的uri Uri uri_data = Uri.parse("content://com.android.contacts/data"); //查出raw_contacts表格中所有id号,也就是用户id Cursor cursor = contentResolver.query(uri_raw, new String[]{"contact_id"}, null, null, null); while(cursor.moveToNext()) { //获得一个contact_id号 String contact_id = cursor.getString(0); System.out.println(" contact_id:"+contact_id); //查找data1表中所有contact_id为当前id的内容 ************注意此处为"mimetype"而不是直接写表中的"mimetype_id",此处是一个视图 Cursor cursor_data1 = contentResolver.query(uri_data, new String[]{"mimetype", "data1"}, "raw_contact_id=?", new String[]{contact_id}, null); while(cursor_data1.moveToNext()) { //查出当前行的mime类型,从而确定当前data1列的数据的类型 String mimetype = cursor_data1.getString(0); System.out.println("*************mimetype*"+mimetype+"*****************"); String data = cursor_data1.getString(1); System.out.println("*************data1*"+data+"*****************"); if("vnd.android.cursor.item/name".equals(mimetype)){ System.out.println("******name:"+data+"********"); }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){ System.out.println("******phone:"+data+"********"); }else if("vnd.android.cursor.item/email_v2".equals(mimetype)){ System.out.println("******email:"+data+"********"); } } } } }
将上述代码封装成一个工具类,用于获取联系人信息
public class ReadContactUtils { /** * 获取本机通讯录信息,返回通讯录中每个条目的List * @param context 传入上下文,用于获取ContentResolver内容解析者 * @return */ public static List<Contact> getContacts(Context context) { List<Contact> list = new ArrayList<Contact>(); Contact contact=null; ContentResolver contentResolver = context.getContentResolver(); Uri uri_raw = Uri.parse("content://com.android.contacts/raw_contacts"); Uri uri_data1 = Uri.parse("content://com.android.contacts/data"); Cursor cursor = contentResolver.query(uri_raw, new String[]{"contact_id"}, null, null, null);//由于要返回所有的条目,所以不需要写后面的参数 while(cursor.moveToNext()) { //从raw_contact_id表中获取contact_id String contact_id = cursor.getString(0); //System.out.println("*******"+contact_id+"********"); if(contact_id != null) { contact = new Contact(); //使用contact_id查出data表中对应的所有对应项 ,这些对应项就是一个联系人的所有信息 Cursor cursor_data1 = contentResolver.query(uri_data1, new String[]{"mimetype", "data1"}, "raw_contact_id=?" ,new String[]{contact_id}, null); while(cursor_data1.moveToNext()) { //获取表的数据的类型 String mimetype = cursor_data1.getString(0); String data1 = cursor_data1.getString(1); //System.out.println("****mimetype*"+mimetype+"******data1*"+data1+"****"); //根据不同类型找到data1相应的位置 if("vnd.android.cursor.item/name".equals(mimetype)){ contact.setName(data1); }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){ contact.setPhone(data1); }else if("vnd.android.cursor.item/email_v2".equals(mimetype)){ contact.setEmail(data1); } } } list.add(contact); } return list; } }
2.写入联系人信息 例程
注意应当先在raw_contact_id表中加入新的contact_id,然后再添加data2中的各项信息。否则data2中不能插入信息。 public void click(View v) { String name = et_name.getText().toString().trim(); String email = et_email.getText().toString().trim(); String phone = et_phone.getText().toString().trim(); ContentResolver contentResolver = getContentResolver(); Uri uri_raw = Uri.parse("content://com.android.contacts/raw_contacts"); Uri uri_data1 = Uri.parse("content://com.android.contacts/data"); //看看raw_contact_id中的contact_id到第几条了 Cursor cursor = contentResolver.query(uri_raw, null, null, null, null); int count = cursor.getCount(); int id = count+1; //在raw_contact_id表中加入新信息的contact_id ContentValues idValues = new ContentValues(); idValues.put("contact_id", id); contentResolver.insert(uri_raw, idValues); //分别加入信息中的每个行 ContentValues contentValues = new ContentValues(); contentValues.put("raw_contact_id", id); contentValues.put("mimetype", "vnd.android.cursor.item/name"); contentValues.put("data1", name); contentResolver.insert(uri_data1, contentValues); contentValues.put("raw_contact_id", id); contentValues.put("mimetype", "vnd.android.cursor.item/phone_v2"); contentValues.put("data1", phone); contentResolver.insert(uri_data1, contentValues); contentValues.put("raw_contact_id", id); contentValues.put("mimetype", "vnd.android.cursor.item/email_v2"); contentValues.put("data1", email); contentResolver.insert(uri_data1, contentValues); }
3.内容观察者ContentObserver
public class MainActivity extends Activity { private Uri uri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); uri = Uri.parse("content://sms"); //第二个参数的解释 为true可以是不精确的路径 为false必须是精确路径 //notifyForDescendents If true changes to URIs beginning with uri will also cause //notifications to be sent. If false only changes to the exact URI specified by uri //will cause notifications to be sent. If true, than any URI values at or below the //specified URI will also trigger a match. getContentResolver().registerContentObserver(uri, true, new MyObeserver(new Handler())); } class MyObeserver extends ContentObserver { public MyObeserver(Handler handler) { super(handler); } //发现监视路径下的数据库发生变化就会调用此方法 @Override public void onChange(boolean selfChange) { //把短信的address 和 body内容取出来 Cursor cursor = getContentResolver().query(uri, new String[]{"address","body"}, null, null, "date desc"); cursor.moveToFirst(); String address = cursor.getString(0); String body = cursor.getString(1); System.out.println("body:"+body+"address:"+address); super.onChange(selfChange); } } }
4.内容提供者的原理简析
前几个条目主要说了我们如何获取其他数据的数据库信息,使用的是内容解析者提供的方法来对其他程序的数据库进行操作。下面我们看一下数据库提供方程序是如何工作的。
1.同四大组件中其他的三个一样,也是继承一个类(ContentProvider),并为这个类在清单文件中配置一下。我们需要实现其中的增删改查方法。
public class MyContentProvider extends ContentProvider { @Override public boolean onCreate() { } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { } } 清单文件 name : 内容提供者的路径 authorities : 内容提供者的主机名 <provider android:name="com.example.readprivatedata.MyContentProvider" android:authorities="com.example.myprovider"> </provider> 2.有了增删改查的方法,但是我们去操作哪站表,或者哪张表中的哪些数据呢?者就需要我们配置另外一个参数,用于找到对应的数据。我们使用**UriMatcher**类进行操作。 private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //参数分别为 主机名 要操作的数据的标识 该标识对应的数字 matcher.addURI("com.example.myprovider", "info", INFO); 当我们进行增删改查操作时,从完整uri,通过match方法获取code码,每个code码对应操作不同的数据 int code = matcher.match(uri);获取当前uri对应的code码
例程
内容提供者
public class MyContentProvider extends ContentProvider { //用于匹配调用哪个函数 private static final int INFO = 1; private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private MyOpenHelper helper; static{ //可以为matcher添加多个uri,用于操作不同的数据 matcher.addURI("com.example.myprovider", "info", INFO); } @Override public boolean onCreate() { //创建这个Provider时创建数据库,后面有这个类的源码 其中包含一张名为"info"的表格 helper = new MyOpenHelper(getContext()); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //获取code码 int code = matcher.match(uri); System.out.println("query******code:"+code+"*******"); //当code码和我们为某个数据预定义的code一样时,就进行对应的操作 if(code == INFO) { System.out.println("*******query********"); SQLiteDatabase db = helper.getReadableDatabase(); Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder); return cursor; }else { throw new IllegalArgumentException("query路径不匹配 请检查"); } } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { int code = matcher.match(uri); System.out.println("insert******code:"+code+"*******"); if(code == INFO) { System.out.println("*******insert********"); //匹配成功 SQLiteDatabase db = helper.getReadableDatabase(); //代表插入到了多少行 long insert = db.insert("info", null, values); return Uri.parse("com.itheima.account.provider"+insert); }else { throw new IllegalArgumentException("insert路径不匹配 请检查"); } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int code = matcher.match(uri); System.out.println("delete******code:"+code+"*******"); if(code == INFO) { System.out.println("*******delete********"); SQLiteDatabase db = helper.getReadableDatabase(); int delete = db.delete("info", selection, selectionArgs); //删除了多少行 return delete; }else { throw new IllegalArgumentException("3路径不匹配 请检查"); } } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int code = matcher.match(uri); System.out.println(" update******code:"+code+"*******"); if(code == INFO) { System.out.println("*******update********"); SQLiteDatabase db = helper.getReadableDatabase(); int update = db.update("info", values, selection, selectionArgs); //删除了多少行 return update; }else { throw new IllegalArgumentException("4路径不匹配 请检查"); } } } 创建数据库的类 public class MyOpenHelper extends SQLiteOpenHelper { public MyOpenHelper(Context context) { super(context, "account.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),money varchar(20))"); //初始化2条数据 db.execSQL("insert into info ('name','money') values ('张三','2000')"); db.execSQL("insert into info ('name','money') values ('李四','5000')"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { System.out.println("onUpgrade"); } }
内容解析者
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click_insert(View v) { ContentValues contentValues = new ContentValues(); contentValues.put("name", "haha"); contentValues.put("money", 10000); //注意,uri决定了要操作的表,内容提供者在调用insert方法时,根据uri对应的code只找到相应的分支,这个分支对应的操作是操作info指定的数据 getContentResolver().insert(Uri.parse("content://com.example.myprovider/info"), contentValues); } public void click_delete(View v) { getContentResolver().delete(Uri.parse("content://com.example.myprovider/info"), "name=?", new String[]{"haha"}); } public void click_update(View v) { } public void click_find(View v) { } }
相关文章推荐
- Android基础总结.doc(第三节、 ListView和内容提供者)
- 安卓:内容提供者(基础知识)
- 安卓航班Android开发经典教程大总结1----基础编程及源码推送
- android基础之内容提供者创建
- Android核心基础-5.Android 数据存储与访问-4.ContentProvider 内容提供者
- 安卓基础学习错误总结
- Android核心基础-5.Android 数据存储与访问-4.ContentProvider 内容提供者-示例(操作联系人)
- C#基础语法---运算符(6.25晚上学内容总结)
- 安卓基础总结 httpClient上传下载
- 协议protocol和代理模式基础内容总结和举例
- 安卓基础知识总结
- 安卓基础——adb相关内容
- android基础之内容提供者使用
- 安卓四大组件----内容提供者
- 【Android基础】内容提供者ContentProvider的使用详解
- Android之内容提供者ContentProvider的总结
- 安卓航班Android开发经典教程大总结1----基础编程及源码推送
- 安卓基础总结 网络基础 Connector post get
- 基础学习总结(六)--getContentRolver()的应用、内容监听者ContentObserver
- 安卓基础知识总结