Android VCard联系人备份恢复(导入/导出)详解

首先我们简单的看下在Android中联系人的存储结构.

工作环境:android 2.3.3
联系人的主要数据存放在raw_contacts和data表里,它两构成主从表关系。

raw_contacts表结构:

Android VCard联系人备份恢复(导入/导出)详解

data表结构:
Android VCard联系人备份恢复(导入/导出)详解
每个联系人在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个类的源码如下.

Android VCard联系人备份恢复(导入/导出)详解 View Code
  1 /*

  2  * Copyright (C) 2007 The Android Open Source Project

  3  *

  4  * Licensed under the Apache License, Version 2.0 (the "License");

  5  * you may not use this file except in compliance with the License.

  6  * You may obtain a copy of the License at

  7  *

  8  *      http://www.apache.org/licenses/LICENSE-2.0

  9  *

 10  * Unless required by applicable law or agreed to in writing, software

 11  * distributed under the License is distributed on an "AS IS" BASIS,

 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 13  * See the License for the specific language governing permissions and

 14  * limitations under the License.

 15  */

 16 

 17 package a_vcard.android.syncml.pim.vcard;

 18 

 19 //import android.content.AbstractSyncableContentProvider;

 20 //import android.content.ContentResolver;

 21 //import android.content.ContentUris;

 22 //import android.content.ContentValues;

 23 //import android.net.Uri;

 24 import a_vcard.android.provider.Contacts;

 25 import a_vcard.android.provider.Contacts.ContactMethods;

 26 //import android.provider.Contacts.Extensions;

 27 //import android.provider.Contacts.GroupMembership;

 28 //import android.provider.Contacts.Organizations;

 29 //import android.provider.Contacts.People;

 30 import a_vcard.android.provider.Contacts.Phones;

 31 //import android.provider.Contacts.Photos;

 32 import a_vcard.android.syncml.pim.PropertyNode;

 33 import a_vcard.android.syncml.pim.VNode;

 34 import a_vcard.android.telephony.PhoneNumberUtils;

 35 import a_vcard.android.text.TextUtils;

 36 import a_vcard.android.util.Log;

 37 

 38 import java.util.ArrayList;

 39 import java.util.HashMap;

 40 import java.util.Iterator;

 41 import java.util.List;

 42 import java.util.Locale;

 43 import java.util.Map;

 44 import java.util.Map.Entry;

 45 

 46 /**

 47  * The parameter class of VCardComposer.

 48  * This class standy by the person-contact in

 49  * Android system, we must use this class instance as parameter to transmit to

 50  * VCardComposer so that create vCard string.

 51  */

 52 // TODO: rename the class name, next step

 53 public class ContactStruct {

 54     private static final String LOG_TAG = "ContactStruct";

 55     

 56     // Note: phonetic name probably should be "LAST FIRST MIDDLE" for European languages, and

 57     //       space should be added between each element while it should not be in Japanese.

 58     //       But unfortunately, we currently do not have the data and are not sure whether we should

 59     //       support European version of name ordering.

 60     //

 61     // TODO: Implement the logic described above if we really need European version of

 62     //        phonetic name handling. Also, adding the appropriate test case of vCard would be

 63     //        highly appreciated.

 64     public static final int NAME_ORDER_TYPE_ENGLISH = 0;

 65     public static final int NAME_ORDER_TYPE_JAPANESE = 1;

 66 

 67     /** MUST exist */

 68     public String name;

 69     public String phoneticName;

 70     /** maybe folding */

 71     public List<String> notes = new ArrayList<String>();

 72     /** maybe folding */

 73     public String title;

 74     /** binary bytes of pic. */

 75     public byte[] photoBytes;

 76     /** The type of Photo (e.g. JPEG, BMP, etc.) */

 77     public String photoType;

 78     /** Only for GET. Use addPhoneList() to PUT. */

 79     public List<PhoneData> phoneList;

 80     /** Only for GET. Use addContactmethodList() to PUT. */

 81     public List<ContactMethod> contactmethodList;

 82     /** Only for GET. Use addOrgList() to PUT. */

 83     public List<OrganizationData> organizationList;

 84     /** Only for GET. Use addExtension() to PUT */

 85     public Map<String, List<String>> extensionMap;

 86 

 87     // Use organizationList instead when handling ORG.

 88     @Deprecated

 89     public String company;

 90     

 91     public static class PhoneData {

 92         public int type;

 93         /** maybe folding */

 94         public String data;

 95         public String label;

 96         public boolean isPrimary; 

 97     }

 98 

 99     public static class ContactMethod {

100         // Contacts.KIND_EMAIL, Contacts.KIND_POSTAL

101         public int kind;

102         // e.g. Contacts.ContactMethods.TYPE_HOME, Contacts.PhoneColumns.TYPE_HOME

103         // If type == Contacts.PhoneColumns.TYPE_CUSTOM, label is used.

104         public int type;

105         public String data;

106         // Used only when TYPE is TYPE_CUSTOM.

107         public String label;

108         public boolean isPrimary;

109     }

110     

111     public static class OrganizationData {

112         public int type;

113         public String companyName;

114         public String positionName;

115         public boolean isPrimary;

116     }

117 

118     /**

119      * Add a phone info to phoneList.

120      * @param data phone number

121      * @param type type col of content://contacts/phones

122      * @param label lable col of content://contacts/phones

123      */

124     public void addPhone(int type, String data, String label, boolean isPrimary){

125         if (phoneList == null) {

126             phoneList = new ArrayList<PhoneData>();

127         }

128         PhoneData phoneData = new PhoneData();

129         phoneData.type = type;

130         

131         StringBuilder builder = new StringBuilder();

132         String trimed = data.trim();

133         int length = trimed.length();

134         for (int i = 0; i < length; i++) {

135             char ch = trimed.charAt(i);

136             if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) {

137                 builder.append(ch);

138             }

139         }

140         phoneData.data = PhoneNumberUtils.formatNumber(builder.toString());

141         phoneData.label = label;

142         phoneData.isPrimary = isPrimary;

143         phoneList.add(phoneData);

144     }

145 

146     /**

147      * Add a contactmethod info to contactmethodList.

148      * @param kind integer value defined in Contacts.java

149      * (e.g. Contacts.KIND_EMAIL)

150      * @param type type col of content://contacts/contact_methods

151      * @param data contact data

152      * @param label extra string used only when kind is Contacts.KIND_CUSTOM.

153      */

154     public void addContactmethod(int kind, int type, String data,

155             String label, boolean isPrimary){

156         if (contactmethodList == null) {

157             contactmethodList = new ArrayList<ContactMethod>();

158         }

159         ContactMethod contactMethod = new ContactMethod();

160         contactMethod.kind = kind;

161         contactMethod.type = type;

162         contactMethod.data = data;

163         contactMethod.label = label;

164         contactMethod.isPrimary = isPrimary;

165         contactmethodList.add(contactMethod);

166     }

167     

168     /**

169      * Add a Organization info to organizationList.

170      */

171     public void addOrganization(int type, String companyName, String positionName,

172             boolean isPrimary) {

173         if (organizationList == null) {

174             organizationList = new ArrayList<OrganizationData>();

175         }

176         OrganizationData organizationData = new OrganizationData();

177         organizationData.type = type;

178         organizationData.companyName = companyName;

179         organizationData.positionName = positionName;

180         organizationData.isPrimary = isPrimary;

181         organizationList.add(organizationData);

182     }

183 

184     /**

185      * Set "position" value to the appropriate data. If there's more than one

186      * OrganizationData objects, the value is set to the last one. If there's no

187      * OrganizationData object, a new OrganizationData is created, whose company name is

188      * empty.  

189      * 

190      * TODO: incomplete logic. fix this:

191      * 

192      * e.g. This assumes ORG comes earlier, but TITLE may come earlier like this, though we do not

193      * know how to handle it in general cases...

194      * ----

195      * TITLE:Software Engineer

196      * ORG:Google

197      * ----

198      */

199     public void setPosition(String positionValue) {

200         if (organizationList == null) {

201             organizationList = new ArrayList<OrganizationData>();

202         }

203         int size = organizationList.size();

204         if (size == 0) {

205             addOrganization(Contacts.OrganizationColumns.TYPE_OTHER, "", null, false);

206             size = 1;

207         }

208         OrganizationData lastData = organizationList.get(size - 1);

209         lastData.positionName = positionValue;

210     }

211     

212     public void addExtension(PropertyNode propertyNode) {

213         if (propertyNode.propValue.length() == 0) {

214             return;

215         }

216         // Now store the string into extensionMap.

217         List<String> list;

218         String name = propertyNode.propName;

219         if (extensionMap == null) {

220             extensionMap = new HashMap<String, List<String>>();

221         }

222         if (!extensionMap.containsKey(name)){

223             list = new ArrayList<String>();

224             extensionMap.put(name, list);

225         } else {

226             list = extensionMap.get(name);

227         }        

228         

229         list.add(propertyNode.encode());

230     }

231     

232     private static String getNameFromNProperty(List<String> elems, int nameOrderType) {

233         // Family, Given, Middle, Prefix, Suffix. (1 - 5)

234         int size = elems.size();

235         if (size > 1) {

236             StringBuilder builder = new StringBuilder();

237             boolean builderIsEmpty = true;

238             // Prefix

239             if (size > 3 && elems.get(3).length() > 0) {

240                 builder.append(elems.get(3));

241                 builderIsEmpty = false;

242             }

243             String first, second;

244             if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) {

245                 first = elems.get(0);

246                 second = elems.get(1);

247             } else {

248                 first = elems.get(1);

249                 second = elems.get(0);

250             }

251             if (first.length() > 0) {

252                 if (!builderIsEmpty) {

253                     builder.append(' ');

254                 }

255                 builder.append(first);

256                 builderIsEmpty = false;

257             }

258             // Middle name

259             if (size > 2 && elems.get(2).length() > 0) {

260                 if (!builderIsEmpty) {

261                     builder.append(' ');

262                 }

263                 builder.append(elems.get(2));

264                 builderIsEmpty = false;

265             }

266             if (second.length() > 0) {

267                 if (!builderIsEmpty) {

268                     builder.append(' ');

269                 }

270                 builder.append(second);

271                 builderIsEmpty = false;

272             }

273             // Suffix

274             if (size > 4 && elems.get(4).length() > 0) {

275                 if (!builderIsEmpty) {

276                     builder.append(' ');

277                 }

278                 builder.append(elems.get(4));

279                 builderIsEmpty = false;

280             }

281             return builder.toString();

282         } else if (size == 1) {

283             return elems.get(0);

284         } else {

285             return "";

286         }

287     }

288     

289     public static ContactStruct constructContactFromVNode(VNode node,

290             int nameOrderType) {

291         if (!node.VName.equals("VCARD")) {

292             // Impossible in current implementation. Just for safety.

293             Log.e(LOG_TAG, "Non VCARD data is inserted.");

294             return null;

295         }

296 

297         // For name, there are three fields in vCard: FN, N, NAME.

298         // We prefer FN, which is a required field in vCard 3.0 , but not in vCard 2.1.

299         // Next, we prefer NAME, which is defined only in vCard 3.0.

300         // Finally, we use N, which is a little difficult to parse.

301         String fullName = null;

302         String nameFromNProperty = null;

303 

304         // Some vCard has "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", and

305         // "X-PHONETIC-LAST-NAME"

306         String xPhoneticFirstName = null;

307         String xPhoneticMiddleName = null;

308         String xPhoneticLastName = null;

309         

310         ContactStruct contact = new ContactStruct();

311 

312         // Each Column of four properties has ISPRIMARY field

313         // (See android.provider.Contacts)

314         // If false even after the following loop, we choose the first

315         // entry as a "primary" entry.

316         boolean prefIsSetAddress = false;

317         boolean prefIsSetPhone = false;

318         boolean prefIsSetEmail = false;

319         boolean prefIsSetOrganization = false;

320         

321         for (PropertyNode propertyNode: node.propList) {

322             String name = propertyNode.propName;

323 

324             if (TextUtils.isEmpty(propertyNode.propValue)) {

325                 continue;

326             }

327             

328             if (name.equals("VERSION")) {

329                 // vCard version. Ignore this.

330             } else if (name.equals("FN")) {

331                 fullName = propertyNode.propValue;

332             } else if (name.equals("NAME") && fullName == null) {

333                 // Only in vCard 3.0. Use this if FN does not exist.

334                 // Though, note that vCard 3.0 requires FN.

335                 fullName = propertyNode.propValue;

336             } else if (name.equals("N")) {

337                 nameFromNProperty = getNameFromNProperty(propertyNode.propValue_vector,

338                         nameOrderType);

339             } else if (name.equals("SORT-STRING")) {

340                 contact.phoneticName = propertyNode.propValue;

341             } else if (name.equals("SOUND")) {

342                 if (propertyNode.paramMap_TYPE.contains("X-IRMC-N") &&

343                         contact.phoneticName == null) {

344                     // Some Japanese mobile phones use this field for phonetic name,

345                     // since vCard 2.1 does not have "SORT-STRING" type.

346                     // Also, in some cases, the field has some ';' in it.

347                     // We remove them.

348                     StringBuilder builder = new StringBuilder();

349                     String value = propertyNode.propValue;

350                     int length = value.length();

351                     for (int i = 0; i < length; i++) {

352                         char ch = value.charAt(i);

353                         if (ch != ';') {

354                             builder.append(ch);

355                         }

356                     }

357                     contact.phoneticName = builder.toString();

358                 } else {

359                     contact.addExtension(propertyNode);

360                 }

361             } else if (name.equals("ADR")) {

362                 List<String> values = propertyNode.propValue_vector;

363                 boolean valuesAreAllEmpty = true;

364                 for (String value : values) {

365                     if (value.length() > 0) {

366                         valuesAreAllEmpty = false;

367                         break;

368                     }

369                 }

370                 if (valuesAreAllEmpty) {

371                     continue;

372                 }

373 

374                 int kind = Contacts.KIND_POSTAL;

375                 int type = -1;

376                 String label = "";

377                 boolean isPrimary = false;

378                 for (String typeString : propertyNode.paramMap_TYPE) {

379                     if (typeString.equals("PREF") && !prefIsSetAddress) {

380                         // Only first "PREF" is considered.

381                         prefIsSetAddress = true;

382                         isPrimary = true;

383                     } else if (typeString.equalsIgnoreCase("HOME")) {

384                         type = Contacts.ContactMethodsColumns.TYPE_HOME;

385                         label = "";

386                     } else if (typeString.equalsIgnoreCase("WORK") || 

387                             typeString.equalsIgnoreCase("COMPANY")) {

388                         // "COMPANY" seems emitted by Windows Mobile, which is not

389                         // specifically supported by vCard 2.1. We assume this is same

390                         // as "WORK".

391                         type = Contacts.ContactMethodsColumns.TYPE_WORK;

392                         label = "";

393                     } else if (typeString.equalsIgnoreCase("POSTAL")) {

394                         kind = Contacts.KIND_POSTAL;

395                     } else if (typeString.equalsIgnoreCase("PARCEL") || 

396                             typeString.equalsIgnoreCase("DOM") ||

397                             typeString.equalsIgnoreCase("INTL")) {

398                         // We do not have a kind or type matching these.

399                         // TODO: fix this. We may need to split entries into two.

400                         // (e.g. entries for KIND_POSTAL and KIND_PERCEL)

401                     } else if (typeString.toUpperCase().startsWith("X-") &&

402                             type < 0) {

403                         type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;

404                         label = typeString.substring(2);

405                     } else if (type < 0) {

406                         // vCard 3.0 allows iana-token. Also some vCard 2.1 exporters

407                         // emit non-standard types. We do not handle their values now.

408                         type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;

409                         label = typeString;

410                     }

411                 }

412                 // We use "HOME" as default

413                 if (type < 0) {

414                     type = Contacts.ContactMethodsColumns.TYPE_HOME;

415                 }

416                                 

417                 // adr-value    = 0*6(text-value ";") text-value

418                 //              ; PO Box, Extended Address, Street, Locality, Region, Postal

419                 //              ; Code, Country Name

420                 String address;

421                 List<String> list = propertyNode.propValue_vector;

422                 int size = list.size();

423                 if (size > 1) {

424                     StringBuilder builder = new StringBuilder();

425                     boolean builderIsEmpty = true;

426                     if (Locale.getDefault().getCountry().equals(Locale.JAPAN.getCountry())) {

427                         // In Japan, the order is reversed.

428                         for (int i = size - 1; i >= 0; i--) {

429                             String addressPart = list.get(i);

430                             if (addressPart.length() > 0) {

431                                 if (!builderIsEmpty) {

432                                     builder.append(' ');

433                                 }

434                                 builder.append(addressPart);

435                                 builderIsEmpty = false;

436                             }

437                         }

438                     } else {

439                         for (int i = 0; i < size; i++) {

440                             String addressPart = list.get(i);

441                             if (addressPart.length() > 0) {

442                                 if (!builderIsEmpty) {

443                                     builder.append(' ');

444                                 }

445                                 builder.append(addressPart);

446                                 builderIsEmpty = false;

447                             }

448                         }

449                     }

450                     address = builder.toString().trim();

451                 } else {

452                     address = propertyNode.propValue; 

453                 }

454                 contact.addContactmethod(kind, type, address, label, isPrimary);

455             } else if (name.equals("ORG")) {

456                 // vCard specification does not specify other types.

457                 int type = Contacts.OrganizationColumns.TYPE_WORK;

458                 boolean isPrimary = false;

459                 

460                 for (String typeString : propertyNode.paramMap_TYPE) {

461                     if (typeString.equals("PREF") && !prefIsSetOrganization) {

462                         // vCard specification officially does not have PREF in ORG.

463                         // This is just for safety.

464                         prefIsSetOrganization = true;

465                         isPrimary = true;

466                     }

467                     // XXX: Should we cope with X- words?

468                 }

469 

470                 List<String> list = propertyNode.propValue_vector; 

471                 int size = list.size();

472                 StringBuilder builder = new StringBuilder();

473                 for (Iterator<String> iter = list.iterator(); iter.hasNext();) {

474                     builder.append(iter.next());

475                     if (iter.hasNext()) {

476                         builder.append(' ');

477                     }

478                 }

479 

480                 contact.addOrganization(type, builder.toString(), "", isPrimary);

481             } else if (name.equals("TITLE")) {

482                 contact.setPosition(propertyNode.propValue);

483             } else if (name.equals("ROLE")) {

484                 contact.setPosition(propertyNode.propValue);

485             } else if (name.equals("PHOTO")) {

486                 // We prefer PHOTO to LOGO.

487                 String valueType = propertyNode.paramMap.getAsString("VALUE");

488                 if (valueType != null && valueType.equals("URL")) {

489                     // TODO: do something.

490                 } else {

491                     // Assume PHOTO is stored in BASE64. In that case,

492                     // data is already stored in propValue_bytes in binary form.

493                     // It should be automatically done by VBuilder (VDataBuilder/VCardDatabuilder) 

494                     contact.photoBytes = propertyNode.propValue_bytes;

495                     String type = propertyNode.paramMap.getAsString("TYPE");

496                     if (type != null) {

497                         contact.photoType = type;

498                     }

499                 }

500             } else if (name.equals("LOGO")) {

501                 // When PHOTO is not available this is not URL,

502                 // we use this instead of PHOTO.

503                 String valueType = propertyNode.paramMap.getAsString("VALUE");

504                 if (valueType != null && valueType.equals("URL")) {

505                     // TODO: do something.

506                 } else if (contact.photoBytes == null) {

507                     contact.photoBytes = propertyNode.propValue_bytes;

508                     String type = propertyNode.paramMap.getAsString("TYPE");

509                     if (type != null) {

510                         contact.photoType = type;

511                     }

512                 }

513             } else if (name.equals("EMAIL")) {

514                 int type = -1;

515                 String label = null;

516                 boolean isPrimary = false;

517                 for (String typeString : propertyNode.paramMap_TYPE) {

518                     if (typeString.equals("PREF") && !prefIsSetEmail) {

519                         // Only first "PREF" is considered.

520                         prefIsSetEmail = true;

521                         isPrimary = true;

522                     } else if (typeString.equalsIgnoreCase("HOME")) {

523                         type = Contacts.ContactMethodsColumns.TYPE_HOME;

524                     } else if (typeString.equalsIgnoreCase("WORK")) {

525                         type = Contacts.ContactMethodsColumns.TYPE_WORK;

526                     } else if (typeString.equalsIgnoreCase("CELL")) {

527                         // We do not have Contacts.ContactMethodsColumns.TYPE_MOBILE yet.

528                         type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;

529                         label = Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME;

530                     } else if (typeString.toUpperCase().startsWith("X-") &&

531                             type < 0) {

532                         type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;

533                         label = typeString.substring(2);

534                     } else if (type < 0) {

535                         // vCard 3.0 allows iana-token.

536                         // We may have INTERNET (specified in vCard spec),

537                         // SCHOOL, etc.

538                         type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;

539                         label = typeString;

540                     }

541                 }

542                 // We use "OTHER" as default.

543                 if (type < 0) {

544                     type = Contacts.ContactMethodsColumns.TYPE_OTHER;

545                 }

546                 contact.addContactmethod(Contacts.KIND_EMAIL,

547                         type, propertyNode.propValue,label, isPrimary);

548             } else if (name.equals("TEL")) {

549                 int type = -1;

550                 String label = null;

551                 boolean isPrimary = false;

552                 boolean isFax = false;

553                 for (String typeString : propertyNode.paramMap_TYPE) {

554                     if (typeString.equals("PREF") && !prefIsSetPhone) {

555                         // Only first "PREF" is considered.

556                         prefIsSetPhone = true;

557                         isPrimary = true;

558                     } else if (typeString.equalsIgnoreCase("HOME")) {

559                         type = Contacts.PhonesColumns.TYPE_HOME;

560                     } else if (typeString.equalsIgnoreCase("WORK")) {

561                         type = Contacts.PhonesColumns.TYPE_WORK;

562                     } else if (typeString.equalsIgnoreCase("CELL")) {

563                         type = Contacts.PhonesColumns.TYPE_MOBILE;

564                     } else if (typeString.equalsIgnoreCase("PAGER")) {

565                         type = Contacts.PhonesColumns.TYPE_PAGER;

566                     } else if (typeString.equalsIgnoreCase("FAX")) {

567                         isFax = true;

568                     } else if (typeString.equalsIgnoreCase("VOICE") ||

569                             typeString.equalsIgnoreCase("MSG")) {

570                         // Defined in vCard 3.0. Ignore these because they

571                         // conflict with "HOME", "WORK", etc.

572                         // XXX: do something?

573                     } else if (typeString.toUpperCase().startsWith("X-") &&

574                             type < 0) {

575                         type = Contacts.PhonesColumns.TYPE_CUSTOM;

576                         label = typeString.substring(2);

577                     } else if (type < 0){

578                         // We may have MODEM, CAR, ISDN, etc...

579                         type = Contacts.PhonesColumns.TYPE_CUSTOM;

580                         label = typeString;

581                     }

582                 }

583                 // We use "HOME" as default

584                 if (type < 0) {

585                     type = Contacts.PhonesColumns.TYPE_HOME;

586                 }

587                 if (isFax) {

588                     if (type == Contacts.PhonesColumns.TYPE_HOME) {

589                         type = Contacts.PhonesColumns.TYPE_FAX_HOME; 

590                     } else if (type == Contacts.PhonesColumns.TYPE_WORK) {

591                         type = Contacts.PhonesColumns.TYPE_FAX_WORK; 

592                     }

593                 }

594 

595                 contact.addPhone(type, propertyNode.propValue, label, isPrimary);

596             } else if (name.equals("NOTE")) {

597                 contact.notes.add(propertyNode.propValue);

598             } else if (name.equals("BDAY")) {

599                 contact.addExtension(propertyNode);

600             } else if (name.equals("URL")) {

601                 contact.addExtension(propertyNode);

602             } else if (name.equals("REV")) {                

603                 // Revision of this VCard entry. I think we can ignore this.

604                 contact.addExtension(propertyNode);

605             } else if (name.equals("UID")) {

606                 contact.addExtension(propertyNode);

607             } else if (name.equals("KEY")) {

608                 // Type is X509 or PGP? I don't know how to handle this...

609                 contact.addExtension(propertyNode);

610             } else if (name.equals("MAILER")) {

611                 contact.addExtension(propertyNode);

612             } else if (name.equals("TZ")) {

613                 contact.addExtension(propertyNode);

614             } else if (name.equals("GEO")) {

615                 contact.addExtension(propertyNode);

616             } else if (name.equals("NICKNAME")) {

617                 // vCard 3.0 only.

618                 contact.addExtension(propertyNode);

619             } else if (name.equals("CLASS")) {

620                 // vCard 3.0 only.

621                 // e.g. CLASS:CONFIDENTIAL

622                 contact.addExtension(propertyNode);

623             } else if (name.equals("PROFILE")) {

624                 // VCard 3.0 only. Must be "VCARD". I think we can ignore this.

625                 contact.addExtension(propertyNode);

626             } else if (name.equals("CATEGORIES")) {

627                 // VCard 3.0 only.

628                 // e.g. CATEGORIES:INTERNET,IETF,INDUSTRY,INFORMATION TECHNOLOGY

629                 contact.addExtension(propertyNode);

630             } else if (name.equals("SOURCE")) {

631                 // VCard 3.0 only.

632                 contact.addExtension(propertyNode);

633             } else if (name.equals("PRODID")) {

634                 // VCard 3.0 only.

635                 // To specify the identifier for the product that created

636                 // the vCard object.

637                 contact.addExtension(propertyNode);

638             } else if (name.equals("X-PHONETIC-FIRST-NAME")) {

639                 xPhoneticFirstName = propertyNode.propValue;

640             } else if (name.equals("X-PHONETIC-MIDDLE-NAME")) {

641                 xPhoneticMiddleName = propertyNode.propValue;

642             } else if (name.equals("X-PHONETIC-LAST-NAME")) {

643                 xPhoneticLastName = propertyNode.propValue;

644             } else {

645                 // Unknown X- words and IANA token.

646                 contact.addExtension(propertyNode);

647             }

648         }

649 

650         if (fullName != null) {

651             contact.name = fullName;

652         } else if(nameFromNProperty != null) {

653             contact.name = nameFromNProperty;

654         } else {

655             contact.name = "";

656         }

657 

658         if (contact.phoneticName == null &&

659                 (xPhoneticFirstName != null || xPhoneticMiddleName != null ||

660                         xPhoneticLastName != null)) {

661             // Note: In Europe, this order should be "LAST FIRST MIDDLE". See the comment around

662             //       NAME_ORDER_TYPE_* for more detail.

663             String first;

664             String second;

665             if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) {

666                 first = xPhoneticLastName;

667                 second = xPhoneticFirstName;

668             } else {

669                 first = xPhoneticFirstName;

670                 second = xPhoneticLastName;

671             }

672             StringBuilder builder = new StringBuilder();

673             if (first != null) {

674                 builder.append(first);

675             }

676             if (xPhoneticMiddleName != null) {

677                 builder.append(xPhoneticMiddleName);

678             }

679             if (second != null) {

680                 builder.append(second);

681             }

682             contact.phoneticName = builder.toString();

683         }

684         

685         // Remove unnecessary white spaces.

686         // It is found that some mobile phone emits  phonetic name with just one white space

687         // when a user does not specify one.

688         // This logic is effective toward such kind of weird data.

689         if (contact.phoneticName != null) {

690             contact.phoneticName = contact.phoneticName.trim();

691         }

692 

693         // If there is no "PREF", we choose the first entries as primary.

694         if (!prefIsSetPhone &&

695                 contact.phoneList != null && 

696                 contact.phoneList.size() > 0) {

697             contact.phoneList.get(0).isPrimary = true;

698         }

699 

700         if (!prefIsSetAddress && contact.contactmethodList != null) {

701             for (ContactMethod contactMethod : contact.contactmethodList) {

702                 if (contactMethod.kind == Contacts.KIND_POSTAL) {

703                     contactMethod.isPrimary = true;

704                     break;

705                 }

706             }

707         }

708         if (!prefIsSetEmail && contact.contactmethodList != null) {

709             for (ContactMethod contactMethod : contact.contactmethodList) {

710                 if (contactMethod.kind == Contacts.KIND_EMAIL) {

711                     contactMethod.isPrimary = true;

712                     break;

713                 }

714             }

715         }

716         if (!prefIsSetOrganization &&

717                 contact.organizationList != null &&

718                 contact.organizationList.size() > 0) {

719             contact.organizationList.get(0).isPrimary = true;

720         }

721         

722         return contact;

723     }

724     

725     public String displayString() {

726         if (name.length() > 0) {

727             return name;

728         }

729         if (contactmethodList != null && contactmethodList.size() > 0) {

730             for (ContactMethod contactMethod : contactmethodList) {

731                 if (contactMethod.kind == Contacts.KIND_EMAIL && contactMethod.isPrimary) {

732                     return contactMethod.data;

733                 }

734             }

735         }

736         if (phoneList != null && phoneList.size() > 0) {

737             for (PhoneData phoneData : phoneList) {

738                 if (phoneData.isPrimary) {

739                     return phoneData.data;

740                 }

741             }

742         }

743         return "";

744     }

745     

746 //    private void pushIntoContentProviderOrResolver(Object contentSomething,

747 //            long myContactsGroupId) {

748 //        ContentResolver resolver = null;

749 //        AbstractSyncableContentProvider provider = null;

750 //        if (contentSomething instanceof ContentResolver) {

751 //            resolver = (ContentResolver)contentSomething;

752 //        } else if (contentSomething instanceof AbstractSyncableContentProvider) {

753 //            provider = (AbstractSyncableContentProvider)contentSomething;

754 //        } else {

755 //            Log.e(LOG_TAG, "Unsupported object came.");

756 //            return;

757 //        }

758 //

759 //        ContentValues contentValues = new ContentValues();

760 //        contentValues.put(People.NAME, name);

761 //        contentValues.put(People.PHONETIC_NAME, phoneticName);

762 //

763 //        if (notes.size() > 1) {

764 //            StringBuilder builder = new StringBuilder();

765 //            for (String note : notes) {

766 //                builder.append(note);

767 //                builder.append("\n");

768 //            }

769 //            contentValues.put(People.NOTES, builder.toString());

770 //        } else if (notes.size() == 1){

771 //            contentValues.put(People.NOTES, notes.get(0));

772 //        }

773 //

774 //        Uri personUri;

775 //        long personId = 0;

776 //        if (resolver != null) {

777 //            personUri = Contacts.People.createPersonInMyContactsGroup(

778 //                    resolver, contentValues);

779 //            if (personUri != null) {

780 //                personId = ContentUris.parseId(personUri);

781 //            }

782 //        } else {

783 //            personUri = provider.nonTransactionalInsert(People.CONTENT_URI, contentValues);

784 //            if (personUri != null) {

785 //                personId = ContentUris.parseId(personUri);

786 //                ContentValues values = new ContentValues();

787 //                values.put(GroupMembership.PERSON_ID, personId);

788 //                values.put(GroupMembership.GROUP_ID, myContactsGroupId);

789 //                Uri resultUri = provider.nonTransactionalInsert(

790 //                        GroupMembership.CONTENT_URI, values);

791 //                if (resultUri == null) {

792 //                    Log.e(LOG_TAG, "Faild to insert the person to MyContact.");

793 //                    provider.nonTransactionalDelete(personUri, null, null);

794 //                    personUri = null;

795 //                }

796 //            }

797 //        }

798 //

799 //        if (personUri == null) {

800 //            Log.e(LOG_TAG, "Failed to create the contact.");

801 //            return;

802 //        }

803 //

804 //        if (photoBytes != null) {

805 //            if (resolver != null) {

806 //                People.setPhotoData(resolver, personUri, photoBytes);

807 //            } else {

808 //                Uri photoUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY);

809 //                ContentValues values = new ContentValues();

810 //                values.put(Photos.DATA, photoBytes);

811 //                provider.update(photoUri, values, null, null);

812 //            }

813 //        }

814 //

815 //        long primaryPhoneId = -1;

816 //        if (phoneList != null && phoneList.size() > 0) {

817 //            for (PhoneData phoneData : phoneList) {

818 //                ContentValues values = new ContentValues();

819 //                values.put(Contacts.PhonesColumns.TYPE, phoneData.type);

820 //                if (phoneData.type == Contacts.PhonesColumns.TYPE_CUSTOM) {

821 //                    values.put(Contacts.PhonesColumns.LABEL, phoneData.label);

822 //                }

823 //                // Already formatted.

824 //                values.put(Contacts.PhonesColumns.NUMBER, phoneData.data);

825 //

826 //                // Not sure about Contacts.PhonesColumns.NUMBER_KEY ...

827 //                values.put(Contacts.PhonesColumns.ISPRIMARY, 1);

828 //                values.put(Contacts.Phones.PERSON_ID, personId);

829 //                Uri phoneUri;

830 //                if (resolver != null) {

831 //                    phoneUri = resolver.insert(Phones.CONTENT_URI, values);

832 //                } else {

833 //                    phoneUri = provider.nonTransactionalInsert(Phones.CONTENT_URI, values);

834 //                }

835 //                if (phoneData.isPrimary) {

836 //                    primaryPhoneId = Long.parseLong(phoneUri.getLastPathSegment());

837 //                }

838 //            }

839 //        }

840 //

841 //        long primaryOrganizationId = -1;

842 //        if (organizationList != null && organizationList.size() > 0) {

843 //            for (OrganizationData organizationData : organizationList) {

844 //                ContentValues values = new ContentValues();

845 //                // Currently, we do not use TYPE_CUSTOM.

846 //                values.put(Contacts.OrganizationColumns.TYPE,

847 //                        organizationData.type);

848 //                values.put(Contacts.OrganizationColumns.COMPANY,

849 //                        organizationData.companyName);

850 //                values.put(Contacts.OrganizationColumns.TITLE,

851 //                        organizationData.positionName);

852 //                values.put(Contacts.OrganizationColumns.ISPRIMARY, 1);

853 //                values.put(Contacts.OrganizationColumns.PERSON_ID, personId);

854 //

855 //                Uri organizationUri;

856 //                if (resolver != null) {

857 //                    organizationUri = resolver.insert(Organizations.CONTENT_URI, values);

858 //                } else {

859 //                    organizationUri = provider.nonTransactionalInsert(

860 //                            Organizations.CONTENT_URI, values);

861 //                }

862 //                if (organizationData.isPrimary) {

863 //                    primaryOrganizationId = Long.parseLong(organizationUri.getLastPathSegment());

864 //                }

865 //            }

866 //        }

867 //

868 //        long primaryEmailId = -1;

869 //        if (contactmethodList != null && contactmethodList.size() > 0) {

870 //            for (ContactMethod contactMethod : contactmethodList) {

871 //                ContentValues values = new ContentValues();

872 //                values.put(Contacts.ContactMethodsColumns.KIND, contactMethod.kind);

873 //                values.put(Contacts.ContactMethodsColumns.TYPE, contactMethod.type);

874 //                if (contactMethod.type == Contacts.ContactMethodsColumns.TYPE_CUSTOM) {

875 //                    values.put(Contacts.ContactMethodsColumns.LABEL, contactMethod.label);

876 //                }

877 //                values.put(Contacts.ContactMethodsColumns.DATA, contactMethod.data);

878 //                values.put(Contacts.ContactMethodsColumns.ISPRIMARY, 1);

879 //                values.put(Contacts.ContactMethods.PERSON_ID, personId);

880 //

881 //                if (contactMethod.kind == Contacts.KIND_EMAIL) {

882 //                    Uri emailUri;

883 //                    if (resolver != null) {

884 //                        emailUri = resolver.insert(ContactMethods.CONTENT_URI, values);

885 //                    } else {

886 //                        emailUri = provider.nonTransactionalInsert(

887 //                                ContactMethods.CONTENT_URI, values);

888 //                    }

889 //                    if (contactMethod.isPrimary) {

890 //                        primaryEmailId = Long.parseLong(emailUri.getLastPathSegment());

891 //                    }

892 //                } else {  // probably KIND_POSTAL

893 //                    if (resolver != null) {

894 //                        resolver.insert(ContactMethods.CONTENT_URI, values);

895 //                    } else {

896 //                        provider.nonTransactionalInsert(

897 //                                ContactMethods.CONTENT_URI, values);

898 //                    }

899 //                }

900 //            }

901 //        }

902 //

903 //        if (extensionMap != null && extensionMap.size() > 0) {

904 //            ArrayList<ContentValues> contentValuesArray;

905 //            if (resolver != null) {

906 //                contentValuesArray = new ArrayList<ContentValues>();

907 //            } else {

908 //                contentValuesArray = null;

909 //            }

910 //            for (Entry<String, List<String>> entry : extensionMap.entrySet()) {

911 //                String key = entry.getKey();

912 //                List<String> list = entry.getValue();

913 //                for (String value : list) {

914 //                    ContentValues values = new ContentValues();

915 //                    values.put(Extensions.NAME, key);

916 //                    values.put(Extensions.VALUE, value);

917 //                    values.put(Extensions.PERSON_ID, personId);

918 //                    if (resolver != null) {

919 //                        contentValuesArray.add(values);

920 //                    } else {

921 //                        provider.nonTransactionalInsert(Extensions.CONTENT_URI, values);

922 //                    }

923 //                }

924 //            }

925 //            if (resolver != null) {

926 //                resolver.bulkInsert(Extensions.CONTENT_URI,

927 //                        contentValuesArray.toArray(new ContentValues[0]));

928 //            }

929 //        }

930 //

931 //        if (primaryPhoneId >= 0 || primaryOrganizationId >= 0 || primaryEmailId >= 0) {

932 //            ContentValues values = new ContentValues();

933 //            if (primaryPhoneId >= 0) {

934 //                values.put(People.PRIMARY_PHONE_ID, primaryPhoneId);

935 //            }

936 //            if (primaryOrganizationId >= 0) {

937 //                values.put(People.PRIMARY_ORGANIZATION_ID, primaryOrganizationId);

938 //            }

939 //            if (primaryEmailId >= 0) {

940 //                values.put(People.PRIMARY_EMAIL_ID, primaryEmailId);

941 //            }

942 //            if (resolver != null) {

943 //                resolver.update(personUri, values, null, null);

944 //            } else {

945 //                provider.nonTransactionalUpdate(personUri, values, null, null);

946 //            }

947 //        }

948 //    }

949 //

950 //    /**

951 //     * Push this object into database in the resolver.

952 //     */

953 //    public void pushIntoContentResolver(ContentResolver resolver) {

954 //        pushIntoContentProviderOrResolver(resolver, 0);

955 //    }

956 //

957 //    /**

958 //     * Push this object into AbstractSyncableContentProvider object.

959 //     */

960 //    public void pushIntoAbstractSyncableContentProvider(

961 //            AbstractSyncableContentProvider provider, long myContactsGroupId) {

962 //        boolean successful = false;

963 //        provider.beginTransaction();

964 //        try {

965 //            pushIntoContentProviderOrResolver(provider, myContactsGroupId);

966 //            successful = true;

967 //        } finally {

968 //            provider.endTransaction(successful);

969 //        }

970 //    }

971     

972     public boolean isIgnorable() {

973         return TextUtils.isEmpty(name) &&

974                 TextUtils.isEmpty(phoneticName) &&

975                 (phoneList == null || phoneList.size() == 0) &&

976                 (contactmethodList == null || contactmethodList.size() == 0);

977     }

978 }
Android VCard联系人备份恢复(导入/导出)详解 View Code
   1 /*

   2  * Copyright (C) 2006 The Android Open Source Project

   3  *

   4  * Licensed under the Apache License, Version 2.0 (the "License");

   5  * you may not use this file except in compliance with the License.

   6  * You may obtain a copy of the License at

   7  *

   8  *      http://www.apache.org/licenses/LICENSE-2.0

   9  *

  10  * Unless required by applicable law or agreed to in writing, software

  11  * distributed under the License is distributed on an "AS IS" BASIS,

  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  13  * See the License for the specific language governing permissions and

  14  * limitations under the License.

  15  */

  16 

  17 package a_vcard.android.provider;

  18 

  19 //import com.android.internal.R;

  20 

  21 //import android.content.ContentResolver;

  22 //import android.content.ContentUris;

  23 //import android.content.ContentValues;

  24 //import android.content.Context;

  25 //import android.content.Intent;

  26 //import android.database.Cursor;

  27 //import android.graphics.Bitmap;

  28 //import android.graphics.BitmapFactory;

  29 //import android.net.Uri;

  30 //import android.text.TextUtils;

  31 //import android.util.Log;

  32 //import android.widget.ImageView;

  33 

  34 //import java.io.ByteArrayInputStream;

  35 //import java.io.InputStream;

  36 

  37 /**

  38  * The Contacts provider stores all information about contacts.

  39  */

  40 public class Contacts {

  41     private static final String TAG = "Contacts";

  42     

  43     public static final String AUTHORITY = "contacts";

  44 

  45 //    /**

  46 //     * The content:// style URL for this provider

  47 //     */

  48 //    public static final Uri CONTENT_URI =

  49 //        Uri.parse("content://" + AUTHORITY);

  50 

  51     /** Signifies an email address row that is stored in the ContactMethods table */

  52     public static final int KIND_EMAIL = 1;

  53     /** Signifies a postal address row that is stored in the ContactMethods table */

  54     public static final int KIND_POSTAL = 2;

  55     /** Signifies an IM address row that is stored in the ContactMethods table */

  56     public static final int KIND_IM = 3;

  57     /** Signifies an Organization row that is stored in the Organizations table */

  58     public static final int KIND_ORGANIZATION = 4;

  59     /** Signifies an Phone row that is stored in the Phones table */

  60     public static final int KIND_PHONE = 5;

  61 

  62     /**

  63      * no public constructor since this is a utility class

  64      */

  65     private Contacts() {}

  66 

  67 //    /**

  68 //     * Columns from the Settings table that other columns join into themselves.

  69 //     */

  70 //    public interface SettingsColumns {

  71 //        /**

  72 //         * The _SYNC_ACCOUNT to which this setting corresponds. This may be null.

  73 //         * <P>Type: TEXT</P>

  74 //         */

  75 //        public static final String _SYNC_ACCOUNT = "_sync_account";

  76 //

  77 //        /**

  78 //         * The key of this setting.

  79 //         * <P>Type: TEXT</P>

  80 //         */

  81 //        public static final String KEY = "key";

  82 //

  83 //        /**

  84 //         * The value of this setting.

  85 //         * <P>Type: TEXT</P>

  86 //         */

  87 //        public static final String VALUE = "value";

  88 //    }

  89 //

  90 //    /**

  91 //     * The settings over all of the people

  92 //     */

  93 //    public static final class Settings implements BaseColumns, SettingsColumns {

  94 //        /**

  95 //         * no public constructor since this is a utility class

  96 //         */

  97 //        private Settings() {}

  98 //

  99 //        /**

 100 //         * The content:// style URL for this table

 101 //         */

 102 //        public static final Uri CONTENT_URI =

 103 //            Uri.parse("content://contacts/settings");

 104 //

 105 //        /**

 106 //         * The directory twig for this sub-table

 107 //         */

 108 //        public static final String CONTENT_DIRECTORY = "settings";

 109 //

 110 //        /**

 111 //         * The default sort order for this table

 112 //         */

 113 //        public static final String DEFAULT_SORT_ORDER = "key ASC";

 114 //

 115 //        /**

 116 //         * A setting that is used to indicate if we should sync down all groups for the

 117 //         * specified account. For this setting the _SYNC_ACCOUNT column must be set.

 118 //         * If this isn't set then we will only sync the groups whose SHOULD_SYNC column

 119 //         * is set to true.

 120 //         * <p>

 121 //         * This is a boolean setting. It is true if it is set and it is anything other than the

 122 //         * emptry string or "0".

 123 //         */

 124 //        public static final String SYNC_EVERYTHING = "syncEverything";

 125 //

 126 //        public static String getSetting(ContentResolver cr, String account, String key) {

 127 //            // For now we only support a single account and the UI doesn't know what

 128 //            // the account name is, so we're using a global setting for SYNC_EVERYTHING.

 129 //            // Some day when we add multiple accounts to the UI this should honor the account

 130 //            // that was asked for.

 131 //            String selectString;

 132 //            String[] selectArgs;

 133 //            if (false) {

 134 //                selectString = (account == null)

 135 //                        ? "_sync_account is null AND key=?"

 136 //                        : "_sync_account=? AND key=?";

 137 //                selectArgs = (account == null)

 138 //                ? new String[]{key}

 139 //                : new String[]{account, key};

 140 //            } else {

 141 //                selectString = "key=?";

 142 //                selectArgs = new String[] {key};

 143 //            }

 144 //            Cursor cursor = cr.query(Settings.CONTENT_URI, new String[]{VALUE},

 145 //                    selectString, selectArgs, null);

 146 //            try {

 147 //                if (!cursor.moveToNext()) return null;

 148 //                return cursor.getString(0);

 149 //            } finally {

 150 //                cursor.close();

 151 //            }

 152 //        }

 153 //

 154 //        public static void setSetting(ContentResolver cr, String account, String key,

 155 //                String value) {

 156 //            ContentValues values = new ContentValues();

 157 //            // For now we only support a single account and the UI doesn't know what

 158 //            // the account name is, so we're using a global setting for SYNC_EVERYTHING.

 159 //            // Some day when we add multiple accounts to the UI this should honor the account

 160 //            // that was asked for.

 161 //            //values.put(_SYNC_ACCOUNT, account);

 162 //            values.put(KEY, key);

 163 //            values.put(VALUE, value);

 164 //            cr.update(Settings.CONTENT_URI, values, null, null);

 165 //        }

 166 //    }

 167 //

 168     /**

 169      * Columns from the People table that other tables join into themselves.

 170      */

 171     public interface PeopleColumns {

 172         /**

 173          * The person's name.

 174          * <P>Type: TEXT</P>

 175          */

 176         public static final String NAME = "name";

 177 

 178         /**

 179          * Phonetic equivalent of the person's name, in a locale-dependent

 180          * character set (e.g. hiragana for Japanese).

 181          * Used for pronunciation and/or collation in some languages.

 182          * <p>Type: TEXT</P>

 183          */

 184         public static final String PHONETIC_NAME = "phonetic_name";

 185         

 186         /**

 187          * The display name. If name is not null name, else if number is not null number,

 188          * else if email is not null email.

 189          * <P>Type: TEXT</P>

 190          */

 191         public static final String DISPLAY_NAME = "display_name";

 192 

 193         /**

 194          * The field for sorting list phonetically. The content of this field

 195          * may not be human readable but phonetically sortable.

 196          * <P>Type: TEXT</p>

 197          * @hide Used only in Contacts application for now.

 198          */

 199         public static final String SORT_STRING = "sort_string";

 200         

 201         /**

 202          * Notes about the person.

 203          * <P>Type: TEXT</P>

 204          */

 205         public static final String NOTES = "notes";

 206 

 207         /**

 208          * The number of times a person has been contacted

 209          * <P>Type: INTEGER</P>

 210          */

 211         public static final String TIMES_CONTACTED = "times_contacted";

 212 

 213         /**

 214          * The last time a person was contacted.

 215          * <P>Type: INTEGER</P>

 216          */

 217         public static final String LAST_TIME_CONTACTED = "last_time_contacted";

 218 

 219         /**

 220          * A custom ringtone associated with a person. Not always present.

 221          * <P>Type: TEXT (URI to the ringtone)</P>

 222          */

 223         public static final String CUSTOM_RINGTONE = "custom_ringtone";

 224 

 225         /**

 226          * Whether the person should always be sent to voicemail. Not always

 227          * present.

 228          * <P>Type: INTEGER (0 for false, 1 for true)</P>

 229          */

 230         public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";

 231 

 232         /**

 233          * Is the contact starred?

 234          * <P>Type: INTEGER (boolean)</P>

 235          */

 236         public static final String STARRED = "starred";

 237 

 238         /**

 239          * The server version of the photo

 240          * <P>Type: TEXT (the version number portion of the photo URI)</P>

 241          */

 242         public static final String PHOTO_VERSION = "photo_version";       

 243     }

 244 //

 245 //    /**

 246 //     * This table contains people.

 247 //     */

 248 //    public static final class People implements BaseColumns, SyncConstValue, PeopleColumns,

 249 //            PhonesColumns, PresenceColumns {

 250 //        /**

 251 //         * no public constructor since this is a utility class

 252 //         */

 253 //        private People() {}

 254 //

 255 //        /**

 256 //         * The content:// style URL for this table

 257 //         */

 258 //        public static final Uri CONTENT_URI =

 259 //            Uri.parse("content://contacts/people");

 260 //

 261 //        /**

 262 //         * The content:// style URL for filtering people by name. The filter

 263 //         * argument should be passed as an additional path segment after this URI.

 264 //         */

 265 //        public static final Uri CONTENT_FILTER_URI =

 266 //            Uri.parse("content://contacts/people/filter");

 267 //

 268 //        /**

 269 //         * The content:// style URL for the table that holds the deleted

 270 //         * contacts.

 271 //         */

 272 //        public static final Uri DELETED_CONTENT_URI =

 273 //            Uri.parse("content://contacts/deleted_people");

 274 //

 275 //        /**

 276 //         * The content:// style URL for filtering people that have a specific

 277 //         * E-mail or IM address. The filter argument should be passed as an

 278 //         * additional path segment after this URI. This matches any people with

 279 //         * at least one E-mail or IM {@link ContactMethods} that match the

 280 //         * filter.

 281 //         *

 282 //         * Not exposed because we expect significant changes in the contacts

 283 //         * schema and do not want to have to support this.

 284 //         * @hide

 285 //         */

 286 //        public static final Uri WITH_EMAIL_OR_IM_FILTER_URI =

 287 //            Uri.parse("content://contacts/people/with_email_or_im_filter");

 288 //

 289 //        /**

 290 //         * The MIME type of {@link #CONTENT_URI} providing a directory of

 291 //         * people.

 292 //         */

 293 //        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person";

 294 //

 295 //        /**

 296 //         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single

 297 //         * person.

 298 //         */

 299 //        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";

 300 //

 301 //        /**

 302 //         * The default sort order for this table

 303 //         */

 304 //        public static final String DEFAULT_SORT_ORDER = People.NAME + " ASC";

 305 //

 306 //        /**

 307 //         * The ID of the persons preferred phone number.

 308 //         * <P>Type: INTEGER (foreign key to phones table on the _ID field)</P>

 309 //         */

 310 //        public static final String PRIMARY_PHONE_ID = "primary_phone";

 311 //

 312 //        /**

 313 //         * The ID of the persons preferred email.

 314 //         * <P>Type: INTEGER (foreign key to contact_methods table on the

 315 //         * _ID field)</P>

 316 //         */

 317 //        public static final String PRIMARY_EMAIL_ID = "primary_email";

 318 //

 319 //        /**

 320 //         * The ID of the persons preferred organization.

 321 //         * <P>Type: INTEGER (foreign key to organizations table on the

 322 //         * _ID field)</P>

 323 //         */

 324 //        public static final String PRIMARY_ORGANIZATION_ID = "primary_organization";

 325 //

 326 //        /**

 327 //         * Mark a person as having been contacted.

 328 //         *

 329 //         * @param resolver the ContentResolver to use

 330 //         * @param personId the person who was contacted

 331 //         */

 332 //        public static void markAsContacted(ContentResolver resolver, long personId) {

 333 //            Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId);

 334 //            uri = Uri.withAppendedPath(uri, "update_contact_time");

 335 //            ContentValues values = new ContentValues();

 336 //            // There is a trigger in place that will update TIMES_CONTACTED when

 337 //            // LAST_TIME_CONTACTED is modified.

 338 //            values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());

 339 //            resolver.update(uri, values, null, null);

 340 //        }

 341 //

 342 //        /**

 343 //         * @hide Used in vCard parser code.

 344 //         */

 345 //        public static long tryGetMyContactsGroupId(ContentResolver resolver) {

 346 //            Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,

 347 //                    Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null);

 348 //            if (groupsCursor != null) {

 349 //                try {

 350 //                    if (groupsCursor.moveToFirst()) {

 351 //                        return groupsCursor.getLong(0);

 352 //                    }

 353 //                } finally {

 354 //                    groupsCursor.close();

 355 //                }

 356 //            }

 357 //            return 0;

 358 //        }

 359 //

 360 //        /**

 361 //         * Adds a person to the My Contacts group.

 362 //         *

 363 //         * @param resolver the resolver to use

 364 //         * @param personId the person to add to the group

 365 //         * @return the URI of the group membership row

 366 //         * @throws IllegalStateException if the My Contacts group can't be found

 367 //         */

 368 //        public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) {

 369 //            long groupId = tryGetMyContactsGroupId(resolver);

 370 //            if (groupId == 0) {

 371 //                throw new IllegalStateException("Failed to find the My Contacts group");

 372 //            }

 373 //

 374 //            return addToGroup(resolver, personId, groupId);

 375 //        }

 376 //

 377 //        /**

 378 //         * Adds a person to a group referred to by name.

 379 //         *

 380 //         * @param resolver the resolver to use

 381 //         * @param personId the person to add to the group

 382 //         * @param groupName the name of the group to add the contact to

 383 //         * @return the URI of the group membership row

 384 //         * @throws IllegalStateException if the group can't be found

 385 //         */

 386 //        public static Uri addToGroup(ContentResolver resolver, long personId, String groupName) {

 387 //            long groupId = 0;

 388 //            Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,

 389 //                    Groups.NAME + "=?", new String[] { groupName }, null);

 390 //            if (groupsCursor != null) {

 391 //                try {

 392 //                    if (groupsCursor.moveToFirst()) {

 393 //                        groupId = groupsCursor.getLong(0);

 394 //                    }

 395 //                } finally {

 396 //                    groupsCursor.close();

 397 //                }

 398 //            }

 399 //

 400 //            if (groupId == 0) {

 401 //                throw new IllegalStateException("Failed to find the My Contacts group");

 402 //            }

 403 //

 404 //            return addToGroup(resolver, personId, groupId);

 405 //        }

 406 //

 407 //        /**

 408 //         * Adds a person to a group.

 409 //         *

 410 //         * @param resolver the resolver to use

 411 //         * @param personId the person to add to the group

 412 //         * @param groupId the group to add the person to

 413 //         * @return the URI of the group membership row

 414 //         */

 415 //        public static Uri addToGroup(ContentResolver resolver, long personId, long groupId) {

 416 //            ContentValues values = new ContentValues();

 417 //            values.put(GroupMembership.PERSON_ID, personId);

 418 //            values.put(GroupMembership.GROUP_ID, groupId);

 419 //            return resolver.insert(GroupMembership.CONTENT_URI, values);

 420 //        }

 421 //

 422 //        private static final String[] GROUPS_PROJECTION = new String[] {

 423 //            Groups._ID,

 424 //        };

 425 //

 426 //        /**

 427 //         * Creates a new contacts and adds it to the "My Contacts" group.

 428 //         *

 429 //         * @param resolver the ContentResolver to use

 430 //         * @param values the values to use when creating the contact

 431 //         * @return the URI of the contact, or null if the operation fails

 432 //         */

 433 //        public static Uri createPersonInMyContactsGroup(ContentResolver resolver,

 434 //                ContentValues values) {

 435 //

 436 //            Uri contactUri = resolver.insert(People.CONTENT_URI, values);

 437 //            if (contactUri == null) {

 438 //                Log.e(TAG, "Failed to create the contact");

 439 //                return null;

 440 //            }

 441 //

 442 //            if (addToMyContactsGroup(resolver, ContentUris.parseId(contactUri)) == null) {

 443 //                resolver.delete(contactUri, null, null);

 444 //                return null;

 445 //            }

 446 //            return contactUri;

 447 //        }

 448 //

 449 //        public static Cursor queryGroups(ContentResolver resolver, long person) {

 450 //            return resolver.query(GroupMembership.CONTENT_URI, null, "person=?",

 451 //                    new String[]{String.valueOf(person)}, Groups.DEFAULT_SORT_ORDER);

 452 //        }

 453 //

 454 //        /**

 455 //         * Set the photo for this person. data may be null

 456 //         * @param cr the ContentResolver to use

 457 //         * @param person the Uri of the person whose photo is to be updated

 458 //         * @param data the byte[] that represents the photo

 459 //         */

 460 //        public static void setPhotoData(ContentResolver cr, Uri person, byte[] data) {

 461 //            Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);

 462 //            ContentValues values = new ContentValues();

 463 //            values.put(Photos.DATA, data);

 464 //            cr.update(photoUri, values, null, null);

 465 //        }

 466 //

 467 //        /**

 468 //         * Opens an InputStream for the person's photo and returns the photo as a Bitmap.

 469 //         * If the person's photo isn't present returns the placeholderImageResource instead.

 470 //         * @param person the person whose photo should be used

 471 //         */

 472 //        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri person) {

 473 //            Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);

 474 //            Cursor cursor = cr.query(photoUri, new String[]{Photos.DATA}, null, null, null);

 475 //            try {

 476 //                if (!cursor.moveToNext()) {

 477 //                    return null;

 478 //                }

 479 //                byte[] data = cursor.getBlob(0);

 480 //                if (data == null) {

 481 //                    return null;

 482 //                }

 483 //                return new ByteArrayInputStream(data);

 484 //            } finally {

 485 //                cursor.close();

 486 //            }

 487 //        }

 488 //

 489 //        /**

 490 //         * Opens an InputStream for the person's photo and returns the photo as a Bitmap.

 491 //         * If the person's photo isn't present returns the placeholderImageResource instead.

 492 //         * @param context the Context

 493 //         * @param person the person whose photo should be used

 494 //         * @param placeholderImageResource the image resource to use if the person doesn't

 495 //         *   have a photo

 496 //         * @param options the decoding options, can be set to null

 497 //         */

 498 //        public static Bitmap loadContactPhoto(Context context, Uri person,

 499 //                int placeholderImageResource, BitmapFactory.Options options) {

 500 //            if (person == null) {

 501 //                return loadPlaceholderPhoto(placeholderImageResource, context, options);

 502 //            }

 503 //

 504 //            InputStream stream = openContactPhotoInputStream(context.getContentResolver(), person);

 505 //            Bitmap bm = stream != null ? BitmapFactory.decodeStream(stream, null, options) : null;

 506 //            if (bm == null) {

 507 //                bm = loadPlaceholderPhoto(placeholderImageResource, context, options);

 508 //            }

 509 //            return bm;

 510 //        }

 511 //

 512 //        private static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context,

 513 //                BitmapFactory.Options options) {

 514 //            if (placeholderImageResource == 0) {

 515 //                return null;

 516 //            }

 517 //            return BitmapFactory.decodeResource(context.getResources(),

 518 //                    placeholderImageResource, options);

 519 //        }

 520 

 521         /**

 522          * A sub directory of a single person that contains all of their Phones.

 523          */

 524         public static final class Phones implements BaseColumns, PhonesColumns,

 525                 PeopleColumns {

 526             /**

 527              * no public constructor since this is a utility class

 528              */

 529             private Phones() {}

 530 

 531             /**

 532              * The directory twig for this sub-table

 533              */

 534             public static final String CONTENT_DIRECTORY = "phones";

 535 

 536             /**

 537              * The default sort order for this table

 538              */

 539             public static final String DEFAULT_SORT_ORDER = "number ASC";

 540         }

 541 

 542         /**

 543          * A subdirectory of a single person that contains all of their

 544          * ContactMethods.

 545          */

 546         public static final class ContactMethods

 547                 implements BaseColumns, ContactMethodsColumns, PeopleColumns {

 548             /**

 549              * no public constructor since this is a utility class

 550              */

 551             private ContactMethods() {}

 552 

 553             /**

 554              * The directory twig for this sub-table

 555              */

 556             public static final String CONTENT_DIRECTORY = "contact_methods";

 557 

 558             /**

 559              * The default sort order for this table

 560              */

 561             public static final String DEFAULT_SORT_ORDER = "data ASC";

 562         }

 563 

 564 //        /**

 565 //         * The extensions for a person

 566 //         */

 567 //        public static class Extensions implements BaseColumns, ExtensionsColumns {

 568 //            /**

 569 //             * no public constructor since this is a utility class

 570 //             */

 571 //            private Extensions() {}

 572 //

 573 //            /**

 574 //             * The directory twig for this sub-table

 575 //             */

 576 //            public static final String CONTENT_DIRECTORY = "extensions";

 577 //

 578 //            /**

 579 //             * The default sort order for this table

 580 //             */

 581 //            public static final String DEFAULT_SORT_ORDER = "name ASC";

 582 //

 583 //            /**

 584 //             * The ID of the person this phone number is assigned to.

 585 //             * <P>Type: INTEGER (long)</P>

 586 //             */

 587 //            public static final String PERSON_ID = "person";

 588 //        }

 589 //    }

 590 //

 591 //    /**

 592 //     * Columns from the groups table.

 593 //     */

 594 //    public interface GroupsColumns {

 595 //        /**

 596 //         * The group name.

 597 //         * <P>Type: TEXT</P>

 598 //         */

 599 //        public static final String NAME = "name";

 600 //

 601 //        /**

 602 //         * Notes about the group.

 603 //         * <P>Type: TEXT</P>

 604 //         */

 605 //        public static final String NOTES = "notes";

 606 //

 607 //        /**

 608 //         * Whether this group should be synced if the SYNC_EVERYTHING settings is false

 609 //         * for this group's account.

 610 //         * <P>Type: INTEGER (boolean)</P>

 611 //         */

 612 //        public static final String SHOULD_SYNC = "should_sync";

 613 //

 614 //        /**

 615 //         * The ID of this group if it is a System Group, null otherwise.

 616 //         * <P>Type: TEXT</P>

 617 //         */

 618 //        public static final String SYSTEM_ID = "system_id";

 619 //    }

 620 //

 621 //    /**

 622 //     * This table contains the groups for an account.

 623 //     */

 624 //    public static final class Groups

 625 //            implements BaseColumns, SyncConstValue, GroupsColumns {

 626 //        /**

 627 //         * no public constructor since this is a utility class

 628 //         */

 629 //        private Groups() {}

 630 //

 631 //        /**

 632 //         * The content:// style URL for this table

 633 //         */

 634 //        public static final Uri CONTENT_URI =

 635 //            Uri.parse("content://contacts/groups");

 636 //

 637 //        /**

 638 //         * The content:// style URL for the table that holds the deleted

 639 //         * groups.

 640 //         */

 641 //        public static final Uri DELETED_CONTENT_URI =

 642 //            Uri.parse("content://contacts/deleted_groups");

 643 //

 644 //        /**

 645 //         * The MIME type of {@link #CONTENT_URI} providing a directory of

 646 //         * groups.

 647 //         */

 648 //        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup";

 649 //

 650 //        /**

 651 //         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single

 652 //         * group.

 653 //         */

 654 //        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup";

 655 //

 656 //        /**

 657 //         * The default sort order for this table

 658 //         */

 659 //        public static final String DEFAULT_SORT_ORDER = NAME + " ASC";

 660 //

 661 //        /**

 662 //         *

 663 //         */

 664 //        public static final String GROUP_ANDROID_STARRED = "Starred in Android";

 665 //

 666 //        /**

 667 //         * The "My Contacts" system group.

 668 //         */

 669 //        public static final String GROUP_MY_CONTACTS = "Contacts";

 670 //    }

 671 //

 672     /**

 673      * Columns from the Phones table that other columns join into themselves.

 674      */

 675     public interface PhonesColumns {

 676         /**

 677          * The type of the the phone number.

 678          * <P>Type: INTEGER (one of the constants below)</P>

 679          */

 680         public static final String TYPE = "type";

 681 

 682         public static final int TYPE_CUSTOM = 0;

 683         public static final int TYPE_HOME = 1;

 684         public static final int TYPE_MOBILE = 2;

 685         public static final int TYPE_WORK = 3;

 686         public static final int TYPE_FAX_WORK = 4;

 687         public static final int TYPE_FAX_HOME = 5;

 688         public static final int TYPE_PAGER = 6;

 689         public static final int TYPE_OTHER = 7;

 690 

 691         /**

 692          * The user provided label for the phone number, only used if TYPE is TYPE_CUSTOM.

 693          * <P>Type: TEXT</P>

 694          */

 695         public static final String LABEL = "label";

 696 

 697         /**

 698          * The phone number as the user entered it.

 699          * <P>Type: TEXT</P>

 700          */

 701         public static final String NUMBER = "number";

 702 

 703         /**

 704          * The normalized phone number

 705          * <P>Type: TEXT</P>

 706          */

 707         public static final String NUMBER_KEY = "number_key";

 708 

 709         /**

 710          * Whether this is the primary phone number

 711          * <P>Type: INTEGER (if set, non-0 means true)</P>

 712          */

 713         public static final String ISPRIMARY = "isprimary";

 714     }

 715 //

 716 //    /**

 717 //     * This table stores phone numbers and a reference to the person that the

 718 //     * contact method belongs to. Phone numbers are stored separately from

 719 //     * other contact methods to make caller ID lookup more efficient.

 720 //     */

 721 //    public static final class Phones

 722 //            implements BaseColumns, PhonesColumns, PeopleColumns {

 723 //        /**

 724 //         * no public constructor since this is a utility class

 725 //         */

 726 //        private Phones() {}

 727 //

 728 //        public static final CharSequence getDisplayLabel(Context context, int type,

 729 //                CharSequence label, CharSequence[] labelArray) {

 730 //            CharSequence display = "";

 731 //

 732 //            if (type != People.Phones.TYPE_CUSTOM) {

 733 //                CharSequence[] labels = labelArray != null? labelArray

 734 //                        : context.getResources().getTextArray(

 735 //                                com.android.internal.R.array.phoneTypes);

 736 //                try {

 737 //                    display = labels[type - 1];

 738 //                } catch (ArrayIndexOutOfBoundsException e) {

 739 //                    display = labels[People.Phones.TYPE_HOME - 1];

 740 //                }

 741 //            } else {

 742 //                if (!TextUtils.isEmpty(label)) {

 743 //                    display = label;

 744 //                }

 745 //            }

 746 //            return display;

 747 //        }

 748 //

 749 //        public static final CharSequence getDisplayLabel(Context context, int type,

 750 //                CharSequence label) {

 751 //            return getDisplayLabel(context, type, label, null);

 752 //        }

 753 //

 754 //        /**

 755 //         * The content:// style URL for this table

 756 //         */

 757 //        public static final Uri CONTENT_URI =

 758 //            Uri.parse("content://contacts/phones");

 759 //

 760 //        /**

 761 //         * The content:// style URL for filtering phone numbers

 762 //         */

 763 //        public static final Uri CONTENT_FILTER_URL =

 764 //            Uri.parse("content://contacts/phones/filter");

 765 //

 766 //        /**

 767 //         * The MIME type of {@link #CONTENT_URI} providing a directory of

 768 //         * phones.

 769 //         */

 770 //        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone";

 771 //

 772 //        /**

 773 //         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single

 774 //         * phone.

 775 //         */

 776 //        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";

 777 //

 778 //        /**

 779 //         * The default sort order for this table

 780 //         */

 781 //        public static final String DEFAULT_SORT_ORDER = "name ASC";

 782 //

 783 //        /**

 784 //         * The ID of the person this phone number is assigned to.

 785 //         * <P>Type: INTEGER (long)</P>

 786 //         */

 787 //        public static final String PERSON_ID = "person";

 788 //    }

 789 //

 790 //    public static final class GroupMembership implements BaseColumns, GroupsColumns {

 791 //        /**

 792 //         * no public constructor since this is a utility class

 793 //         */

 794 //        private GroupMembership() {}

 795 //

 796 //        /**

 797 //         * The content:// style URL for this table

 798 //         */

 799 //        public static final Uri CONTENT_URI =

 800 //            Uri.parse("content://contacts/groupmembership");

 801 //

 802 //        /**

 803 //         * The content:// style URL for this table

 804 //         */

 805 //        public static final Uri RAW_CONTENT_URI =

 806 //            Uri.parse("content://contacts/groupmembershipraw");

 807 //

 808 //        /**

 809 //         * The directory twig for this sub-table

 810 //         */

 811 //        public static final String CONTENT_DIRECTORY = "groupmembership";

 812 //        /**

 813 //         * The MIME type of {@link #CONTENT_URI} providing a directory of all

 814 //         * person groups.

 815 //         */

 816 //        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership";

 817 //

 818 //        /**

 819 //         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single

 820 //         * person group.

 821 //         */

 822 //        public static final String CONTENT_ITEM_TYPE =

 823 //                "vnd.android.cursor.item/contactsgroupmembership";

 824 //

 825 //        /**

 826 //         * The default sort order for this table

 827 //         */

 828 //        public static final String DEFAULT_SORT_ORDER = "group_id ASC";

 829 //

 830 //        /**

 831 //         * The row id of the accounts group.

 832 //         * <P>Type: TEXT</P>

 833 //         */

 834 //        public static final String GROUP_ID = "group_id";

 835 //

 836 //        /**

 837 //         * The sync id of the group.

 838 //         * <P>Type: TEXT</P>

 839 //         */

 840 //        public static final String GROUP_SYNC_ID = "group_sync_id";

 841 //

 842 //        /**

 843 //         * The account of the group.

 844 //         * <P>Type: TEXT</P>

 845 //         */

 846 //        public static final String GROUP_SYNC_ACCOUNT = "group_sync_account";

 847 //

 848 //        /**

 849 //         * The row id of the person.

 850 //         * <P>Type: TEXT</P>

 851 //         */

 852 //        public static final String PERSON_ID = "person";

 853 //    }

 854 //

 855     /**

 856      * Columns from the ContactMethods table that other tables join into

 857      * themseleves.

 858      */

 859     public interface ContactMethodsColumns {

 860         /**

 861          * The kind of the the contact method. For example, email address,

 862          * postal address, etc.

 863          * <P>Type: INTEGER (one of the values below)</P>

 864          */

 865         public static final String KIND = "kind";

 866 

 867         /**

 868          * The type of the contact method, must be one of the types below.

 869          * <P>Type: INTEGER (one of the values below)</P>

 870          */

 871         public static final String TYPE = "type";

 872         public static final int TYPE_CUSTOM = 0;

 873         public static final int TYPE_HOME = 1;

 874         public static final int TYPE_WORK = 2;

 875         public static final int TYPE_OTHER = 3;

 876 

 877         /**

 878          * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future.

 879          */

 880         public static final int MOBILE_EMAIL_TYPE_INDEX = 2;

 881 

 882         /**

 883          * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future.

 884          * This is not "mobile" but "CELL" since vCard uses it for identifying mobile phone.

 885          */

 886         public static final String MOBILE_EMAIL_TYPE_NAME = "_AUTO_CELL";

 887 

 888         /**

 889          * The user defined label for the the contact method.

 890          * <P>Type: TEXT</P>

 891          */

 892         public static final String LABEL = "label";

 893 

 894         /**

 895          * The data for the contact method.

 896          * <P>Type: TEXT</P>

 897          */

 898         public static final String DATA = "data";

 899 

 900         /**

 901          * Auxiliary data for the contact method.

 902          * <P>Type: TEXT</P>

 903          */

 904         public static final String AUX_DATA = "aux_data";

 905 

 906         /**

 907          * Whether this is the primary organization

 908          * <P>Type: INTEGER (if set, non-0 means true)</P>

 909          */

 910         public static final String ISPRIMARY = "isprimary";

 911     }

 912 //

 913 //    /**

 914 //     * This table stores all non-phone contact methods and a reference to the

 915 //     * person that the contact method belongs to.

 916 //     */

 917 //    public static final class ContactMethods

 918 //            implements BaseColumns, ContactMethodsColumns, PeopleColumns {

 919 //        /**

 920 //         * The column with latitude data for postal locations

 921 //         * <P>Type: REAL</P>

 922 //         */

 923 //        public static final String POSTAL_LOCATION_LATITUDE = DATA;

 924 //

 925 //        /**

 926 //         * The column with longitude data for postal locations

 927 //         * <P>Type: REAL</P>

 928 //         */

 929 //        public static final String POSTAL_LOCATION_LONGITUDE = AUX_DATA;

 930 //

 931 //        /**

 932 //         * The predefined IM protocol types. The protocol can either be non-present, one

 933 //         * of these types, or a free-form string. These cases are encoded in the AUX_DATA

 934 //         * column as:

 935 //         *  - null

 936 //         *  - pre:<an integer, one of the protocols below>

 937 //         *  - custom:<a string>

 938 //         */

 939 //        public static final int PROTOCOL_AIM = 0;

 940 //        public static final int PROTOCOL_MSN = 1;

 941 //        public static final int PROTOCOL_YAHOO = 2;

 942 //        public static final int PROTOCOL_SKYPE = 3;

 943 //        public static final int PROTOCOL_QQ = 4;

 944 //        public static final int PROTOCOL_GOOGLE_TALK = 5;

 945 //        public static final int PROTOCOL_ICQ = 6;

 946 //        public static final int PROTOCOL_JABBER = 7;

 947 //

 948 //        public static String encodePredefinedImProtocol(int protocol) {

 949 //            return "pre:" + protocol;

 950 //        }

 951 //

 952 //        public static String encodeCustomImProtocol(String protocolString) {

 953 //            return "custom:" + protocolString;

 954 //        }

 955 //

 956 //        public static Object decodeImProtocol(String encodedString) {

 957 //            if (encodedString == null) {

 958 //                return null;

 959 //            }

 960 //

 961 //            if (encodedString.startsWith("pre:")) {

 962 //                return Integer.parseInt(encodedString.substring(4));

 963 //            }

 964 //

 965 //            if (encodedString.startsWith("custom:")) {

 966 //                return encodedString.substring(7);

 967 //            }

 968 //

 969 //            throw new IllegalArgumentException(

 970 //                    "the value is not a valid encoded protocol, " + encodedString);

 971 //        }

 972 //

 973 //        /**

 974 //         * This looks up the provider name defined in

 975 //         * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.

 976 //         * This is used for interacting with the IM application.

 977 //         *

 978 //         * @param protocol the protocol ID

 979 //         * @return the provider name the IM app uses for the given protocol, or null if no

 980 //         * provider is defined for the given protocol

 981 //         * @hide

 982 //         */

 983 //        public static String lookupProviderNameFromId(int protocol) {

 984 //            switch (protocol) {

 985 //                case PROTOCOL_GOOGLE_TALK:

 986 //                    return Im.ProviderNames.GTALK;

 987 //                case PROTOCOL_AIM:

 988 //                    return Im.ProviderNames.AIM;

 989 //                case PROTOCOL_MSN:

 990 //                    return Im.ProviderNames.MSN;

 991 //                case PROTOCOL_YAHOO:

 992 //                    return Im.ProviderNames.YAHOO;

 993 //                case PROTOCOL_ICQ:

 994 //                    return Im.ProviderNames.ICQ;

 995 //                case PROTOCOL_JABBER:

 996 //                    return Im.ProviderNames.JABBER;

 997 //                case PROTOCOL_SKYPE:

 998 //                    return Im.ProviderNames.SKYPE;

 999 //                case PROTOCOL_QQ:

1000 //                    return Im.ProviderNames.QQ;

1001 //            }

1002 //            return null;

1003 //        }

1004 //

1005 //        /**

1006 //         * no public constructor since this is a utility class

1007 //         */

1008 //        private ContactMethods() {}

1009 //

1010 //        public static final CharSequence getDisplayLabel(Context context, int kind,

1011 //                int type, CharSequence label) {

1012 //            CharSequence display = "";

1013 //            switch (kind) {

1014 //                case KIND_EMAIL: {

1015 //                    if (type != People.ContactMethods.TYPE_CUSTOM) {

1016 //                        CharSequence[] labels = context.getResources().getTextArray(

1017 //                                com.android.internal.R.array.emailAddressTypes);

1018 //                        try {

1019 //                            display = labels[type - 1];

1020 //                        } catch (ArrayIndexOutOfBoundsException e) {

1021 //                            display = labels[ContactMethods.TYPE_HOME - 1];

1022 //                        }

1023 //                    } else {

1024 //                        if (!TextUtils.isEmpty(label)) {

1025 //                            if (label.toString().equals(MOBILE_EMAIL_TYPE_NAME)) {

1026 //                                display =

1027 //                                    context.getString(

1028 //                                            com.android.internal.R.string.mobileEmailTypeName);

1029 //                            } else {

1030 //                                display = label;

1031 //                            }

1032 //                        }

1033 //                    }

1034 //                    break;

1035 //                }

1036 //

1037 //                case KIND_POSTAL: {

1038 //                    if (type != People.ContactMethods.TYPE_CUSTOM) {

1039 //                        CharSequence[] labels = context.getResources().getTextArray(

1040 //                                com.android.internal.R.array.postalAddressTypes);

1041 //                        try {

1042 //                            display = labels[type - 1];

1043 //                        } catch (ArrayIndexOutOfBoundsException e) {

1044 //                            display = labels[ContactMethods.TYPE_HOME - 1];

1045 //                        }

1046 //                    } else {

1047 //                        if (!TextUtils.isEmpty(label)) {

1048 //                            display = label;

1049 //                        }

1050 //                    }

1051 //                    break;

1052 //                }

1053 //

1054 //                default:

1055 //                    display = context.getString(R.string.untitled);

1056 //            }

1057 //            return display;

1058 //        }

1059 //

1060 //        /**

1061 //         * Add a longitude and latitude location to a postal address.

1062 //         *

1063 //         * @param context the context to use when updating the database

1064 //         * @param postalId the address to update

1065 //         * @param latitude the latitude for the address

1066 //         * @param longitude the longitude for the address

1067 //         */

1068 //        public void addPostalLocation(Context context, long postalId,

1069 //                double latitude, double longitude) {

1070 //            final ContentResolver resolver = context.getContentResolver();

1071 //            // Insert the location

1072 //            ContentValues values = new ContentValues(2);

1073 //            values.put(POSTAL_LOCATION_LATITUDE, latitude);

1074 //            values.put(POSTAL_LOCATION_LONGITUDE, longitude);

1075 //            Uri loc = resolver.insert(CONTENT_URI, values);

1076 //            long locId = ContentUris.parseId(loc);

1077 //

1078 //            // Update the postal address

1079 //            values.clear();

1080 //            values.put(AUX_DATA, locId);

1081 //            resolver.update(ContentUris.withAppendedId(CONTENT_URI, postalId), values, null, null);

1082 //        }

1083 //

1084 //        /**

1085 //         * The content:// style URL for this table

1086 //         */

1087 //        public static final Uri CONTENT_URI =

1088 //            Uri.parse("content://contacts/contact_methods");

1089 //

1090 //        /**

1091 //         * The content:// style URL for sub-directory of e-mail addresses.

1092 //         */

1093 //        public static final Uri CONTENT_EMAIL_URI =

1094 //            Uri.parse("content://contacts/contact_methods/email");

1095 //

1096 //        /**

1097 //         * The MIME type of {@link #CONTENT_URI} providing a directory of

1098 //         * phones.

1099 //         */

1100 //        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods";

1101 //

1102 //        /**

1103 //         * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\

1104 //         * multiple {@link Contacts#KIND_EMAIL} entries.

1105 //         */

1106 //        public static final String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";

1107 //

1108 //        /**

1109 //         * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\

1110 //         * multiple {@link Contacts#KIND_POSTAL} entries.

1111 //         */

1112 //        public static final String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address";

1113 //

1114 //        /**

1115 //         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single

1116 //         * {@link Contacts#KIND_EMAIL} entry.

1117 //         */

1118 //        public static final String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";

1119 //

1120 //        /**

1121 //         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single

1122 //         * {@link Contacts#KIND_POSTAL} entry.

1123 //         */

1124 //        public static final String CONTENT_POSTAL_ITEM_TYPE

1125 //                = "vnd.android.cursor.item/postal-address";

1126 //

1127 //        /**

1128 //         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single

1129 //         * {@link Contacts#KIND_IM} entry.

1130 //         */

1131 //        public static final String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im";

1132 //

1133 //        /**

1134 //         * The default sort order for this table

1135 //         */

1136 //        public static final String DEFAULT_SORT_ORDER = "name ASC";

1137 //

1138 //        /**

1139 //         * The ID of the person this contact method is assigned to.

1140 //         * <P>Type: INTEGER (long)</P>

1141 //         */

1142 //        public static final String PERSON_ID = "person";

1143 //    }

1144 //

1145 //    /**

1146 //     * The IM presence columns with some contacts specific columns mixed in.

1147 //     */

1148 //    public interface PresenceColumns extends Im.CommonPresenceColumns {

1149 //        /**

1150 //         * The IM service the presence is coming from. Formatted using either

1151 //         * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or

1152 //         * {@link Contacts.ContactMethods#encodeCustomImProtocol}.

1153 //         * <P>Type: STRING</P>

1154 //         */

1155 //        public static final String IM_PROTOCOL = "im_protocol";

1156 //

1157 //        /**

1158 //         * The IM handle the presence item is for. The handle is scoped to

1159 //         * the {@link #IM_PROTOCOL}.

1160 //         * <P>Type: STRING</P>

1161 //         */

1162 //        public static final String IM_HANDLE = "im_handle";

1163 //

1164 //        /**

1165 //         * The IM account for the local user that the presence data came from.

1166 //         * <P>Type: STRING</P>

1167 //         */

1168 //        public static final String IM_ACCOUNT = "im_account";

1169 //    }

1170 //

1171 //    /**

1172 //     * Contains presence information about contacts.

1173 //     * @hide

1174 //     */

1175 //    public static final class Presence

1176 //            implements BaseColumns, PresenceColumns, PeopleColumns {

1177 //        /**

1178 //         * The content:// style URL for this table

1179 //         */

1180 //        public static final Uri CONTENT_URI =

1181 //            Uri.parse("content://contacts/presence");

1182 //

1183 //        /**

1184 //         * The ID of the person this presence item is assigned to.

1185 //         * <P>Type: INTEGER (long)</P>

1186 //         */

1187 //        public static final String PERSON_ID = "person";

1188 //

1189 //        /**

1190 //         * Gets the resource ID for the proper presence icon.

1191 //         *

1192 //         * @param status the status to get the icon for

1193 //         * @return the resource ID for the proper presence icon

1194 //         */

1195 //        public static final int getPresenceIconResourceId(int status) {

1196 //            switch (status) {

1197 //                case Contacts.People.AVAILABLE:

1198 //                    return com.android.internal.R.drawable.presence_online;

1199 //

1200 //                case Contacts.People.IDLE:

1201 //                case Contacts.People.AWAY:

1202 //                    return com.android.internal.R.drawable.presence_away;

1203 //

1204 //                case Contacts.People.DO_NOT_DISTURB:

1205 //                    return com.android.internal.R.drawable.presence_busy;

1206 //

1207 //                case Contacts.People.INVISIBLE:

1208 //                    return com.android.internal.R.drawable.presence_invisible;

1209 //

1210 //                case Contacts.People.OFFLINE:

1211 //                default:

1212 //                    return com.android.internal.R.drawable.presence_offline;

1213 //            }

1214 //        }

1215 //

1216 //        /**

1217 //         * Sets a presence icon to the proper graphic

1218 //         *

1219 //         * @param icon the icon to to set

1220 //         * @param serverStatus that status

1221 //         */

1222 //        public static final void setPresenceIcon(ImageView icon, int serverStatus) {

1223 //            icon.setImageResource(getPresenceIconResourceId(serverStatus));

1224 //        }

1225 //    }

1226 //

1227     /**

1228      * Columns from the Organizations table that other columns join into themselves.

1229      */

1230     public interface OrganizationColumns {

1231         /**

1232          * The type of the organizations.

1233          * <P>Type: INTEGER (one of the constants below)</P>

1234          */

1235         public static final String TYPE = "type";

1236 

1237         public static final int TYPE_CUSTOM = 0;

1238         public static final int TYPE_WORK = 1;

1239         public static final int TYPE_OTHER = 2;

1240 

1241         /**

1242          * The user provided label, only used if TYPE is TYPE_CUSTOM.

1243          * <P>Type: TEXT</P>

1244          */

1245         public static final String LABEL = "label";

1246 

1247         /**

1248          * The name of the company for this organization.

1249          * <P>Type: TEXT</P>

1250          */

1251         public static final String COMPANY = "company";

1252 

1253         /**

1254          * The title within this organization.

1255          * <P>Type: TEXT</P>

1256          */

1257         public static final String TITLE = "title";

1258 

1259         /**

1260          * The person this organization is tied to.

1261          * <P>Type: TEXT</P>

1262          */

1263         public static final String PERSON_ID = "person";

1264 

1265         /**

1266          * Whether this is the primary organization

1267          * <P>Type: INTEGER (if set, non-0 means true)</P>

1268          */

1269         public static final String ISPRIMARY = "isprimary";

1270     }

1271 //

1272 //    /**

1273 //     * A sub directory of a single person that contains all of their Phones.

1274 //     */

1275 //    public static final class Organizations implements BaseColumns, OrganizationColumns {

1276 //        /**

1277 //         * no public constructor since this is a utility class

1278 //         */

1279 //        private Organizations() {}

1280 //

1281 //        public static final CharSequence getDisplayLabel(Context context, int type,

1282 //                CharSequence label) {

1283 //            CharSequence display = "";

1284 //

1285 //            if (type != TYPE_CUSTOM) {

1286 //                CharSequence[] labels = context.getResources().getTextArray(

1287 //                        com.android.internal.R.array.organizationTypes);

1288 //                try {

1289 //                    display = labels[type - 1];

1290 //                } catch (ArrayIndexOutOfBoundsException e) {

1291 //                    display = labels[Organizations.TYPE_WORK - 1];

1292 //                }

1293 //            } else {

1294 //                if (!TextUtils.isEmpty(label)) {

1295 //                    display = label;

1296 //                }

1297 //            }

1298 //            return display;

1299 //        }

1300 //

1301 //        /**

1302 //         * The content:// style URL for this table

1303 //         */

1304 //        public static final Uri CONTENT_URI =

1305 //            Uri.parse("content://contacts/organizations");

1306 //

1307 //        /**

1308 //         * The directory twig for this sub-table

1309 //         */

1310 //        public static final String CONTENT_DIRECTORY = "organizations";

1311 //

1312 //        /**

1313 //         * The default sort order for this table

1314 //         */

1315 //        public static final String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";

1316 //    }

1317 //

1318 //    /**

1319 //     * Columns from the Photos table that other columns join into themselves.

1320 //     */

1321 //    public interface PhotosColumns {

1322 //        /**

1323 //         * The _SYNC_VERSION of the photo that was last downloaded

1324 //         * <P>Type: TEXT</P>

1325 //         */

1326 //        public static final String LOCAL_VERSION = "local_version";

1327 //

1328 //        /**

1329 //         * The person this photo is associated with.

1330 //         * <P>Type: TEXT</P>

1331 //         */

1332 //        public static final String PERSON_ID = "person";

1333 //

1334 //        /**

1335 //         * non-zero if a download is required and the photo isn't marked as a bad resource.

1336 //         * You must specify this in the columns in order to use it in the where clause.

1337 //         * <P>Type: INTEGER(boolean)</P>

1338 //         */

1339 //        public static final String DOWNLOAD_REQUIRED = "download_required";

1340 //

1341 //        /**

1342 //         * non-zero if this photo is known to exist on the server

1343 //         * <P>Type: INTEGER(boolean)</P>

1344 //         */

1345 //        public static final String EXISTS_ON_SERVER = "exists_on_server";

1346 //

1347 //        /**

1348 //         * Contains the description of the upload or download error from

1349 //         * the previous attempt. If null then the previous attempt succeeded.

1350 //         * <P>Type: TEXT</P>

1351 //         */

1352 //        public static final String SYNC_ERROR = "sync_error";

1353 //

1354 //        /**

1355 //         * The image data, or null if there is no image.

1356 //         * <P>Type: BLOB</P>

1357 //         */

1358 //        public static final String DATA = "data";

1359 //

1360 //    }

1361 //

1362 //    /**

1363 //     * The photos over all of the people

1364 //     */

1365 //    public static final class Photos implements BaseColumns, PhotosColumns, SyncConstValue {

1366 //        /**

1367 //         * no public constructor since this is a utility class

1368 //         */

1369 //        private Photos() {}

1370 //

1371 //        /**

1372 //         * The content:// style URL for this table

1373 //         */

1374 //        public static final Uri CONTENT_URI =

1375 //            Uri.parse("content://contacts/photos");

1376 //

1377 //        /**

1378 //         * The directory twig for this sub-table

1379 //         */

1380 //        public static final String CONTENT_DIRECTORY = "photo";

1381 //

1382 //        /**

1383 //         * The default sort order for this table

1384 //         */

1385 //        public static final String DEFAULT_SORT_ORDER = "person ASC";

1386 //    }

1387 //

1388 //    public interface ExtensionsColumns {

1389 //        /**

1390 //         * The name of this extension. May not be null. There may be at most one row for each name.

1391 //         * <P>Type: TEXT</P>

1392 //         */

1393 //        public static final String NAME = "name";

1394 //

1395 //        /**

1396 //         * The value of this extension. May not be null.

1397 //         * <P>Type: TEXT</P>

1398 //         */

1399 //        public static final String VALUE = "value";

1400 //    }

1401 //

1402 //    /**

1403 //     * The extensions for a person

1404 //     */

1405 //    public static final class Extensions implements BaseColumns, ExtensionsColumns {

1406 //        /**

1407 //         * no public constructor since this is a utility class

1408 //         */

1409 //        private Extensions() {}

1410 //

1411 //        /**

1412 //         * The content:// style URL for this table

1413 //         */

1414 //        public static final Uri CONTENT_URI =

1415 //            Uri.parse("content://contacts/extensions");

1416 //

1417 //        /**

1418 //         * The MIME type of {@link #CONTENT_URI} providing a directory of

1419 //         * phones.

1420 //         */

1421 //        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions";

1422 //

1423 //        /**

1424 //         * The MIME type of a {@link #CONTENT_URI} subdirectory of a single

1425 //         * phone.

1426 //         */

1427 //        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions";

1428 //        /**

1429 //         * The default sort order for this table

1430 //         */

1431 //        public static final String DEFAULT_SORT_ORDER = "person, name ASC";

1432 //

1433 //        /**

1434 //         * The ID of the person this phone number is assigned to.

1435 //         * <P>Type: INTEGER (long)</P>

1436 //         */

1437 //        public static final String PERSON_ID = "person";

1438 //    }

1439 //

1440 //    /**

1441 //     * Contains helper classes used to create or manage {@link android.content.Intent Intents}

1442 //     * that involve contacts.

1443 //     */

1444 //    public static final class Intents {

1445 //        /**

1446 //         * This is the intent that is fired when a search suggestion is clicked on.

1447 //         */

1448 //        public static final String SEARCH_SUGGESTION_CLICKED =

1449 //                "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";

1450 //

1451 //        /**

1452 //         * This is the intent that is fired when a search suggestion for dialing a number

1453 //         * is clicked on.

1454 //         */

1455 //        public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =

1456 //                "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";

1457 //

1458 //        /**

1459 //         * This is the intent that is fired when a search suggestion for creating a contact

1460 //         * is clicked on.

1461 //         */

1462 //        public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =

1463 //                "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";

1464 //

1465 //        /**

1466 //         * Starts an Activity that lets the user pick a contact to attach an image to.

1467 //         * After picking the contact it launches the image cropper in face detection mode.

1468 //         */

1469 //        public static final String ATTACH_IMAGE =

1470 //                "com.android.contacts.action.ATTACH_IMAGE";

1471 //

1472 //        /**

1473 //         * Takes as input a data URI with a mailto: or tel: scheme. If a single

1474 //         * contact exists with the given data it will be shown. If no contact

1475 //         * exists, a dialog will ask the user if they want to create a new

1476 //         * contact with the provided details filled in. If multiple contacts

1477 //         * share the data the user will be prompted to pick which contact they

1478 //         * want to view.

1479 //         * <p>

1480 //         * For <code>mailto:</code> URIs, the scheme specific portion must be a

1481 //         * raw email address, such as one built using

1482 //         * {@link Uri#fromParts(String, String, String)}.

1483 //         * <p>

1484 //         * For <code>tel:</code> URIs, the scheme specific portion is compared

1485 //         * to existing numbers using the standard caller ID lookup algorithm.

1486 //         * The number must be properly encoded, for example using

1487 //         * {@link Uri#fromParts(String, String, String)}.

1488 //         * <p>

1489 //         * Any extras from the {@link Insert} class will be passed along to the

1490 //         * create activity if there are no contacts to show.

1491 //         * <p>

1492 //         * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip

1493 //         * prompting the user when the contact doesn't exist.

1494 //         */

1495 //        public static final String SHOW_OR_CREATE_CONTACT =

1496 //                "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";

1497 //

1498 //        /**

1499 //         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new

1500 //         * contact if no matching contact found. Otherwise, default behavior is

1501 //         * to prompt user with dialog before creating.

1502 //         * <p>

1503 //         * Type: BOOLEAN

1504 //         */

1505 //        public static final String EXTRA_FORCE_CREATE =

1506 //                "com.android.contacts.action.FORCE_CREATE";

1507 //

1508 //        /**

1509 //         * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact

1510 //         * description to be shown when prompting user about creating a new

1511 //         * contact.

1512 //         * <p>

1513 //         * Type: STRING

1514 //         */

1515 //        public static final String EXTRA_CREATE_DESCRIPTION =

1516 //            "com.android.contacts.action.CREATE_DESCRIPTION";

1517 //

1518 //        /**

1519 //         * Intents related to the Contacts app UI.

1520 //         */

1521 //        public static final class UI {

1522 //            /**

1523 //             * The action for the default contacts list tab.

1524 //             */

1525 //            public static final String LIST_DEFAULT =

1526 //                    "com.android.contacts.action.LIST_DEFAULT";

1527 //

1528 //            /**

1529 //             * The action for the contacts list tab.

1530 //             */

1531 //            public static final String LIST_GROUP_ACTION =

1532 //                    "com.android.contacts.action.LIST_GROUP";

1533 //

1534 //            /**

1535 //             * When in LIST_GROUP_ACTION mode, this is the group to display.

1536 //             */

1537 //            public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";

1538 //

1539 //            /**

1540 //             * The action for the all contacts list tab.

1541 //             */

1542 //            public static final String LIST_ALL_CONTACTS_ACTION =

1543 //                    "com.android.contacts.action.LIST_ALL_CONTACTS";

1544 //

1545 //            /**

1546 //             * The action for the contacts with phone numbers list tab.

1547 //             */

1548 //            public static final String LIST_CONTACTS_WITH_PHONES_ACTION =

1549 //                    "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";

1550 //

1551 //            /**

1552 //             * The action for the starred contacts list tab.

1553 //             */

1554 //            public static final String LIST_STARRED_ACTION =

1555 //                    "com.android.contacts.action.LIST_STARRED";

1556 //

1557 //            /**

1558 //             * The action for the frequent contacts list tab.

1559 //             */

1560 //            public static final String LIST_FREQUENT_ACTION =

1561 //                    "com.android.contacts.action.LIST_FREQUENT";

1562 //

1563 //            /**

1564 //             * The action for the "strequent" contacts list tab. It first lists the starred

1565 //             * contacts in alphabetical order and then the frequent contacts in descending

1566 //             * order of the number of times they have been contacted.

1567 //             */

1568 //            public static final String LIST_STREQUENT_ACTION =

1569 //                    "com.android.contacts.action.LIST_STREQUENT";

1570 //

1571 //            /**

1572 //             * A key for to be used as an intent extra to set the activity

1573 //             * title to a custom String value.

1574 //             */

1575 //            public static final String TITLE_EXTRA_KEY =

1576 //                "com.android.contacts.extra.TITLE_EXTRA";

1577 //

1578 //            /**

1579 //             * Activity Action: Display a filtered list of contacts

1580 //             * <p>

1581 //             * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for

1582 //             * filtering

1583 //             * <p>

1584 //             * Output: Nothing.

1585 //             */

1586 //            public static final String FILTER_CONTACTS_ACTION =

1587 //                "com.android.contacts.action.FILTER_CONTACTS";

1588 //

1589 //            /**

1590 //             * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}

1591 //             * intents to supply the text on which to filter.

1592 //             */

1593 //            public static final String FILTER_TEXT_EXTRA_KEY =

1594 //                "com.android.contacts.extra.FILTER_TEXT";

1595 //        }

1596 //

1597 //        /**

1598 //         * Convenience class that contains string constants used

1599 //         * to create contact {@link android.content.Intent Intents}.

1600 //         */

1601 //        public static final class Insert {

1602 //            /** The action code to use when adding a contact */

1603 //            public static final String ACTION = Intent.ACTION_INSERT;

1604 //

1605 //            /**

1606 //             * If present, forces a bypass of quick insert mode.

1607 //             */

1608 //            public static final String FULL_MODE = "full_mode";

1609 //

1610 //            /**

1611 //             * The extra field for the contact name.

1612 //             * <P>Type: String</P>

1613 //             */

1614 //            public static final String NAME = "name";

1615 //

1616 //            /**

1617 //             * The extra field for the contact phonetic name.

1618 //             * <P>Type: String</P>

1619 //             */

1620 //            public static final String PHONETIC_NAME = "phonetic_name";

1621 //

1622 //            /**

1623 //             * The extra field for the contact company.

1624 //             * <P>Type: String</P>

1625 //             */

1626 //            public static final String COMPANY = "company";

1627 //

1628 //            /**

1629 //             * The extra field for the contact job title.

1630 //             * <P>Type: String</P>

1631 //             */

1632 //            public static final String JOB_TITLE = "job_title";

1633 //

1634 //            /**

1635 //             * The extra field for the contact notes.

1636 //             * <P>Type: String</P>

1637 //             */

1638 //            public static final String NOTES = "notes";

1639 //

1640 //            /**

1641 //             * The extra field for the contact phone number.

1642 //             * <P>Type: String</P>

1643 //             */

1644 //            public static final String PHONE = "phone";

1645 //

1646 //            /**

1647 //             * The extra field for the contact phone number type.

1648 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},

1649 //             *  or a string specifying a custom label.</P>

1650 //             */

1651 //            public static final String PHONE_TYPE = "phone_type";

1652 //

1653 //            /**

1654 //             * The extra field for the phone isprimary flag.

1655 //             * <P>Type: boolean</P>

1656 //             */

1657 //            public static final String PHONE_ISPRIMARY = "phone_isprimary";

1658 //

1659 //            /**

1660 //             * The extra field for an optional second contact phone number.

1661 //             * <P>Type: String</P>

1662 //             */

1663 //            public static final String SECONDARY_PHONE = "secondary_phone";

1664 //

1665 //            /**

1666 //             * The extra field for an optional second contact phone number type.

1667 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},

1668 //             *  or a string specifying a custom label.</P>

1669 //             */

1670 //            public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";

1671 //

1672 //            /**

1673 //             * The extra field for an optional third contact phone number.

1674 //             * <P>Type: String</P>

1675 //             */

1676 //            public static final String TERTIARY_PHONE = "tertiary_phone";

1677 //

1678 //            /**

1679 //             * The extra field for an optional third contact phone number type.

1680 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},

1681 //             *  or a string specifying a custom label.</P>

1682 //             */

1683 //            public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";

1684 //

1685 //            /**

1686 //             * The extra field for the contact email address.

1687 //             * <P>Type: String</P>

1688 //             */

1689 //            public static final String EMAIL = "email";

1690 //

1691 //            /**

1692 //             * The extra field for the contact email type.

1693 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}

1694 //             *  or a string specifying a custom label.</P>

1695 //             */

1696 //            public static final String EMAIL_TYPE = "email_type";

1697 //

1698 //            /**

1699 //             * The extra field for the email isprimary flag.

1700 //             * <P>Type: boolean</P>

1701 //             */

1702 //            public static final String EMAIL_ISPRIMARY = "email_isprimary";

1703 //

1704 //            /**

1705 //             * The extra field for an optional second contact email address.

1706 //             * <P>Type: String</P>

1707 //             */

1708 //            public static final String SECONDARY_EMAIL = "secondary_email";

1709 //

1710 //            /**

1711 //             * The extra field for an optional second contact email type.

1712 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}

1713 //             *  or a string specifying a custom label.</P>

1714 //             */

1715 //            public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";

1716 //

1717 //            /**

1718 //             * The extra field for an optional third contact email address.

1719 //             * <P>Type: String</P>

1720 //             */

1721 //            public static final String TERTIARY_EMAIL = "tertiary_email";

1722 //

1723 //            /**

1724 //             * The extra field for an optional third contact email type.

1725 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}

1726 //             *  or a string specifying a custom label.</P>

1727 //             */

1728 //            public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";

1729 //

1730 //            /**

1731 //             * The extra field for the contact postal address.

1732 //             * <P>Type: String</P>

1733 //             */

1734 //            public static final String POSTAL = "postal";

1735 //

1736 //            /**

1737 //             * The extra field for the contact postal address type.

1738 //             * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}

1739 //             *  or a string specifying a custom label.</P>

1740 //             */

1741 //            public static final String POSTAL_TYPE = "postal_type";

1742 //

1743 //            /**

1744 //             * The extra field for the postal isprimary flag.

1745 //             * <P>Type: boolean</P>

1746 //             */

1747 //            public static final String POSTAL_ISPRIMARY = "postal_isprimary";

1748 //

1749 //            /**

1750 //             * The extra field for an IM handle.

1751 //             * <P>Type: String</P>

1752 //             */

1753 //            public static final String IM_HANDLE = "im_handle";

1754 //

1755 //            /**

1756 //             * The extra field for the IM protocol

1757 //             * <P>Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}

1758 //             * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.</P>

1759 //             */

1760 //            public static final String IM_PROTOCOL = "im_protocol";

1761 //

1762 //            /**

1763 //             * The extra field for the IM isprimary flag.

1764 //             * <P>Type: boolean</P>

1765 //             */

1766 //            public static final String IM_ISPRIMARY = "im_isprimary";

1767 //        }

1768 //    }

1769 }

最后附上导入导出的方法

  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         }

 

 

你可能感兴趣的:(android)