本文主要是介绍VCard联系人备份恢复(导入/导出)详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章摘自:http://www.cnblogs.com/lw900320/archive/2013/01/10/2855145.html
首先我们简单的看下在Android中联系人的存储结构.
工作环境:android 2.3.3
联系人的主要数据存放在raw_contacts和data表里,它两构成主从表关系。
raw_contacts表结构:
data表结构:
每个联系人在raw_contacts里有一条记录,像地址,名称,email,电话等等数据都在data存放在data里,这样设计的好处是易扩展,比如要增加一个联系人的email地址时,只要在data里增加一条记录。
下面说说我在开发工作中用到的一些联系人的数据。
名字:
Uri: Uri.parse("content://com.android.contacts/data")
PREFIX = "data4"; //名称前缀
MID_NAME = "data5";//中间名
GIVEN_NAME = "data2";//名字
FAMILY_NAME = "data3";//姓氏
MID_PINYIN="data8"; //中间名拼音
String FAMILY_NAME_PINYIN="data9"; //姓氏拼音
String SUFIX = "data6"; //名称后缀
String SUFIX_PINYIN="data7"; //名字拼音
电话:
Uri: Uri.parse("content://com.android.contacts/data/phones"
phone: "data1";//号码
Type: "data2";//这个字段是整形值,指示电话类型
类型对应关系如下:
TYPE_CUSTOM = 0;
TYPE_HOME = 1;
TYPE_MOBILE = 2;
TYPE_WORK = 3;
TYPE_FAX_WORK = 4;
TYPE_FAX_HOME = 5;
TYPE_PAGER = 6;
TYPE_OTHER = 7;
Email:
Uri:Uri.parse("content://com.android.contacts/data/emails")
Email: "data1";//邮箱地址
Type: "data2";//这个字段是整形值,指示Email类型
类型对应关系如下:
TYPE_CUSTOM = 0;
TYPE_HOME = 1;
TYPE_WORK = 2;
TYPE_OTHER = 3;
TYPE_MOBILE = 4;
地址:
Uri:Uri.parse("content://com.android.contacts/data/postals")
STREET="data4";//街道
CITY="data8";//城市
STATE="data7";//州
ZIP_CODE="data9";//邮政编码
Type:"data2";//type的类型如下
TYPE_CUSTOM = 0;
TYPE_HOME = 1;
TYPE_WORK = 2;
TYPE_OTHER = 3;
好的下面开始介绍VCard的导出和导入.
VCard规范 通俗点讲,就是让知道规范的人都能认识它.
在使用VCard时,我们需要下载VCard 的jar包
下载后里面会有2个Example {ReadExample.java / WriteExample.java} 。
但是凭借这两个Example,不足以让你更好的完成其他信息的备份和恢复,于是你要看下源码。
其中比较的2个类的源码如下.
最后附上导入导出的方法
1 package com.hh.assistant.app.vo; 2 3 import java.io.BufferedReader; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.io.InputStreamReader; 9 import java.io.OutputStreamWriter; 10 import java.io.UnsupportedEncodingException; 11 import java.util.ArrayList; 12 import java.util.List; 13 14 import a_vcard.android.provider.Contacts; 15 import a_vcard.android.syncml.pim.VDataBuilder; 16 import a_vcard.android.syncml.pim.VNode; 17 import a_vcard.android.syncml.pim.vcard.ContactStruct; 18 import a_vcard.android.syncml.pim.vcard.ContactStruct.ContactMethod; 19 import a_vcard.android.syncml.pim.vcard.ContactStruct.PhoneData; 20 import a_vcard.android.syncml.pim.vcard.VCardComposer; 21 import a_vcard.android.syncml.pim.vcard.VCardException; 22 import a_vcard.android.syncml.pim.vcard.VCardParser; 23 import android.app.Activity; 24 import android.content.ContentUris; 25 import android.content.ContentValues; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.os.Environment; 29 import android.provider.ContactsContract; 30 import android.provider.ContactsContract.CommonDataKinds.Email; 31 import android.provider.ContactsContract.CommonDataKinds.Phone; 32 import android.provider.ContactsContract.CommonDataKinds.StructuredName; 33 import android.provider.ContactsContract.RawContacts; 34 import android.provider.ContactsContract.RawContacts.Data; 35 import android.widget.Toast; 36 37 38 /** 39 * 联系人信息包装类 40 * 41 * @author LW 42 * 43 */ 44 public class ContactInfo { 45 46 /** MUST exist */ 47 private String name; // 姓名 48 49 /** 联系人电话信息 */ 50 public static class PhoneInfo{ 51 /** 联系电话类型 */ 52 public int type; 53 /** 联系电话 */ 54 public String number; 55 } 56 57 /** 联系人邮箱信息 */ 58 public static class EmailInfo{ 59 /** 邮箱类型 */ 60 public int type; 61 /** 邮箱 */ 62 public String email; 63 } 64 65 private List<PhoneInfo> phoneList = new ArrayList<PhoneInfo>(); // 联系号码 66 private List<EmailInfo> email = new ArrayList<EmailInfo>(); // Email 67 68 /** 69 * 构造联系人信息 70 * @param name 联系人姓名 71 */ 72 public ContactInfo(String name) { 73 this.name = name; 74 } 75 76 /** 姓名 */ 77 public String getName() { 78 return name; 79 } 80 /** 姓名 */ 81 public ContactInfo setName(String name) { 82 this.name = name; 83 return this; 84 } 85 /** 联系电话信息 */ 86 public List<PhoneInfo> getPhoneList() { 87 return phoneList; 88 } 89 /** 联系电话信息 */ 90 public ContactInfo setPhoneList(List<PhoneInfo> phoneList) { 91 this.phoneList = phoneList; 92 return this; 93 } 94 /** 邮箱信息 */ 95 public List<EmailInfo> getEmail() { 96 return email; 97 } 98 /** 邮箱信息 */ 99 public ContactInfo setEmail(List<EmailInfo> email) { 100 this.email = email; 101 return this; 102 } 103 104 @Override 105 public String toString() { 106 return "{name: "+name+", number: "+phoneList+", email: "+email+"}"; 107 } 108 109 /** 110 * 联系人 111 * 备份/还原操作 112 * @author LW 113 * 114 */ 115 public static class ContactHandler { 116 117 private static ContactHandler instance_ = new ContactHandler(); 118 119 /** 获取实例 */ 120 public static ContactHandler getInstance(){ 121 return instance_; 122 } 123 124 /** 125 * 获取联系人指定信息 126 * @param projection 指定要获取的列数组, 获取全部列则设置为null 127 * @return 128 * @throws Exception 129 */ 130 public Cursor queryContact(Activity context, String[] projection){ 131 // 获取联系人的所需信息 132 Cursor cur = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null); 133 return cur; 134 } 135 136 /** 137 * 获取联系人信息 138 * @param context 139 * @return 140 */ 141 public List<ContactInfo> getContactInfo(Activity context){ 142 List<ContactInfo> infoList = new ArrayList<ContactInfo>(); 143 144 Cursor cur = queryContact(context, null); 145 146 if(cur.moveToFirst()){ 147 do{ 148 149 // 获取联系人id号 150 String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID)); 151 // 获取联系人姓名 152 String displayName = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); 153 ContactInfo info = new ContactInfo(displayName);// 初始化联系人信息 154 155 // 查看联系人有多少电话号码, 如果没有返回0 156 int phoneCount = cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); 157 158 if(phoneCount>0){ 159 160 Cursor phonesCursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id , null, null); 161 162 if(phonesCursor.moveToFirst()) { 163 List<ContactInfo.PhoneInfo> phoneNumberList = new ArrayList<ContactInfo.PhoneInfo>(); 164 do{ 165 // 遍历所有电话号码 166 String phoneNumber = phonesCursor.getString(phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 167 // 对应的联系人类型 168 int type = phonesCursor.getInt(phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE)); 169 170 // 初始化联系人电话信息 171 ContactInfo.PhoneInfo phoneInfo = new ContactInfo.PhoneInfo(); 172 phoneInfo.type=type; 173 phoneInfo.number=phoneNumber; 174 175 phoneNumberList.add(phoneInfo); 176 }while(phonesCursor.moveToNext()); 177 // 设置联系人电话信息 178 info.setPhoneList(phoneNumberList); 179 } 180 } 181 182 // 获得联系人的EMAIL 183 Cursor emailCur = context.getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID+"="+id, null, null); 184 185 if(emailCur.moveToFirst()){ 186 List<ContactInfo.EmailInfo> emailList = new ArrayList<ContactInfo.EmailInfo>(); 187 do{ 188 // 遍历所有的email 189 String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA1)); 190 int type = emailCur.getInt(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE)); 191 192 // 初始化联系人邮箱信息 193 ContactInfo.EmailInfo emailInfo=new ContactInfo.EmailInfo(); 194 emailInfo.type=type; // 设置邮箱类型 195 emailInfo.email=email; // 设置邮箱地址 196 197 emailList.add(emailInfo); 198 }while(emailCur.moveToNext()); 199 200 info.setEmail(emailList); 201 } 202 203 //Cursor postalCursor = getContentResolver().query(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, null, ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + "=" + id, null, null); 204 infoList.add(info); 205 }while(cur.moveToNext()); 206 } 207 return infoList; 208 } 209 210 /** 211 * 备份联系人 212 */ 213 public void backupContacts(Activity context, List<ContactInfo> infos){ 214 215 try { 216 217 String path = Environment.getExternalStorageDirectory() + "/contacts.vcf"; 218 219 OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(path),"UTF-8"); 220 221 VCardComposer composer = new VCardComposer(); 222 223 for (ContactInfo info : infos) 224 { 225 ContactStruct contact = new ContactStruct(); 226 contact.name = info.getName(); 227 // 获取联系人电话信息, 添加至 ContactStruct 228 List<ContactInfo.PhoneInfo> numberList = info 229 .getPhoneList(); 230 for (ContactInfo.PhoneInfo phoneInfo : numberList) 231 { 232 contact.addPhone(phoneInfo.type, phoneInfo.number, 233 null, true); 234 } 235 // 获取联系人Email信息, 添加至 ContactStruct 236 List<ContactInfo.EmailInfo> emailList = info.getEmail(); 237 for (ContactInfo.EmailInfo emailInfo : emailList) 238 { 239 contact.addContactmethod(Contacts.KIND_EMAIL, 240 emailInfo.type, emailInfo.email, null, true); 241 } 242 String vcardString = composer.createVCard(contact, 243 VCardComposer.VERSION_VCARD30_INT); 244 writer.write(vcardString); 245 writer.write("\n"); 246 247 writer.flush(); 248 } 249 writer.close(); 250 251 } catch (UnsupportedEncodingException e) { 252 e.printStackTrace(); 253 } catch (FileNotFoundException e) { 254 e.printStackTrace(); 255 } catch (VCardException e) { 256 e.printStackTrace(); 257 } catch (IOException e) { 258 e.printStackTrace(); 259 } 260 261 Toast.makeText(context, "备份成功!", Toast.LENGTH_SHORT).show(); 262 } 263 264 265 /** 266 * 获取vCard文件中的联系人信息 267 * @return 268 */ 269 public List<ContactInfo> restoreContacts() throws Exception { 270 List<ContactInfo> contactInfoList = new ArrayList<ContactInfo>(); 271 272 VCardParser parse = new VCardParser(); 273 VDataBuilder builder = new VDataBuilder(); 274 String file = Environment.getExternalStorageDirectory() + "/contacts.vcf"; 275 276 BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); 277 278 String vcardString = ""; 279 String line; 280 while((line = reader.readLine()) != null) { 281 vcardString += line + "\n"; 282 } 283 reader.close(); 284 285 boolean parsed = parse.parse(vcardString, "UTF-8", builder); 286 287 if(!parsed){ 288 throw new VCardException("Could not parse vCard file: "+ file); 289 } 290 291 List<VNode> pimContacts = builder.vNodeList; 292 293 for (VNode contact : pimContacts) { 294 295 ContactStruct contactStruct=ContactStruct.constructContactFromVNode(contact, 1); 296 // 获取备份文件中的联系人电话信息 297 List<PhoneData> phoneDataList = contactStruct.phoneList; 298 List<ContactInfo.PhoneInfo> phoneInfoList = new ArrayList<ContactInfo.PhoneInfo>(); 299 for(PhoneData phoneData : phoneDataList){ 300 ContactInfo.PhoneInfo phoneInfo = new ContactInfo.PhoneInfo(); 301 phoneInfo.number=phoneData.data; 302 phoneInfo.type=phoneData.type; 303 phoneInfoList.add(phoneInfo); 304 } 305 306 // 获取备份文件中的联系人邮箱信息 307 List<ContactMethod> emailList = contactStruct.contactmethodList; 308 List<ContactInfo.EmailInfo> emailInfoList = new ArrayList<ContactInfo.EmailInfo>(); 309 // 存在 Email 信息 310 if (null!=emailList) 311 { 312 for (ContactMethod contactMethod : emailList) 313 { 314 if (Contacts.KIND_EMAIL == contactMethod.kind) 315 { 316 ContactInfo.EmailInfo emailInfo = new ContactInfo.EmailInfo(); 317 emailInfo.email = contactMethod.data; 318 emailInfo.type = contactMethod.type; 319 emailInfoList.add(emailInfo); 320 } 321 } 322 } 323 ContactInfo info = new ContactInfo(contactStruct.name).setPhoneList(phoneInfoList).setEmail(emailInfoList); 324 contactInfoList.add(info); 325 } 326 327 return contactInfoList; 328 } 329 330 331 /** 332 * 向手机中录入联系人信息 333 * @param info 要录入的联系人信息 334 */ 335 public void addContacts(Activity context, ContactInfo info){ 336 ContentValues values = new ContentValues(); 337 //首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId 338 Uri rawContactUri = context.getContentResolver().insert(RawContacts.CONTENT_URI, values); 339 long rawContactId = ContentUris.parseId(rawContactUri); 340 341 //往data表入姓名数据 342 values.clear(); 343 values.put(Data.RAW_CONTACT_ID, rawContactId); 344 values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); 345 values.put(StructuredName.GIVEN_NAME, info.getName()); 346 context.getContentResolver().insert( 347 android.provider.ContactsContract.Data.CONTENT_URI, values); 348 349 // 获取联系人电话信息 350 List<ContactInfo.PhoneInfo> phoneList = info.getPhoneList(); 351 /** 录入联系电话 */ 352 for (ContactInfo.PhoneInfo phoneInfo : phoneList) { 353 values.clear(); 354 values.put(android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId); 355 values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 356 // 设置录入联系人电话信息 357 values.put(Phone.NUMBER, phoneInfo.number); 358 values.put(Phone.TYPE, phoneInfo.type); 359 // 往data表入电话数据 360 context.getContentResolver().insert( 361 android.provider.ContactsContract.Data.CONTENT_URI, values); 362 } 363 364 // 获取联系人邮箱信息 365 List<ContactInfo.EmailInfo> emailList = info.getEmail(); 366 367 /** 录入联系人邮箱信息 */ 368 for (ContactInfo.EmailInfo email : emailList) { 369 values.clear(); 370 values.put(android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId); 371 values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 372 // 设置录入的邮箱信息 373 values.put(Email.DATA, email.email); 374 values.put(Email.TYPE, email.type); 375 // 往data表入Email数据 376 context.getContentResolver().insert( 377 android.provider.ContactsContract.Data.CONTENT_URI, values); 378 } 379 380 } 381 382 } 383 }
1 // 获取联系人处理实例 2 ContactInfo.ContactHandler handler=ContactInfo.ContactHandler.getInstance(); 3 4 switch (id) { 5 case R.id.save_linkman: 6 // 获取要备份的信息 7 List<ContactInfo> _infoList = handler.getContactInfo(this); 8 handler.backupContacts(this, _infoList); // 备份联系人信息 9 break; 10 11 case R.id.restore_linkman: // 恢复 12 try { 13 // 获取要恢复的联系人信息 14 List<ContactInfo> infoList = handler.restoreContacts(); 15 for (ContactInfo contactInfo : infoList) { 16 // 恢复联系人 17 handler.addContacts(this, contactInfo); 18 } 19 20 Toast.makeText(this, "导入联系人信息成功!", Toast.LENGTH_LONG); 21 22 } catch (Exception e) { 23 Toast.makeText(this, "导入联系人信息失败!", Toast.LENGTH_SHORT).show(); 24 e.printStackTrace(); 25 } 26 27 break; 28 }
这篇关于VCard联系人备份恢复(导入/导出)详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!