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

本站文章欢迎转载,转载请标明出处 android开发交流群:69650580 
独学而无友,则孤陋而寡闻
上篇文章介绍了,为自己应用开发ContentProvider的基本流程,实际开发中很少应用希望自己的数据能被其它应用访问到,但是Android系统中内置绑定程序却有许多的程序容许其数据被其它应用访问并使用,我们可以打开文档的android.provider包中定义了许多关于日历、联系人、多媒体的类,这些都是系统开发的ContentProvider接口,如下图


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

   

实现功能:

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

2、  获得当前通话记录

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

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



	
        
    

contacts.xml 联系人listview单项样式



   
    
     

   
    
    
  

   
    



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



   
    
     

   
    
    
  

   
    


根据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> list = null;
	// listView适配器
	private SimpleAdapter simple = null;
	private final static int CONTEXTMENU_DETAIL = Menu.FIRST;
	private final static int CONTEXTMENU_DELETE = Menu.FIRST + 1;

	@Override
	public 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 stub
				result = queryContacts();
				// 查询结果交给activity托管
				ContentProviderExActivity.this.startManagingCursor(result);
				list = new ArrayList>();
				while (result.moveToNext()) {
					Map map = new HashMap();
					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 stub
				Intent 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);

	}

	@Override
	public 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);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		// TODO Auto-generated method stub
		super.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> list = null;
	private Cursor result = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.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>();
				while (result.moveToNext()) {
					// 显示五个部分:姓名、通话起始时间、通话时间、通话类型、来电号码
					Map map = new HashMap();
					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;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.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






你可能感兴趣的:(android系列)