android开发数据操作(二)——ContentProvider操作实例

来源:互联网 发布:雀神麻将软件 编辑:程序博客网 时间:2024/05/22 06:28

本站文章欢迎转载,转载请标明出处 android开发交流群:69650580 
独学而无友,则孤陋而寡闻

上篇文章介绍了,为自己应用开发ContentProvider的基本流程,实际开发中很少应用希望自己的数据能被其它应用访问到,但是Android系统中内置绑定程序却有许多的程序容许其数据被其它应用访问并使用,我们可以打开文档的android.provider包中定义了许多关于日历、联系人、多媒体的类,这些都是系统开发的ContentProvider接口,如下图


下面通过一个联系人ContentProvider的操作,先看程序效果图:

   

实现功能:

1、  获得手机当前所有联系人

2、  获得当前通话记录

下面开始正式程序,首先是界面清单

main.xml 程序主界面 包括俩个按钮和一个ListView

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" ><LinearLayoutandroid:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal">            <Button    android:id="@+id/query"        android:layout_width="fill_parent"        android:layout_weight="1"        android:layout_height="wrap_content"        android:text="联系人" />    <Button        android:id="@+id/log"        android:layout_width="fill_parent"        android:layout_weight="1"        android:layout_height="wrap_content"        android:visibility="gone"        android:text=" 通话记录"/>    </LinearLayout><ListView    android:id="@+id/contacts"    android:layout_width="fill_parent"    android:layout_height="wrap_content"/></LinearLayout>

contacts.xml 联系人listview单项样式

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" ><LinearLayout    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >       <TextView        android:id="@+id/name"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/>    <TextView        android:id="@+id/phone"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content" /> </LinearLayout><LinearLayout    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >       <TextView        android:id="@+id/time"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/>    <TextView        android:id="@+id/duration"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content" />  </LinearLayout><LinearLayout    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >       <TextView        android:id="@+id/type"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/></LinearLayout></LinearLayout>

calllog.xml 通话记录中listview单项样式

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" ><LinearLayout    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >       <TextView        android:id="@+id/log_name"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/>    <TextView        android:id="@+id/log_phone"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content" /> </LinearLayout><LinearLayout    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >       <TextView        android:id="@+id/log_time"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/>    <TextView        android:id="@+id/log_duration"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content" />  </LinearLayout><LinearLayout    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >       <TextView        android:id="@+id/log_type"        android:layout_weight="1"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/></LinearLayout></LinearLayout>

根据ContentProvider的操作规律,关键点是获得要操作数据的URI地址,下面是联系人的操作地址:

联系人的Uri: ContactsContract.Contacts.CONTENT_URI

通话记录的URI:android.provider.CallLog.Calls.CONTENT_URI

下面是源文件清单:

ContentProviderExActivity.java 程序入口 及获取联系人列表

package com.freshstu;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.app.Activity;import android.content.ContentResolver;import android.database.Cursor;import android.os.Bundle;import android.provider.ContactsContract;import android.view.ContextMenu;import android.view.ContextMenu.ContextMenuInfo;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.AdapterView;import android.widget.Button;import android.widget.ListView;import android.widget.SimpleAdapter;import android.widget.Toast;import android.net.*;import android.content.*;public class ContentProviderExActivity extends Activity {/** Called when the activity is first created. */private Button queryBut = null;private Button logBut = null;private ListView listView = null;// 存放返会结果private Cursor result = null;// 存放显示数据private List<Map<String, Object>> list = null;// listView适配器private SimpleAdapter simple = null;private final static int CONTEXTMENU_DETAIL = Menu.FIRST;private final static int CONTEXTMENU_DELETE = Menu.FIRST + 1;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// 获取控件queryBut = (Button) findViewById(R.id.query);logBut = (Button) findViewById(R.id.log);listView = (ListView) findViewById(R.id.contacts);queryBut.setOnClickListener(new OnClickListener() {public void onClick(View arg0) {// TODO Auto-generated method stubresult = queryContacts();// 查询结果交给activity托管ContentProviderExActivity.this.startManagingCursor(result);list = new ArrayList<Map<String, Object>>();while (result.moveToNext()) {Map<String, Object> map = new HashMap<String, Object>();map.put("name", result.getString(result.getColumnIndex(ContactsContract.Contacts._ID)));/* * System.out.println(result.getString(result * .getColumnIndex * (ContactsContract.CommonDataKinds.Phone.NUMBER))); */map.put("phone",result.getString(result.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));System.out.println(result.getString(result.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));list.add(map);}System.out.println("list size:" + list.size());simple = new SimpleAdapter(ContentProviderExActivity.this,list, R.layout.contacts,new String[] { "name", "phone" }, new int[] {R.id.name, R.id.phone });System.out.println("simpleadpter set over:" + list.size());listView.setAdapter(simple);// 为控件绑定上下文菜单registerForContextMenu(listView);}});logBut.setVisibility(View.VISIBLE);logBut.setOnClickListener(new OnClickListener(){public void onClick(View v) {// TODO Auto-generated method stubIntent intent = new Intent(ContentProviderExActivity.this,CallLog.class);startActivity(intent);}});}private Cursor queryContacts() {// 获取客户端CR对象ContentResolver cr = super.getContentResolver();return cr.query(ContactsContract.Contacts.CONTENT_URI, null, null,null, null);}@Overridepublic boolean onContextItemSelected(MenuItem item) {// TODO Auto-generated method stub// 上下文菜单响应事件AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();// 这个位置就是map中的位置int position = menuInfo.position;String contactId = list.get(position).get("name").toString();switch (item.getItemId()) {case CONTEXTMENU_DETAIL:String phoneSelection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID+ "=?";String[] phoneSelectionArgs = new String[] { contactId };Cursor tempResult = super.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,phoneSelection, phoneSelectionArgs, null);StringBuffer buf = new StringBuffer();buf.append("号码为:");while (tempResult.moveToNext()) {buf.append(tempResult.getString(tempResult.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));}Toast.makeText(ContentProviderExActivity.this, buf,Toast.LENGTH_SHORT).show();break;case CONTEXTMENU_DELETE:int id = super.getContentResolver().delete(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,Long.parseLong(contactId)), null, null);list.remove(position);simple.notifyDataSetChanged();Toast.makeText(ContentProviderExActivity.this, "数据" + id + "已删除",Toast.LENGTH_SHORT).show();break;}return super.onContextItemSelected(item);}@Overridepublic void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {// TODO Auto-generated method stubsuper.onCreateContextMenu(menu, v, menuInfo);menu.setHeaderTitle("设置");menu.add(0, CONTEXTMENU_DETAIL, 0, "查询该联系人");menu.add(0, CONTEXTMENU_DELETE, 1, "删除该联系人");}}
CallLog.java 通话记录列表

package com.freshstu;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.app.Activity;import android.database.Cursor;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ListView;import android.widget.SimpleAdapter;import android.provider.*;public class CallLog extends Activity {private Button queryBut = null;private Button logBut = null;private ListView listView = null;private SimpleAdapter simple = null;private List<Map<String, Object>> list = null;private Cursor result = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.main);listView = (ListView) findViewById(R.id.contacts);queryBut = (Button) findViewById(R.id.query);logBut = (Button) findViewById(R.id.log);queryBut.setVisibility(View.GONE);logBut.setVisibility(View.VISIBLE);logBut.setOnClickListener(new OnClickListener() {public void onClick(View v) {// TODO Auto-generated method stub// 这里是查询函数result = queryCallLog();System.out.println("通话记录条数:" + result.getCount());list = new ArrayList<Map<String, Object>>();while (result.moveToNext()) {// 显示五个部分:姓名、通话起始时间、通话时间、通话类型、来电号码Map<String, Object> map = new HashMap<String, Object>();String tempName = result.getString(result.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME));if (tempName == null || "".equals(tempName)) {tempName = "号码不详";}map.put("name", tempName);map.put("time",result.getString(result.getColumnIndex(android.provider.CallLog.Calls.DATE)));map.put("phone",result.getString(result.getColumnIndex(android.provider.CallLog.Calls.NUMBER)));map.put("duration",result.getString(result.getColumnIndex(android.provider.CallLog.Calls.DURATION)));int tid = result.getInt(result.getColumnIndex(android.provider.CallLog.Calls.TYPE));String tempType =null;switch (tid) {case 1:tempType = "来电";break;case 2:tempType = "去电";break;case 3:tempType = "未接";break;}map.put("type",tempType);list.add(map);}System.out.println("list size:" + list.size());simple = new SimpleAdapter(CallLog.this, list,R.layout.calllog, new String[] { "name", "phone","time", "duration", "type" }, new int[] {R.id.log_name, R.id.log_phone, R.id.log_time,R.id.log_duration, R.id.log_type });listView.setAdapter(simple);}});}private Cursor queryCallLog() {// 获得客户端对象ContentResolver并进行查询操作return super.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI, null, null, null,android.provider.CallLog.Calls.DEFAULT_SORT_ORDER);}}

其中有一点,需要说明的query操作会返回一个Cursor,获取Cursor后需要将数据遍历到listView中去,除了传统的遍历方法以外还有一个专用的适配器SimpleCursorAdapter,通过该适配器可以一次性的将数据呈现出来,而不用手动写代码遍历将数据放到List集合中,不过这样操作有一个缺点就是无法截获数据对数据加工,比如上面通话记录中返回的通话类型是int值,分别代表3个不同状态,想要将这3个状态变得更友好,就必须对查询返回的数据进行加工,而SimpleCursorAdapter就无法进行这样的操作,其直接将数据转化为显示状态。所以如果你希望查询得到的数据能够符合你自己的要求,希望再加功就最好使用前者,相反使用后者可以生省不少力

package com.freshstu;import android.app.Activity;import android.database.Cursor;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.*;import android.widget.SimpleAdapter;public class CopyOfCallLog extends Activity {private Button queryBut = null;private Button logBut = null;private ListView listView = null;private ListAdapter listAdapter = null;private Cursor result = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.main);listView = (ListView) findViewById(R.id.contacts);queryBut = (Button) findViewById(R.id.query);logBut = (Button) findViewById(R.id.log);queryBut.setVisibility(View.GONE);logBut.setVisibility(View.VISIBLE);logBut.setOnClickListener(new OnClickListener() {public void onClick(View v) {// TODO Auto-generated method stub// 这里是查询函数result = queryCallLog();System.out.println("通话记录条数:" + result.getCount());listAdapter = new SimpleCursorAdapter(CopyOfCallLog.this,R.layout.calllog,result,new String[] {android.provider.CallLog.Calls.CACHED_NAME,android.provider.CallLog.Calls.NUMBER,android.provider.CallLog.Calls.DATE,android.provider.CallLog.Calls.DURATION,android.provider.CallLog.Calls.TYPE },new int[] { R.id.log_name, R.id.log_phone,R.id.log_time, R.id.log_duration, R.id.log_type });listView.setAdapter(listAdapter);}});}private Cursor queryCallLog() {// 获得客户端对象ContentResolver并进行查询操作return super.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI, null, null, null,android.provider.CallLog.Calls.DEFAULT_SORT_ORDER);}}

这里是使用后的效果图(注意红圈标注通话类型的显示)


结束语:

         Contentprovider的开发比较复杂,但是其使用却相对简单的多,只要能找到正确的数据位置(uri), 其它操作与操作SQLIte数据库基本一致。

代码下载:

http://115.com/file/c283izeb