Conversion to provider-based Account. What works:

* Editing existing accounts
 * Two placeholder accounts are written

What breaks (in approx order of planned fixes)
 * Some details of account editing
 * New account creation,
 * Viewing mailboxes & messages
 * Mail sync using accounts
 * Import of existing accounts
This commit is contained in:
Andrew Stadler 2009-06-03 16:11:36 -07:00
parent 361a7225f2
commit 9019315b26
12 changed files with 690 additions and 252 deletions

View File

@ -16,37 +16,37 @@
package com.android.email.activity;
import com.android.email.Account;
import com.android.email.Email;
import com.android.email.MessagingController;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.activity.setup.AccountSettings;
import com.android.email.activity.setup.AccountSetupBasics;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import com.android.email.mail.store.LocalStore;
import com.android.email.mail.store.LocalStore.LocalFolder;
import com.android.email.provider.EmailStore;
import com.android.email.provider.EmailStore.Account;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.NotificationManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
@ -62,8 +62,24 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
};
private int mSecretKeyCodeIndex = 0;
private Account mSelectedContextAccount;
private static final String ICICLE_SELECTED_ACCOUNT = "com.android.email.selectedAccount";
private EmailStore.Account mSelectedContextAccount;
/**
* Support for list adapter
*/
private final static String[] sFromColumns = new String[] {
EmailStore.AccountColumns.DISPLAY_NAME,
EmailStore.AccountColumns.EMAIL_ADDRESS,
EmailStore.RECORD_ID
};
private final int[] sToIds = new int[] {
R.id.description,
R.id.email,
R.id.new_message_count
};
/**
* Start the Accounts list activity. Uses the CLEAR_TOP flag which means that other stacked
* activities may be killed in order to get back to Accounts.
@ -85,16 +101,24 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
findViewById(R.id.add_new_account).setOnClickListener(this);
registerForContextMenu(listView);
if (icicle != null && icicle.containsKey("selectedContextAccount")) {
mSelectedContextAccount = (Account) icicle.getSerializable("selectedContextAccount");
if (icicle != null && icicle.containsKey(ICICLE_SELECTED_ACCOUNT)) {
mSelectedContextAccount = (Account) icicle.getParcelable(ICICLE_SELECTED_ACCOUNT);
}
Cursor c = this.managedQuery(
EmailStore.Account.CONTENT_URI,
EmailStore.Account.CONTENT_PROJECTION,
null, null);
AccountsAdapter a = new AccountsAdapter(this,
R.layout.accounts_item, c, sFromColumns, sToIds);
listView.setAdapter(a);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mSelectedContextAccount != null) {
outState.putSerializable("selectedContextAccount", mSelectedContextAccount);
outState.putParcelable(ICICLE_SELECTED_ACCOUNT, mSelectedContextAccount);
}
}
@ -105,21 +129,14 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
NotificationManager notifMgr = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notifMgr.cancel(1);
refresh();
}
private void refresh() {
Account[] accounts = Preferences.getPreferences(this).getAccounts();
getListView().setAdapter(new AccountsAdapter(accounts));
}
private void onAddNewAccount() {
AccountSetupBasics.actionNewAccount(this);
}
private void onEditAccount(Account account) {
AccountSettings.actionSettings(this, account);
private void onEditAccount(long accountId) {
AccountSettings.actionSettings(this, accountId);
}
private void onRefresh() {
@ -127,18 +144,16 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
}
private void onCompose() {
Account defaultAccount =
Preferences.getPreferences(this).getDefaultAccount();
EmailStore.Account defaultAccount = EmailStore.Account.getDefaultAccount(this);
if (defaultAccount != null) {
MessageCompose.actionCompose(this, defaultAccount);
}
else {
MessageCompose.actionCompose(this, defaultAccount.mId);
} else {
onAddNewAccount();
}
}
private void onOpenAccount(Account account) {
FolderMessageList.actionHandleAccount(this, account);
private void onOpenAccount(long accountId) {
FolderMessageList.actionHandleAccount(this, accountId);
}
public void onClick(View view) {
@ -147,8 +162,8 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
}
}
private void onDeleteAccount(Account account) {
mSelectedContextAccount = account;
private void onDeleteAccount(long accountId) {
mSelectedContextAccount = Account.restoreAccountWithId(this, accountId);
showDialog(DIALOG_REMOVE_ACCOUNT);
}
@ -172,24 +187,25 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
dismissDialog(DIALOG_REMOVE_ACCOUNT);
try {
LocalStore localStore = (LocalStore) Store.getInstance(
mSelectedContextAccount.getLocalStoreUri(),
mSelectedContextAccount.getLocalStoreUri(Accounts.this),
getApplication(),
null);
// Delete Remote store at first.
Store.getInstance(
mSelectedContextAccount.getStoreUri(),
mSelectedContextAccount.getStoreUri(Accounts.this),
getApplication(),
localStore.getPersistentCallbacks()).delete();
// Remove the Store instance from cache.
Store.removeInstance(mSelectedContextAccount.getStoreUri());
Store.removeInstance(mSelectedContextAccount.getStoreUri(Accounts.this));
// If no error, then delete LocalStore
localStore.delete();
} catch (Exception e) {
// Ignore
}
mSelectedContextAccount.delete(Preferences.getPreferences(Accounts.this));
Uri uri = ContentUris.withAppendedId(
EmailStore.Account.CONTENT_URI, mSelectedContextAccount.mId);
Accounts.this.getContentResolver().delete(uri, null, null);
Email.setServicesEnabled(Accounts.this);
refresh();
}
})
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
@ -202,24 +218,26 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)item.getMenuInfo();
Account account = (Account)getListView().getItemAtPosition(menuInfo.position);
Cursor c = (Cursor) getListView().getItemAtPosition(menuInfo.position);
long accountId = c.getLong(Account.CONTENT_ID_COLUMN);
switch (item.getItemId()) {
case R.id.delete_account:
onDeleteAccount(account);
onDeleteAccount(accountId);
break;
case R.id.edit_account:
onEditAccount(account);
onEditAccount(accountId);
break;
case R.id.open:
onOpenAccount(account);
onOpenAccount(accountId);
break;
}
return true;
}
public void onItemClick(AdapterView parent, View view, int position, long id) {
Account account = (Account)parent.getItemAtPosition(position);
onOpenAccount(account);
Cursor c = (Cursor) getListView().getItemAtPosition(position);
long accountId = c.getLong(Account.CONTENT_ID_COLUMN);
onOpenAccount(accountId);
}
@Override
@ -271,61 +289,34 @@ public class Accounts extends ListActivity implements OnItemClickListener, OnCli
}
return super.onKeyDown(keyCode, event);
}
private static class AccountsAdapter extends SimpleCursorAdapter {
class AccountsAdapter extends ArrayAdapter<Account> {
public AccountsAdapter(Account[] accounts) {
super(Accounts.this, 0, accounts);
public AccountsAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
setViewBinder(new MyViewBinder());
}
/**
* This is only used for the unread messages count. Most of the views are handled
* normally by SimpleCursorAdapter.
*/
private static class MyViewBinder implements SimpleCursorAdapter.ViewBinder {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Account account = getItem(position);
View view;
if (convertView != null) {
view = convertView;
}
else {
view = getLayoutInflater().inflate(R.layout.accounts_item, parent, false);
}
AccountViewHolder holder = (AccountViewHolder) view.getTag();
if (holder == null) {
holder = new AccountViewHolder();
holder.description = (TextView) view.findViewById(R.id.description);
holder.email = (TextView) view.findViewById(R.id.email);
holder.newMessageCount = (TextView) view.findViewById(R.id.new_message_count);
view.setTag(holder);
}
holder.description.setText(account.getDescription());
holder.email.setText(account.getEmail());
if (account.getEmail().equals(account.getDescription())) {
holder.email.setVisibility(View.GONE);
}
int unreadMessageCount = 0;
try {
LocalStore localStore = (LocalStore) Store.getInstance(
account.getLocalStoreUri(),
getApplication(),
null);
LocalFolder localFolder = (LocalFolder) localStore.getFolder(Email.INBOX);
if (localFolder.exists()) {
unreadMessageCount = localFolder.getUnreadMessageCount();
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (view.getId() == R.id.new_message_count) {
int unreadMessageCount = 0; // TODO get unread count from Account
if (unreadMessageCount <= 0) {
view.setVisibility(View.GONE);
} else {
((TextView)view).setText(String.valueOf(unreadMessageCount));
}
return true;
}
return false;
}
catch (MessagingException me) {
/*
* This is not expected to fail under normal circumstances.
*/
throw new RuntimeException("Unable to get unread count from local store.", me);
}
holder.newMessageCount.setText(Integer.toString(unreadMessageCount));
holder.newMessageCount.setVisibility(unreadMessageCount > 0 ? View.VISIBLE : View.GONE);
return view;
}
class AccountViewHolder {
public TextView description;
public TextView email;
public TextView newMessageCount;
}
}
}

View File

@ -399,6 +399,26 @@ public class FolderMessageList extends ExpandableListActivity {
public static void actionHandleAccount(Context context, Account account) {
actionHandleAccount(context, account, null);
}
/**
* Open a specific account. This replaces the old non-provider based version.
* @param context
* @param id
*/
public static void actionHandleAccount(Context context, long id) {
actionHandleAccount(context, id, null);
}
/**
* Open a specific account. This replaces the old non-provider based version.
* @param context
* @param id
* @param initialFolder The folder to open, or null for none
*/
public static void actionHandleAccount(Context context, long id, String initialFolder) {
// TODO Auto-generated method stub
// DO NOT CHECK IN UNTIL WRITTEN
}
public static Intent actionHandleAccountIntent(Context context, Account account, String initialFolder) {
Intent intent = new Intent(context, FolderMessageList.class);

View File

@ -221,6 +221,16 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
}
}
/**
* Compose a new message using the given account, or the default account if -1
* @param context
* @param defaultAccountId
*/
public static void actionCompose(Accounts context, long defaultAccountId) {
// TODO Auto-generated method stub
// DO NOT CHECK IN until written
}
/**
* Compose a new message as a reply to the given message. If replyAll is true the function
* is reply all instead of simply reply.

View File

@ -16,12 +16,12 @@
package com.android.email.activity;
import com.android.email.Account;
import com.android.email.Email;
import com.android.email.Preferences;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailStore;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
@ -32,25 +32,41 @@ import android.util.Log;
* can configure an account.
* If a single account is configured the user is taken directly to the FolderMessageList for
* the INBOX of that account.
* If more than one account is configuref the user is takaen to the Accounts Activity so they
* If more than one account is configured the user is taken to the Accounts Activity so they
* can select an account.
*/
public class Welcome extends Activity {
private static final boolean DEBUG_ADD_TEST_ACCOUNTS = false; // DO NOT CHECK IN "TRUE"
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (false) {
if (DEBUG_ADD_TEST_ACCOUNTS) {
testAccounts();
}
Account[] accounts = Preferences.getPreferences(this).getAccounts();
if (accounts.length == 1) {
FolderMessageList.actionHandleAccount(this, accounts[0], Email.INBOX);
} else {
Accounts.actionShowAccounts(this);
// Find out how many accounts we have, and if there's just one, go directly to it
Cursor c = null;
try {
c = getContentResolver().query(
EmailStore.Account.CONTENT_URI,
EmailStore.Account.CONTENT_PROJECTION,
null, null, null);
if (c.getCount() == 1) {
c.moveToFirst();
EmailStore.Account account = EmailContent.getContent(c, EmailStore.Account.class);
FolderMessageList.actionHandleAccount(this, account.mId, Email.INBOX);
}
} finally {
if (c != null) {
c.close();
}
}
// Otherwise (n=0 or n>1) go to the account info screen
Accounts.actionShowAccounts(this);
finish();
}
@ -75,8 +91,9 @@ public class Welcome extends Activity {
acct1.mHostAuthSend = sha;
acct1.mDisplayName = "Nextobject";
acct1.mEmailAddress = "foo@nextobject.com";
acct1.mIsDefault = true;
acct1.save(this);
acct1.saveOrUpdate(this);
ha = new EmailStore.HostAuth();
ha.mAddress = "imap.gmail.com";
@ -95,17 +112,17 @@ public class Welcome extends Activity {
acct2.mHostAuthSend = sha;
acct2.mDisplayName = "Google";
acct2.mEmailAddress = "mblank@google.com";
acct2.mIsDefault = true; // this should supercede the previous one
acct2.save(this);
acct2.saveOrUpdate(this);
// Should be null
// TODO this should move to unit tests of the new Account code
acct = EmailStore.Account.getDefaultAccount(this);
Log.i("EmailApp", "Default (Nextobject) = " + acct == null ? "none" : acct.mDisplayName);
EmailStore.Account.setDefaultAccount(this, acct2.mId);
Log.i("EmailApp", "Default (Google) = " + (acct == null ? "none" : acct.mDisplayName));
acct1.setDefaultAccount(true);
acct1.saveOrUpdate(this);
acct = EmailStore.Account.getDefaultAccount(this);
Log.i("EmailApp", "Default (Google) = " + acct == null ? "none" : acct.mDisplayName);
EmailStore.Account.setDefaultAccount(this, acct1.mId);
acct = EmailStore.Account.getDefaultAccount(this);
Log.i("EmailApp", "Default (Nextobject) = " + acct == null ? "none" : acct.mDisplayName);
Log.i("EmailApp", "Default (Nextobject) = " + (acct == null ? "none" : acct.mDisplayName));
}
}

View File

@ -20,11 +20,14 @@ import com.android.email.Account;
import com.android.email.Email;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.activity.Accounts;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Sender;
import com.android.email.mail.Store;
import com.android.email.provider.EmailStore;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
@ -40,8 +43,9 @@ import android.view.KeyEvent;
public class AccountSettings extends PreferenceActivity {
private static final String EXTRA_ACCOUNT = "account";
private static final String EXTRA_ACCOUNT_ID = "account_id";
private static final String PREFERENCE_TOP_CATERGORY = "account_settings";
private static final String PREFERENCE_TOP_CATEGORY = "account_settings";
private static final String PREFERENCE_DESCRIPTION = "account_description";
private static final String PREFERENCE_NAME = "account_name";
private static final String PREFERENCE_FREQUENCY = "account_check_frequency";
@ -54,7 +58,8 @@ public class AccountSettings extends PreferenceActivity {
private static final String PREFERENCE_OUTGOING = "outgoing";
private static final String PREFERENCE_ADD_ACCOUNT = "add_account";
private Account mAccount;
private long mAccountId;
private EmailStore.Account mAccount;
private EditTextPreference mAccountDescription;
private EditTextPreference mAccountName;
@ -65,21 +70,37 @@ public class AccountSettings extends PreferenceActivity {
private CheckBoxPreference mAccountVibrate;
private RingtonePreference mAccountRingtone;
/**
* Entry point using old-style
* TODO remove
*/
@Deprecated
public static void actionSettings(Activity fromActivity, Account account) {
Intent i = new Intent(fromActivity, AccountSettings.class);
i.putExtra(EXTRA_ACCOUNT, account);
fromActivity.startActivity(i);
}
/**
* Entry point using provider-based Account
*/
public static void actionSettings(Accounts fromActivity, long accountId) {
Intent i = new Intent(fromActivity, AccountSettings.class);
i.putExtra(EXTRA_ACCOUNT_ID, accountId);
fromActivity.startActivity(i);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
Intent i = getIntent();
mAccountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1);
mAccount = EmailStore.Account.restoreAccountWithId(this, mAccountId);
addPreferencesFromResource(R.xml.account_settings_preferences);
PreferenceCategory topCategory = (PreferenceCategory) findPreference(PREFERENCE_TOP_CATERGORY);
PreferenceCategory topCategory = (PreferenceCategory) findPreference(PREFERENCE_TOP_CATEGORY);
topCategory.setTitle(getString(R.string.account_settings_title_fmt));
mAccountDescription = (EditTextPreference) findPreference(PREFERENCE_DESCRIPTION);
@ -109,7 +130,7 @@ public class AccountSettings extends PreferenceActivity {
mCheckFrequency = (ListPreference) findPreference(PREFERENCE_FREQUENCY);
// Before setting value, we may need to adjust the lists
Store.StoreInfo info = Store.StoreInfo.getStoreInfo(mAccount.getStoreUri(), this);
Store.StoreInfo info = Store.StoreInfo.getStoreInfo(mAccount.getStoreUri(this), this);
if (info.mPushSupported) {
mCheckFrequency.setEntries(R.array.account_settings_check_frequency_entries_push);
mCheckFrequency.setEntryValues(R.array.account_settings_check_frequency_values_push);
@ -150,11 +171,11 @@ public class AccountSettings extends PreferenceActivity {
}
mAccountDefault = (CheckBoxPreference) findPreference(PREFERENCE_DEFAULT);
mAccountDefault.setChecked(
mAccount.equals(Preferences.getPreferences(this).getDefaultAccount()));
mAccountDefault.setChecked(mAccount.mIsDefault);
mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY);
mAccountNotify.setChecked(mAccount.isNotifyNewMail());
mAccountNotify.setChecked(0 !=
(mAccount.getFlags() & EmailStore.Account.FLAGS_NOTIFY_NEW_MAIL));
mAccountRingtone = (RingtonePreference) findPreference(PREFERENCE_RINGTONE);
@ -164,7 +185,8 @@ public class AccountSettings extends PreferenceActivity {
prefs.edit().putString(PREFERENCE_RINGTONE, mAccount.getRingtone()).commit();
mAccountVibrate = (CheckBoxPreference) findPreference(PREFERENCE_VIBRATE);
mAccountVibrate.setChecked(mAccount.isVibrate());
mAccountVibrate.setChecked(0 !=
(mAccount.getFlags() & EmailStore.Account.FLAGS_VIBRATE));
findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener(
new Preference.OnPreferenceClickListener() {
@ -178,7 +200,7 @@ public class AccountSettings extends PreferenceActivity {
Preference prefOutgoing = findPreference(PREFERENCE_OUTGOING);
boolean showOutgoing = true;
try {
Sender sender = Sender.getInstance(mAccount.getSenderUri(), getApplication());
Sender sender = Sender.getInstance(mAccount.getSenderUri(this), getApplication());
if (sender != null) {
Class<? extends android.app.Activity> setting = sender.getSettingActivityClass();
showOutgoing = (setting != null);
@ -209,28 +231,25 @@ public class AccountSettings extends PreferenceActivity {
});
}
@Override
public void onResume() {
super.onResume();
mAccount.refresh(Preferences.getPreferences(this));
}
private void saveSettings() {
if (mAccountDefault.isChecked()) {
Preferences.getPreferences(this).setDefaultAccount(mAccount);
}
int newFlags = mAccount.getFlags() &
~(EmailStore.Account.FLAGS_NOTIFY_NEW_MAIL | EmailStore.Account.FLAGS_VIBRATE);
mAccount.setDefaultAccount(mAccountDefault.isChecked());
mAccount.setDescription(mAccountDescription.getText());
mAccount.setName(mAccountName.getText());
mAccount.setNotifyNewMail(mAccountNotify.isChecked());
newFlags |= mAccountNotify.isChecked() ? EmailStore.Account.FLAGS_NOTIFY_NEW_MAIL : 0;
mAccount.setAutomaticCheckIntervalMinutes(Integer.parseInt(mCheckFrequency.getValue()));
if (mSyncWindow != null)
{
mAccount.setSyncWindow(Integer.parseInt(mSyncWindow.getValue()));
}
mAccount.setVibrate(mAccountVibrate.isChecked());
newFlags |= mAccountVibrate.isChecked() ? EmailStore.Account.FLAGS_VIBRATE : 0;
SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences();
mAccount.setRingtone(prefs.getString(PREFERENCE_RINGTONE, null));
mAccount.save(Preferences.getPreferences(this));
mAccount.setFlags(newFlags);
mAccount.saveOrUpdate(this);
Email.setServicesEnabled(this);
}
@ -244,12 +263,12 @@ public class AccountSettings extends PreferenceActivity {
private void onIncomingSettings() {
try {
Store store = Store.getInstance(mAccount.getStoreUri(), getApplication(), null);
Store store = Store.getInstance(mAccount.getStoreUri(this), getApplication(), null);
if (store != null) {
Class<? extends android.app.Activity> setting = store.getSettingActivityClass();
if (setting != null) {
java.lang.reflect.Method m = setting.getMethod("actionEditIncomingSettings",
android.app.Activity.class, Account.class);
android.app.Activity.class, EmailStore.Account.class);
m.invoke(null, this, mAccount);
}
}
@ -260,12 +279,12 @@ public class AccountSettings extends PreferenceActivity {
private void onOutgoingSettings() {
try {
Sender sender = Sender.getInstance(mAccount.getSenderUri(), getApplication());
Sender sender = Sender.getInstance(mAccount.getSenderUri(this), getApplication());
if (sender != null) {
Class<? extends android.app.Activity> setting = sender.getSettingActivityClass();
if (setting != null) {
java.lang.reflect.Method m = setting.getMethod("actionEditOutgoingSettings",
android.app.Activity.class, Account.class);
android.app.Activity.class, EmailStore.Account.class);
m.invoke(null, this, mAccount);
}
}

View File

@ -21,8 +21,9 @@ import com.android.email.R;
import com.android.email.mail.AuthenticationFailedException;
import com.android.email.mail.CertificateValidationException;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import com.android.email.mail.Sender;
import com.android.email.mail.Store;
import com.android.email.provider.EmailStore;
import android.app.Activity;
import android.app.AlertDialog;
@ -67,6 +68,7 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen
private boolean mDestroyed;
@Deprecated
public static void actionCheckSettings(Activity fromActivity, Account account,
boolean checkIncoming, boolean checkOutgoing) {
Intent i = new Intent(fromActivity, AccountSetupCheckSettings.class);
@ -76,6 +78,15 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen
fromActivity.startActivityForResult(i, 1);
}
public static void actionCheckSettings(Activity fromActivity, EmailStore.Account account,
boolean checkIncoming, boolean checkOutgoing) {
Intent i = new Intent(fromActivity, AccountSetupCheckSettings.class);
i.putExtra(EXTRA_ACCOUNT, account);
i.putExtra(EXTRA_CHECK_INCOMING, checkIncoming);
i.putExtra(EXTRA_CHECK_OUTGOING, checkOutgoing);
fromActivity.startActivityForResult(i, 1);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -86,6 +97,18 @@ public class AccountSetupCheckSettings extends Activity implements OnClickListen
setMessage(R.string.account_setup_check_settings_retr_info_msg);
mProgressBar.setIndeterminate(true);
// Placeholder - for "new" accounts, always return "OK" for validation, so we
// can continue debugging new code. Must remove this.
try {
EmailStore.Account acct = (EmailStore.Account)
getIntent().getParcelableExtra(EXTRA_ACCOUNT);
setResult(RESULT_OK);
finish();
return;
} catch (java.lang.ClassCastException cce) {
// old style Account - just continue to old code for now
}
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
mCheckIncoming = (boolean)getIntent().getBooleanExtra(EXTRA_CHECK_INCOMING, false);

View File

@ -20,6 +20,7 @@ import com.android.email.Account;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.Utility;
import com.android.email.provider.EmailStore;
import android.app.Activity;
import android.content.Intent;
@ -66,7 +67,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
private Spinner mDeletePolicyView;
private EditText mImapPathPrefixView;
private Button mNextButton;
private Account mAccount;
private EmailStore.Account mAccount;
private boolean mMakeDefault;
public static void actionIncomingSettings(Activity fromActivity, Account account, boolean makeDefault) {
@ -76,6 +77,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
fromActivity.startActivity(i);
}
@Deprecated
public static void actionEditIncomingSettings(Activity fromActivity, Account account) {
Intent i = new Intent(fromActivity, AccountSetupIncoming.class);
i.setAction(Intent.ACTION_EDIT);
@ -83,6 +85,14 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
fromActivity.startActivity(i);
}
public static void actionEditIncomingSettings(Activity fromActivity, EmailStore.Account account)
{
Intent i = new Intent(fromActivity, AccountSetupIncoming.class);
i.setAction(Intent.ACTION_EDIT);
i.putExtra(EXTRA_ACCOUNT, account);
fromActivity.startActivity(i);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -168,7 +178,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
*/
mPortView.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
mAccount = (EmailStore.Account)getIntent().getParcelableExtra(EXTRA_ACCOUNT);
mMakeDefault = getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
/*
@ -176,11 +186,12 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
* we saved
*/
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
mAccount = (EmailStore.Account)savedInstanceState.getParcelable(EXTRA_ACCOUNT);
}
try {
URI uri = new URI(mAccount.getStoreUri());
// TODO this should be accessed directly via the HostAuth structure
URI uri = new URI(mAccount.getStoreUri(this));
String username = null;
String password = null;
if (uri.getUserInfo() != null) {
@ -216,7 +227,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
mImapPathPrefixView.setText(uri.getPath().substring(1));
}
} else {
throw new Error("Unknown account type: " + mAccount.getStoreUri());
throw new Error("Unknown account type: " + mAccount.getStoreUri(this));
}
for (int i = 0; i < mAccountSchemes.length; i++) {
@ -249,7 +260,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(EXTRA_ACCOUNT, mAccount);
outState.putParcelable(EXTRA_ACCOUNT, mAccount);
}
/**
@ -281,7 +292,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
mAccount.save(Preferences.getPreferences(this));
mAccount.saveOrUpdate(this);
finish();
} else {
/*
@ -289,7 +300,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
* password the user just set for incoming.
*/
try {
URI oldUri = new URI(mAccount.getSenderUri());
URI oldUri = new URI(mAccount.getSenderUri(this));
URI uri = new URI(
oldUri.getScheme(),
mUsernameView.getText().toString().trim() + ":"
@ -299,7 +310,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
null,
null,
null);
mAccount.setSenderUri(uri.toString());
mAccount.setSenderUri(this, uri.toString());
} catch (URISyntaxException use) {
/*
* If we can't set up the URL we just continue. It's only for
@ -307,7 +318,6 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
*/
}
AccountSetupOutgoing.actionOutgoingSettings(this, mAccount, mMakeDefault);
finish();
}
@ -341,7 +351,7 @@ public class AccountSetupIncoming extends Activity implements OnClickListener {
private void onNext() {
try {
URI uri = getUri();
mAccount.setStoreUri(uri.toString());
mAccount.setStoreUri(this, uri.toString());
} catch (URISyntaxException use) {
/*
* It's unrecoverable if we cannot create a URI from components that

View File

@ -21,6 +21,7 @@ import com.android.email.Email;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.mail.Store;
import com.android.email.provider.EmailStore;
import android.app.Activity;
import android.content.Intent;
@ -45,6 +46,7 @@ public class AccountSetupOptions extends Activity implements OnClickListener {
private Account mAccount;
@Deprecated
public static void actionOptions(Activity fromActivity, Account account, boolean makeDefault) {
Intent i = new Intent(fromActivity, AccountSetupOptions.class);
i.putExtra(EXTRA_ACCOUNT, account);
@ -52,6 +54,14 @@ public class AccountSetupOptions extends Activity implements OnClickListener {
fromActivity.startActivity(i);
}
public static void actionOptions(Activity fromActivity, EmailStore.Account account,
boolean makeDefault) {
Intent i = new Intent(fromActivity, AccountSetupOptions.class);
i.putExtra(EXTRA_ACCOUNT, account);
i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
fromActivity.startActivity(i);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

View File

@ -20,6 +20,7 @@ import com.android.email.Account;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.Utility;
import com.android.email.provider.EmailStore;
import android.app.Activity;
import android.content.Intent;
@ -64,9 +65,10 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
private ViewGroup mRequireLoginSettingsView;
private Spinner mSecurityTypeView;
private Button mNextButton;
private Account mAccount;
private EmailStore.Account mAccount;
private boolean mMakeDefault;
@Deprecated
public static void actionOutgoingSettings(Activity fromActivity, Account account,
boolean makeDefault) {
Intent i = new Intent(fromActivity, AccountSetupOutgoing.class);
@ -75,6 +77,15 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
fromActivity.startActivity(i);
}
public static void actionOutgoingSettings(Activity fromActivity, EmailStore.Account account,
boolean makeDefault) {
Intent i = new Intent(fromActivity, AccountSetupOutgoing.class);
i.putExtra(EXTRA_ACCOUNT, account);
i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
fromActivity.startActivity(i);
}
@Deprecated
public static void actionEditOutgoingSettings(Activity fromActivity, Account account) {
Intent i = new Intent(fromActivity, AccountSetupOutgoing.class);
i.setAction(Intent.ACTION_EDIT);
@ -82,6 +93,14 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
fromActivity.startActivity(i);
}
public static void actionEditOutgoingSettings(Activity fromActivity, EmailStore.Account account)
{
Intent i = new Intent(fromActivity, AccountSetupOutgoing.class);
i.setAction(Intent.ACTION_EDIT);
i.putExtra(EXTRA_ACCOUNT, account);
fromActivity.startActivity(i);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -152,7 +171,7 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
*/
mPortView.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
mAccount = (EmailStore.Account)getIntent().getParcelableExtra(EXTRA_ACCOUNT);
mMakeDefault = (boolean)getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
/*
@ -160,11 +179,12 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
* we saved
*/
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
mAccount = (EmailStore.Account)savedInstanceState.getParcelable(EXTRA_ACCOUNT);
}
try {
URI uri = new URI(mAccount.getSenderUri());
// TODO this should be accessed directly via the HostAuth structure
URI uri = new URI(mAccount.getSenderUri(this));
String username = null;
String password = null;
if (uri.getUserInfo() != null) {
@ -212,7 +232,7 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(EXTRA_ACCOUNT, mAccount);
outState.putParcelable(EXTRA_ACCOUNT, mAccount);
}
/**
@ -248,7 +268,7 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
mAccount.save(Preferences.getPreferences(this));
mAccount.saveOrUpdate(this);
finish();
} else {
AccountSetupOptions.actionOptions(this, mAccount, mMakeDefault);
@ -281,8 +301,9 @@ public class AccountSetupOutgoing extends Activity implements OnClickListener,
private void onNext() {
try {
// TODO this should be accessed directly via the HostAuth structure
URI uri = getUri();
mAccount.setSenderUri(uri.toString());
mAccount.setSenderUri(this, uri.toString());
} catch (URISyntaxException use) {
/*
* It's unrecoverable if we cannot create a URI from components that

View File

@ -63,13 +63,17 @@ public abstract class EmailContent {
return null;
}
// Convenience method that saves or updates some Content
/**
* Convenience method to save or update content. Note: This is designed to save or update
* a single row, not for any bulk changes.
*/
public Uri saveOrUpdate(Context context) {
if (!isSaved())
return context.getContentResolver().insert(mBaseUri, toContentValues());
else {
if (update(context, toContentValues()) == 1)
if (!isSaved()) {
return save(context);
} else {
if (update(context, toContentValues()) == 1) {
return getUri();
}
return null;
}
}

View File

@ -55,7 +55,7 @@ public class EmailProvider extends ContentProvider {
// In these early versions, updating the database version will cause all tables to be deleted
// Obviously, we'll handle upgrades differently once things are a bit stable
public static final int DATABASE_VERSION = 11;
public static final int DATABASE_VERSION = 12;
protected static final String EMAIL_AUTHORITY = "com.android.email.provider";
@ -411,6 +411,7 @@ public class EmailProvider extends ContentProvider {
case ATTACHMENT_ID:
case MAILBOX_ID:
case ACCOUNT_ID:
case HOSTAUTH_ID:
String id = uri.getPathSegments().get(1);
result = db.update(TABLE_NAMES[table], values, whereWithId(id, selection),
selectionArgs);
@ -419,6 +420,7 @@ public class EmailProvider extends ContentProvider {
case ATTACHMENT:
case MAILBOX:
case ACCOUNT:
case HOSTAUTH:
result = db.update(TABLE_NAMES[table], values, selection, selectionArgs);
break;
default:

View File

@ -33,6 +33,7 @@ import android.os.RemoteException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.UUID;
/**
@ -502,9 +503,25 @@ public class EmailStore {
public static final String FLAGS = "flags";
// Default account
public static final String IS_DEFAULT = "isDefault";
// Old-Style UUID for compatibility with previous versions
public static final String COMPATIBILITY_UUID = "compatibilityUuid";
// User name (for outgoing messages)
public static final String SENDER_NAME = "senderName";
// Ringtone
public static final String RINGTONE_URI = "ringtoneUri";
}
public static final class Account extends EmailContent implements AccountColumns, Parcelable {
public final static int FLAGS_NOTIFY_NEW_MAIL = 1;
public final static int FLAGS_VIBRATE = 2;
public static final int FLAGS_DELETE_POLICY_MASK = 4+8;
public static final int FLAGS_DELETE_POLICY_SHIFT = 2;
public static final int DELETE_POLICY_NEVER = 0;
public static final int DELETE_POLICY_7DAYS = 1;
public static final int DELETE_POLICY_ON_DELETE = 2;
public String mDisplayName;
public String mEmailAddress;
public String mSyncKey;
@ -514,6 +531,9 @@ public class EmailStore {
public long mHostAuthKeySend;
public int mFlags;
public boolean mIsDefault;
public String mCompatibilityUuid;
public String mSenderName;
public String mRingtoneUri;
// Convenience for creating an account
public transient HostAuth mHostAuthRecv;
@ -528,13 +548,18 @@ public class EmailStore {
public static final int CONTENT_HOST_AUTH_KEY_RECV_COLUMN = 6;
public static final int CONTENT_HOST_AUTH_KEY_SEND_COLUMN = 7;
public static final int CONTENT_FLAGS_COLUMN = 8;
public static final int CONTENT_DEFAULT_COLUMN = 9;
public static final int CONTENT_IS_DEFAULT_COLUMN = 9;
public static final int CONTENT_COMPATIBILITY_UUID_COLUMN = 10;
public static final int CONTENT_SENDER_NAME_COLUMN = 11;
public static final int CONTENT_RINGTONE_URI_COLUMN = 12;
public static final String[] CONTENT_PROJECTION = new String[] {
RECORD_ID, AccountColumns.DISPLAY_NAME,
AccountColumns.EMAIL_ADDRESS, AccountColumns.SYNC_KEY, AccountColumns.SYNC_LOOKBACK,
AccountColumns.SYNC_FREQUENCY, AccountColumns.HOST_AUTH_KEY_RECV,
AccountColumns.HOST_AUTH_KEY_SEND, AccountColumns.FLAGS, AccountColumns.IS_DEFAULT
AccountColumns.HOST_AUTH_KEY_SEND, AccountColumns.FLAGS, AccountColumns.IS_DEFAULT,
AccountColumns.COMPATIBILITY_UUID, AccountColumns.SENDER_NAME,
AccountColumns.RINGTONE_URI,
};
/**
@ -542,6 +567,12 @@ public class EmailStore {
*/
public Account() {
mBaseUri = CONTENT_URI;
// other defaults (policy)
mRingtoneUri = "content://settings/system/notification_sound";
mSyncFrequency = -1;
mSyncLookback = -1;
mFlags = FLAGS_NOTIFY_NEW_MAIL;
}
public static final String TABLE_NAME = "Account";
@ -561,7 +592,10 @@ public class EmailStore {
+ AccountColumns.HOST_AUTH_KEY_RECV + " integer, "
+ AccountColumns.HOST_AUTH_KEY_SEND + " integer, "
+ AccountColumns.FLAGS + " integer, "
+ AccountColumns.IS_DEFAULT + " integer"
+ AccountColumns.IS_DEFAULT + " integer, "
+ AccountColumns.COMPATIBILITY_UUID + " text, "
+ AccountColumns.SENDER_NAME + " text, "
+ AccountColumns.RINGTONE_URI + " text "
+ ");";
db.execSQL("create table " + TABLE_NAME + s);
}
@ -602,39 +636,242 @@ public class EmailStore {
mHostAuthKeyRecv = cursor.getLong(CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
mHostAuthKeySend = cursor.getLong(CONTENT_HOST_AUTH_KEY_SEND_COLUMN);
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
mIsDefault = cursor.getInt(CONTENT_DEFAULT_COLUMN) == 1;
mIsDefault = cursor.getInt(CONTENT_IS_DEFAULT_COLUMN) == 1;
mCompatibilityUuid = cursor.getString(CONTENT_COMPATIBILITY_UUID_COLUMN);
mSenderName = cursor.getString(CONTENT_SENDER_NAME_COLUMN);
mRingtoneUri = cursor.getString(CONTENT_RINGTONE_URI_COLUMN);
return this;
}
private long getId(Uri u) {
return Long.parseLong(u.getPathSegments().get(1));
}
/**
* Set the default Account
* @param context
* @return true if succeeds; false otherwise
* @return the user-visible name for the account
*/
static public boolean setDefaultAccount(Context context, long id) {
ArrayList<ContentProviderOperation> opArray = new ArrayList<ContentProviderOperation>();
ContentValues cv1 = new ContentValues();
cv1.put(AccountColumns.IS_DEFAULT, 0);
opArray.add(ContentProviderOperation.newUpdate(CONTENT_URI).withValues(cv1).build());
ContentValues cv2 = new ContentValues();
cv2.put(AccountColumns.IS_DEFAULT, 1);
opArray.add(ContentProviderOperation.newUpdate(CONTENT_URI)
.withValues(cv2)
.withSelection("_id=" + id, null)
.build());
try {
context.getContentResolver().applyBatch(EmailProvider.EMAIL_AUTHORITY, opArray);
return true;
} catch (RemoteException e) {
// There is nothing to be done here; return false to indicate failure
} catch (OperationApplicationException e) {
// There is nothing to be done here; return false to indicate failure
public String getDescription() {
return mDisplayName;
}
/**
* Set the description. Be sure to call save() to commit to database.
* @param description the new description
*/
public void setDescription(String description) {
mDisplayName = description;
}
/**
* @return the sender's name for this account
*/
public String getName() {
return mSenderName;
}
/**
* Set the sender's name. Be sure to call save() to commit to database.
* @param name the new sender name
*/
public void setName(String name) {
mSenderName = name;
}
/**
* @return the minutes per check (for polling)
* TODO define sentinel values for "never", "push", etc. See Account.java
*/
public int getAutomaticCheckIntervalMinutes()
{
return mSyncFrequency;
}
/**
* Set the minutes per check (for polling). Be sure to call save() to commit to database.
* TODO define sentinel values for "never", "push", etc. See Account.java
* @param minutes the number of minutes between polling checks
*/
public void setAutomaticCheckIntervalMinutes(int minutes)
{
mSyncFrequency = minutes;
}
/**
* @return the sync lookback window in # of days
* TODO define sentinel values for "all", "1 month", etc. See Account.java
*/
public int getSyncWindow() {
return mSyncLookback;
}
/**
* Set the sync lookback window in # of days. Be sure to call save() to commit to database.
* TODO define sentinel values for "all", "1 month", etc. See Account.java
* @param days number of days to look back for syncing messages
*/
public void setSyncWindow(int days) {
mSyncLookback = days;
}
/**
* @return the flags for this account
* @see #FLAGS_NOTIFY_NEW_MAIL
* @see #FLAGS_VIBRATE
*/
public int getFlags() {
return mFlags;
}
/**
* Set the flags for this account
* @see #FLAGS_NOTIFY_NEW_MAIL
* @see #FLAGS_VIBRATE
* @param newFlags the new value for the flags
*/
public void setFlags(int newFlags) {
mFlags = newFlags;
}
/**
* @return the ringtone Uri for this account
*/
public String getRingtone() {
return mRingtoneUri;
}
/**
* Set the ringtone Uri for this account
* @param newUri the new URI string for the ringtone for this account
*/
public void setRingtone(String newUri) {
mRingtoneUri = newUri;
}
/**
* Set the "delete policy" as a simple 0,1,2 value set.
* @param newPolicy the new delete policy
*/
public void setDeletePolicy(int newPolicy) {
mFlags &= ~FLAGS_DELETE_POLICY_MASK;
mFlags |= (newPolicy << FLAGS_DELETE_POLICY_SHIFT) & FLAGS_DELETE_POLICY_MASK;
}
/**
* Return the "delete policy" as a simple 0,1,2 value set.
* @return the current delete policy
*/
public int getDeletePolicy() {
return (mFlags & FLAGS_DELETE_POLICY_MASK) >> FLAGS_DELETE_POLICY_SHIFT;
}
/**
* Return the Uuid associated with this account. This is primarily for compatibility
* with accounts set up by previous versions, because there are externals references
* to the Uuid (e.g. desktop shortcuts).
*/
String getUuid() {
if (mCompatibilityUuid == null || mCompatibilityUuid.length() == 0) {
mCompatibilityUuid = UUID.randomUUID().toString();
}
return false;
return mCompatibilityUuid;
}
/**
* For compatibility while converting to provider model, generate a "store URI"
*
* @return a string in the form of a Uri, as used by the other parts of the email app
*/
public String getStoreUri(Context context) {
// reconstitute if necessary
if (mHostAuthRecv == null) {
mHostAuthRecv = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
}
// convert if available
if (mHostAuthRecv != null) {
String storeUri = mHostAuthRecv.getStoreUri();
if (storeUri != null) {
return storeUri;
}
}
return "";
}
/**
* For compatibility while converting to provider model, generate a "sender URI"
*
* @return a string in the form of a Uri, as used by the other parts of the email app
*/
public String getSenderUri(Context context) {
// reconstitute if necessary
if (mHostAuthSend == null) {
mHostAuthSend = HostAuth.restoreHostAuthWithId(context, mHostAuthKeySend);
}
// convert if available
if (mHostAuthSend != null) {
String senderUri = mHostAuthSend.getStoreUri();
if (senderUri != null) {
return senderUri;
}
}
return "";
}
/**
* For compatibility while converting to provider model, set the store URI
*
* @param the new value
*/
public void setStoreUri(Context context, String senderUri) {
// reconstitute or create if necessary
if (mHostAuthRecv == null) {
if (mHostAuthKeyRecv != 0) {
mHostAuthRecv = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
} else {
mHostAuthRecv = new EmailStore.HostAuth();
}
}
if (mHostAuthRecv != null) {
mHostAuthRecv.setStoreUri(senderUri);
}
}
/**
* For compatibility while converting to provider model, set the sender URI
*
* @param the new value
*/
public void setSenderUri(Context context, String senderUri) {
// reconstitute or create if necessary
if (mHostAuthSend == null) {
if (mHostAuthKeySend != 0) {
mHostAuthSend = HostAuth.restoreHostAuthWithId(context, mHostAuthKeySend);
} else {
mHostAuthSend = new EmailStore.HostAuth();
}
}
if (mHostAuthSend != null) {
mHostAuthSend.setStoreUri(senderUri);
}
}
/**
* For compatibility while converting to provider model, generate a "local store URI"
*
* @return a string in the form of a Uri, as used by the other parts of the email app
*/
public String getLocalStoreUri(Context context) {
return "local://localhost/" + context.getDatabasePath(getUuid() + ".db");
}
/**
* Set the account to be the default account. If this is set to "true", when the account
* is saved, all other accounts will have the same value set to "false".
* @param newDefaultState the new default state - if true, others will be cleared.
*/
public void setDefaultAccount(boolean newDefaultState) {
mIsDefault = newDefaultState;
}
static private Account getAccountWhere(Context context, String where) {
@ -664,14 +901,55 @@ public class EmailStore {
return acct;
}
private ContentProviderOperation.Builder getSaveOrUpdateBuilder(boolean doSave,
Uri uri, long id) {
if (doSave) {
return ContentProviderOperation.newInsert(uri);
} else {
return ContentProviderOperation.newUpdate(ContentUris.withAppendedId(uri, id));
}
}
/**
* Do not use Account.save(). Use Account.saveOrUpdate()
*/
@Override
public Uri save(Context context) {
throw new UnsupportedOperationException();
}
/**
* Do not use Account.update(). Use Account.saveOrUpdate()
*/
@Override
public int update(Context context, ContentValues contentValues) {
throw new UnsupportedOperationException();
}
/*
* Override this so that we can store the HostAuth's first and link them to the Account
* (non-Javadoc)
* @see com.android.email.provider.EmailContent#save(android.content.Context)
*/
public Uri save(Context context) {
if (mHostAuthRecv == null && mHostAuthSend == null)
return super.save(context);
@Override
public Uri saveOrUpdate(Context context) {
boolean doSave = !isSaved();
// This logic is in place so I can (a) short circuit the expensive stuff when
// possible, and (b) override (and throw) if anyone tries to call save() or update()
// directly for Account, which are unsupported.
if (mHostAuthRecv == null && mHostAuthSend == null && mIsDefault == false) {
if (doSave) {
return super.save(context);
} else {
if (super.update(context, toContentValues()) == 1) {
return getUri();
}
return null;
}
}
int index = 0;
int recvIndex = -1;
int sendIndex = -1;
@ -681,22 +959,29 @@ public class EmailStore {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
if (mHostAuthRecv != null) {
recvIndex = index++;
ops.add(ContentProviderOperation
.newInsert(mHostAuthRecv.mBaseUri)
ops.add(getSaveOrUpdateBuilder(doSave, mHostAuthRecv.mBaseUri, mHostAuthRecv.mId)
.withValues(mHostAuthRecv.toContentValues())
.build());
}
if (mHostAuthSend != null) {
sendIndex = index++;
ops.add(ContentProviderOperation
.newInsert(mHostAuthSend.mBaseUri)
ops.add(getSaveOrUpdateBuilder(doSave, mHostAuthSend.mBaseUri, mHostAuthSend.mId)
.withValues(mHostAuthSend.toContentValues())
.build());
}
// Create operations for making this the only default account
// Note, these are always updates because they change existing accounts
if (mIsDefault) {
index++;
ContentValues cv1 = new ContentValues();
cv1.put(AccountColumns.IS_DEFAULT, 0);
ops.add(ContentProviderOperation.newUpdate(CONTENT_URI).withValues(cv1).build());
}
// Now do the Account
ContentValues cv = null;
if (recvIndex >= 0 || sendIndex >= 0) {
if (doSave && (recvIndex >= 0 || sendIndex >= 0)) {
cv = new ContentValues();
if (recvIndex >= 0) {
cv.put(Account.HOST_AUTH_KEY_RECV, recvIndex);
@ -706,26 +991,34 @@ public class EmailStore {
}
}
ContentProviderOperation.Builder b =
ContentProviderOperation.newInsert(mBaseUri).withValues(toContentValues());
ContentProviderOperation.Builder b = getSaveOrUpdateBuilder(doSave, mBaseUri, mId);
b.withValues(toContentValues());
if (cv != null) {
b.withValueBackReferences(cv);
}
ops.add(b.build());
try {
ContentProviderResult[] res =
ContentProviderResult[] results =
context.getContentResolver().applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
// Set the mId's of the various saved objects
if (recvIndex >= 0) {
mHostAuthRecv.mId = getId(res[recvIndex].uri);
// If saving, set the mId's of the various saved objects
if (doSave) {
if (recvIndex >= 0) {
long newId = getId(results[recvIndex].uri);
mHostAuthKeyRecv = newId;
mHostAuthRecv.mId = newId;
}
if (sendIndex >= 0) {
long newId = getId(results[sendIndex].uri);
mHostAuthKeySend = newId;
mHostAuthSend.mId = newId;
}
Uri u = results[index].uri;
mId = getId(u);
return u;
} else {
return null;
}
if (sendIndex >= 0) {
mHostAuthSend.mId = getId(res[recvIndex].uri);
}
Uri u = res[index].uri;
mId = getId(u);
return u;
} catch (RemoteException e) {
// There is nothing to be done here; fail by returning null
} catch (OperationApplicationException e) {
@ -745,7 +1038,10 @@ public class EmailStore {
values.put(AccountColumns.HOST_AUTH_KEY_RECV, mHostAuthKeyRecv);
values.put(AccountColumns.HOST_AUTH_KEY_SEND, mHostAuthKeySend);
values.put(AccountColumns.FLAGS, mFlags);
values.put(AccountColumns.IS_DEFAULT, mIsDefault);
values.put(AccountColumns.IS_DEFAULT, mIsDefault ? 1 : 0);
values.put(AccountColumns.COMPATIBILITY_UUID, mCompatibilityUuid);
values.put(AccountColumns.SENDER_NAME, mSenderName);
values.put(AccountColumns.RINGTONE_URI, mRingtoneUri);
return values;
}
@ -774,6 +1070,8 @@ public class EmailStore {
* Supports Parcelable
*/
public void writeToParcel(Parcel dest, int flags) {
// mBaseUri is not parceled
dest.writeLong(mId);
dest.writeString(mDisplayName);
dest.writeString(mEmailAddress);
dest.writeString(mSyncKey);
@ -783,6 +1081,9 @@ public class EmailStore {
dest.writeLong(mHostAuthKeySend);
dest.writeInt(mFlags);
dest.writeByte(mIsDefault ? (byte)1 : (byte)0);
dest.writeString(mCompatibilityUuid);
dest.writeString(mSenderName);
dest.writeString(mRingtoneUri);
if (mHostAuthRecv != null) {
dest.writeByte((byte)1);
@ -803,6 +1104,8 @@ public class EmailStore {
* Supports Parcelable
*/
public Account(Parcel in) {
mBaseUri = EmailStore.Account.CONTENT_URI;
mId = in.readLong();
mDisplayName = in.readString();
mEmailAddress = in.readString();
mSyncKey = in.readString();
@ -812,6 +1115,9 @@ public class EmailStore {
mHostAuthKeySend = in.readLong();
mFlags = in.readInt();
mIsDefault = in.readByte() == 1;
mCompatibilityUuid = in.readString();
mSenderName = in.readString();
mRingtoneUri = in.readString();
mHostAuthRecv = null;
if (in.readByte() == 1) {
@ -1125,7 +1431,7 @@ public class EmailStore {
@Override
@SuppressWarnings("unchecked")
public EmailStore.Mailbox restore(Cursor cursor) {
mBaseUri = EmailStore.Attachment.CONTENT_URI;
mBaseUri = EmailStore.Mailbox.CONTENT_URI;
mDisplayName = cursor.getString(CONTENT_DISPLAY_NAME_COLUMN);
mServerId = cursor.getString(CONTENT_SERVER_ID_COLUMN);
mParentServerId = cursor.getString(CONTENT_PARENT_SERVER_ID_COLUMN);
@ -1172,49 +1478,46 @@ public class EmailStore {
static final String ADDRESS = "address";
// The port to use for the connection
static final String PORT = "port";
// Whether SSL is to be used
static final String SSL = "ssl";
// Whether TLS is to be used
static final String TLS = "tls";
// General purpose flags
static final String FLAGS = "flags";
// The login (user name)
static final String LOGIN = "login";
// Password
static final String PASSWORD = "password";
// A domain or path, if required (used in IMAP and EAS)
static final String DOMAIN = "domain";
// Whether authentication is required
static final String FLAG_AUTHENTICATE = "flagAuthenticate";
// Foreign key of the Account this is attached to
static final String ACCOUNT_KEY = "accountKey";
}
public static final class HostAuth extends EmailContent implements HostAuthColumns, Parcelable {
private static final int FLAG_SSL = 1;
private static final int FLAG_TLS = 2;
private static final int FLAG_AUTHENTICATE = 4;
public String mProtocol;
public String mAddress;
public int mPort;
public boolean mSsl;
public boolean mTls;
public int mFlags;
public String mLogin;
public String mPassword;
public String mDomain;
public boolean mFlagAuthenticate;
public long mAccountKey;
public static final int CONTENT_ID_COLUMN = 0;
public static final int CONTENT_PROTOCOL_COLUMN = 1;
public static final int CONTENT_ADDRESS_COLUMN = 2;
public static final int CONTENT_PORT_COLUMN = 3;
public static final int CONTENT_SSL_COLUMN = 4;
public static final int CONTENT_TLS_COLUMN = 5;
public static final int CONTENT_LOGIN_COLUMN = 6;
public static final int CONTENT_PASSWORD_COLUMN = 7;
public static final int CONTENT_DOMAIN_COLUMN = 8;
public static final int CONTENT_FLAG_AUTHENTICATE_COLUMN = 9;
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 10;
public static final int CONTENT_FLAGS_COLUMN = 4;
public static final int CONTENT_LOGIN_COLUMN = 5;
public static final int CONTENT_PASSWORD_COLUMN = 6;
public static final int CONTENT_DOMAIN_COLUMN = 7;
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 8;
public static final String[] CONTENT_PROJECTION = new String[] {
RECORD_ID, HostAuthColumns.PROTOCOL, HostAuthColumns.ADDRESS, HostAuthColumns.PORT,
HostAuthColumns.SSL, HostAuthColumns.TLS, HostAuthColumns.LOGIN,
HostAuthColumns.PASSWORD, HostAuthColumns.DOMAIN, HostAuthColumns.FLAG_AUTHENTICATE,
HostAuthColumns.FLAGS, HostAuthColumns.LOGIN,
HostAuthColumns.PASSWORD, HostAuthColumns.DOMAIN,
HostAuthColumns.ACCOUNT_KEY
};
@ -1223,6 +1526,10 @@ public class EmailStore {
*/
public HostAuth() {
mBaseUri = CONTENT_URI;
// other defaults policy)
mPort = -1;
mFlags = FLAG_AUTHENTICATE;
}
public static final String TABLE_NAME = "HostAuth";
@ -1237,12 +1544,10 @@ public class EmailStore {
+ HostAuthColumns.PROTOCOL + " text, "
+ HostAuthColumns.ADDRESS + " text, "
+ HostAuthColumns.PORT + " integer, "
+ HostAuthColumns.SSL + " integer, "
+ HostAuthColumns.TLS + " integer, "
+ HostAuthColumns.FLAGS + " integer, "
+ HostAuthColumns.LOGIN + " text, "
+ HostAuthColumns.PASSWORD + " text, "
+ HostAuthColumns.DOMAIN + " text, "
+ HostAuthColumns.FLAG_AUTHENTICATE + " text, "
+ HostAuthColumns.ACCOUNT_KEY + " integer"
+ ");";
db.execSQL("create table " + TABLE_NAME + s);
@ -1281,16 +1586,14 @@ public class EmailStore {
@Override
@SuppressWarnings("unchecked")
public EmailStore.HostAuth restore(Cursor cursor) {
mBaseUri = EmailStore.Attachment.CONTENT_URI;
mBaseUri = EmailStore.HostAuth.CONTENT_URI;
mProtocol = cursor.getString(CONTENT_PROTOCOL_COLUMN);
mAddress = cursor.getString(CONTENT_ADDRESS_COLUMN);
mPort = cursor.getInt(CONTENT_PORT_COLUMN);
mSsl = cursor.getInt(CONTENT_SSL_COLUMN) == 1;
mTls = cursor.getInt(CONTENT_TLS_COLUMN) == 1;
mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
mLogin = cursor.getString(CONTENT_LOGIN_COLUMN);
mPassword = cursor.getString(CONTENT_PASSWORD_COLUMN);
mDomain = cursor.getString(CONTENT_DOMAIN_COLUMN);
mFlagAuthenticate = cursor.getInt(CONTENT_FLAG_AUTHENTICATE_COLUMN) == 1;
mAccountKey = cursor.getLong(CONTENT_ACCOUNT_KEY_COLUMN);
return this;
}
@ -1301,12 +1604,10 @@ public class EmailStore {
values.put(HostAuthColumns.PROTOCOL, mProtocol);
values.put(HostAuthColumns.ADDRESS, mAddress);
values.put(HostAuthColumns.PORT, mPort);
values.put(HostAuthColumns.SSL, mSsl);
values.put(HostAuthColumns.TLS, mTls);
values.put(HostAuthColumns.FLAGS, mFlags);
values.put(HostAuthColumns.LOGIN, mLogin);
values.put(HostAuthColumns.PASSWORD, mPassword);
values.put(HostAuthColumns.DOMAIN, mDomain);
values.put(HostAuthColumns.FLAG_AUTHENTICATE, mFlagAuthenticate);
values.put(HostAuthColumns.ACCOUNT_KEY, mAccountKey);
return values;
}
@ -1318,9 +1619,9 @@ public class EmailStore {
*/
public String getStoreUri() {
String security = "";
if (mSsl) {
if ((mFlags & FLAG_SSL) != 0) {
security = "+ssl+";
} else if (mTls) {
} else if ((mFlags & FLAG_TLS) != 0) {
security = "+tls+";
}
@ -1358,15 +1659,25 @@ public class EmailStore {
}
}
String[] schemeParts = uri.getScheme().split("+");
String[] schemeParts = uri.getScheme().split("\\+");
mProtocol = (schemeParts.length >= 1) ? schemeParts[0] : null;
boolean ssl = false;
boolean tls = false;
if (schemeParts.length >= 2) {
if ("ssl".equals(schemeParts[1])) {
mSsl = true;
ssl = true;
} else if ("tls".equals(schemeParts[1])) {
mTls = true;
tls = true;
}
}
mFlags &= ~(FLAG_SSL | FLAG_TLS);
if (ssl) {
mFlags |= FLAG_SSL;
}
if (tls) {
mFlags |= FLAG_TLS;
}
mAddress = uri.getHost();
mPort = uri.getPort();
@ -1374,13 +1685,13 @@ public class EmailStore {
// infer port# from protocol + security
// SSL implies a different port - TLS runs in the "regular" port
if ("pop3".equals(mProtocol)) {
mPort = mSsl ? 995 : 110;
mPort = ssl ? 995 : 110;
} else if ("imap".equals(mProtocol)) {
mPort = mSsl ? 993 : 143;
mPort = ssl ? 993 : 143;
} else if ("eas".equals(mProtocol)) {
mPort = mSsl ? 443 : 80;
mPort = ssl ? 443 : 80;
} else if ("smtp".equals(mProtocol)) {
mPort = mSsl ? 465 : 25;
mPort = ssl ? 465 : 25;
}
}
@ -1423,15 +1734,15 @@ public class EmailStore {
* Supports Parcelable
*/
public void writeToParcel(Parcel dest, int flags) {
// mBaseUri is not parceled
dest.writeLong(mId);
dest.writeString(mProtocol);
dest.writeString(mAddress);
dest.writeInt(mPort);
dest.writeByte(mSsl ? (byte) 1 : (byte) 0);
dest.writeByte(mTls ? (byte) 1 : (byte) 0);
dest.writeInt(mFlags);
dest.writeString(mLogin);
dest.writeString(mPassword);
dest.writeString(mDomain);
dest.writeByte(mFlagAuthenticate ? (byte) 1 : (byte) 0);
dest.writeLong(mAccountKey);
}
@ -1439,15 +1750,15 @@ public class EmailStore {
* Supports Parcelable
*/
public HostAuth(Parcel in) {
mBaseUri = CONTENT_URI;
mId = in.readLong();
mProtocol = in.readString();
mAddress = in.readString();
mPort = in.readInt();
mSsl = in.readByte() == 1;
mTls = in.readByte() == 1;
mFlags = in.readInt();
mLogin = in.readString();
mPassword = in.readString();
mDomain = in.readString();
mFlagAuthenticate = in.readByte() == 1;
mAccountKey = in.readLong();
}