From 63343b607e92c8136634cc4eeb029c2060ab3702 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 14 Mar 2014 16:36:04 +0100 Subject: [PATCH] Simple search function for contacts --- res/layout/contacts_list.xml | 30 +++++++ src/org/linphone/ContactsFragment.java | 89 +++++++++++++++++-- src/org/linphone/LinphoneManager.java | 18 ++-- .../linphone/compatibility/ApiNinePlus.java | 19 ++-- .../linphone/compatibility/Compatibility.java | 20 ++++- 5 files changed, 152 insertions(+), 24 deletions(-) diff --git a/res/layout/contacts_list.xml b/res/layout/contacts_list.xml index ff9a324e5..7d9eb902b 100644 --- a/res/layout/contacts_list.xml +++ b/res/layout/contacts_list.xml @@ -67,6 +67,36 @@ + + + + + + + + diff --git a/src/org/linphone/ContactsFragment.java b/src/org/linphone/ContactsFragment.java index 617241844..3378569e5 100644 --- a/src/org/linphone/ContactsFragment.java +++ b/src/org/linphone/ContactsFragment.java @@ -23,12 +23,15 @@ import org.linphone.compatibility.Compatibility; import org.linphone.core.LinphoneFriend; import org.linphone.core.PresenceActivityType; +import android.annotation.SuppressLint; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -37,6 +40,7 @@ import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AlphabetIndexer; import android.widget.BaseAdapter; +import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; @@ -46,6 +50,7 @@ import android.widget.TextView; /** * @author Sylvain Berfini */ +@SuppressLint("DefaultLocale") public class ContactsFragment extends Fragment implements OnClickListener, OnItemClickListener { private Handler mHandler = new Handler(); @@ -57,6 +62,9 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte private AlphabetIndexer indexer; private boolean editOnClick = false, editConsumed = false, onlyDisplayChatAddress = false; private String sipAddressToAdd; + private ImageView clearSearchField; + private EditText searchField; + private Cursor searchCursor; private static ContactsFragment instance; @@ -99,6 +107,29 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte allContacts.setEnabled(onlyDisplayLinphoneContacts); linphoneContacts.setEnabled(!allContacts.isEnabled()); + + + 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()); + } + }); return view; } @@ -109,22 +140,63 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte if (id == R.id.allContacts) { onlyDisplayLinphoneContacts = false; - changeContactsAdapter(); + if (searchField.getText().toString().length() > 0) { + searchContacts(); + } else { + changeContactsAdapter(); + } } else if (id == R.id.linphoneContacts) { onlyDisplayLinphoneContacts = true; - changeContactsAdapter(); - + if (searchField.getText().toString().length() > 0) { + searchContacts(); + } else { + changeContactsAdapter(); + } } else if (id == R.id.newContact) { editConsumed = true; LinphoneActivity.instance().addContact(null, sipAddressToAdd); } + else if (id == R.id.clearSearchField) { + searchField.setText(""); + } + } + + private void searchContacts() { + searchContacts(searchField.getText().toString()); + } + + private void searchContacts(String search) { + if (search == null || search.length() == 0) { + changeContactsAdapter(); + return; + } + + changeContactsToggle(); + + if (searchCursor != null) { + searchCursor.close(); + } + + if (onlyDisplayLinphoneContacts) { + searchCursor = Compatibility.getSIPContactsCursor(getActivity().getContentResolver(), search); + indexer = new AlphabetIndexer(searchCursor, Compatibility.getCursorDisplayNameColumnIndex(searchCursor), " ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + contactsList.setAdapter(new ContactsListAdapter(null, searchCursor)); + } else { + searchCursor = Compatibility.getContactsCursor(getActivity().getContentResolver(), search); + indexer = new AlphabetIndexer(searchCursor, Compatibility.getCursorDisplayNameColumnIndex(searchCursor), " ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + contactsList.setAdapter(new ContactsListAdapter(null, searchCursor)); + } } private void changeContactsAdapter() { changeContactsToggle(); + if (searchCursor != null) { + searchCursor.close(); + } + Cursor allContactsCursor = LinphoneActivity.instance().getAllContactsCursor(); Cursor sipContactsCursor = LinphoneActivity.instance().getSIPContactsCursor(); @@ -199,6 +271,9 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte @Override public void onPause() { instance = null; + if (searchCursor != null) { + searchCursor.close(); + } super.onPause(); } @@ -206,7 +281,11 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte mHandler.post(new Runnable() { @Override public void run() { - changeContactsAdapter(); + if (searchField != null && searchField.getText().toString().length() > 0) { + searchContacts(searchField.getText().toString()); + } else { + changeContactsAdapter(); + } contactsList.setSelectionFromTop(lastKnownPosition, 0); } }); @@ -231,7 +310,7 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte } public Object getItem(int position) { - if (position >= contacts.size()) { + if (contacts == null || position >= contacts.size()) { return Compatibility.getContact(getActivity().getContentResolver(), cursor, position); } else { return contacts.get(position); diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 4f4ee6996..8099edee5 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -21,9 +21,6 @@ package org.linphone; import static android.media.AudioManager.MODE_RINGTONE; import static android.media.AudioManager.STREAM_RING; import static android.media.AudioManager.STREAM_VOICE_CALL; -import static org.linphone.core.LinphoneCall.State.CallEnd; -import static org.linphone.core.LinphoneCall.State.Error; -import static org.linphone.core.LinphoneCall.State.IncomingReceived; import java.io.File; import java.io.FileInputStream; @@ -71,7 +68,6 @@ import org.linphone.core.PayloadType; import org.linphone.core.PresenceActivityType; import org.linphone.core.PresenceModel; import org.linphone.core.PublishState; -import org.linphone.core.Reason; import org.linphone.core.SubscriptionState; import org.linphone.mediastream.Log; import org.linphone.mediastream.Version; @@ -184,7 +180,7 @@ public class LinphoneManager implements LinphoneCoreListener { mRingbackSoundFile = basePath + "/ringback.wav"; mPauseSoundFile = basePath + "/toy_mono.wav"; mChatDatabaseFile = basePath + "/linphone-history.db"; - mErrorToneFile = basePath + "/error_tone.wav"; + mErrorToneFile = basePath + "/error.wav"; mPrefs = LinphonePreferences.instance(); mAudioManager = ((AudioManager) c.getSystemService(Context.AUDIO_SERVICE)); @@ -964,7 +960,7 @@ public class LinphoneManager implements LinphoneCoreListener { @SuppressLint("Wakelock") public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) { Log.i("new state [",state,"]"); - if (state == IncomingReceived && !call.equals(lc.getCurrentCall())) { + if (state == State.IncomingReceived && !call.equals(lc.getCurrentCall())) { if (call.getReplacedCall()!=null){ // attended transfer // it will be accepted automatically. @@ -972,14 +968,14 @@ public class LinphoneManager implements LinphoneCoreListener { } } - if (state == IncomingReceived && mR.getBoolean(R.bool.auto_answer_calls)) { + if (state == State.IncomingReceived && mR.getBoolean(R.bool.auto_answer_calls)) { try { mLc.acceptCall(call); } catch (LinphoneCoreException e) { e.printStackTrace(); } } - else if (state == IncomingReceived || (state == State.CallIncomingEarlyMedia && mR.getBoolean(R.bool.allow_ringing_while_early_media))) { + else if (state == State.IncomingReceived || (state == State.CallIncomingEarlyMedia && mR.getBoolean(R.bool.allow_ringing_while_early_media))) { // Brighten screen for at least 10 seconds if (mLc.getCallsNb() == 1) { ringingCall = call; @@ -991,7 +987,7 @@ public class LinphoneManager implements LinphoneCoreListener { stopRinging(); } - if (state == LinphoneCall.State.Connected) { + if (state == State.Connected) { if (mLc.getCallsNb() == 1) { requestAudioFocus(); Compatibility.setAudioManagerInCallMode(mAudioManager); @@ -1002,7 +998,7 @@ public class LinphoneManager implements LinphoneCoreListener { } } - if (state == CallEnd || state == Error) { + if (state == State.CallReleased || state == State.Error) { if (mLc.getCallsNb() == 0) { if (mAudioFocused){ int res=mAudioManager.abandonAudioFocus(null); @@ -1021,7 +1017,7 @@ public class LinphoneManager implements LinphoneCoreListener { } } - if (state == CallEnd) { + if (state == State.CallEnd) { if (mLc.getCallsNb() == 0) { if (mIncallWakeLock != null && mIncallWakeLock.isHeld()) { mIncallWakeLock.release(); diff --git a/src/org/linphone/compatibility/ApiNinePlus.java b/src/org/linphone/compatibility/ApiNinePlus.java index 2018647c7..b56b1714c 100644 --- a/src/org/linphone/compatibility/ApiNinePlus.java +++ b/src/org/linphone/compatibility/ApiNinePlus.java @@ -128,21 +128,28 @@ public class ApiNinePlus { return list; } - public static Cursor getContactsCursor(ContentResolver cr) { - String req = Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE - + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL"; + public static Cursor getContactsCursor(ContentResolver cr, String search) { + 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 " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))"; - req += " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE - + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL)"; + if (search != null) { + req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'"; + } return ApiFivePlus.getGeneralContactCursor(cr, req, true); } - public static Cursor getSIPContactsCursor(ContentResolver cr) { + public static Cursor getSIPContactsCursor(ContentResolver cr, String search) { String req = null; req = Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL"; + if (search != null) { + req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'"; + } + return ApiFivePlus.getGeneralContactCursor(cr, req, true); } diff --git a/src/org/linphone/compatibility/Compatibility.java b/src/org/linphone/compatibility/Compatibility.java index 277a65ac6..3bd970992 100644 --- a/src/org/linphone/compatibility/Compatibility.java +++ b/src/org/linphone/compatibility/Compatibility.java @@ -82,7 +82,15 @@ public class Compatibility { public static Cursor getContactsCursor(ContentResolver cr) { if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { - return ApiNinePlus.getContactsCursor(cr); + return ApiNinePlus.getContactsCursor(cr, null); + } else { + return ApiFivePlus.getContactsCursor(cr); + } + } + + public static Cursor getContactsCursor(ContentResolver cr, String search) { + if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { + return ApiNinePlus.getContactsCursor(cr, search); } else { return ApiFivePlus.getContactsCursor(cr); } @@ -90,7 +98,15 @@ public class Compatibility { public static Cursor getSIPContactsCursor(ContentResolver cr) { if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { - return ApiNinePlus.getSIPContactsCursor(cr); + return ApiNinePlus.getSIPContactsCursor(cr, null); + } else { + return ApiFivePlus.getSIPContactsCursor(cr); + } + } + + public static Cursor getSIPContactsCursor(ContentResolver cr, String search) { + if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { + return ApiNinePlus.getSIPContactsCursor(cr, search); } else { return ApiFivePlus.getSIPContactsCursor(cr); }