1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-30 13:12:25 -05:00

Initial support for a button to look up contacts in a contact provider

This commit is contained in:
Jesse Vincent 2011-03-22 18:06:11 +11:00
parent 0b7280b212
commit 81644d0f4b
8 changed files with 296 additions and 49 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -31,44 +31,93 @@
android:layout_marginRight="6dip" android:layout_marginRight="6dip"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textAppearance="?android:attr/textAppearanceMedium" /> android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
<MultiAutoCompleteTextView android:id="@+id/to_wrapper"
android:id="@+id/to"
android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="6dip" android:baselineAligned="true"
android:layout_marginRight="6dip" android:layout_marginLeft="6dip"
android:inputType="textEmailAddress|textMultiLine" android:layout_marginRight="6dip"
android:imeOptions="actionNext" android:layout_width="fill_parent">
android:hint="@string/message_compose_to_hint" <MultiAutoCompleteTextView
android:textColor="@android:color/primary_text_light" android:id="@+id/to"
android:textAppearance="?android:attr/textAppearanceMedium" /> android:layout_height="wrap_content"
android:inputType="textEmailAddress|textMultiLine"
<MultiAutoCompleteTextView android:imeOptions="actionNext"
android:id="@+id/cc" android:hint="@string/message_compose_to_hint"
android:layout_width="fill_parent" android:textColor="@android:color/primary_text_light"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="fill_parent"
android:layout_marginRight="6dip"
android:layout_weight="5"
/>
<ImageButton
android:id="@+id/add_to"
android:src="@drawable/ic_button_contacts"
android:layout_weight="1"
android:layout_height="fill_parent"
android:layout_width="60dip"
android:layout_marginTop="1dip"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/cc_wrapper"
android:visibility="gone"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="6dip" android:baselineAligned="true"
android:layout_marginRight="6dip" android:layout_marginLeft="6dip"
android:inputType="textEmailAddress|textMultiLine" android:layout_marginRight="6dip"
android:imeOptions="actionNext" android:layout_width="fill_parent">
android:hint="@string/message_compose_cc_hint" <MultiAutoCompleteTextView
android:textColor="@android:color/primary_text_light" android:id="@+id/cc"
android:textAppearance="?android:attr/textAppearanceMedium" android:layout_width="fill_parent"
android:visibility="gone" /> android:layout_height="wrap_content"
android:layout_weight="5"
<MultiAutoCompleteTextView android:layout_marginRight="6dip"
android:id="@+id/bcc" android:inputType="textEmailAddress|textMultiLine"
android:layout_width="fill_parent" android:imeOptions="actionNext"
android:hint="@string/message_compose_cc_hint"
android:textColor="@android:color/primary_text_light"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<ImageButton
android:id="@+id/add_cc"
android:src="@drawable/ic_button_contacts"
android:layout_weight="1"
android:layout_width="60dip"
android:layout_height="fill_parent"
android:layout_marginTop="1dip"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/bcc_wrapper"
android:visibility="gone"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="6dip" android:baselineAligned="true"
android:layout_marginRight="6dip" android:layout_marginLeft="6dip"
android:inputType="textEmailAddress|textMultiLine" android:layout_marginRight="6dip"
android:imeOptions="actionNext" android:layout_width="fill_parent">
android:hint="@string/message_compose_bcc_hint"
android:textColor="@android:color/primary_text_light" <MultiAutoCompleteTextView
android:textAppearance="?android:attr/textAppearanceMedium" android:id="@+id/bcc"
android:visibility="gone" /> android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginRight="6dip"
android:layout_weight="5"
android:inputType="textEmailAddress|textMultiLine"
android:imeOptions="actionNext"
android:hint="@string/message_compose_bcc_hint"
android:textColor="@android:color/primary_text_light"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<ImageButton
android:layout_marginTop="1dip"
android:layout_height="fill_parent"
android:id="@+id/add_bcc"
android:layout_weight="1"
android:layout_width="60dip"
android:src="@drawable/ic_button_contacts"
/>
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/layout_encrypt" android:id="@+id/layout_encrypt"

View File

@ -267,6 +267,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
<string name="message_compose_reply_header_fmt"><xliff:g id="sender">%s</xliff:g> wrote:\n\n</string> <string name="message_compose_reply_header_fmt"><xliff:g id="sender">%s</xliff:g> wrote:\n\n</string>
<string name="message_compose_quoted_text_label">Quoted text</string> <string name="message_compose_quoted_text_label">Quoted text</string>
<string name="message_compose_error_no_recipients">You must add at least one recipient.</string> <string name="message_compose_error_no_recipients">You must add at least one recipient.</string>
<string name="error_contact_address_not_found">No email address could be found.</string>
<string name="message_compose_downloading_attachments_toast">Some attachments were not downloaded. They will be downloaded automatically before this message is sent.</string> <string name="message_compose_downloading_attachments_toast">Some attachments were not downloaded. They will be downloaded automatically before this message is sent.</string>
<string name="message_compose_attachments_skipped_toast">Some attachments cannot be forwarded because they have not been downloaded.</string> <string name="message_compose_attachments_skipped_toast">Some attachments cannot be forwarded because they have not been downloaded.</string>

View File

@ -115,6 +115,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1; private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
private static final int ACTIVITY_CHOOSE_IDENTITY = 2; private static final int ACTIVITY_CHOOSE_IDENTITY = 2;
private static final int ACTIVITY_CHOOSE_ACCOUNT = 3; private static final int ACTIVITY_CHOOSE_ACCOUNT = 3;
private static final int CONTACT_PICKER_TO = 4;
private static final int CONTACT_PICKER_CC = 5;
private static final int CONTACT_PICKER_BCC = 6;
/** /**
* Regular expression to remove the first localized "Re:" prefix in subjects. * Regular expression to remove the first localized "Re:" prefix in subjects.
@ -129,6 +133,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
*/ */
private Account mAccount; private Account mAccount;
private Contacts mContacts;
/** /**
* This identity's settings are used for message composition. * This identity's settings are used for message composition.
* Note: This has to be an identity of the account {@link #mAccount}. * Note: This has to be an identity of the account {@link #mAccount}.
@ -156,6 +163,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private TextView mFromView; private TextView mFromView;
private LinearLayout mCcWrapper;
private LinearLayout mBccWrapper;
private MultiAutoCompleteTextView mToView; private MultiAutoCompleteTextView mToView;
private MultiAutoCompleteTextView mCcView; private MultiAutoCompleteTextView mCcView;
private MultiAutoCompleteTextView mBccView; private MultiAutoCompleteTextView mBccView;
@ -175,6 +184,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private TextView mCryptoSignatureUserId; private TextView mCryptoSignatureUserId;
private TextView mCryptoSignatureUserIdRest; private TextView mCryptoSignatureUserIdRest;
private ImageButton mAddToFromContacts;
private ImageButton mAddCcFromContacts;
private ImageButton mAddBccFromContacts;
private PgpData mPgpData = null; private PgpData mPgpData = null;
private String mReferences; private String mReferences;
@ -354,16 +367,24 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
return; return;
} }
mContacts = Contacts.getInstance(MessageCompose.this);
mAddressAdapter = EmailAddressAdapter.getInstance(this); mAddressAdapter = EmailAddressAdapter.getInstance(this);
mAddressValidator = new EmailAddressValidator(); mAddressValidator = new EmailAddressValidator();
mFromView = (TextView)findViewById(R.id.from); mFromView = (TextView) findViewById(R.id.from);
mToView = (MultiAutoCompleteTextView)findViewById(R.id.to); mToView = (MultiAutoCompleteTextView) findViewById(R.id.to);
mCcView = (MultiAutoCompleteTextView)findViewById(R.id.cc); mCcView = (MultiAutoCompleteTextView) findViewById(R.id.cc);
mBccView = (MultiAutoCompleteTextView)findViewById(R.id.bcc); mBccView = (MultiAutoCompleteTextView) findViewById(R.id.bcc);
mSubjectView = (EditText)findViewById(R.id.subject); mSubjectView = (EditText) findViewById(R.id.subject);
mSubjectView.getInputExtras(true).putBoolean("allowEmoji", true); mSubjectView.getInputExtras(true).putBoolean("allowEmoji", true);
mAddToFromContacts = (ImageButton) findViewById(R.id.add_to);
mAddCcFromContacts = (ImageButton) findViewById(R.id.add_cc);
mAddBccFromContacts = (ImageButton) findViewById(R.id.add_bcc);
mCcWrapper = (LinearLayout) findViewById(R.id.cc_wrapper);
mBccWrapper = (LinearLayout) findViewById(R.id.bcc_wrapper);
EditText upperSignature = (EditText)findViewById(R.id.upper_signature); EditText upperSignature = (EditText)findViewById(R.id.upper_signature);
EditText lowerSignature = (EditText)findViewById(R.id.lower_signature); EditText lowerSignature = (EditText)findViewById(R.id.lower_signature);
@ -420,6 +441,28 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
mMessageContentView.addTextChangedListener(watcher); mMessageContentView.addTextChangedListener(watcher);
mQuotedText.addTextChangedListener(watcher); mQuotedText.addTextChangedListener(watcher);
/* Yes, there really are poeple who ship versions of android without a contact picker */
if (mContacts.hasContactPicker()) {
mAddToFromContacts.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) {
doLaunchContactPicker(CONTACT_PICKER_TO);
}
});
mAddCcFromContacts.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) {
doLaunchContactPicker(CONTACT_PICKER_CC);
}
});
mAddBccFromContacts.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) {
doLaunchContactPicker(CONTACT_PICKER_BCC);
}
});
} else {
mAddToFromContacts.setVisibility(View.GONE);
mAddCcFromContacts.setVisibility(View.GONE);
mAddBccFromContacts.setVisibility(View.GONE);
}
/* /*
* We set this to invisible by default. Other methods will turn it back on if it's * We set this to invisible by default. Other methods will turn it back on if it's
* needed. * needed.
@ -780,9 +823,12 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
addAttachment(uri); addAttachment(uri);
} }
mMessageFormat = (MessageFormat)savedInstanceState.getSerializable(STATE_KEY_MESSAGE_FORMAT); mMessageFormat = (MessageFormat) savedInstanceState
mCcView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN) ? View.VISIBLE : View.GONE); .getSerializable(STATE_KEY_MESSAGE_FORMAT);
mBccView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_BCC_SHOWN) ? View.VISIBLE : View.GONE); mCcWrapper.setVisibility(savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN) ? View.VISIBLE
: View.GONE);
mBccWrapper.setVisibility(savedInstanceState
.getBoolean(STATE_KEY_BCC_SHOWN) ? View.VISIBLE : View.GONE);
if (mMessageFormat == MessageFormat.HTML) { if (mMessageFormat == MessageFormat.HTML) {
mQuotedHtmlContent = (InsertableHtmlContent) savedInstanceState.getSerializable(STATE_KEY_HTML_QUOTE); mQuotedHtmlContent = (InsertableHtmlContent) savedInstanceState.getSerializable(STATE_KEY_HTML_QUOTE);
mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ? View.VISIBLE : View.GONE); mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ? View.VISIBLE : View.GONE);
@ -1354,8 +1400,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
} }
private void onAddCcBcc() { private void onAddCcBcc() {
mCcView.setVisibility(View.VISIBLE); mCcWrapper.setVisibility(View.VISIBLE);
mBccView.setVisibility(View.VISIBLE); mBccWrapper.setVisibility(View.VISIBLE);
} }
/** /**
@ -1483,10 +1529,37 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
break; break;
case ACTIVITY_CHOOSE_ACCOUNT: case ACTIVITY_CHOOSE_ACCOUNT:
onAccountChosen(data); onAccountChosen(data);
break;
case CONTACT_PICKER_TO:
case CONTACT_PICKER_CC:
case CONTACT_PICKER_BCC:
String email = mContacts.getEmailFromContactPicker(data);
if (email.length() == 0) {
Toast.makeText(this, getString(R.string.error_contact_address_not_found), Toast.LENGTH_LONG).show();
return;
}
if (requestCode == CONTACT_PICKER_TO) {
addAddress(mToView, new Address(email, ""));
} else if (requestCode == CONTACT_PICKER_CC) {
addAddress(mCcView, new Address(email, ""));
} else if (requestCode == CONTACT_PICKER_BCC) {
addAddress(mBccView, new Address(email, ""));
} else {
return;
}
break; break;
} }
} }
public void doLaunchContactPicker(int resultId) {
startActivityForResult(mContacts.contactPickerIntent(), resultId);
}
private void onAccountChosen(final Intent intent) { private void onAccountChosen(final Intent intent) {
final Bundle extras = intent.getExtras(); final Bundle extras = intent.getExtras();
final String uuid = extras.getString(ChooseAccount.EXTRA_ACCOUNT); final String uuid = extras.getString(ChooseAccount.EXTRA_ACCOUNT);
@ -2451,10 +2524,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
} }
try { try {
final Contacts contacts = Contacts.getInstance(MessageCompose.this); mContacts.markAsContacted(message.getRecipients(RecipientType.TO));
contacts.markAsContacted(message.getRecipients(RecipientType.TO)); mContacts.markAsContacted(message.getRecipients(RecipientType.CC));
contacts.markAsContacted(message.getRecipients(RecipientType.CC)); mContacts.markAsContacted(message.getRecipients(RecipientType.BCC));
contacts.markAsContacted(message.getRecipients(RecipientType.BCC));
} catch (Exception e) { } catch (Exception e) {
Log.e(K9.LOG_TAG, "Failed to mark contact as contacted.", e); Log.e(K9.LOG_TAG, "Failed to mark contact as contacted.", e);
} }

View File

@ -6,6 +6,7 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.os.Build; import android.os.Build;
import android.content.Intent;
import android.util.Log; import android.util.Log;
import com.fsck.k9.K9; import com.fsck.k9.K9;
import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Address;
@ -166,4 +167,42 @@ public abstract class Contacts {
* contacts to be marked as contacted. * contacts to be marked as contacted.
*/ */
public abstract void markAsContacted(final Address[] addresses); public abstract void markAsContacted(final Address[] addresses);
/*
* Returns the intent necessary to open a contact picker
*
*/
public abstract Intent contactPickerIntent();
/* Given a contact picker intent, returns the primary email
* address of that contact
*
* @param intent The {@link Intent} returned by this contact picker
*/
public abstract String getEmailFromContactPicker(final Intent intent);
/*
* Does the device actually have a Contacts application suitable
* for picking a contact. As hard as it is to believe, some
* vendors ship without it.
*/
public boolean hasContactPicker() {
if (mContext.getPackageManager().queryIntentActivities(contactPickerIntent(), 0).size() > 0) {
return true;
} else {
return false;
}
}
} }

View File

@ -4,8 +4,12 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.util.Log;
import android.provider.Contacts; import android.provider.Contacts;
import android.provider.Contacts.ContactMethods;
import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Address;
import com.fsck.k9.K9;
/** /**
* Access the contacts on the device using the old API (introduced in SDK 1). * Access the contacts on the device using the old API (introduced in SDK 1).
@ -218,6 +222,49 @@ public class ContactsSdk3_4 extends com.fsck.k9.helper.Contacts {
} }
} }
@Override
public Intent contactPickerIntent() {
return new Intent(Intent.ACTION_PICK, Contacts.People.CONTENT_URI);
}
@Override
public String getEmailFromContactPicker(final Intent data) {
Cursor cursor = null;
Cursor cursor2 = null;
String email = "";
try {
Uri result = data.getData();
cursor = mContentResolver.query(result, null, null, null, null);
if (cursor.moveToFirst()) {
String emailId = cursor.getString(cursor.getColumnIndex(Contacts.People.PRIMARY_EMAIL_ID));
cursor2 = mContext.getContentResolver().query(ContactMethods.CONTENT_EMAIL_URI, new String[] { ContactMethods.DATA }, "contact_methods._id=?", new String[] { emailId }, null);
if (cursor2.moveToFirst()) {
email = cursor2.getString(0);
}
}
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Failed to get email data", e);
} finally {
if (cursor != null) {
cursor.close();
}
if (cursor2 != null) {
cursor2.close();
}
}
return email;
}
/** /**
* Return a {@link Cursor} instance that can be used to fetch information * Return a {@link Cursor} instance that can be used to fetch information
* about the contact with the given email address. * about the contact with the given email address.

View File

@ -6,11 +6,13 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.util.Log;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents; import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.Email;
import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Address;
import com.fsck.k9.K9;
/** /**
* Access the contacts on the device using the API introduced with SDK 5. * Access the contacts on the device using the API introduced with SDK 5.
@ -190,6 +192,43 @@ public class ContactsSdk5 extends com.fsck.k9.helper.Contacts {
} }
} }
@Override
public Intent contactPickerIntent() {
return new Intent(Intent.ACTION_PICK, android.provider.ContactsContract.Contacts.CONTENT_URI);
}
@Override
public String getEmailFromContactPicker(final Intent data) {
Cursor cursor = null;
String email = "";
try {
Uri result = data.getData();
Log.v(K9.LOG_TAG, "Got a contact result: " + result.toString());
// get the contact id from the Uri
String id = result.getLastPathSegment();
cursor = mContentResolver.query(Email.CONTENT_URI,
null, Email.CONTACT_ID + "=?", new String[] { id },
null);
int emailIdx = cursor.getColumnIndex(Email.DATA);
if (cursor.moveToFirst()) {
email = cursor.getString(emailIdx);
}
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Failed to get email data", e);
} finally {
if (cursor != null) {
cursor.close();
}
}
return email;
}
/** /**
* Return a {@link Cursor} instance that can be used to fetch information * Return a {@link Cursor} instance that can be used to fetch information
* about the contact with the given email address. * about the contact with the given email address.