mirror of
https://github.com/moparisthebest/k-9
synced 2025-02-07 02:30:10 -05:00
Added helper class to access contacts. Uses the old contacts API for SDK/API 3+4 devices and the new API for SDK/API 5+ devices.
All places that accessed the contacts have been updated to use this helper class.
This commit is contained in:
parent
0eb342ef5a
commit
0e4c1dfacb
@ -16,66 +16,58 @@
|
||||
|
||||
package com.fsck.k9;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.database.Cursor;
|
||||
import android.view.View;
|
||||
import android.widget.ResourceCursorAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
public abstract class EmailAddressAdapter extends ResourceCursorAdapter
|
||||
public class EmailAddressAdapter extends ResourceCursorAdapter
|
||||
{
|
||||
private static EmailAddressAdapter sInstance;
|
||||
private static Context sContext;
|
||||
|
||||
public static EmailAddressAdapter getInstance(Context context)
|
||||
{
|
||||
if (sInstance == null)
|
||||
{
|
||||
String className;
|
||||
|
||||
sContext = context;
|
||||
|
||||
/*
|
||||
* Check the version of the SDK we are running on. Choose an
|
||||
* implementation class designed for that version of the SDK.
|
||||
*/
|
||||
int sdkVersion = Integer.parseInt(Build.VERSION.SDK); // Cupcake style
|
||||
if (sdkVersion < Build.VERSION_CODES.ECLAIR)
|
||||
{
|
||||
className = "com.fsck.k9.EmailAddressAdapterSdk3_4";
|
||||
}
|
||||
else
|
||||
{
|
||||
className = "com.fsck.k9.EmailAddressAdapterSdk5";
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the required class by name and instantiate it.
|
||||
*/
|
||||
try
|
||||
{
|
||||
Class<? extends EmailAddressAdapter> clazz =
|
||||
Class.forName(className).asSubclass(EmailAddressAdapter.class);
|
||||
sInstance = clazz.newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
sInstance = new EmailAddressAdapter(context);
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static Context getContext()
|
||||
|
||||
private Contacts mContacts;
|
||||
|
||||
private EmailAddressAdapter(Context context)
|
||||
{
|
||||
return sContext;
|
||||
super(context, R.layout.recipient_dropdown_item, null);
|
||||
mContacts = Contacts.getInstance(context);
|
||||
}
|
||||
|
||||
protected ContentResolver mContentResolver;
|
||||
|
||||
public EmailAddressAdapter()
|
||||
@Override
|
||||
public final String convertToString(final Cursor cursor)
|
||||
{
|
||||
super(getContext(), R.layout.recipient_dropdown_item, null);
|
||||
mContentResolver = getContext().getContentResolver();
|
||||
final String name = mContacts.getName(cursor);
|
||||
final String address = mContacts.getEmail(cursor);;
|
||||
|
||||
return new Address(address, name).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bindView(final View view, final Context context, final Cursor cursor)
|
||||
{
|
||||
final TextView text1 = (TextView) view.findViewById(R.id.text1);
|
||||
final TextView text2 = (TextView) view.findViewById(R.id.text2);
|
||||
text1.setText(mContacts.getName(cursor));
|
||||
text2.setText(mContacts.getEmail(cursor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor runQueryOnBackgroundThread(CharSequence constraint)
|
||||
{
|
||||
return mContacts.searchContacts(constraint);
|
||||
}
|
||||
}
|
||||
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.fsck.k9;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.provider.Contacts.ContactMethods;
|
||||
import android.provider.Contacts.People;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import com.fsck.k9.mail.Address;
|
||||
|
||||
import static android.provider.Contacts.ContactMethods.CONTENT_EMAIL_URI;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class EmailAddressAdapterSdk3_4 extends EmailAddressAdapter
|
||||
{
|
||||
public static final int NAME_INDEX = 1;
|
||||
|
||||
public static final int DATA_INDEX = 2;
|
||||
|
||||
private static final String SORT_ORDER = People.TIMES_CONTACTED + " DESC, " + People.NAME;
|
||||
|
||||
private static final String[] PROJECTION =
|
||||
{
|
||||
ContactMethods._ID, // 0
|
||||
ContactMethods.NAME, // 1
|
||||
ContactMethods.DATA // 2
|
||||
};
|
||||
|
||||
@Override
|
||||
public final String convertToString(Cursor cursor)
|
||||
{
|
||||
String name = cursor.getString(NAME_INDEX);
|
||||
String address = cursor.getString(DATA_INDEX);
|
||||
|
||||
return new Address(address, name).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bindView(View view, Context context, Cursor cursor)
|
||||
{
|
||||
TextView text1 = (TextView)view.findViewById(R.id.text1);
|
||||
TextView text2 = (TextView)view.findViewById(R.id.text2);
|
||||
text1.setText(cursor.getString(NAME_INDEX));
|
||||
text2.setText(cursor.getString(DATA_INDEX));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor runQueryOnBackgroundThread(CharSequence constraint)
|
||||
{
|
||||
String where = null;
|
||||
|
||||
if (constraint != null)
|
||||
{
|
||||
String filter = DatabaseUtils.sqlEscapeString(constraint.toString() + '%');
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append("("+People.NAME+" LIKE ");
|
||||
s.append(filter);
|
||||
s.append(") OR ("+ContactMethods.DATA+" LIKE ");
|
||||
s.append(filter);
|
||||
s.append(")");
|
||||
|
||||
where = s.toString();
|
||||
}
|
||||
|
||||
return mContentResolver.query(CONTENT_EMAIL_URI, PROJECTION, where, null, SORT_ORDER);
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.fsck.k9;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Email;
|
||||
import android.provider.ContactsContract.Contacts.Data;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import com.fsck.k9.mail.Address;
|
||||
|
||||
public class EmailAddressAdapterSdk5 extends EmailAddressAdapter
|
||||
{
|
||||
public static final int NAME_INDEX = 1;
|
||||
public static final int DATA_INDEX = 2;
|
||||
|
||||
private static final String SORT_ORDER = Contacts.TIMES_CONTACTED
|
||||
+ " DESC, " + Contacts.DISPLAY_NAME;
|
||||
|
||||
private static final String[] PROJECTION =
|
||||
{
|
||||
Data._ID, // 0
|
||||
Contacts.DISPLAY_NAME, // 1
|
||||
Email.DATA // 2
|
||||
};
|
||||
|
||||
@Override
|
||||
public final String convertToString(Cursor cursor)
|
||||
{
|
||||
String name = cursor.getString(NAME_INDEX);
|
||||
String address = cursor.getString(DATA_INDEX);
|
||||
|
||||
return new Address(address, name).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bindView(View view, Context context, Cursor cursor)
|
||||
{
|
||||
TextView text1 = (TextView) view.findViewById(R.id.text1);
|
||||
TextView text2 = (TextView) view.findViewById(R.id.text2);
|
||||
text1.setText(cursor.getString(NAME_INDEX));
|
||||
text2.setText(cursor.getString(DATA_INDEX));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor runQueryOnBackgroundThread(CharSequence constraint)
|
||||
{
|
||||
String filter = constraint == null ? "" : constraint.toString();
|
||||
Uri uri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, Uri.encode(filter));
|
||||
Cursor c = mContentResolver.query(uri, PROJECTION, null, null, SORT_ORDER);
|
||||
// To prevent expensive execution in the UI thread
|
||||
// Cursors get lazily executed, so if you don't call anything on the cursor before
|
||||
// returning it from the background thread you'll have a complied program for the cursor,
|
||||
// but it won't have been executed to generate the data yet. Often the execution is more
|
||||
// expensive than the compilation...
|
||||
if (c != null)
|
||||
{
|
||||
c.getCount();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
@ -27,8 +27,6 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.provider.Contacts;
|
||||
import android.provider.Contacts.Intents;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.StyleSpan;
|
||||
@ -55,9 +53,6 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.provider.ContactsContract.Data;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Email;
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.FontSizes;
|
||||
@ -67,6 +62,7 @@ import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.CryptoProvider;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Message;
|
||||
@ -156,6 +152,8 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
|
||||
private FontSizes mFontSizes = K9.getFontSizes();
|
||||
|
||||
private Contacts mContacts;
|
||||
|
||||
/**
|
||||
* Pair class is only available since API Level 5, so we need
|
||||
* this helper class unfortunately
|
||||
@ -724,6 +722,7 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
{
|
||||
super.onCreate(icicle, false);
|
||||
|
||||
mContacts = Contacts.getInstance(this);
|
||||
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
@ -1294,31 +1293,12 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
{
|
||||
try
|
||||
{
|
||||
Address senderEmail = mMessage.getFrom()[0];
|
||||
Uri contactUri = Uri.fromParts("mailto", senderEmail.getAddress(), null);
|
||||
|
||||
Intent contactIntent = new Intent(Contacts.Intents.SHOW_OR_CREATE_CONTACT);
|
||||
contactIntent.setData(contactUri);
|
||||
|
||||
// Pass along full E-mail string for possible create dialog
|
||||
contactIntent.putExtra(Contacts.Intents.EXTRA_CREATE_DESCRIPTION,
|
||||
senderEmail.toString());
|
||||
|
||||
// Only provide personal name hint if we have one
|
||||
String senderPersonal = senderEmail.getPersonal();
|
||||
if (senderPersonal != null)
|
||||
{
|
||||
contactIntent.putExtra(Intents.Insert.NAME, senderPersonal);
|
||||
}
|
||||
|
||||
startActivity(contactIntent);
|
||||
final Address senderEmail = mMessage.getFrom()[0];
|
||||
mContacts.createContact(this, senderEmail);
|
||||
}
|
||||
catch (MessagingException me)
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Config.LOGV)
|
||||
{
|
||||
Log.v(K9.LOG_TAG, "loadMessageForViewHeadersAvailable", me);
|
||||
}
|
||||
Log.e(K9.LOG_TAG, "Couldn't create contact", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2168,24 +2148,12 @@ public class MessageView extends K9Activity implements OnClickListener
|
||||
if (hasPictures && (mShowPictures == false))
|
||||
{
|
||||
boolean forceShowPictures = false;
|
||||
if (account.getShowPictures() == Account.ShowPictures.ALWAYS)
|
||||
if ((account.getShowPictures() == Account.ShowPictures.ALWAYS) ||
|
||||
((account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS) &&
|
||||
mContacts.isInContacts(message.getFrom()[0].getAddress())))
|
||||
{
|
||||
forceShowPictures = true;
|
||||
}
|
||||
else if (account.getShowPictures() == Account.ShowPictures.ONLY_FROM_CONTACTS)
|
||||
{
|
||||
// TODO: change to _COUNT for speed
|
||||
Cursor c = getContentResolver().query(Data.CONTENT_URI, new String[]{Data._ID},
|
||||
Data.MIMETYPE + "='" + Email.CONTENT_ITEM_TYPE + "' AND "
|
||||
+ Data.DATA1 + "=? AND "
|
||||
+ Data.IN_VISIBLE_GROUP + "='1'",
|
||||
new String[] { message.getFrom()[0].getAddress() }, null);
|
||||
|
||||
if ((c != null) && (c.getCount() > 0))
|
||||
{
|
||||
forceShowPictures = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (forceShowPictures)
|
||||
{
|
||||
|
@ -7,11 +7,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Contacts;
|
||||
import android.provider.Contacts.People.ContactMethods;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
@ -22,6 +18,7 @@ import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import com.fsck.k9.*;
|
||||
import com.fsck.k9.activity.K9Activity;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.helper.Utility;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
@ -153,20 +150,7 @@ public class AccountSetupBasics extends K9Activity
|
||||
String name = null;
|
||||
try
|
||||
{
|
||||
String projection[] =
|
||||
{
|
||||
ContactMethods.NAME
|
||||
};
|
||||
Cursor c = getContentResolver().query(
|
||||
// TODO: For Android 2.0, needs to change to ContactsContract.People...
|
||||
Uri.withAppendedPath(Contacts.People.CONTENT_URI, "owner"), projection, null, null,
|
||||
null);
|
||||
if (c.getCount() > 0)
|
||||
{
|
||||
c.moveToFirst();
|
||||
name = c.getString(0);
|
||||
c.close();
|
||||
}
|
||||
name = Contacts.getInstance(this).getOwnerName();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
168
src/com/fsck/k9/helper/Contacts.java
Normal file
168
src/com/fsck/k9/helper/Contacts.java
Normal file
@ -0,0 +1,168 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.mail.Address;
|
||||
|
||||
/**
|
||||
* Helper class to access the contacts stored on the device. This is needed
|
||||
* because the original contacts API introduced with SDK 1 was deprecated with
|
||||
* SDK 5 and will eventually be removed in newer SDK versions.
|
||||
* A class that uses the latest contacts API available on the device will be
|
||||
* loaded at runtime.
|
||||
*
|
||||
* @see ContactsSdk3_4
|
||||
* @see ContactsSdk5
|
||||
*/
|
||||
public abstract class Contacts
|
||||
{
|
||||
/**
|
||||
* Instance of the SDK specific class that interfaces with the contacts
|
||||
* API.
|
||||
*/
|
||||
private static Contacts sInstance = null;
|
||||
|
||||
/**
|
||||
* Get SDK specific instance of the Contacts class.
|
||||
*
|
||||
* @param context A {@link Context} instance.
|
||||
* @return Appropriate {@link Contacts} instance for this device.
|
||||
*/
|
||||
public static Contacts getInstance(Context context)
|
||||
{
|
||||
if (sInstance == null)
|
||||
{
|
||||
/*
|
||||
* Check the version of the SDK we are running on. Choose an
|
||||
* implementation class designed for that version of the SDK.
|
||||
*/
|
||||
int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
|
||||
|
||||
String className = null;
|
||||
if (sdkVersion <= Build.VERSION_CODES.DONUT)
|
||||
{
|
||||
className = "com.fsck.k9.helper.ContactsSdk3_4";
|
||||
}
|
||||
else if (sdkVersion >= Build.VERSION_CODES.ECLAIR)
|
||||
{
|
||||
className = "com.fsck.k9.helper.ContactsSdk5";
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the required class by name and instantiate it.
|
||||
*/
|
||||
try
|
||||
{
|
||||
Class<? extends Contacts> clazz =
|
||||
Class.forName(className).asSubclass(Contacts.class);
|
||||
|
||||
Constructor<? extends Contacts> constructor = clazz.getConstructor(Context.class);
|
||||
sInstance = constructor.newInstance(context);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Couldn't find class: " + className, e);
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Couldn't instantiate class: " + className, e);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Couldn't access class: " + className, e);
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Couldn't find constructor of class: " + className, e);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Wrong arguments for constructor of class: " + className, e);
|
||||
}
|
||||
catch (InvocationTargetException e)
|
||||
{
|
||||
Log.e(K9.LOG_TAG, "Couldn't invoke constructor of class: " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
||||
protected Context mContext;
|
||||
protected ContentResolver mContentResolver;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param context A {@link Context} instance.
|
||||
*/
|
||||
protected Contacts(Context context)
|
||||
{
|
||||
mContext = context;
|
||||
mContentResolver = context.getContentResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the device's owner.
|
||||
*
|
||||
* @return The name of the owner if available. <tt>null</tt>, otherwise.
|
||||
*/
|
||||
public abstract String getOwnerName();
|
||||
|
||||
/**
|
||||
* Start the activity to add information to an existing contact or add a
|
||||
* new one.
|
||||
*
|
||||
* @param activity Object of the currently active activity.
|
||||
* @param email An {@link Address} instance containing the email address
|
||||
* of the entity you want to add to the contacts. Optionally
|
||||
* the instance also contains the (display) name of that
|
||||
* entity.
|
||||
*/
|
||||
public abstract void createContact(Activity activity, Address email);
|
||||
|
||||
/**
|
||||
* Check whether the provided email address belongs to one of the contacts.
|
||||
*
|
||||
* @param emailAddress The email address to look for.
|
||||
* @return <tt>true</tt>, if the email address belongs to a contact.
|
||||
* <tt>false</tt>, otherwise.
|
||||
*/
|
||||
public abstract boolean isInContacts(String emailAddress);
|
||||
|
||||
/**
|
||||
* Filter the contacts matching the given search term.
|
||||
*
|
||||
* @param filter The search term to filter the contacts.
|
||||
* @return A {@link Cursor} instance that can be used to get the
|
||||
* matching contacts.
|
||||
*/
|
||||
public abstract Cursor searchContacts(CharSequence filter);
|
||||
|
||||
/**
|
||||
* Extract the name from a {@link Cursor} instance returned by
|
||||
* {@link #searchContacts(CharSequence)}.
|
||||
*
|
||||
* @param cursor The {@link Cursor} instance.
|
||||
* @return The name of the contact in the {@link Cursor}'s current row.
|
||||
*/
|
||||
public abstract String getName(Cursor cursor);
|
||||
|
||||
/**
|
||||
* Extract the email address from a {@link Cursor} instance returned by
|
||||
* {@link #searchContacts(CharSequence)}.
|
||||
*
|
||||
* @param cursor The {@link Cursor} instance.
|
||||
* @return The email address of the contact in the {@link Cursor}'s current
|
||||
* row.
|
||||
*/
|
||||
public abstract String getEmail(Cursor cursor);
|
||||
}
|
186
src/com/fsck/k9/helper/ContactsSdk3_4.java
Normal file
186
src/com/fsck/k9/helper/ContactsSdk3_4.java
Normal file
@ -0,0 +1,186 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.Contacts;
|
||||
import com.fsck.k9.mail.Address;
|
||||
|
||||
/**
|
||||
* Access the contacts on the device using the old API (introduced in SDK 1).
|
||||
*
|
||||
* @see android.provider.Contacts
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class ContactsSdk3_4 extends com.fsck.k9.helper.Contacts
|
||||
{
|
||||
/**
|
||||
* The order in which the search results are returned by
|
||||
* {@link #searchContacts(CharSequence)}.
|
||||
*/
|
||||
private static final String SORT_ORDER =
|
||||
Contacts.People.TIMES_CONTACTED + " DESC, " +
|
||||
Contacts.People.NAME;
|
||||
|
||||
/**
|
||||
* Array of columns to load from the database.
|
||||
*
|
||||
* Important: The _ID field is needed by
|
||||
* {@link com.fsck.k9.EmailAddressAdapter} or more specificly by
|
||||
* {@link android.widget.ResourceCursorAdapter}.
|
||||
*/
|
||||
private static final String PROJECTION[] = {
|
||||
Contacts.People.ContactMethods._ID,
|
||||
Contacts.People.ContactMethods.NAME,
|
||||
Contacts.People.ContactMethods.DATA
|
||||
};
|
||||
|
||||
/**
|
||||
* Index of the name field in the projection. This must match the order in
|
||||
* {@link #PROJECTION}.
|
||||
*/
|
||||
private static final int NAME_INDEX = 1;
|
||||
|
||||
/**
|
||||
* Index of the email address field in the projection. This must match the
|
||||
* order in {@link #PROJECTION}.
|
||||
*/
|
||||
private static final int EMAIL_INDEX = 2;
|
||||
|
||||
|
||||
public ContactsSdk3_4(final Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createContact(final Activity activity, final Address email)
|
||||
{
|
||||
final Uri contactUri = Uri.fromParts("mailto", email.getAddress(), null);
|
||||
|
||||
final Intent contactIntent = new Intent(Contacts.Intents.SHOW_OR_CREATE_CONTACT);
|
||||
contactIntent.setData(contactUri);
|
||||
|
||||
// Pass along full E-mail string for possible create dialog
|
||||
contactIntent.putExtra(Contacts.Intents.EXTRA_CREATE_DESCRIPTION,
|
||||
email.toString());
|
||||
|
||||
// Only provide personal name hint if we have one
|
||||
final String senderPersonal = email.getPersonal();
|
||||
if (senderPersonal != null)
|
||||
{
|
||||
contactIntent.putExtra(Contacts.Intents.Insert.NAME, senderPersonal);
|
||||
}
|
||||
|
||||
activity.startActivity(contactIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOwnerName()
|
||||
{
|
||||
String name = null;
|
||||
final Cursor c = mContentResolver.query(
|
||||
Uri.withAppendedPath(Contacts.People.CONTENT_URI, "owner"),
|
||||
PROJECTION,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
if (c.getCount() > 0)
|
||||
{
|
||||
c.moveToFirst();
|
||||
name = c.getString(NAME_INDEX);
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInContacts(final String emailAddress)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
final String where = Contacts.ContactMethods.DATA + "=?";
|
||||
final String[] args = new String[] {emailAddress};
|
||||
|
||||
final Cursor c = mContentResolver.query(
|
||||
Contacts.ContactMethods.CONTENT_EMAIL_URI,
|
||||
PROJECTION,
|
||||
where,
|
||||
args,
|
||||
null);
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
if (c.getCount() > 0)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor searchContacts(final CharSequence constraint)
|
||||
{
|
||||
final String where;
|
||||
final String[] args;
|
||||
if (constraint == null)
|
||||
{
|
||||
where = null;
|
||||
args = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
where = "(" +
|
||||
Contacts.People.NAME + " LIKE ?" +
|
||||
") OR (" +
|
||||
Contacts.ContactMethods.DATA + " LIKE ?" +
|
||||
")";
|
||||
final String filter = constraint.toString() + "%";
|
||||
args = new String[] {filter, filter};
|
||||
}
|
||||
|
||||
final Cursor c = mContentResolver.query(
|
||||
Contacts.ContactMethods.CONTENT_EMAIL_URI,
|
||||
PROJECTION,
|
||||
where,
|
||||
args,
|
||||
SORT_ORDER);
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
/*
|
||||
* To prevent expensive execution in the UI thread:
|
||||
* Cursors get lazily executed, so if you don't call anything on
|
||||
* the cursor before returning it from the background thread you'll
|
||||
* have a complied program for the cursor, but it won't have been
|
||||
* executed to generate the data yet. Often the execution is more
|
||||
* expensive than the compilation...
|
||||
*/
|
||||
c.getCount();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Cursor c)
|
||||
{
|
||||
return c.getString(NAME_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail(Cursor c)
|
||||
{
|
||||
return c.getString(EMAIL_INDEX);
|
||||
}
|
||||
}
|
162
src/com/fsck/k9/helper/ContactsSdk5.java
Normal file
162
src/com/fsck/k9/helper/ContactsSdk5.java
Normal file
@ -0,0 +1,162 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.provider.ContactsContract.Intents;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Email;
|
||||
import com.fsck.k9.mail.Address;
|
||||
|
||||
/**
|
||||
* Access the contacts on the device using the API introduced with SDK 5.
|
||||
*
|
||||
* @see android.provider.ContactsContract
|
||||
*/
|
||||
public class ContactsSdk5 extends com.fsck.k9.helper.Contacts
|
||||
{
|
||||
/**
|
||||
* The order in which the search results are returned by
|
||||
* {@link #searchContacts(CharSequence)}.
|
||||
*/
|
||||
private static final String SORT_ORDER =
|
||||
Contacts.TIMES_CONTACTED + " DESC, " +
|
||||
Contacts.DISPLAY_NAME;
|
||||
|
||||
/**
|
||||
* Array of columns to load from the database.
|
||||
*
|
||||
* Important: The _ID field is needed by
|
||||
* {@link com.fsck.k9.EmailAddressAdapter} or more specificly by
|
||||
* {@link android.widget.ResourceCursorAdapter}.
|
||||
*/
|
||||
private static final String PROJECTION[] = {
|
||||
Contacts._ID,
|
||||
Contacts.DISPLAY_NAME,
|
||||
Email.DATA
|
||||
};
|
||||
|
||||
/**
|
||||
* Index of the name field in the projection. This must match the order in
|
||||
* {@link #PROJECTION}.
|
||||
*/
|
||||
private static final int NAME_INDEX = 1;
|
||||
|
||||
/**
|
||||
* Index of the email address field in the projection. This must match the
|
||||
* order in {@link #PROJECTION}.
|
||||
*/
|
||||
private static final int EMAIL_INDEX = 2;
|
||||
|
||||
|
||||
public ContactsSdk5(final Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createContact(final Activity activity, final Address email)
|
||||
{
|
||||
final Uri contactUri = Uri.fromParts("mailto", email.getAddress(), null);
|
||||
|
||||
final Intent contactIntent = new Intent(Intents.SHOW_OR_CREATE_CONTACT);
|
||||
contactIntent.setData(contactUri);
|
||||
|
||||
// Pass along full E-mail string for possible create dialog
|
||||
contactIntent.putExtra(Intents.EXTRA_CREATE_DESCRIPTION,
|
||||
email.toString());
|
||||
|
||||
// Only provide personal name hint if we have one
|
||||
final String senderPersonal = email.getPersonal();
|
||||
if (senderPersonal != null)
|
||||
{
|
||||
contactIntent.putExtra(Intents.Insert.NAME, senderPersonal);
|
||||
}
|
||||
|
||||
activity.startActivity(contactIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOwnerName()
|
||||
{
|
||||
String name = null;
|
||||
|
||||
// Get the name of the first account that has one.
|
||||
Account[] accounts = AccountManager.get(mContext).getAccounts();
|
||||
for (final Account account : accounts)
|
||||
{
|
||||
if (account.name != null)
|
||||
{
|
||||
name = account.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInContacts(final String emailAddress)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
|
||||
final Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress));
|
||||
final Cursor c = mContentResolver.query(uri, PROJECTION, null, null, null);
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
if (c.getCount() > 0)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
c.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor searchContacts(final CharSequence constraint)
|
||||
{
|
||||
final String filter = (constraint == null) ? "" : constraint.toString();
|
||||
final Uri uri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, Uri.encode(filter));
|
||||
final Cursor c = mContentResolver.query(
|
||||
uri,
|
||||
PROJECTION,
|
||||
null,
|
||||
null,
|
||||
SORT_ORDER);
|
||||
|
||||
if (c != null)
|
||||
{
|
||||
/*
|
||||
* To prevent expensive execution in the UI thread:
|
||||
* Cursors get lazily executed, so if you don't call anything on
|
||||
* the cursor before returning it from the background thread you'll
|
||||
* have a complied program for the cursor, but it won't have been
|
||||
* executed to generate the data yet. Often the execution is more
|
||||
* expensive than the compilation...
|
||||
*/
|
||||
c.getCount();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Cursor c)
|
||||
{
|
||||
return c.getString(NAME_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail(Cursor c)
|
||||
{
|
||||
return c.getString(EMAIL_INDEX);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user