Skip to content
Snippets Groups Projects
Commit f6146f83 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

localservice: add contact cache and thread pool

* Optimize contact loading from system
* Cache results in LocalService
* Listen for system contact change to reload when needed
* Cache standard-size (40dp) contact pictures in LocalService
* Common thread pool to load contact pictures in LocalService

Issue: #78218
Change-Id: I61e28df8d020166933cc4fe24a207b0a760036b2
parent 16b8b44c
No related branches found
No related tags found
No related merge requests found
......@@ -44,6 +44,8 @@ import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
......@@ -57,13 +59,12 @@ import android.widget.SectionIndexer;
import android.widget.TextView;
public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAdapter, SectionIndexer {
private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
Context mContext;
private final ExecutorService infos_fetcher;
private final Context mContext;
private ArrayList<CallContact> mContacts;
private int[] mSectionIndices;
private Character[] mSectionLetters;
WeakReference<ContactListFragment> parent;
WeakReference<ContactListFragment.Callbacks> parent;
private LayoutInflater mInflater;
final private LruCache<Long, Bitmap> mMemoryCache;
......@@ -71,22 +72,16 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
private static final String TAG = ContactsAdapter.class.getSimpleName();
public ContactsAdapter(ContactListFragment contactListFragment) {
public ContactsAdapter(Context c, ContactListFragment.Callbacks cb, LruCache<Long, Bitmap> cache, ExecutorService pool) {
super();
mContext = contactListFragment.getActivity();
mContext = c;
mInflater = LayoutInflater.from(mContext);
parent = new WeakReference<>(contactListFragment);
parent = new WeakReference<>(cb);
mContacts = new ArrayList<>();
mSectionIndices = getSectionIndices();
mSectionLetters = getSectionLetters();
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<Long, Bitmap>(cacheSize){
@Override
protected int sizeOf(Long key, Bitmap bitmap) {
return bitmap.getByteCount() / 1024;
}
};
mMemoryCache = cache;
infos_fetcher = pool;
}
public static final int TYPE_HEADER = 0;
......@@ -142,7 +137,7 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
final CallContact item = mContacts.get(position);
if (entryView.position == position || (entryView.contact != null && entryView.contact.get() != null && item.getId() == entryView.contact.get().getId()))
if (/*entryView.position == position &&*/ (entryView.contact != null && entryView.contact.get() != null && item.getId() == entryView.contact.get().getId()))
return convertView;
entryView.display_name.setText(item.getDisplayName());
......@@ -187,58 +182,10 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
convertView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
parent.get().mCallbacks.onTextContact(item);
}
});
/*
entryView.quick_call.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
parent.get().mCallbacks.onCallContact(item);
}
});
entryView.quick_msg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
parent.get().mCallbacks.onTextContact(item);
}
});
entryView.quick_starred.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "Coming soon", Toast.LENGTH_SHORT).show();
}
});
entryView.quick_edit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
parent.get().mCallbacks.onEditContact(item);
}
});
entryView.quick_discard.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "Coming soon", Toast.LENGTH_SHORT).show();
parent.get().onTextContact(item);
}
});
entryView.quick_edit.setClickable(false);
entryView.quick_discard.setClickable(false);
entryView.quick_starred.setClickable(false);
*/
return convertView;
}
......@@ -335,23 +282,9 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
mContacts = new ArrayList<>();
mSectionIndices = new int[0];
mSectionLetters = new Character[0];
notifyDataSetChanged();
}
/*
public void restore() {
mContacts = new ArrayList<>();
mSectionIndices = getSectionIndices();
mSectionLetters = getSectionLetters();
notifyDataSetChanged();
//notifyDataSetChanged();
}
public void addAll(ArrayList<CallContact> tmp) {
mContacts.addAll(tmp);
mSectionIndices = getSectionIndices();
mSectionLetters = getSectionLetters();
notifyDataSetChanged();
}*/
public void setData(ArrayList<CallContact> contacts) {
mContacts = contacts;
mSectionIndices = getSectionIndices();
......
......@@ -95,7 +95,7 @@ public class ConferenceDFragment extends DialogFragment implements LoaderManager
} else {
baseUri = Contacts.CONTENT_URI;
}
ContactsLoader l = new ContactsLoader(getActivity(), baseUri);
ContactsLoader l = new ContactsLoader(getActivity());
l.forceLoad();
return l;
}
......
......@@ -31,14 +31,13 @@
*/
package cx.ring.fragments;
import java.util.ArrayList;
import cx.ring.R;
import cx.ring.adapters.ContactsAdapter;
import cx.ring.adapters.StarredContactsAdapter;
import cx.ring.loaders.ContactsLoader;
import cx.ring.loaders.LoaderConstants;
import cx.ring.model.CallContact;
import cx.ring.service.LocalService;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
import android.app.Activity;
......@@ -54,7 +53,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.MeasureSpec;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
......@@ -64,16 +62,16 @@ import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.RelativeLayout;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import java.util.ArrayList;
public class ContactListFragment extends Fragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<ContactsLoader.Result> {
public static final String TAG = "ContactListFragment";
ContactsAdapter mListAdapter;
StarredContactsAdapter mGridAdapter;
//SearchView mQuickReturnSearchView;
String mCurFilter;
StickyListHeadersListView mContactList;
......@@ -81,15 +79,12 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
private LinearLayout llMain;
private GridView mStarredGrid;
private TextView favHeadLabel;
//private SwipeListViewTouchListener mSwipeLvTouchListener;
private LinearLayout mHeader;
private ViewGroup newcontact;
@Override
public void onCreate(Bundle savedInBundle) {
super.onCreate(savedInBundle);
mGridAdapter = new StarredContactsAdapter(getActivity());
mListAdapter = new ContactsAdapter(this);
setHasOptionsMenu(true);
}
......@@ -97,38 +92,19 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
/**
* A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
*/
private static final Callbacks sDummyCallbacks = new Callbacks() {
private static class DummyCallbacks extends LocalService.DummyCallbacks implements Callbacks {
@Override
public void onCallContact(CallContact c) {
}
@Override
public void onTextContact(CallContact c) {
}
@Override
public void onEditContact(CallContact c) {
}
@Override
public void onContactDragged() {
}
@Override
public void toggleDrawer() {
}
@Override
public void setDragView(RelativeLayout relativeLayout) {
}
@Override
public void toggleForSearchDrawer() {
}
};
private static final Callbacks sDummyCallbacks = new DummyCallbacks();
public interface Callbacks {
public interface Callbacks extends LocalService.Callbacks {
void onCallContact(CallContact c);
void onTextContact(CallContact c);
void onContactDragged();
void toggleDrawer();
void onEditContact(CallContact item);
void setDragView(RelativeLayout relativeLayout);
void toggleForSearchDrawer();
}
@Override
......@@ -138,6 +114,8 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
mGridAdapter = new StarredContactsAdapter(getActivity());
mListAdapter = new ContactsAdapter(getActivity(), mCallbacks, mCallbacks.getService().get40dpContactCache(), mCallbacks.getService().getThreadPool());
}
@Override
......@@ -158,40 +136,8 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
View inflatedView = inflater.inflate(R.layout.frag_contact_list, container, false);
mHeader = (LinearLayout) inflater.inflate(R.layout.frag_contact_list_header, null);
mContactList = (StickyListHeadersListView) inflatedView.findViewById(R.id.contacts_stickylv);
//mContactList.setDividerHeight(0);
mContactList.setDivider(null);
inflatedView.findViewById(R.id.drag_view).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
/*inflatedView.findViewById(R.id.contact_search_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mContactList.smoothScrollToPosition(0);
mQuickReturnSearchView.setOnQueryTextListener(ContactListFragment.this);
mQuickReturnSearchView.setIconified(false);
mQuickReturnSearchView.setFocusable(true);
mCallbacks.toggleForSearchDrawer();
}
});
inflatedView.findViewById(R.id.slider_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mCallbacks.toggleDrawer();
}
});
mCallbacks.setDragView(((RelativeLayout) inflatedView.findViewById(R.id.slider_button)));
*/
//mQuickReturnSearchView = (SearchView) mHeader.findViewById(R.id.contact_search);
mStarredGrid = (GridView) mHeader.findViewById(R.id.favorites_grid);
llMain = (LinearLayout) mHeader.findViewById(R.id.llMain);
favHeadLabel = (TextView) mHeader.findViewById(R.id.fav_head_label);
......@@ -218,29 +164,14 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
mContactList.setAdapter(mListAdapter);
mStarredGrid.setAdapter(mGridAdapter);
/*mQuickReturnSearchView.setIconifiedByDefault(false);
mQuickReturnSearchView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mQuickReturnSearchView.setIconified(false);
mQuickReturnSearchView.setFocusable(true);
}
});
mQuickReturnSearchView.setOnQueryTextListener(ContactListFragment.this);*/
getLoaderManager().initLoader(LoaderConstants.CONTACT_LOADER, null, this);
onLoadFinished(null, mCallbacks.getService().getSortedContacts());
}
private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> av, View view, int pos, long id) {
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view.findViewById(R.id.photo));
view.startDrag(null, shadowBuilder, view, 0);
mCallbacks.onContactDragged();
return true;
return false;
}
};
......@@ -258,64 +189,15 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
}
private void setListViewListeners() {
/*mSwipeLvTouchListener = new SwipeListViewTouchListener(mContactList.getWrappedList(), new SwipeListViewTouchListener.OnSwipeCallback() {
@Override
public void onSwipeLeft(ListView listView, int[] reverseSortedPositions) {
}
@Override
public void onSwipeRight(ListView listView, View down) {
down.findViewById(R.id.quick_edit).setClickable(true);
down.findViewById(R.id.quick_discard).setClickable(true);
down.findViewById(R.id.quick_starred).setClickable(true);
}
}, true, false);*/
/*mContactList.getWrappedList().setOnDragListener(dragListener);
mContactList.getWrappedList().setOnTouchListener(mSwipeLvTouchListener);*/
mContactList.getWrappedList().setOnItemLongClickListener(mItemLongClickListener);
/*mContactList.getWrappedList().setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view, int pos, long id) {
Log.i(TAG, "Opening Item");
mSwipeLvTouchListener.openItem(view, pos, id);
}
});*/
}
/*
OnDragListener dragListener = new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// Do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_EXITED:
// v.setBackgroundDrawable(null);
break;
case DragEvent.ACTION_DROP:
break;
case DragEvent.ACTION_DRAG_ENDED:
View view1 = (View) event.getLocalState();
view1.setVisibility(View.VISIBLE);
default:
break;
}
return true;
}
};*/
@Override
public boolean onQueryTextChange(String newText) {
mCurFilter = newText;
if (newText.isEmpty()) {
getLoaderManager().restartLoader(LoaderConstants.CONTACT_LOADER, null, this);
getLoaderManager().destroyLoader(LoaderConstants.CONTACT_LOADER);
onLoadFinished(null, mCallbacks.getService().getSortedContacts());
newcontact.setVisibility(View.GONE);
return true;
}
......@@ -339,33 +221,28 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
@Override
public Loader<ContactsLoader.Result> onCreateLoader(int id, Bundle args) {
Uri baseUri;
Log.i(TAG, "createLoader");
if (args != null) {
Uri baseUri = null;
if (args != null)
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, Uri.encode(args.getString("filter")));
} else {
baseUri = Contacts.CONTENT_URI;
}
ContactsLoader l = new ContactsLoader(getActivity(), baseUri);
ContactsLoader l = new ContactsLoader(getActivity(), baseUri, mCallbacks.getService().getContactCache());
l.forceLoad();
return l;
}
@Override
public void onLoadFinished(Loader<ContactsLoader.Result> loader, ContactsLoader.Result data) {
Log.i(TAG, "onLoadFinished with " + data.contacts.size() + " contacts, " + data.starred.size() + " starred.");
mListAdapter.setData(data.contacts);
setListViewListeners();
mGridAdapter.setData(data.starred);
if (data.starred.isEmpty()) {
llMain.setVisibility(View.GONE);
favHeadLabel.setVisibility(View.GONE);
mGridAdapter.removeAll();
} else {
llMain.setVisibility(View.VISIBLE);
favHeadLabel.setVisibility(View.VISIBLE);
mGridAdapter.setData(data.starred);
setGridViewListeners();
mStarredGrid.post(new Runnable() {
......
......@@ -173,7 +173,7 @@ public class TransferDFragment extends DialogFragment implements LoaderManager.L
} else {
baseUri = Contacts.CONTENT_URI;
}
ContactsLoader l = new ContactsLoader(getActivity(), baseUri);
ContactsLoader l = new ContactsLoader(getActivity());
l.forceLoad();
return l;
}
......
/*
* Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
* Copyright (C) 2015 Savoir-faire Linux Inc.
*
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* 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
......@@ -15,18 +16,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package cx.ring.loaders;
......@@ -40,85 +30,172 @@ import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.OperationCanceledException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.Contacts;
import android.util.Log;
import android.util.LongSparseArray;
public class ContactsLoader extends AsyncTaskLoader<ContactsLoader.Result>
{
private static final String TAG = ContactsLoader.class.getSimpleName();
public class Result {
public final ArrayList<CallContact> contacts = new ArrayList<>();
public static class Result {
public final ArrayList<CallContact> contacts = new ArrayList<>(512);
public final ArrayList<CallContact> starred = new ArrayList<>();
}
// These are the Contacts rows that we will retrieve.
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.STARRED };
static final String[] CONTACTS_PHONES_PROJECTION = new String[] { Phone.NUMBER, Phone.TYPE };
static final String[] CONTACTS_SIP_PROJECTION = new String[] { SipAddress.SIP_ADDRESS, SipAddress.TYPE };
static private final String[] CONTACTS_ID_PROJECTION = new String[] { Contacts._ID };
static private final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.STARRED};
static private final String[] CONTACTS_SIP_PROJECTION = new String[] { ContactsContract.CommonDataKinds.Phone.CONTACT_ID, ContactsContract.Data.MIMETYPE, SipAddress.SIP_ADDRESS, SipAddress.TYPE };
static private final String SELECT = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))";
private final Uri baseUri;
private final LongSparseArray<CallContact> filterFrom;
private volatile boolean abandon = false;
static private final String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))";
Uri baseUri;
public ContactsLoader(Context context) {
this(context, null, null);
}
public ContactsLoader(Context context, Uri u) {
public ContactsLoader(Context context, Uri base, LongSparseArray < CallContact > filter) {
super(context);
baseUri = u;
baseUri = base;
filterFrom = filter;
}
private boolean checkCancel() {
return checkCancel(null);
}
private boolean checkCancel(Cursor c) {
if (isLoadInBackgroundCanceled()) {
Log.w(TAG, "Cancelled");
if (c != null)
c.close();
throw new OperationCanceledException();
}
if (abandon) {
Log.w(TAG, "Abandoned");
if (c != null)
c.close();
return true;
}
return false;
}
@Override
public Result loadInBackground() {
Result res = new Result();
ContentResolver cr = getContext().getContentResolver();
Cursor result = cr.query(baseUri, CONTACTS_SUMMARY_PROJECTION, select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
if (result == null)
return res;
int iID = result.getColumnIndex(Contacts._ID);
int iKey = result.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
int iName = result.getColumnIndex(Contacts.DISPLAY_NAME);
int iPhoto = result.getColumnIndex(Contacts.PHOTO_ID);
int iStarred = result.getColumnIndex(Contacts.STARRED);
CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
while (result.moveToNext()) {
long cid = result.getLong(iID);
builder.startNewContact(cid, result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
Cursor cPhones = cr.query(Phone.CONTENT_URI, CONTACTS_PHONES_PROJECTION, Phone.CONTACT_ID + " =" + cid, null, null);
if (cPhones != null) {
while (cPhones.moveToNext()) {
builder.addPhoneNumber(cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)), cPhones.getInt(cPhones.getColumnIndex(Phone.TYPE)));
Log.w(TAG,"Phone:"+cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)));
}
cPhones.close();
}
//Cursor cSip = cr.query(Phone.CONTENT_URI, CONTACTS_SIP_PROJECTION, Phone.CONTACT_ID + "=" + cid, null, null);
Cursor cSip = cr.query(ContactsContract.Data.CONTENT_URI,
CONTACTS_SIP_PROJECTION,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?",
new String[]{String.valueOf(cid), ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}, null);
if (cSip != null) {
while (cSip.moveToNext()) {
builder.addSipNumber(cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)), cSip.getInt(cSip.getColumnIndex(SipAddress.TYPE)));
Log.w(TAG, "SIP Phone for " + cid + " :" + cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)));
long startTime = System.nanoTime();
final Result res = new Result();
if (baseUri != null) {
Cursor result = cr.query(baseUri, CONTACTS_ID_PROJECTION, SELECT, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
if (result == null)
return res;
int iID = result.getColumnIndex(Contacts._ID);
long[] filter_ids = new long[result.getCount()];
int i = 0;
while (result.moveToNext()) {
long cid = result.getLong(iID);
filter_ids[i++] = cid;
}
result.close();
res.contacts.ensureCapacity(filter_ids.length);
int n = filter_ids.length;
for (i = 0; i < n; i++) {
CallContact c = filterFrom.get(filter_ids[i]);
res.contacts.add(c);
if (c.isStared())
res.starred.add(c);
}
}
else {
StringBuilder cids = new StringBuilder();
LongSparseArray<CallContact> cache;
{
Cursor c = cr.query(ContactsContract.Data.CONTENT_URI, CONTACTS_SIP_PROJECTION,
ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=?",
new String[]{Phone.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}, null);
if (c != null) {
cache = new LongSparseArray<>(c.getCount());
cids.ensureCapacity(c.getCount() * 4);
final int iID = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
final int iMime = c.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int iNumber = c.getColumnIndex(SipAddress.SIP_ADDRESS);
final int iType = c.getColumnIndex(SipAddress.TYPE);
while (c.moveToNext()) {
long id = c.getLong(iID);
CallContact contact = cache.get(id);
if (contact == null) {
contact = new CallContact(id);
cache.put(id, contact);
if (cids.length() > 0)
cids.append(",");
cids.append(id);
}
if (Phone.CONTENT_ITEM_TYPE.equals(c.getString(iMime))) {
//Log.w(TAG, "Phone for " + id + " :" + cSip.getString(iNumber));
contact.addPhoneNumber(c.getString(iNumber), c.getInt(iType));
} else {
//Log.w(TAG, "SIP Phone for " + id + " :" + cSip.getString(iNumber));
contact.addNumber(c.getString(iNumber), c.getInt(iType), CallContact.NumberType.SIP);
}
}
c.close();
} else {
cache = new LongSparseArray<>();
}
cSip.close();
}
res.contacts.add(builder.build());
if (result.getInt(iStarred) == 1) {
res.starred.add(builder.build());
if (checkCancel())
return null;
{
Cursor c = cr.query(Contacts.CONTENT_URI, CONTACTS_SUMMARY_PROJECTION,
ContactsContract.Contacts._ID + " in (" + cids.toString() + ")", null,
ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
if (c != null) {
final int iID = c.getColumnIndex(Contacts._ID);
final int iKey = c.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
final int iName = c.getColumnIndex(Contacts.DISPLAY_NAME);
final int iPhoto = c.getColumnIndex(Contacts.PHOTO_ID);
final int iStarred = c.getColumnIndex(Contacts.STARRED);
res.contacts.ensureCapacity(c.getCount());
while (c.moveToNext()) {
long id = c.getLong(iID);
CallContact contact = cache.get(id);
if (contact == null)
Log.w(TAG, "Can't find contact with ID " + id);
else {
contact.setContactInfos(c.getString(iKey), c.getString(iName), c.getLong(iPhoto));
res.contacts.add(contact);
if (c.getInt(iStarred) != 0) {
res.starred.add(contact);
contact.setStared();
}
}
}
c.close();
}
}
}
result.close();
return res;
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1000000;
Log.w(TAG, "Loading " + res.contacts.size() + " system contacts took " + duration / 1000. + "s");
return checkCancel() ? null : res;
}
@Override
protected void onAbandon() {
super.onAbandon();
abandon = true;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment