Android 内置群组,联系人

这样一个需求,手机第一次启动的时候,需要内置一个群组,并且里面有给定的联系人信息,

本来打算写双进程守护的,结果昨天接到一个这样的任务,就先把它做了,发现里面有些操作数据库的东西还是值得看一下。

首先接到这样一个需求第一眼就是懵逼,然后还是得硬着头皮搞,接下来分析下这个需求需要怎么搞:

1、首先第一次启动 Android 有一个开机启动的广播;

2、启动后去内置一个群组;

3、内置客户给的联系人;

4、把联系人加到群组里面。

根据这四个步骤我们来一步一步搞定(透漏一下这篇文章的精华所在 就是最后一步把联系人加到群组里面 这个网上找了好久都没找到)

1、开机启动广播

由于我是基于源码开发的即在android原生的contacts进行修改

android源码中应用层关于contacts的代码位于

packages\apps\Contacts

packages\apps\ContactsCommon

这两个地方

基于源码开发一般先要看看源码中有没有我们需要的开机广播有的话我们就不需要重新去写这些代码了,一方面省事,另一方面既然源码里面已经有

了,我们在去重新写 会显得代码比较混乱。

通过搜索发现有这样一个类BootCmpReceiver.java

中有接受开机广播的地方

else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
            // fix ALPS01003520,when boot complete,remove the contacts if the
            // card of a slot has been removed
            if (!isPhbReady()) {
                processBootComplete(context);
            }
            // [START] add for Preset service number

            presetServiceNumber(context);

            // [END]
        }

  private void presetServiceNumber(Context context) {
        SIMProcessorBase processor = null;
        LogUtils.d(TAG, "presetServiceNumber");
       // processor = new PresetContactsImportProcessor(context, -1, null, null);

        startSimService(context, -1, SIMServiceUtils.SERVICE_WORK_IMPORT_PRESET_CONTACTS);

    }

private void startSimService(Context context, int subId, int workType) {
        Intent intent = null;
        intent = new Intent(context, SIMProcessorService.class);
        intent.putExtra(SIMServiceUtils.SERVICE_SUBSCRIPTION_KEY, subId);
        intent.putExtra(SIMServiceUtils.SERVICE_WORK_TYPE, workType);
        LogUtils.d(TAG, "[startSimService]subId:" + subId + "|workType:" + workType);
        context.startService(intent);
    }

所以我在其中加了这几段启动服务的代码 看这代码结构也许跟google原生的不一样这是我们公司修修改改后的结果 我们主要分析原理

首先找到开机广播 在里面加入我们的函数presetServiceNumber(context) 然后开启服务去执行我们的内置群组、联系人的操作

2、 内置群组

private void addDefaultGroups() {
            Uri uri = Groups.CONTENT_URI;
            StringBuilder selection = new StringBuilder();
            selection.append(Groups.DELETED + "=0");
            selection.append(" AND " + Groups.TITLE + "='" + "ROAMING" + "'");
            Cursor groupCursor = mContext.getContentResolver().query(uri,
                 new String[] { Groups._ID, Groups.TITLE },   selection.toString(), null, null);
            try {
                if (groupCursor != null && groupCursor.getCount() > 0) {
                    return;
                } else {
                    String defaultGroups[] = "ROAMING";
                    final ArrayList operationList = new ArrayList();
                    ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(uri);
                    ContentValues groupValues = new ContentValues();

                        groupValues.put(Groups.ACCOUNT_NAME,AccountType.ACCOUNT_NAME_LOCAL_PHONE);
                        groupValues.put(Groups.ACCOUNT_TYPE,AccountType.ACCOUNT_TYPE_LOCAL_PHONE);
                        groupValues.put(Groups.TITLE, defaultGroups);
                        groupValues.put(Groups.GROUP_IS_READ_ONLY, 1);
                        builder.withValues(groupValues);
                        operationList.add(builder.build());
                        try {
                            mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList);
                            groupValues.clear();
                            operationList.clear();
                        } catch (RemoteException e) {
                           Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
                        } catch (OperationApplicationException e) {
                            Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
                        }

                }
            } finally {
                if (groupCursor != null) {
                    groupCursor.close();
                }
            }
        }

去掉不相关的代码这就是我们内置群组的核心代码,

看上面代码 首先我们去查询群组名为“ROAMING”的群组是否存在。

当Groups.DELETED=0的时候, 是 查询没有被删除的联系人分组

当Groups.DELETED=1的时候,是查询删除的分组

如果存在就return了,不存在我们就是新建,新建群组的大部分都都相似主要是

groupValues.put(Groups.TITLE, defaultGroups); //群组的TITLE

groupValues.put(Groups.GROUP_IS_READ_ONLY, 1); //是否只读

3、内置联系人

private void importDefaultReadonlyContact(){
       for(int i = 0;i < INSERT_PRESET_NAME.length; i++) {
           Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(INSERT_PRESET_NUMBER[i]));
           Cursor contactCursor = mContext.getContentResolver().query(uri,
                              new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_ID}, null, null, null);
               try {
               if (contactCursor != null && contactCursor.getCount() > 0) {
                return;
               } else {
                final ArrayList operationList = new ArrayList();
                ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
                ContentValues contactvalues = new ContentValues();
                contactvalues.put(RawContacts.ACCOUNT_NAME, AccountType.ACCOUNT_NAME_LOCAL_PHONE);
                contactvalues.put(RawContacts.ACCOUNT_TYPE, AccountType.ACCOUNT_TYPE_LOCAL_PHONE);
                contactvalues.put(RawContacts.INDICATE_PHONE_SIM, ContactsContract.RawContacts.INDICATE_PHONE);
                contactvalues.put(RawContacts.IS_SDN_CONTACT, -2);
                builder.withValues(contactvalues);
                builder.withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
                operationList.add(builder.build());
                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
                builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0);
                builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
                builder.withValue(Phone.TYPE, Phone.TYPE_MOBILE);
                builder.withValue(Phone.NUMBER, INSERT_PRESET_NUMBER[i]);
                builder.withValue(Data.IS_PRIMARY, 1);
                operationList.add(builder.build());  

                builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
                builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0);
                builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
                builder.withValue(StructuredName.DISPLAY_NAME, INSERT_PRESET_NAME[i]);
                operationList.add(builder.build());

                try {
                    mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList);
                } catch (RemoteException e) {
                    Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
                } catch (OperationApplicationException e) {
                    Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
                }
           }
       } finally {
           if (contactCursor != null) {
               contactCursor.close();
           }
       }
    }
  }

去掉不相关的代码这就是我们内置联系人的核心代码 其中INSERT_PRESET_NUMBER是我们的联系人号码数组可以写 如{“185…..”,”158…..”,”137….”}等

INSERT_PRESET_NAME是联系人姓名数组可以写 如{“张三”,“李四”,“王五”}等

首先也是查询数据库看看我们的联系人号码是否存在,存在的话就 return

不存在的话就去创建

联系人的操作大部分也都是一样的

主要是

builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); //MIME类型

builder.withValue(Phone.TYPE, Phone.TYPE_MOBILE);//phone类型可以是 号码 姓名之类的

builder.withValue(Phone.NUMBER, INSERT_PRESET_NUMBER[i]);//号码

builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); //MIME类型

builder.withValue(StructuredName.DISPLAY_NAME, INSERT_PRESET_NAME[i]);//姓名

还可以加入邮箱之类的,

builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); //MIME类型

builder.withValue(Email.TYPE, Email.TYPE_MOBILE);//Email类型

builder.withValue(Email.DATA, email);//EMail

4、把联系人加到群组里面。

怎么把联系人加入到群组呢

有两种方法 第一种是内置联系人是 在联系人中加入群组标示;

第二中是内置群组后,把联系人批量导入群组

我们今天用第一种方式实现:

首先看联系人的操作

builder.withValue(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);//MIME类型

builder.withValue(GroupMembership.GROUP_ROW_ID, grpId);//群组

我们可以通过这样把联系人加如群组标签

所以这里我们关键的操作就是找到grpId即我们要加入群组ID

 Uri urigroup = Groups.CONTENT_URI;
       StringBuilder selection = new StringBuilder();
       selection.append(Groups.DELETED + "=0");
       selection.append(" AND " + Groups.TITLE + "='" + "ROAMING CUSTOMER CARE" + "'");
       Cursor groupCursor = mContext.getContentResolver().query(urigroup,
           new String[] { Groups._ID, Groups.TITLE }, selection.toString(), null, null);
       try {
           if(groupCursor!=null && groupCursor.getCount()>0 ){
               while (groupCursor.moveToNext()) {
                   grpId =   groupCursor.getLong(groupCursor.getColumnIndex(Groups._ID));
            }
           }else{
               addDefaultGroups();
           }
       }finally {
           if (groupCursor != null) {
               groupCursor.close();
           }
       }

跟内置群组操作差不多一样但是这么我们如果查询到的话就取出这个群组的id如果不存在就是内置群组,

经过上面这四步我们就能顺利的吧联系人内置到群组里面了。

上一篇:Endless Sky源码学习笔记-3


下一篇:统计功能和子对象的大小信息查询Bug