Android Api Demos登顶之路(十四)Quick Contacts

这个demeo主要演示的是使内容提供者和内容解析者来获取其它应用的数据。Content Provider为不同应用之间共享数据提供了统一的接口,Android系统的每个Content Provider都定义了一个CONTENT_URI,Android中每个Context对象(如Activity)对含有一个ContentResolver,ContentResolver可以根据CONTENT_URI获取对应的Content Provider。

在本例中使用了startManagingCursor(c);对cursor进行托管,但在android3.0以后推出了更为安全和灵活的cursor管理方式,即使用LoaderManager,本例就是在原有的基础上进行了改造,使用LoaderManager来完成这个demo。

在本例中让ManiActivity继承了ListActivity,所以需要去掉setContentView(),不然会报错。

activity_main.xml只做为了listActivity的每个条目的布局。在这里使用了QuickContactBadge组件,该组件继承ImageView,用于显示联系人左侧的图标。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="5dp">

    <QuickContactBadge
        android:id="@+id/badge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:src="@drawable/ic_launcher"
        style="?android:attr/quickContactBadgeStyleSmallWindowSmall"/>

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:layout_marginLeft="10dp"
        android:layout_gravity="center_vertical" />

</LinearLayout>

MainActivity:这里使用了ResourceCursorAdapter的子类作为listActivity的适配器。

public class MainActivity extends ListActivity {
    // 定义需要从联系人中取出的列
    private final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
            Contacts._ID,// 0
            Contacts.DISPLAY_NAME,// 1
            Contacts.STARRED,// 2
            Contacts.TIMES_CONTACTED,// 3
            Contacts.CONTACT_PRESENCE,// 4
            Contacts.PHOTO_ID,// 5
            Contacts.LOOKUP_KEY,// 6
            Contacts.HAS_PHONE_NUMBER // 7
    };

    private static final int SUMMARY_ID_COLUMN_INDEX = 0;
    private static final int SUMMARY_NAME_COLUMN_INDEX = 1;
    private static final int SUMMARY_STARRED_COLUMN_INDEX = 2;
    private static final int SUMMARY_TIMES_CONTACTED_COLUMN_INDEX = 3;
    private static final int SUMMARY_CONTACT_PRESENCE_COLUMN_INDEX = 4;
    private static final int SUMMARY_PHOTO_ID_COLUMN_INDEX = 5;
    private static final int SUMMARY_LOOKUP_KEY_COLUMN_INDEX = 6;
    private static final int SUMMARY_HAS_PHONE_NUMBER_COLUMN_INDEX = 7;

    private static final int LOADER_ID = 1;
    private String selection;
    private ContactListItemAdapter adapter;

    /**
     * android 3.0以后提供了更加安全和灵活的对数据进行异步加载的方式,就是使用LoaderManager
     * 通过它可以轻松地实现对cursor的管理
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        selection = "((" + Contacts.DISPLAY_NAME + " NOTNULL) And ("
                + Contacts.DISPLAY_NAME + "!=‘‘) And ("
                + Contacts.HAS_PHONE_NUMBER + "=1))";
        // flags 这个标志用来决定该适配器的行为。(Android3.0推荐我们传递
        // CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER。设置标志用来添加一个
        // 监听器,监听着参数cursor的数据是否有更变。)
        adapter = new ContactListItemAdapter(MainActivity.this,
                R.layout.activity_main, null,
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        setListAdapter(adapter);

        // 获取LoaderManager
        LoaderManager manager = getLoaderManager();
        // 初始化loader对象
        manager.initLoader(LOADER_ID, null, MyLoader);

        //将游标交给activity托管 startManagingCursor(c);

    }

    private LoaderCallbacks<Cursor> MyLoader = new LoaderCallbacks<Cursor>() {
        // 创建一个loader对象,该对象携带游标
        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            // 创建cursorloader对象第二个参数为内容提供者的Uri,第三个参数为
            // 要查询出哪些列,第四个参数指定查询的条件,第五个参数为查询的参数,
            // 最后一个参数表示 按本地语言的名字降序进行排序
            CursorLoader cl = new CursorLoader(MainActivity.this,
                    Contacts.CONTENT_URI, CONTACTS_SUMMARY_PROJECTION,
                    selection, null, Contacts.DISPLAY_NAME
                            + " COLLATE LOCALIZED ASC");
            return cl;
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
            if (loader.getId() == LOADER_ID) {
                if (cursor == null) {
                    Toast.makeText(MainActivity.this, "查询失败!", 0).show();
                    return;
                }
                if (cursor.getCount() == 0) {
                    Toast.makeText(MainActivity.this, "查询结果为空!", 0).show();
                }
                // 更新UI信息
                /*
                 * 使用内容解析者根据联系人的URI对联系人进行查询,第一个参数为联系人Uri,第二个参数为
                 * 要查询出哪些列,第三个参数指定查询的条件,第四个参数为查询的参数,最后一个参数表示 按本地语言的名字降序进行排序
                 */
                Cursor c = getContentResolver().query(Contacts.CONTENT_URI,
                        CONTACTS_SUMMARY_PROJECTION, selection, null,
                        Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");

                adapter.swapCursor(c);
            }
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {
            Log.i("TAG", "loader was reseted");
        }
    };

    private class ContactListItemAdapter extends ResourceCursorAdapter {

        public ContactListItemAdapter(Context context, int layout, Cursor c,
                int flags) {
            super(context, layout, c, flags);
        }

        /**
         * 找到各个组件
         */
        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View view = super.newView(context, cursor, parent);
            ContactListItemCache cache = new ContactListItemCache();
            cache.nameView = (TextView) view.findViewById(R.id.tv_name);
            cache.badge = (QuickContactBadge) view.findViewById(R.id.badge);
            view.setTag(cache);
            return view;
        }

        /**
         * 为组件赋值
         */
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            ContactListItemCache cache = (ContactListItemCache) view.getTag();
            // 将当前查询到的名字复制到可变长度数组中
            cursor.copyStringToBuffer(SUMMARY_NAME_COLUMN_INDEX,
                    cache.nameBuffer);
            int size = cache.nameBuffer.sizeCopied;
            cache.nameView.setText(cache.nameBuffer.data, 0, size);

            // 为quickContactBadge赋值
            long contactId = cursor.getLong(SUMMARY_ID_COLUMN_INDEX);
            String lookupKey = cursor
                    .getString(SUMMARY_LOOKUP_KEY_COLUMN_INDEX);
            Uri lookupUri = Contacts.getLookupUri(contactId,lookupKey);
            //System.out.println("=====:"+lookupUri.toString());
            // 指定和QuickContactBadge关联的联系人URI
            cache.badge.assignContactUri(lookupUri);
        }

        private class ContactListItemCache {
            public TextView nameView;
            public QuickContactBadge badge;
            // 构造一个可变长度的字符数组
            public CharArrayBuffer nameBuffer = new CharArrayBuffer(128);
        }

    }
}

最后就是需要在配置文件中设置读取系统联系人的权限:

<uses-permission android:name="android.permission.READ_CONTACTS"/>

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 13:20:14

Android Api Demos登顶之路(十四)Quick Contacts的相关文章

Android Api Demos登顶之路(四十)Fragment--&gt;Layout

这个demo演示了fragment的布局特点.本例中在竖屏的状态下,当我们点击列表的条目时 打一个activity来显示这个条目的详细信息. * 而在横屏的状态下由于屏幕足够宽,我们就在界面上同时显示了两个fragment,一个用来 显示标题,另一个用来显示详细信息. layout目录下创建竖屏显示的布局文件:fragment_layout.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayou

Android Api Demos登顶之路(四十五)Loader--&amp;gt;Cursor

这个demo演示了类载入器的用法.关于类载入器的使用我们在前面的demo中已经介绍过了 在此再小小的复习一下. 类载入器的使用步骤: * 1.获取类载入器的管理者LoaderManager manager = tent.getLoaderManager(); * 2.初始化loader MainActivity public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedIn

Android Api Demos登顶之路(四十七)Loader--&gt;Throttle

这个demo演示了如何利用类加载器对自定义的内容提供者共享的数据进行管理 MainActivity public class MainActivity extends Activity { // 定义主机名,用以拼接Uri,Uri表明了内容提供的地址,外部应用通过Uri访问内容提供者,来实现对数据的增删改查 private static final String AUTHORITY = "com.fishtosky.loaderthrottle"; /* * 本例中我们将自定义的一个数

Android Api Demos登顶之路(三十)Display Options

这个demo演示了actionbar的各种布局样式. activity_main.xml <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height=&

Android Api Demos登顶之路(五十二)Search

android 为所有需要提供查询功能的activity提供了两种查询方式:search dialog 和searchview * 这个demo演示了第一种查询方式. * 基本思路:用户提交查询后,Android系统构造一个Intent并把用户的查询内容放在这个Intent中.然后Android启动你定义的用来处理用户查询的Activity(称为Searchable Activity),并把这个Intent发给该Activity. * 使用SearchDialog的步骤 * 1.在res/xml

从零开始学android&lt;android事件的处理方式.二十四.&gt;

在android中一共有 多种事件,每种事件都有自己相对应的处理机制 如以下几种 1 单击事件 View.OnClickListener public abstract void onClick (View v) 单击组件时触发 2 单击事件 View.OnLongClickListener public abstract boolean onLongClick (View v) 长按组件时触发 3 键盘事件 View.OnKeyListener public abstract boolean

Android API Demos 系列之 — 播放GIF动画的类Movie

良好的开端,是成功的一半.A good beginning is half done.  -_- 本文目录 ● 一.什么是GIF ● 二.Android系统和应用如何播放GIF 一.[什么是GIF] Gif动态图片,是通过对多图层的图片,按时间进行不同的切换,以达到动画的效果.Gif动态图片的特点是,图片小,易于随时安置调用.比起一张单调的静态图片,Gif格式的动态图片明显更加的生动和有意思. 二.[Android系统和应用如何播放GIF] 在Android系统的原生控件ImageView并不支

android源码解析之(十四)--&gt;Activity启动流程

好吧,终于要开始讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等, 首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍: An activity represents a single screen with a user interface. For example, an email appl

Android Multimedia框架总结(二十四)MediaMuxer实现手机屏幕录制成gif图

转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53866405 前言:上篇中,介绍是用MediaMuxer与MediaExtractor进入音视频的裁剪,今天用MediaMuxer与AudioRecord与MediaCodec及Surface进行屏幕录制成gif.看下Agenda: 效果图 主体思路 转gif两种方案 MediaMuxer是用于将音频和视频进行混合生成多媒体文件.