获取联系人在Android开发中经常会遇到,最近项目需要用到获取手机联系人的功能,于是写了一个先查询联系人id然后再根据id查询手机号demo,结果慢到怀疑人生(亲测联系人数据1500+)。最后经过优化查询方式后,查询时间在200ms左右(亲测联系人数据1500+)在这里分享给大家,以方便自己好直接拿来用。国际惯例,注:以下测试只查询名字和手机号码
1、查询所有联系人
2、通过姓名获取联系人
3、通过手机号码查询联系人
最后附上源码:
在Android开发中,我经常会遇到需要获取手机通讯录联系人信息,Android手机的通讯录联系人全部都存在系统的数据库中,如果须要获得通讯里联系人的信息就须要访问系统的数据库,才能将信息获取出来。
下面直接贴出代码供大家参考:
程序文件java代码:
import javaioInputStream;
import javautilArrayList;
import androidappListActivity;
import androidcontentContentResolver;
import androidcontentContentUris;
import androidcontentContext;
import androidcontentIntent;
import androiddatabaseCursor;
import androidgraphicsBitmap;
import androidgraphicsBitmapFactory;
import androidnetUri;
import androidosBundle;
import androidproviderContactsContract;
import androidproviderContactsContractCommonDataKindsPhone;
import androidproviderContactsContractCommonDataKindsPhoto;
import androidtextTextUtils;
import androidviewLayoutInflater;
import androidviewView;
import androidviewViewGroup;
import androidwidgetAdapterView;
import androidwidgetBaseAdapter;
import androidwidgetImageView;
import androidwidgetListView;
import androidwidgetTextView;
import androidwidgetAdapterViewOnItemClickListener;
public class ContactsActivity extends ListActivity {
Context mContext = null;
/获取库Phon表字段/
private static final String[] PHONES_PROJECTION = new String[] {
PhoneDISPLAY_NAME, PhoneNUMBER, PhotoPHOTO_ID,PhoneCONTACT_ID };
/联系人显示名称/
private static final int PHONES_DISPLAY_NAME_INDEX = 0;
/电话号码/
private static final int PHONES_NUMBER_INDEX = 1;
/头像ID/
private static final int PHONES_PHOTO_ID_INDEX = 2;
/联系人的ID/
private static final int PHONES_CONTACT_ID_INDEX = 3;
/联系人名称/
private ArrayList<String> mContactsName = new ArrayList<String>();
/联系人头像/
private ArrayList<String> mContactsNumber = new ArrayList<String>();
/联系人头像/
private ArrayList<Bitmap> mContactsPhonto = new ArrayList<Bitmap>();
ListView mListView = null;
MyListAdapter myAdapter = null;
@Override
public void onCreate(Bundle savedInstanceState) {
mContext = this;
mListView = thisgetListView();
/得到手机通讯录联系人信息/
getPhoneContacts();
myAdapter = new MyListAdapter(this);
setListAdapter(myAdapter);
mListViewsetOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<> adapterView, View view,
int position, long id) {
//调用系统方法拨打电话
Intent dialIntent = new Intent(IntentACTION_CALL, Uri
parse("tel:" + mContactsNumberget(position)));
startActivity(dialIntent);
}
});
superonCreate(savedInstanceState);
}
/得到手机通讯录联系人信息/
private void getPhoneContacts() {
ContentResolver resolver = mContextgetContentResolver();
// 获取手机联系人
Cursor phoneCursor = resolverquery(PhoneCONTENT_URI,PHONES_PROJECTION, null, null, null);
if (phoneCursor != null) {
while (phoneCursormoveToNext()) {
//得到手机号码
String phoneNumber = phoneCursorgetString(PHONES_NUMBER_INDEX);
//当手机号码为空的或者为空字段 跳过当前循环
if (TextUtilsisEmpty(phoneNumber))
continue;
//得到联系人名称
String contactName = phoneCursorgetString(PHONES_DISPLAY_NAME_INDEX);
//得到联系人ID
Long contactid = phoneCursorgetLong(PHONES_CONTACT_ID_INDEX);
//得到联系人头像ID
Long photoid = phoneCursorgetLong(PHONES_PHOTO_ID_INDEX);
//得到联系人头像Bitamp
Bitmap contactPhoto = null;
//photoid 大于0 表示联系人有头像 如果没有给此人设置头像则给他一个默认的
if(photoid > 0 ) {
Uri uri =ContentUriswithAppendedId(ContactsContractContactsCONTENT_URI,contactid);
InputStream input = ContactsContractContactsopenContactPhotoInputStream(resolver, uri);
contactPhoto = BitmapFactorydecodeStream(input);
}else {
contactPhoto = BitmapFactorydecodeResource(getResources(), Rdrawablecontact_photo);
}
mContactsNameadd(contactName);
mContactsNumberadd(phoneNumber);
mContactsPhontoadd(contactPhoto);
}
phoneCursorclose();
}
}
/得到手机SIM卡联系人人信息/
private void getSIMContacts() {
ContentResolver resolver = mContextgetContentResolver();
// 获取Sims卡联系人
Uri uri = Uriparse("content://icc/adn");
Cursor phoneCursor = resolverquery(uri, PHONES_PROJECTION, null, null,
null);
if (phoneCursor != null) {
while (phoneCursormoveToNext()) {
// 得到手机号码
String phoneNumber = phoneCursorgetString(PHONES_NUMBER_INDEX);
// 当手机号码为空的或者为空字段 跳过当前循环
if (TextUtilsisEmpty(phoneNumber))
continue;
// 得到联系人名称
String contactName = phoneCursor
getString(PHONES_DISPLAY_NAME_INDEX);
//Sim卡中没有联系人头像
mContactsNameadd(contactName);
mContactsNumberadd(phoneNumber);
}
phoneCursorclose();
}
}
class MyListAdapter extends BaseAdapter {
public MyListAdapter(Context context) {
mContext = context;
}
public int getCount() {
//设置绘制数量
return mContactsNamesize();
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView iamge = null;
TextView title = null;
TextView text = null;
if (convertView == null) {
convertView = LayoutInflaterfrom(mContext)inflate(
Rlayoutcolorlist, null);
iamge = (ImageView) convertViewfindViewById(Ridcolor_image);
title = (TextView) convertViewfindViewById(Ridcolor_title);
text = (TextView) convertViewfindViewById(Ridcolor_text);
}
//绘制联系人名称
titlesetText(mContactsNameget(position));
//绘制联系人号码
textsetText(mContactsNumberget(position));
//绘制联系人头像
iamgesetImageBitmap(mContactsPhontoget(position));
return convertView;
}
}
}
实现如下广播,并且在AndroidManifest中进行注册
public class PhoneReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Systemoutprintln("action"+intentgetAction());
//如果是去电
if(intentgetAction()equals(IntentACTION_NEW_OUTGOING_CALL)){
String phoneNumber = intent
getStringExtra(IntentEXTRA_PHONE_NUMBER);
Logd(TAG, "call OUT:" + phoneNumber);
}else{
//查了下android文档,貌似没有专门用于接收来电的action,所以,非去电即来电
//如果我们想要监听电话的拨打状况,需要这么几步 :
第一:获取电话服务管理器TelephonyManager manager = thisgetSystemService(TELEPHONY_SERVICE);
第二:通过TelephonyManager注册我们要监听的电话状态改变事件。managerlisten(new MyPhoneStateListener(),
PhoneStateListenerLISTEN_CALL_STATE);这里的PhoneStateListenerLISTEN_CALL_STATE就是我们想要
监听的状态改变事件,初次之外,还有很多其他事件哦。
第三步:通过extends PhoneStateListener来定制自己的规则。将其对象传递给第二步作为参数。
第四步:这一步很重要,那就是给应用添加权限。androidpermissionREAD_PHONE_STATE
TelephonyManager tm = (TelephonyManager)contextgetSystemService(ServiceTELEPHONY_SERVICE);
tmlisten(listener, PhoneStateListenerLISTEN_CALL_STATE);
//设置一个监听器
}
}
PhoneStateListener listener=new PhoneStateListener(){
@Override
public void onCallStateChanged(int state, String incomingNumber) {
//注意,方法必须写在super方法后面,否则incomingNumber无法获取到值。
superonCallStateChanged(state, incomingNumber);
switch(state){
case TelephonyManagerCALL_STATE_IDLE:
Systemoutprintln("挂断");
break;
case TelephonyManagerCALL_STATE_OFFHOOK:
Systemoutprintln("接听");
break;
case TelephonyManagerCALL_STATE_RINGING:
Systemoutprintln("响铃:来电号码"+incomingNumber);
//输出来电号码
break;
}
}
限制访问电话号码
在未首先获得 READ_CALL_LOG 权限的情况下,除了应用的用例需要的其他权限之外,运行于 Android 9 上的应用无法读取电话号码或手机状态。
与来电和去电关联的电话号码可在手机状态广播(比如来电和去电的手机状态广播)中看到,并可通过 PhoneStateListener 类访问。 但是,如果没有 READ_CALL_LOG 权限,则 PHONE_STATE_CHANGED 广播和 PhoneStateListener 提供的电话号码字段为空。
要从手机状态中读取电话号码,请根据您的用例更新应用以请求必要的权限:
要通过 PHONE_STATE Intent *** 作读取电话号码,同时需要 READ_CALL_LOG 权限和 READ_PHONE_STATE 权限。
要从 onCallStateChanged() 中读取电话号码,只需要 READ_CALL_LOG 权限。 不需要 READ_PHONE_STATE 权限。
Android的官方文档是没有提供相应的Api的,因为标准的Andoird是没有双卡的,好像也只有国内才会搞双卡双待的神器吧。以下记录一下做这个功能所学习到的东西。直接上代码:
import javalangreflectInvocationTargetException;
import javalangreflectMethod;
import javautilList;
import androidappActivity;
import androidcontentContext;
import androidcontentSharedPreferences;
import androidcontentSharedPreferencesEditor;
import androidosBundle;
import androidpreferencePreferenceManager;
import androidtelephonyCellInfo;
import androidtelephonyTelephonyManager;
import androidviewMenu;
import androidwidgetTextView;
public class MainActivity extends Activity
{
private TextView tv;
private TextView tv2;
// ///////////////////////////////////
static String ISDOUBLE;
static String SIMCARD;
static String SIMCARD_1;
static String SIMCARD_2;
static boolean isDouble;
// //////////////////////////////////
@Override
protected void onCreate(Bundle savedInstanceState)
{
superonCreate(savedInstanceState);
setContentView(Rlayoutactivity_main);
tv = (TextView) findViewById(Ridtext);
tv2 = (TextView) findViewById(Ridtext2);
tv2setText("不知道哪个卡可用!");
getNumber();
}
private void getNumber()
{
TelephonyManager tm = (TelephonyManager) thisgetSystemService(thisTELEPHONY_SERVICE);
String phoneNumber1 = tmgetLine1Number();
// String phoneNumber2 = tmgetGroupIdLevel1();
initIsDoubleTelephone(this);
if (isDouble)
{
// tvsetText("这是双卡手机!");
tvsetText("本机号码是:" + " " + phoneNumber1 + " " + "这是双卡手机!");
} else
{
// tvsetText("这是单卡手机");
tvsetText("本机号码是:" + " " + phoneNumber1 + " " + "这是单卡手机");
}
}
public void initIsDoubleTelephone(Context context)
{
isDouble = true;
Method method = null;
Object result_0 = null;
Object result_1 = null;
TelephonyManager tm = (TelephonyManager) contextgetSystemService(ContextTELEPHONY_SERVICE);
try
{
// 只要在反射getSimStateGemini 这个函数时报了错就是单卡手机(这是我自己的经验,不一定全正确)
method = TelephonyManagerclassgetMethod("getSimStateGemini", new Class[]
{ intclass });
// 获取SIM卡1
result_0 = methodinvoke(tm, new Object[]
{ new Integer(0) });
// 获取SIM卡2
result_1 = methodinvoke(tm, new Object[]
{ new Integer(1) });
} catch (SecurityException e)
{
isDouble = false;
eprintStackTrace();
// Systemoutprintln("1_ISSINGLETELEPHONE:"+etoString());
} catch (NoSuchMethodException e)
{
isDouble = false;
eprintStackTrace();
// Systemoutprintln("2_ISSINGLETELEPHONE:"+etoString());
} catch (IllegalArgumentException e)
{
isDouble = false;
eprintStackTrace();
} catch (IllegalAccessException e)
{
isDouble = false;
eprintStackTrace();
} catch (InvocationTargetException e)
{
isDouble = false;
eprintStackTrace();
} catch (Exception e)
{
isDouble = false;
eprintStackTrace();
// Systemoutprintln("3_ISSINGLETELEPHONE:"+etoString());
}
SharedPreferences sp = PreferenceManagergetDefaultSharedPreferences(context);
Editor editor = spedit();
if (isDouble)
{
// 保存为双卡手机
editorputBoolean(ISDOUBLE, true);
// 保存双卡是否可用
// 如下判断哪个卡可用双卡都可以用
if (result_0toString()equals("5") && result_1toString()equals("5"))
{
if (!spgetString(SIMCARD, "2")equals("0") && !spgetString(SIMCARD, "2")equals("1"))
{
editorputString(SIMCARD, "0");
}
editorputBoolean(SIMCARD_1, true);
editorputBoolean(SIMCARD_2, true);
tv2setText("双卡可用");
} else if (!result_0toString()equals("5") && result_1toString()equals("5"))
{// 卡二可用
if (!spgetString(SIMCARD, "2")equals("0") && !spgetString(SIMCARD, "2")equals("1"))
{
editorputString(SIMCARD, "1");
}
editorputBoolean(SIMCARD_1, false);
editorputBoolean(SIMCARD_2, true);
tv2setText("卡二可用");
} else if (result_0toString()equals("5") && !result_1toString()equals("5"))
{// 卡一可用
if (!spgetString(SIMCARD, "2")equals("0") && !spgetString(SIMCARD, "2")equals("1"))
{
editorputString(SIMCARD, "0");
}
editorputBoolean(SIMCARD_1, true);
editorputBoolean(SIMCARD_2, false);
tv2setText("卡一可用");
} else
{// 两个卡都不可用(飞行模式会出现这种种情况)
editorputBoolean(SIMCARD_1, false);
editorputBoolean(SIMCARD_2, false);
tv2setText("飞行模式");
}
} else
{
// 保存为单卡手机
editorputString(SIMCARD, "0");
editorputBoolean(ISDOUBLE, false);
}
editorcommit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present
getMenuInflater()inflate(Rmenumain, menu);
return true;
}
}
不要忘记添加权限:<uses-permission android:name="androidpermissionREAD_PHONE_STATE" />
import cnteachcourseR;
/
Created by postmaster@teachcoursecn on 2016/5/5
/
public class PhoneNameActivity extends ActionBarActivity {
private static final String TAG = PhoneNameActivityclassgetSimpleName();
private EditText et;
public static void start(Context context) {
start(context, null);
}
public static void start(Context context, Intent extras) {
Intent intent = new Intent();
intentsetClass(context, PhoneNameActivityclass);
intentaddFlags(IntentFLAG_ACTIVITY_CLEAR_TOP
| IntentFLAG_ACTIVITY_SINGLE_TOP);
if (extras != null) {
intentputExtras(extras);
}
contextstartActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
superonCreate(savedInstanceState);
setContentView(Rlayoutactivity_phone_name);
et = (EditText) thisfindViewById(Ridmobile);
}
public void getTelClick(View view) {
String name = etgetText()toString()trim();
number(name);
}
/
通过输入获取电话号码
/
public void number(String name) {
//使用ContentResolver查找联系人数据
Cursor cursor = getContentResolver()query(ContactsContractContactsCONTENT_URI, null, null, null, null);
//遍历查询结果,找到所需号码
while (cursormoveToNext()) {
//获取联系人ID
String contactId = cursorgetString(cursorgetColumnIndex(ContactsContractContacts_ID));
//获取联系人的名字
String contactName = cursorgetString(cursorgetColumnIndex(ContactsContractCommonDataKindsPhoneDISPLAY_NAME));
if (nameequals(contactName)) {
//使用ContentResolver查找联系人的电话号码
Cursor phone = getContentResolver()query(ContactsContractCommonDataKindsPhoneCONTENT_URI, null, ContactsContractCommonDataKindsPhoneCONTACT_ID + " = " + contactId, null, null);
if (phonemoveToNext()) {
String phoneNumber = phonegetString(phonegetColumnIndex(ContactsContractCommonDataKindsPhoneNUMBER));
ToastmakeText(this, phoneNumber+"TeachCourse——blog。。。", ToastLENGTH_SHORT)show();
Logd(TAG, "电话:" + phoneNumber);
break;
}
}
}
}
}
1、修改getTelClick()方法
2、修改Toast面包屑提示
3、修改获取联系人名字方法
4、位置稍微调整
以上就是关于Android快速获取联系人全部的内容,包括:Android快速获取联系人、android开发怎样获取通讯录联系人信息、android开发怎么监控来电并监听等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)