`

android通讯录开发

 
阅读更多
这周也空闲,所以继续花时间看下关于android内部应用的一些东西。比如通讯录,这个东西比自己想的还要麻烦些,通讯录可以和相关的账号关联起来。比如user1,对应有test1,test2,帐户user2对应有联系人test3,test4。因此先得添加帐户,然而模拟器测试的时候发现帐号还得联网绑定才行,结果试了下联不上,晕!
于是试着用程序的方式添加帐号,这个也不容易,在网上找了很久的资料,有本android应用开发揭密有段代码勉强达到效果了,但是有些原理还是不太明白。再结合了下sdk本身的例子contactmanager的代码,把帐号和联系人的功能合在了一起。因此这个功能主要有四个功能:
1.查询帐号
2.增加帐号
3.增加联系人
4.查询联系人

大的功能就是这四个,如果像我这等入行不久的人来看的话,值得细究的东西很多,一个一个的讲的话篇幅会很长,因此挑部分重点的讲下吧!
一、查询帐号部分:

/*查询某一种类型的帐号*/
AccountManager _am = AccountManager.get(this);
Account[] accounts = _am.getAccountsByType(getString(R.string.ACCOUNT_TYPE));

查询所有类型帐号:
AuthenticatorDescription[] accountTypes = AccountManager.get(this).getAuthenticatorTypes();
for (int i = 0; i < a.length; i++) {
     String systemAccountType = a[i].type;
     AuthenticatorDescription ad = getAuthenticatorDescription(systemAccountType,
                    accountTypes);
     AccountData data = new AccountData(a[i].name, ad);
     mAccounts.add(data);
 }

上面这段代码不但能查询所有帐号,还包括每种帐号类型的描述。其中contactmanager有个显示帐号的下拉菜单spinner,如图:


这个东西实现起来有点麻烦。首先添加帐号时,得把帐号相关的基本信息包括图片都包括进去,有个叫authenticator.xml的文件:
 <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.yarin.AccountType"
    android:icon="@drawable/ic_launcher"
    android:smallIcon="@drawable/ic_launcher"
    android:label="@string/ACCOUNT_LABEL"
 />

上面是对帐号图标及label、类型的描述。要达到上面显示的效果,得自定义spinner的外观,代码如下:
private class AccountAdapter extends ArrayAdapter<AccountData> {
        public AccountAdapter(Context context, ArrayList<AccountData> accountData) {
            super(context, android.R.layout.simple_spinner_item, accountData);//simple_spinner_item为系统自带
            setDropDownViewResource(R.layout.account_entry);
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            // Inflate a view template
            if (convertView == null) {
                LayoutInflater layoutInflater = getLayoutInflater();
                convertView = layoutInflater.inflate(R.layout.account_entry, parent, false);
            }
            TextView firstAccountLine = (TextView) convertView.findViewById(R.id.firstAccountLine);
            TextView secondAccountLine = (TextView) convertView.findViewById(R.id.secondAccountLine);
            ImageView accountIcon = (ImageView) convertView.findViewById(R.id.accountIcon);

            // Populate template
            AccountData data = getItem(position);
            firstAccountLine.setText(data.getName());
            secondAccountLine.setText(data.getTypeLabel());
            Drawable icon = data.getIcon();
            if (icon == null) {
                icon = getResources().getDrawable(android.R.drawable.ic_menu_search);//系统图标
            }
            accountIcon.setImageDrawable(icon);
            return convertView;
        }
    }

这个类主要实现了自定义spinner的作用,这引用了外部的布局文件R.layout.account_entry。这个文件相对来说易懂,就不说了。

二、添加帐号。帐号创建这个本人一点不熟悉,代码也是完全参考别人的,代码勉强能看懂。主要是创建一个Service类去掉用继承自AbstractAccountAuthenticator的类,再由继承自AbstractAccountAuthenticator的类去调用继承直AccountAuthenticatorActivity的界面处理类。具体的代码也不难,数据是保存在databases内的account表里面,可到数据库内去查询。

三、增加联系人。这个功能由ContactAdder类完成,具体实现不是比较麻烦,保存动作由ContentResolver类解决,但实现方式有所不同,可分为一次性批量增加与挨个增加。
批量增加代码:
protected void createContactEntry() {
        // Get values from UI
        String name = mContactNameEditText.getText().toString();
        String phone = mContactPhoneEditText.getText().toString();
        String email = mContactEmailEditText.getText().toString();
        int phoneType = mContactPhoneTypes.get(mContactPhoneTypeSpinner.getSelectedItemPosition());
        int emailType = mContactEmailTypes.get(mContactEmailTypeSpinner.getSelectedItemPosition());;

        //批量插入
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName())
                .build());
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)//姓名类型
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
                .build());
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                		ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)//电话类型
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType)
                .build());
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)//邮箱类型
                .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
                .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType)
                .build());

        // Ask the Contact provider to create a new contact
        Log.i(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +
                mSelectedAccount.getType() + ")");
        Log.i(TAG,"Creating contact: " + name);
        try {
            getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (Exception e) {
            // Display warning
            Context ctx = getApplicationContext();
            CharSequence txt = getString(R.string.contactCreationFailure);
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(ctx, txt, duration);
            toast.show();

            // Log exception
            Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);
        }
    }

即通过包装ContentProviderOperation进入list,然后调用applyBatch方法,至于这个applyBatch这个方法到底又做了些什么事呢?本人虽然也下了个android的源码包,但是有些源码没看见,所以细究不了。不过查看数据库的数据发现,至少向contacts、raw_contacts、data三张表增加过数据。在上面的代码中MIMETYPE比较重要,上面的代码中会向data添加三条数据,只是MIMETYPE内容不一样。还会向raw_contacts添加一条数据,同时也会向contacts里面增加一条数据。具体详情可参阅数据库。

单条依次插入数据代码:
public void createContactInsert(){
    	String name = mContactNameEditText.getText().toString();
        String phone = mContactPhoneEditText.getText().toString();
        String email = mContactEmailEditText.getText().toString();
        int phoneType = mContactPhoneTypes.get(mContactPhoneTypeSpinner.getSelectedItemPosition());
        int emailType = mContactEmailTypes.get(mContactEmailTypeSpinner.getSelectedItemPosition());;
        
        ContentValues values = new ContentValues();
        values.put(RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType());
        values.put(RawContacts.ACCOUNT_NAME, mSelectedAccount.getName());
        Uri rawContactUri = this.getContentResolver().insert(RawContacts.CONTENT_URI, values);
        long rawContactId = ContentUris.parseId(rawContactUri);
        
        //往data表入姓名数据
        values.clear();
        values.put(Data.RAW_CONTACT_ID, rawContactId);
        values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
        values.put(StructuredName.DISPLAY_NAME, name);
        this.getContentResolver().insert(Data.CONTENT_URI, values);
        
        //往data表入电话数据
        values.clear();
        values.put(Data.RAW_CONTACT_ID, rawContactId);
        values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
        values.put(Phone.NUMBER, phone);
        values.put(Phone.TYPE, phoneType);
        this.getContentResolver().insert(Data.CONTENT_URI, values);

        //往data表入Email数据
        values.clear();
        values.put(Data.RAW_CONTACT_ID, rawContactId);
        values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
        values.put(Email.DATA, email);
        values.put(Email.TYPE, emailType);
        this.getContentResolver().insert(Data.CONTENT_URI, values);
    }

上面的代码看起来似乎比批量添加更加明白,至少知道insert是做什么的。虽然作用都是一样。

四、查询联系人。主要代码如下:
private Cursor getContacts(){
        // Run query
        Uri uri = ContactsContract.Contacts.CONTENT_URI;
        String[] projection = new String[] {
                ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME
        };
        String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
                (mShowInvisible ? "0" : "1") + "'";
        String[] selectionArgs = null;
        //sort ordering based on localized preferences(sqlite排序用法:根据本地化设置对字符串进行比较排序)
        String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

        return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
    }

初次接触时上面这段代码很不好理解,尤其是根本不了解数据库结构的情况下,而且还有那么未知的字段是怎么来的,URI这些又是怎么来的。其实这个URI就是刚才插入时使用的那个URI,projection表示查询的字段,selection是指查询的参数名,selectonArgs表示参数值,sortOrder表示排序,而那个排序"COLLATE LOCALIZED"是sqlite特有的东西,指排序规则。

上面基本上把本人认为难以理解的部分提及了下,讲得并不是很仔细,因为这个工作量确实不少,基本上花了本人三四天的时候来研究才到这种程度。现在之所以把它写下来,也不是说本人已经参考透了,只是怕再这样搞下去会不了了知,所以趁现在还点印象,把它记录下来。具体工程代码见附件。
  • 大小: 14.3 KB
分享到:
评论

相关推荐

    android通讯录开发源码

    这份"android通讯录开发源码"应该包含了一系列用于构建自定义通讯录应用的代码和资源。下面将详细介绍在这个领域开发时可能涉及的关键知识点。 1. **Android权限管理**:在访问或修改通讯录数据之前,应用必须请求`...

    Android通讯录开发.zip

    这个"Android通讯录开发"项目包含了源码和使用说明,帮助开发者了解整个开发流程。 首先,我们从Android系统的架构出发,Android通讯录的开发主要依赖于Android提供的Contacts Provider。Contacts Provider是一个...

    Android源码通讯录的开发_完整代码.zip

    在Android平台上,开发一个完整的通讯录应用涉及到许多关键知识点,包括数据存储、用户界面设计、查询与筛选功能、联系人同步以及权限管理等。这里,我们将深入探讨这些方面。 首先,通讯录应用的核心是数据存储。...

    Android通讯录的开发-完整代码

    以上就是基于标题“Android通讯录的开发-完整代码”和描述“Android]通讯录的开发_完整代码,项目可直接运行,欢迎下载学习”的主要技术知识点。通过学习和实践这个项目,开发者可以深入了解Android应用开发的各个...

    Android通讯录源代码

    1. **Android SDK与API**: Android通讯录源代码基于特定版本的Android SDK开发,可能使用了不同的API级别来兼容不同版本的Android系统。理解Android的版本差异和API层次对于正确解析和运行源代码至关重要。 2. **...

    Android通讯录的源代码

    本项目是基于Java语言开发的Android通讯录应用,提供了全面的通讯录功能,旨在帮助开发者理解如何在Android平台上构建这样一个实用的应用。以下是关于这个项目的一些关键知识点和实现细节。 1. **AndroidManifest....

    Android代码-完整的通讯录项目源码.zip

    《深入解析Android通讯录项目源码》 在Android开发领域,构建一个完整的通讯录项目是一项基础且重要的任务,它涉及到用户界面设计、数据管理、权限控制等多个方面。本篇文章将通过对"Android代码-完整的通讯录项目...

    Android 完整的通讯录项目源码.rar

    【Android 完整的通讯录项目源码】是一款适合初学者进行学习和实践的安卓应用开发项目,它涵盖了Android平台上创建一个基本通讯录应用所需的关键技术。通过这个项目,你可以了解到如何在Android环境中构建一个功能...

    自己做的android通讯录

    总的来说,“自己做的android通讯录”项目涵盖了Android应用开发的多个核心方面,是一个很好的实践平台,有助于开发者深入理解Android系统的运作机制,提升移动应用开发能力。通过这样的实践,开发者可以学习到如何...

    仿android通讯录demo

    通过以上分析,我们可以看出,【仿android通讯录demo】项目涵盖了Android开发的多个关键领域,包括UI设计、数据操作、事件处理、权限管理以及用户体验优化等,是学习和实践Android开发的一个良好实例。

    Android通讯录源码

    这份"Android通讯录源码"提供了一个实现这一功能的实例,让我们来深入探讨其中的关键技术。 1. **Android UI 设计**:在Android应用中,通讯录通常使用ListView或RecyclerView来显示联系人列表。这些组件允许动态...

    ANDROID通讯录代码

    本资源专注于Android通讯录的编程实践,旨在帮助开发者了解如何在Android应用中实现与系统通讯录的交互。下面我们将深入探讨相关知识点。 1. **Android权限管理**:在访问通讯录之前,你需要在AndroidManifest.xml...

    android通讯录简单项目源码

    总结,这个"android通讯录简单项目源码"涵盖了Android应用开发的核心技术,包括数据库操作、ContentProvider、UI设计、权限管理以及异步处理等。通过深入研究和理解这些知识点,你可以构建更复杂、功能丰富的Android...

    基于Android的通讯录开发增加界面03

    基于Android开发的教程和源代码 对Android开发有一定的帮助

    Android studio 通讯录开发

    使用Android开发 简单 强悍 适合初学者,代码具有登录界面,注册界面,添加通讯录联系人,修改联系人,删除联系人,查询联系人等多个功能,简单使用十分适合初学者练习 参考使用 内有apk 可直接在手机上运行

    Android项目视频教程通讯录的开发_完整代码.zip

    下面,我们将详细解析开发Android通讯录应用涉及的关键知识点。 1. **Android Studio**:Android项目开发主要依赖于Android Studio,这是一个集成开发环境(IDE),提供了丰富的工具和功能,如代码编辑、调试、性能...

    Android应用源码通讯录的开发_完整代码.zip

    【Android应用源码通讯录的开发】是一个关于构建Android应用程序的实践项目,主要涉及的是通讯录功能的实现。在这个项目中,开发者会学习到如何在Android平台上创建一个用户友好的、功能完备的联系人管理应用。这个...

Global site tag (gtag.js) - Google Analytics