linphone-去掉linphone的ContactsListFragment联系人界面

说明

  1. 这里主要是从本机联系人中获取所有的联系人。
  2. 还有linphone的联系人。
  3. 添加联系人。联系人中还可以添加SIP拨号。

看图

联系人界面

需要分析的点

  1. 如何从本机中获取联系人。
  2. 如何区分是sip用户还是手机号码用户。

分析心得

  1. 竟然是在LinphoneActivity中onStart()方法中申请权限

逻辑功能点分析

获取联系人

#ContactsListFragment
   private Cursor getContactsCursor(ContentResolver cr) {
        String req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
                + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL "
                + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
                + "' AND " + CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))";
        Log.i("[ContactsManager] getContactsCursor --> req --> " + req);
        String[] projection = new String[]{Data.CONTACT_ID, Data.DISPLAY_NAME_PRIMARY};
        String query = Data.DISPLAY_NAME_PRIMARY + " IS NOT NULL AND (" + req + ")";
        Log.i("[ContactsManager] getContactsCursor query --> " + query);

        Cursor cursor = cr.query(Data.CONTENT_URI, projection, query, null, " lower(" + Data.DISPLAY_NAME_PRIMARY + ") COLLATE UNICODE ASC");
        if (cursor == null) {
            return cursor;
        }

        MatrixCursor result = new MatrixCursor(cursor.getColumnNames());
        Set<String> groupBy = new HashSet<String>();
        while (cursor.moveToNext()) {
            String name = cursor.getString(cursor.getColumnIndex(Data.DISPLAY_NAME_PRIMARY));
            if (!groupBy.contains(name)) {
                groupBy.add(name);
                Object[] newRow = new Object[cursor.getColumnCount()];

                int contactID = cursor.getColumnIndex(Data.CONTACT_ID);
                int displayName = cursor.getColumnIndex(Data.DISPLAY_NAME_PRIMARY);

                newRow[contactID] = cursor.getString(contactID);
                newRow[displayName] = cursor.getString(displayName);
                result.addRow(newRow);
            }
        }
        cursor.close();
        return result;
    }
    private synchronized void fetchContactsSync() {
        List<LinphoneContact> contacts = new ArrayList<LinphoneContact>();
        List<LinphoneContact> sipContacts = new ArrayList<LinphoneContact>();
        Date contactsTime = new Date();

        LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
        if (lc != null) {
            for (LinphoneFriend friend : lc.getFriendList()) {
                LinphoneContact contact = (LinphoneContact) ((LinphoneFriendImpl) friend).getUserData();
                if (contact != null) {
                    contacts.add(contact);
                    if (contact.getAndroidId() != null) {
                        androidContactsCache.put(contact.getAndroidId(), contact);
                    }
                } else {
                    if (friend.getRefKey() != null) {
                        // Friend has a refkey and but no LinphoneContact => represents a native contact stored in db from a previous version of Linphone, remove it
                        lc.removeFriend(friend);
                    } else {
                        // No refkey so it's a standalone contact
                        contact = new LinphoneContact();
                        contact.setFriend(friend);
                        contact.refresh();
                        if (contact.hasAddress()) {
                            sipContacts.add(contact);
                        }
                        contacts.add(contact);
                    }
                }
            }
        }

        long timeElapsed = (new Date()).getTime() - contactsTime.getTime();
        String time = String.format("%02d:%02d",
                TimeUnit.MILLISECONDS.toMinutes(timeElapsed),
                TimeUnit.MILLISECONDS.toSeconds(timeElapsed) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeElapsed)));
        Log.i("[ContactsManager] Step 0 for " + contacts.size() + " contacts: " + time + " elapsed since starting");

        if (hasContactsAccess()) {
            androidContactsCache.clear();
            List<String> nativeIds = new ArrayList<String>();
            Cursor c = getContactsCursor(contentResolver);
            if (c != null) {
                while (c.moveToNext()) {
                    String id = c.getString(c.getColumnIndex(Data.CONTACT_ID));
                    String displayName = c.getString(c.getColumnIndex(Data.DISPLAY_NAME_PRIMARY));

                    nativeIds.add(id);
                    boolean created = false;
                    LinphoneContact contact = androidContactsCache.get(id);
                    if (contact == null) {
                        created = true;
                        contact = new LinphoneContact();
                        contact.setAndroidId(id);
                    }

                    contact.setFullName(displayName);
                    /*contact.getAndroidIds();*/
                    if (created) {
                        contacts.add(contact);
                        androidContactsCache.put(id, contact);
                    }
                }
                c.close();
            }

            boolean isOrgVisible = LinphoneManager.getInstance().getContext().getResources().getBoolean(R.bool.display_contact_organization);
            if (isOrgVisible) {
                c = getOrganizationCursor(contentResolver);
                if (c != null) {
                    while (c.moveToNext()) {
                        String id = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
                        String org = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Organization.COMPANY));
                        LinphoneContact contact = androidContactsCache.get(id);
                        if (contact != null) {
                            contact.setOrganization(org);
                        }
                    }
                    c.close();
                }
            }

            for (LinphoneContact contact : androidContactsCache.values()) {
                String id = contact.getAndroidId();
                if (id != null && !nativeIds.contains(id)) {
                    // Has been removed since last fetch
                    lc.removeFriend(contact.getLinphoneFriend());
                    contacts.remove(contact);
                }
            }
            nativeIds.clear();

            timeElapsed = (new Date()).getTime() - contactsTime.getTime();
            time = String.format("%02d:%02d",
                    TimeUnit.MILLISECONDS.toMinutes(timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds(timeElapsed) -
                            TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeElapsed)));
            Log.i("[ContactsManager] Step 1 for " + contacts.size() + " contacts: " + time + " elapsed since starting");

            c = getPhonesCursor(contentResolver);
            if (c != null) {
                while (c.moveToNext()) {
                    String id = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
                    String number = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    LinphoneContact contact = androidContactsCache.get(id);
                    if (contact != null) {
                        contact.addNumberOrAddress(new LinphoneNumberOrAddress(number, false));
                    }
                }
                c.close();
            }
            c = getSipCursor(contentResolver);
            if (c != null) {
                while (c.moveToNext()) {
                    String id = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
                    String sip = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS));
                    LinphoneContact contact = androidContactsCache.get(id);
                    if (contact != null) {
                        contact.addNumberOrAddress(new LinphoneNumberOrAddress(sip, true));
                        if (!sipContacts.contains(contact)) {
                            sipContacts.add(contact);
                        }
                    }
                }
                c.close();
            }

            timeElapsed = (new Date()).getTime() - contactsTime.getTime();
            time = String.format("%02d:%02d",
                    TimeUnit.MILLISECONDS.toMinutes(timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds(timeElapsed) -
                            TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeElapsed)));
            Log.i("[ContactsManager] Step 2 for " + contacts.size() + " contacts: " + time + " elapsed since starting");

            for (LinphoneContact contact : contacts) {
                // Create the LinphoneFriends matching the native contacts
                contact.createOrUpdateLinphoneFriendFromNativeContact();
            }
            timeElapsed = (new Date()).getTime() - contactsTime.getTime();
            time = String.format("%02d:%02d",
                    TimeUnit.MILLISECONDS.toMinutes(timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds(timeElapsed) -
                            TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeElapsed)));
            Log.i("[ContactsManager] Step 3 for " + contacts.size() + " contacts: " + time + " elapsed since starting");

            androidContactsCache.clear();
        } else {
            Log.w("[Permission] Read contacts permission wasn't granted, only fetch LinphoneFriends");
        }

        Collections.sort(contacts);
        Collections.sort(sipContacts);
        setContacts(contacts);
        setSipContacts(sipContacts);

        LinphoneManager.getLc().getFriendLists()[0].updateSubscriptions();
        for (ContactsUpdatedListener listener : contactsUpdatedListeners) {
            listener.onContactsUpdated();
        }
    }

联系人分类

获取数据的时候直接分成了两份, 一份是联系人列表,另一份是linphone联系人列表。

创建联系人到本地

LinphoneActivity.instance().addContact(null, sipAddressToAdd);
# ContactEditorFragment.java
# LinphoneContact.createContact()

//添加字段后,最后调用CopntentProvider原生的applyPath方法。
# ContactsManager.getInstance().getContentResolver().applyBatch(ContactsContract.AUTHORITY, changesToCommit);

搜索联系人

# 先监听事件
searchField = (EditText) view.findViewById(R.id.searchField);
searchField.addTextChangedListener(new TextWatcher() {
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        searchContacts(searchField.getText().toString());
    }
});
# 搜索
private void searchContacts(String search) {
    if (search == null || search.length() == 0) {
        changeContactsAdapter();
        return;
    }
    changeContactsToggle();

    isSearchMode = true;

    if (onlyDisplayLinphoneContacts) {
        contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts(search)));
    } else {
        contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getContacts(search)));
    }
}

完整界面代码

开发中的代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorH"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/top_bar"
        android:orientation="horizontal"
        android:background="@color/colorF"
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2">

            <ImageView
                android:id="@+id/all_contacts"
                android:src="@drawable/contacts_all"
                android:background="@drawable/toolbar_button"
                android:contentDescription="@string/content_description_all_contacts"
                android:padding="15dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

            <View
                android:id="@+id/all_contacts_select"
                android:background="@color/colorA"
                android:layout_width="match_parent"
                android:layout_height="5dp"
                android:layout_alignParentBottom="true"/>
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2">

            <ImageView
                android:id="@+id/linphone_contacts"
                android:src="@drawable/contacts_sip"
                android:background="@drawable/toolbar_button"
                android:contentDescription="@string/content_description_linphone_contacts"
                android:gravity="center"
                android:padding="15dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

            <View
                android:id="@+id/linphone_contacts_select"
                android:background="@color/colorA"
                android:layout_width="match_parent"
                android:layout_height="5dp"
                android:visibility="gone"
                android:layout_alignParentBottom="true"/>
        </RelativeLayout>

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2"/>

        <ImageView
            android:id="@+id/newContact"
            android:src="@drawable/contact_add"
            android:background="@drawable/toolbar_button"
            android:contentDescription="@string/content_description_new_contact"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2"
            android:padding="15dp"/>

        <ImageView
            android:id="@+id/edit"
            android:src="@drawable/edit_list_button"
            android:background="@drawable/toolbar_button"
            android:contentDescription="@string/content_description_edit_list"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2"
            android:padding="15dp"/>
    </LinearLayout>

    <include layout="@layout/edit_list"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">

        <EditText
            android:contentDescription="@string/content_description_search_contact"
            android:textCursorDrawable="@null"
            android:id="@+id/searchField"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:textColor="@android:color/black"
            android:background="@drawable/resizable_textfield"
            android:gravity="center"
            android:paddingRight="5dp"
            android:inputType="textPersonName"/>

        <ImageView
            android:id="@+id/clearSearchField"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/clean_field_default"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"/>

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/contactsList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:divider="@color/colorE"
            android:fastScrollEnabled="true"
            android:fastScrollAlwaysVisible="true"
            android:dividerHeight="1dp" />

        <ProgressBar
            android:id="@+id/contactsFetchInProgress"
            style="?android:attr/progressBarStyle"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:visibility="gone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/noSipContact"
            android:text="@string/no_sip_contact"
            style="@style/font6"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_centerVertical="true"/>

        <TextView
            android:id="@+id/noContact"
            android:text="@string/no_contact"
            android:visibility="gone"
            style="@style/font6"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_centerVertical="true"/>

    </RelativeLayout>

</LinearLayout>

完整Fragment代码

/*
ContactsListFragment.java
Copyright (C) 2015  Belledonne Communications, Grenoble, France

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package org.linphone;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import android.app.Dialog;
import android.app.Fragment;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SectionIndexer;
import android.widget.TextView;

/**
 * @author Sylvain Berfini
 */
public class ContactsListFragment extends Fragment implements OnClickListener, OnItemClickListener, ContactsUpdatedListener {
    private LayoutInflater mInflater;
    private ListView contactsList;
    private TextView noSipContact, noContact;
    private ImageView allContacts, linphoneContacts, newContact, edit, selectAll, deselectAll, delete, cancel;
    private boolean onlyDisplayLinphoneContacts, isEditMode, isSearchMode;
    private View allContactsSelected, linphoneContactsSelected;
    private LinearLayout editList, topbar;
    private int lastKnownPosition;
    private boolean editOnClick = false, editConsumed = false, onlyDisplayChatAddress = false;
    private String sipAddressToAdd;
    private ImageView clearSearchField;
    private EditText searchField;
    private ProgressBar contactsFetchInProgress;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mInflater = inflater;
        View view = inflater.inflate(R.layout.contacts_list, container, false);

        if (getArguments() != null) {
            editOnClick = getArguments().getBoolean("EditOnClick");
            sipAddressToAdd = getArguments().getString("SipAddress");

            onlyDisplayChatAddress = getArguments().getBoolean("ChatAddressOnly");
        }

        noSipContact = (TextView) view.findViewById(R.id.noSipContact);
        noContact = (TextView) view.findViewById(R.id.noContact);

        contactsList = (ListView) view.findViewById(R.id.contactsList);
        contactsList.setOnItemClickListener(this);

        allContacts = (ImageView) view.findViewById(R.id.all_contacts);
        allContacts.setOnClickListener(this);

        linphoneContacts = (ImageView) view.findViewById(R.id.linphone_contacts);
        linphoneContacts.setOnClickListener(this);

        allContactsSelected = view.findViewById(R.id.all_contacts_select);
        linphoneContactsSelected = view.findViewById(R.id.linphone_contacts_select);

        newContact = (ImageView) view.findViewById(R.id.newContact);
        newContact.setOnClickListener(this);
        newContact.setEnabled(LinphoneManager.getLc().getCallsNb() == 0);

        allContacts.setEnabled(onlyDisplayLinphoneContacts);
        linphoneContacts.setEnabled(!allContacts.isEnabled());

        selectAll = (ImageView) view.findViewById(R.id.select_all);
        selectAll.setOnClickListener(this);

        deselectAll = (ImageView) view.findViewById(R.id.deselect_all);
        deselectAll.setOnClickListener(this);

        delete = (ImageView) view.findViewById(R.id.delete);
        delete.setOnClickListener(this);

        editList = (LinearLayout) view.findViewById(R.id.edit_list);
        topbar = (LinearLayout) view.findViewById(R.id.top_bar);

        cancel = (ImageView) view.findViewById(R.id.cancel);
        cancel.setOnClickListener(this);

        edit = (ImageView) view.findViewById(R.id.edit);
        edit.setOnClickListener(this);

        clearSearchField = (ImageView) view.findViewById(R.id.clearSearchField);
        clearSearchField.setOnClickListener(this);

        searchField = (EditText) view.findViewById(R.id.searchField);
        searchField.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                searchContacts(searchField.getText().toString());
            }
        });

        contactsFetchInProgress = (ProgressBar) view.findViewById(R.id.contactsFetchInProgress);
        contactsFetchInProgress.setVisibility(View.VISIBLE);

        return view;
    }

    public int getNbItemsChecked(){
        int size = contactsList.getAdapter().getCount();
        int nb = 0;
        for(int i=0; i<size; i++) {
            if(contactsList.isItemChecked(i)) {
                nb ++;
            }
        }
        return nb;
    }

    public void enabledDeleteButton(Boolean enabled){
        if(enabled){
            delete.setEnabled(true);
        } else {
            if (getNbItemsChecked() == 0){
                delete.setEnabled(false);
            }
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();

        if (id == R.id.select_all) {
            deselectAll.setVisibility(View.VISIBLE);
            selectAll.setVisibility(View.GONE);
            enabledDeleteButton(true);
            selectAllList(true);
            return;
        }
        if (id == R.id.deselect_all) {
            deselectAll.setVisibility(View.GONE);
            selectAll.setVisibility(View.VISIBLE);
            enabledDeleteButton(false);
            selectAllList(false);
            return;
        }

        if (id == R.id.cancel) {
            quitEditMode();
            return;
        }

        if (id == R.id.delete) {
            final Dialog dialog = LinphoneActivity.instance().displayDialog(getString(R.string.delete_text));
            Button delete = (Button) dialog.findViewById(R.id.delete_button);
            Button cancel = (Button) dialog.findViewById(R.id.cancel);

            delete.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    removeContacts();
                    dialog.dismiss();
                    quitEditMode();
                }
            });

            cancel.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    dialog.dismiss();
                    quitEditMode();
                }
            });
            dialog.show();
            return;
        }

        if (id == R.id.edit) {
            editList.setVisibility(View.VISIBLE);
            topbar.setVisibility(View.GONE);
            enabledDeleteButton(false);
            isEditMode = true;
        }

        if (id == R.id.all_contacts) {
            onlyDisplayLinphoneContacts = false;
            allContactsSelected.setVisibility(View.VISIBLE);
            allContacts.setEnabled(false);
            linphoneContacts.setEnabled(true);
            linphoneContactsSelected.setVisibility(View.INVISIBLE);
        }
        else if (id == R.id.linphone_contacts) {
            allContactsSelected.setVisibility(View.INVISIBLE);
            linphoneContactsSelected.setVisibility(View.VISIBLE);
            linphoneContacts.setEnabled(false);
            allContacts.setEnabled(true);
            onlyDisplayLinphoneContacts = true;

        }

        if(isEditMode){
            deselectAll.setVisibility(View.GONE);
            selectAll.setVisibility(View.VISIBLE);
        }

        if (searchField.getText().toString().length() > 0) {
            searchContacts();
        } else {
            changeContactsAdapter();
        }

        if (id == R.id.newContact) {
            editConsumed = true;
            LinphoneActivity.instance().addContact(null, sipAddressToAdd);
        }
        else if (id == R.id.clearSearchField) {
            searchField.setText("");
        }
    }

    private void selectAllList(boolean isSelectAll){
        int size = contactsList.getAdapter().getCount();
        for(int i=0; i<size; i++) {
            contactsList.setItemChecked(i,isSelectAll);
        }
    }

    private void removeContacts() {
        ArrayList<String> ids = new ArrayList<String>();
        int size = contactsList.getAdapter().getCount();

        for (int i = size - 1; i >= 0; i--) {
            if (contactsList.isItemChecked(i)) {
                LinphoneContact contact = (LinphoneContact) contactsList.getAdapter().getItem(i);
                if (contact.isAndroidContact()) {
                    contact.deleteFriend();
                    ids.add(contact.getAndroidId());
                } else {
                    contact.delete();
                }
            }
        }

        ContactsManager.getInstance().deleteMultipleContactsAtOnce(ids);
    }

    public void quitEditMode(){
        isEditMode = false;
        editList.setVisibility(View.GONE);
        topbar.setVisibility(View.VISIBLE);
        invalidate();
        if(getResources().getBoolean(R.bool.isTablet)){
            displayFirstContact();
        }
    }

    public void displayFirstContact(){
        if (contactsList != null && contactsList.getAdapter() != null && contactsList.getAdapter().getCount() > 0) {
            LinphoneActivity.instance().displayContact((LinphoneContact) contactsList.getAdapter().getItem(0), false);
        } else {
            LinphoneActivity.instance().displayEmptyFragment();
        }
    }

    private void searchContacts() {
        searchContacts(searchField.getText().toString());
    }

    private void searchContacts(String search) {
        if (search == null || search.length() == 0) {
            changeContactsAdapter();
            return;
        }
        changeContactsToggle();

        isSearchMode = true;

        if (onlyDisplayLinphoneContacts) {
            contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
            contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts(search)));
        } else {
            contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
            contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getContacts(search)));
        }
    }

    private void changeContactsAdapter() {
        changeContactsToggle();

        isSearchMode = false;
        noSipContact.setVisibility(View.GONE);
        noContact.setVisibility(View.GONE);
        contactsList.setVisibility(View.VISIBLE);

        ContactsListAdapter adapter;
        contactsList.setFastScrollEnabled(false);
        if (onlyDisplayLinphoneContacts) {
            contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
            adapter = new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts());
            contactsList.setAdapter(adapter);
            edit.setEnabled(true);
        } else {
            contactsList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
            adapter = new ContactsListAdapter(ContactsManager.getInstance().getContacts());
            contactsList.setAdapter(adapter);
            edit.setEnabled(true);
        }
        contactsList.setFastScrollEnabled(true);
        adapter.notifyDataSetInvalidated();


        if (adapter.getCount() > 0) {
            contactsFetchInProgress.setVisibility(View.GONE);
        }
        ContactsManager.getInstance().setLinphoneContactsPrefered(onlyDisplayLinphoneContacts);
    }

    private void changeContactsToggle() {
        if (onlyDisplayLinphoneContacts) {
            allContacts.setEnabled(true);
            allContactsSelected.setVisibility(View.INVISIBLE);
            linphoneContacts.setEnabled(false);
            linphoneContactsSelected.setVisibility(View.VISIBLE);
        } else {
            allContacts.setEnabled(false);
            allContactsSelected.setVisibility(View.VISIBLE);
            linphoneContacts.setEnabled(true);
            linphoneContactsSelected.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
        LinphoneContact contact = (LinphoneContact) adapter.getItemAtPosition(position);
        if (editOnClick) {
            editConsumed = true;
            LinphoneActivity.instance().editContact(contact, sipAddressToAdd);
        } else {
            lastKnownPosition = contactsList.getFirstVisiblePosition();
            LinphoneActivity.instance().displayContact(contact, onlyDisplayChatAddress);
        }
    }

    @Override
    public void onResume() {
        ContactsManager.addContactsListener(this);
        super.onResume();

        if (editConsumed) {
            editOnClick = false;
            sipAddressToAdd = null;
        }

        if (LinphoneActivity.isInstanciated()) {
            LinphoneActivity.instance().selectMenu(FragmentsAvailable.CONTACTS_LIST);
            LinphoneActivity.instance().hideTabBar(false);
            onlyDisplayLinphoneContacts = ContactsManager.getInstance().isLinphoneContactsPrefered();
        }
        changeContactsToggle();
        invalidate();
    }

    @Override
    public void onPause() {
        ContactsManager.removeContactsListener(this);
        super.onPause();
    }

    @Override
    public void onContactsUpdated() {
        ContactsListAdapter adapter = (ContactsListAdapter)contactsList.getAdapter();
        if (adapter != null) {
            contactsList.setFastScrollEnabled(false);
            if (onlyDisplayLinphoneContacts) {
                adapter.updateDataSet(ContactsManager.getInstance().getSIPContacts());
            } else {
                adapter.updateDataSet(ContactsManager.getInstance().getContacts());
            }
            contactsList.setFastScrollEnabled(true);
            contactsFetchInProgress.setVisibility(View.GONE);
        }
    }

    public void invalidate() {
        if (searchField != null && searchField.getText().toString().length() > 0) {
            searchContacts(searchField.getText().toString());
        } else {
            changeContactsAdapter();
        }
        contactsList.setSelectionFromTop(lastKnownPosition, 0);
    }

    class ContactsListAdapter extends BaseAdapter implements SectionIndexer {
        private class ViewHolder {
            public CheckBox delete;
            public ImageView linphoneFriend;
            public TextView name;
            public LinearLayout separator;
            public TextView separatorText;
            public ImageView contactPicture;
            public TextView organization;
            //public ImageView friendStatus;

            public ViewHolder(View view) {
                delete = (CheckBox) view.findViewById(R.id.delete);
                linphoneFriend = (ImageView) view.findViewById(R.id.friendLinphone);
                name = (TextView) view.findViewById(R.id.name);
                separator = (LinearLayout) view.findViewById(R.id.separator);
                separatorText = (TextView) view.findViewById(R.id.separator_text);
                contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
                organization = (TextView) view.findViewById(R.id.contactOrganization);
                //friendStatus = (ImageView) view.findViewById(R.id.friendStatus);
            }
        }

        private List<LinphoneContact> contacts;
        String[] sections;
        ArrayList<String> sectionsList;
        Map<String, Integer>map = new LinkedHashMap<String, Integer>();

        ContactsListAdapter(List<LinphoneContact> contactsList) {
            updateDataSet(contactsList);
        }

        public void updateDataSet(List<LinphoneContact> contactsList) {
            contacts = contactsList;

            map = new LinkedHashMap<String, Integer>();
            String prevLetter = null;
            for (int i = 0; i < contacts.size(); i++) {
                LinphoneContact contact = contacts.get(i);
                String fullName = contact.getFullName();
                if (fullName == null || fullName.isEmpty()) {
                    continue;
                }
                String firstLetter = fullName.substring(0, 1).toUpperCase(Locale.getDefault());
                if (!firstLetter.equals(prevLetter)) {
                    prevLetter = firstLetter;
                    map.put(firstLetter, i);
                }
            }
            sectionsList = new ArrayList<String>(map.keySet());
            sections = new String[sectionsList.size()];
            sectionsList.toArray(sections);

            notifyDataSetChanged();
        }

        public int getCount() {
            return contacts.size();
        }

        public Object getItem(int position) {
            if (position >= getCount()) return null;
            return contacts.get(position);
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = null;
            LinphoneContact contact = (LinphoneContact) getItem(position);
            if (contact == null) return null;

            ViewHolder holder = null;
            if (convertView != null) {
                view = convertView;
                holder = (ViewHolder) view.getTag();
            } else {
                view = mInflater.inflate(R.layout.contact_cell, parent, false);
                holder = new ViewHolder(view);
                view.setTag(holder);
            }

            holder.name.setText(contact.getFullName());

            if (!isSearchMode) {
                if (getPositionForSection(getSectionForPosition(position)) != position) {
                    holder.separator.setVisibility(View.GONE);
                } else {
                    holder.separator.setVisibility(View.VISIBLE);
                    String fullName = contact.getFullName();
                    if (fullName != null && !fullName.isEmpty()) {
                        holder.separatorText.setText(String.valueOf(fullName.charAt(0)));
                    }
                }
            } else {
                holder.separator.setVisibility(View.GONE);
            }

            if (contact.isInLinphoneFriendList()) {
                holder.linphoneFriend.setVisibility(View.VISIBLE);
            } else {
                holder.linphoneFriend.setVisibility(View.GONE);
            }

            if (contact.hasPhoto()) {
                LinphoneUtils.setThumbnailPictureFromUri(getActivity(), holder.contactPicture, contact.getThumbnailUri());
            } else {
                holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap());
            }

            boolean isOrgVisible = getResources().getBoolean(R.bool.display_contact_organization);
            String org = contact.getOrganization();
            if (org != null && !org.isEmpty() && isOrgVisible) {
                holder.organization.setText(org);
                holder.organization.setVisibility(View.VISIBLE);
            } else {
                holder.organization.setVisibility(View.GONE);
            }

            if (isEditMode) {
                holder.delete.setVisibility(View.VISIBLE);
                holder.delete.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                        contactsList.setItemChecked(position, b);
                        if(getNbItemsChecked() == getCount()){
                            deselectAll.setVisibility(View.VISIBLE);
                            selectAll.setVisibility(View.GONE);
                            enabledDeleteButton(true);
                        } else {
                            if(getNbItemsChecked() == 0){
                                deselectAll.setVisibility(View.GONE);
                                selectAll.setVisibility(View.VISIBLE);
                                enabledDeleteButton(false);
                            } else {
                                deselectAll.setVisibility(View.GONE);
                                selectAll.setVisibility(View.VISIBLE);
                                enabledDeleteButton(true);
                            }
                        }
                    }
                });
                if (contactsList.isItemChecked(position)) {
                    holder.delete.setChecked(true);
                } else {
                    holder.delete.setChecked(false);
                }
            } else {
                holder.delete.setVisibility(View.INVISIBLE);
            }

            /*LinphoneFriend[] friends = LinphoneManager.getLc().getFriendList();
            if (!ContactsManager.getInstance().isContactPresenceDisabled() && friends != null) {
                holder.friendStatus.setVisibility(View.VISIBLE);
                PresenceActivityType presenceActivity = friends[0].getPresenceModel().getActivity().getType();
                if (presenceActivity == PresenceActivityType.Online) {
                    holder.friendStatus.setImageResource(R.drawable.led_connected);
                } else if (presenceActivity == PresenceActivityType.Busy) {
                    holder.friendStatus.setImageResource(R.drawable.led_error);
                } else if (presenceActivity == PresenceActivityType.Away) {
                    holder.friendStatus.setImageResource(R.drawable.led_inprogress);
                } else if (presenceActivity == PresenceActivityType.Offline) {
                    holder.friendStatus.setImageResource(R.drawable.led_disconnected);
                } else {
                    holder.friendStatus.setImageResource(R.drawable.call_quality_indicator_0);
                }
            }*/

            return view;
        }

        @Override
        public Object[] getSections() {
            return sections;
        }

        @Override
        public int getPositionForSection(int sectionIndex) {
            if (sectionIndex >= sections.length || sectionIndex < 0) {
                return 0;
            }
            return map.get(sections[sectionIndex]);
        }

        @Override
        public int getSectionForPosition(int position) {
            if (position >= contacts.size() || position < 0) {
                return 0;
            }
            LinphoneContact contact = contacts.get(position);
            String fullName = contact.getFullName();
            if (fullName == null || fullName.isEmpty()) {
                return 0;
            }
            String letter = fullName.substring(0, 1).toUpperCase(Locale.getDefault());
            return sectionsList.indexOf(letter);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/AdrianAndroid/article/details/70227268