com.googlecode.CallerLookup.Main.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.CallerLookup.Main.java

Source

/*
 * Copyright (C) 2010 Fridvin Logi
 *
 * 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.googlecode.CallerLookup;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnCancelListener;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;

public class Main extends Activity implements OnClickListener, OnItemSelectedListener {
    class LookupEntry {
        public String mName = null;
        public String mURL = null;
        public String mRegExp = null;

        public LookupEntry() {
        }

        public LookupEntry(String name, String url, String regExp) {
            mName = name;
            mURL = url;
            mRegExp = regExp;
        }

        public LookupEntry(JSONObject object) throws JSONException {
            mName = object.getString("name");
            mURL = object.getString("url");
            mRegExp = object.getString("regexp");
        }

        public JSONObject toJSONObject() throws JSONException {
            JSONObject object = new JSONObject();
            object.put("name", mName);
            object.put("url", mURL);
            object.put("regexp", mRegExp);
            return object;
        }
    }

    public static final String PREFS = "CallerLookupPrefs";
    public static final String PREFS_LOOKUP = "lookup";
    public static final String PREFS_URL = "url";
    public static final String PREFS_REGEXP = "regexp";
    public static final String PREFS_NOTIFY = "notify";
    public static final String PREFS_UPDATE = "update";
    public static final String STATE_TESTINPUT = "testinput";

    public static final int MENU_CUSTOMIZE = Menu.FIRST + 1;
    public static final int MENU_SAVE = Menu.FIRST + 2;
    public static final int MENU_REMOVE = Menu.FIRST + 3;
    public static final int MENU_SUBMIT = Menu.FIRST + 4;
    public static final int MENU_UPDATE = Menu.FIRST + 5;
    public static final int MENU_HELP = Menu.FIRST + 6;

    public static final int MESSAGE_UPDATE_FINISHED = 1;
    public static final int MESSAGE_UPDATE_UNNECESSARY = 2;

    public static final int DIALOG_PROGRESS = 1;

    public static final String EMAIL_ADDRESS = "fridvin@gmail.com";
    public static final String EMAIL_SUBJECT = "CallerLookup entry";

    public static final String UPDATE_URL = "http://caller-lookup.googlecode.com/svn/trunk/res/xml/lookups.xml";
    public static final String UPDATE_FILE = "CallerLookupEntries.xml";

    public static final String SAVED_FILE = "CallerLookupUserEntries.json";
    public static final String SAVED_PREFIX = "* ";

    private boolean mIgnoreItemSelection = false;
    private boolean mIgnoreLookupResult = false;

    private TestLookupThread mLookupThread = null;

    private ProgressDialog mProgressDialog = null;

    private HashMap<String, LookupEntry> mLookupEntries = null;
    private HashMap<String, LookupEntry> mUserLookupEntries = null;

    private SharedPreferences mPrefs;

    private Spinner mLookup;
    private EditText mURL;
    private EditText mRegExp;
    private EditText mTestInput;
    private Button mTestButton;
    private CheckBox mNotify;

    private final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            dismissDialog(DIALOG_PROGRESS);
            switch (msg.what) {
            case TestLookupThread.MESSAGE_COMPLETE:
                if (!mIgnoreLookupResult && (mLookupThread != null) && (mLookupThread.mCaller != null)) {
                    Context context = getApplicationContext();
                    Toast.makeText(context, mLookupThread.mCaller, Toast.LENGTH_LONG).show();

                    SharedPreferences prefs = context.getSharedPreferences(PREFS, 0);
                    if (prefs.getBoolean(PREFS_NOTIFY, false)) {
                        CallerLookupService.addNotification(context, mLookupThread.mNumber, mLookupThread.mCaller);
                    }
                }

                mIgnoreLookupResult = false;
                mLookupThread = null;
                break;
            case TestLookupThread.MESSAGE_ERROR:
                Log.d("DEBUG", "Error: " + msg.getData().getString("Message"));
                mIgnoreLookupResult = false;
                mLookupThread.stopThread();
                mLookupThread = null;
                break;
            default:
                break;
            }
        }
    };

    private final Handler mUpdateHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_UPDATE_FINISHED:
                updateLookupEntries();
                dismissDialog(DIALOG_PROGRESS);
                Toast.makeText(getApplicationContext(),
                        getApplicationContext().getResources().getText(R.string.UpdateFinished), Toast.LENGTH_SHORT)
                        .show();
                break;
            case MESSAGE_UPDATE_UNNECESSARY:
                dismissDialog(DIALOG_PROGRESS);
                Toast.makeText(getApplicationContext(),
                        getApplicationContext().getResources().getText(R.string.UpdateNotNeeded),
                        Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
            }
        }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mLookup = (Spinner) findViewById(R.id.Lookup);
        mURL = (EditText) findViewById(R.id.URL);
        mRegExp = (EditText) findViewById(R.id.RegExp);
        mTestInput = (EditText) findViewById(R.id.TestInput);
        mTestButton = (Button) findViewById(R.id.TestButton);
        mNotify = (CheckBox) findViewById(R.id.Notify);

        mPrefs = getSharedPreferences(PREFS, 0);
        mURL.setText(mPrefs.getString(PREFS_URL, ""));
        mRegExp.setText(mPrefs.getString(PREFS_REGEXP, ""));
        mNotify.setChecked(mPrefs.getBoolean(PREFS_NOTIFY, false));

        mLookup.setOnItemSelectedListener(this);
        mTestButton.setOnClickListener(this);

        updateLookupEntries();

        if (mPrefs.getAll().isEmpty()) {
            savePreferences();
        }

        if (getLastNonConfigurationInstance() != null) {
            mLookupThread = (TestLookupThread) getLastNonConfigurationInstance();
            mLookupThread.mActivityHandler = mHandler;

            if (mLookupThread.isAlive()) {
                showDialog(DIALOG_PROGRESS);
            } else {
                dismissDialog(DIALOG_PROGRESS);
                mLookupThread = null;
            }
        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        if (id != DIALOG_PROGRESS) {
            return super.onCreateDialog(id);
        }

        mProgressDialog = new ProgressDialog(Main.this);
        mProgressDialog.setMessage(getString(R.string.ProgressMessage));
        mProgressDialog.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                // TODO: stop mLookupThread instead of doing this ignore-lookup-result hack
                mIgnoreLookupResult = true;
            }
        });
        return mProgressDialog;
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        mIgnoreItemSelection = true;
        mLookup.setSelection(savedInstanceState.getInt(PREFS_LOOKUP));
        mURL.setText(savedInstanceState.getString(PREFS_URL));
        mRegExp.setText(savedInstanceState.getString(PREFS_REGEXP));
        mTestInput.setText(savedInstanceState.getString(STATE_TESTINPUT));
        mNotify.setChecked(savedInstanceState.getBoolean(PREFS_NOTIFY));
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt(PREFS_LOOKUP, mLookup.getSelectedItemPosition());
        outState.putString(PREFS_URL, mURL.getText().toString());
        outState.putString(PREFS_REGEXP, mRegExp.getText().toString());
        outState.putString(STATE_TESTINPUT, mTestInput.getText().toString());
        outState.putBoolean(PREFS_NOTIFY, mNotify.isChecked());
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        removeDialog(DIALOG_PROGRESS);
        mProgressDialog = null;
        if (mLookupThread != null) {
            mLookupThread.mActivityHandler = null; // avoid memory leak
            return mLookupThread;
        }

        return super.onRetainNonConfigurationInstance();
    }

    @Override
    protected void onPause() {
        super.onPause();
        savePreferences();
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == mTestButton.getId()) {
            String number = mTestInput.getText().toString();

            if (number.length() > 0) {
                String lookup = mURL.getText().toString();
                String regExp = mRegExp.getText().toString();

                savePreferences();

                showDialog(DIALOG_PROGRESS);
                mLookupThread = new TestLookupThread(mHandler);
                mLookupThread.mURL = lookup;
                mLookupThread.mRegExp = regExp;
                mLookupThread.mNumber = number;
                mLookupThread.start();
            }
        }
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if (parent.getId() == mLookup.getId()) {
            if (mIgnoreItemSelection) {
                mIgnoreItemSelection = false;
                return;
            }

            if (position == 0) {
                mURL.setText("");
                mURL.setEnabled(true);
                mURL.setFocusableInTouchMode(true);
                mRegExp.setText("");
                mRegExp.setEnabled(true);
                mRegExp.setFocusableInTouchMode(true);
            } else {
                mURL.setEnabled(false);
                mURL.setFocusable(false);
                mURL.clearFocus();
                mRegExp.setEnabled(false);
                mRegExp.setFocusable(false);
                mRegExp.clearFocus();

                String name = mLookup.getItemAtPosition(position).toString();
                LookupEntry lookupEntry = mLookupEntries.get(name);
                assert (lookupEntry != null);
                mURL.setText(lookupEntry.mURL);
                mRegExp.setText(lookupEntry.mRegExp);
            }
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(Menu.NONE, MENU_CUSTOMIZE, Menu.NONE, R.string.Customize);
        menu.add(Menu.NONE, MENU_SAVE, Menu.NONE, R.string.Save);
        menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.Remove);
        menu.add(Menu.NONE, MENU_SUBMIT, Menu.NONE, R.string.Submit);
        menu.add(Menu.NONE, MENU_UPDATE, Menu.NONE, R.string.Update);
        menu.add(Menu.NONE, MENU_HELP, Menu.NONE, R.string.Help);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        assert ((mLookup.getSelectedItemPosition() == 0)
                || (mLookupEntries.get(mLookup.getSelectedItem().toString()) != null));
        boolean custom = (mLookup.getSelectedItemPosition() == 0);
        boolean saved = (!custom
                && mLookupEntries.get(mLookup.getSelectedItem().toString()).mName.startsWith(SAVED_PREFIX));
        boolean empty = (mURL.getText().toString().length() <= 0);

        MenuItem customize = menu.findItem(MENU_CUSTOMIZE);
        assert (customize != null);
        customize.setEnabled(!custom);

        MenuItem save = menu.findItem(MENU_SAVE);
        assert (save != null);
        save.setEnabled(custom && !empty);

        MenuItem remove = menu.findItem(MENU_REMOVE);
        assert (remove != null);
        remove.setEnabled(saved);

        MenuItem submit = menu.findItem(MENU_SUBMIT);
        assert (submit != null);
        submit.setEnabled((custom || saved) && !empty);

        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case MENU_CUSTOMIZE:
            if (item.isEnabled()) {
                doCustomize();
            }
            return true;
        case MENU_SAVE:
            if (item.isEnabled()) {
                doSave();
            }
            return true;
        case MENU_REMOVE:
            if (item.isEnabled()) {
                doRemove();
            }
            return true;
        case MENU_SUBMIT:
            if (item.isEnabled()) {
                doSubmit();
            }
            return true;
        case MENU_UPDATE:
            if (item.isEnabled()) {
                doUpdate();
            }
            return true;
        case MENU_HELP:
            if (item.isEnabled()) {
                doHelp();
            }
            return true;
        default:
            break;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("unchecked")
    public void updateLookupEntries() {
        parseLookupEntries();

        ArrayAdapter<CharSequence> adapter = (ArrayAdapter<CharSequence>) mLookup.getAdapter();
        if (adapter == null) {
            adapter = new ArrayAdapter<CharSequence>(getApplicationContext(), android.R.layout.simple_spinner_item);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            mLookup.setAdapter(adapter);
        } else {
            adapter.clear();
        }

        adapter.add("Custom");
        for (String lookupEntryName : mLookupEntries.keySet()) {
            adapter.add(lookupEntryName);
        }

        for (String lookupEntryName : mUserLookupEntries.keySet()) {
            assert (!mLookupEntries.containsKey(lookupEntryName));
            mLookupEntries.put(lookupEntryName, mUserLookupEntries.get(lookupEntryName));
            adapter.add(lookupEntryName);
        }

        String name = mPrefs.getString(PREFS_LOOKUP, "Custom");
        if ((name.length() > 0) && !name.equals("Custom")) {
            int count = mLookup.getCount();
            for (int i = 1; i < count; i++) {
                if (mLookup.getItemAtPosition(i).toString().equals(name)) {
                    mLookup.setSelection(i);
                    break;
                }
            }
        } else {
            if (mLookup.getSelectedItemPosition() != 0) {
                mIgnoreItemSelection = true;
                mLookup.setSelection(0);
            }
        }
    }

    public void parseLookupEntries() {
        mLookupEntries = new HashMap<String, LookupEntry>();
        mUserLookupEntries = new HashMap<String, LookupEntry>();

        boolean updateFound = false;
        for (String fileName : getApplicationContext().fileList()) {
            if (fileName.equals(UPDATE_FILE)) {
                try {
                    FileInputStream file = getApplicationContext().openFileInput(UPDATE_FILE);
                    XmlPullParser xml = Xml.newPullParser();
                    xml.setInput(file, null);
                    parseLookupEntries(xml, mLookupEntries);
                    file.close();
                    updateFound = true;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (XmlPullParserException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else if (fileName.equals(SAVED_FILE)) {
                try {
                    FileInputStream file = getApplicationContext().openFileInput(SAVED_FILE);
                    InputStreamReader reader = new InputStreamReader(file);
                    char[] content = new char[8000];
                    reader.read(content);
                    JSONArray userLookupEntries = new JSONArray(new String(content));
                    int count = userLookupEntries.length();
                    for (int i = 0; i < count; i++) {
                        JSONObject userLookupEntry = userLookupEntries.getJSONObject(i);
                        mUserLookupEntries.put(userLookupEntry.getString("name"), new LookupEntry(userLookupEntry));
                    }
                    file.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        if (!updateFound) {
            XmlResourceParser xml = getApplicationContext().getResources().getXml(R.xml.lookups);
            parseLookupEntries(xml, mLookupEntries);
            xml.close();
        }
    }

    public void parseLookupEntries(XmlPullParser xml, HashMap<String, LookupEntry> lookupEntries) {
        try {
            for (int eventType = xml.getEventType(); eventType != XmlPullParser.END_DOCUMENT; eventType = xml
                    .next()) {
                if ((eventType == XmlPullParser.START_TAG) && xml.getName().equals("lookupEntry")) {
                    eventType = xml.next();
                    LookupEntry lookupEntry = new LookupEntry();
                    while ((eventType != XmlPullParser.END_TAG) && (eventType != XmlPullParser.END_DOCUMENT)) {
                        if (eventType == XmlPullParser.START_TAG) {
                            if (xml.getName().equals("name")) {
                                assert (lookupEntry.mName == null);
                                eventType = xml.next();
                                xml.require(XmlPullParser.TEXT, null, null);
                                lookupEntry.mName = xml.getText();
                            } else if (xml.getName().equals("url")) {
                                assert (lookupEntry.mURL == null);
                                eventType = xml.next();
                                xml.require(XmlPullParser.TEXT, null, null);
                                lookupEntry.mURL = xml.getText();
                            } else {
                                assert (xml.getName().equals("regexp"));
                                assert (lookupEntry.mRegExp == null);
                                eventType = xml.next();
                                xml.require(XmlPullParser.TEXT, null, null);
                                lookupEntry.mRegExp = xml.getText();
                            }

                            eventType = xml.next();
                            xml.require(XmlPullParser.END_TAG, null, null);
                        }
                        eventType = xml.next();
                    }

                    if ((lookupEntry.mName != null) && (lookupEntry.mURL != null)
                            && (lookupEntry.mRegExp != null)) {
                        lookupEntries.put(lookupEntry.mName, lookupEntry);
                    }
                }
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void addUserLookupEntry(String name) {
        mUserLookupEntries.put(name,
                new LookupEntry(name, mURL.getText().toString(), mRegExp.getText().toString()));
        mLookupEntries.put(name, new LookupEntry(name, mURL.getText().toString(), mRegExp.getText().toString()));
        saveUserLookupEntries();
    }

    public void removeUserLookupEntry(String name) {
        mLookupEntries.remove(name);
        mUserLookupEntries.remove(name);
        saveUserLookupEntries();
    }

    public void savePreferences() {
        SharedPreferences.Editor prefsEditor = mPrefs.edit();
        prefsEditor.putString(PREFS_LOOKUP, mLookup.getSelectedItem().toString());
        prefsEditor.putString(PREFS_URL, mURL.getText().toString());
        prefsEditor.putString(PREFS_REGEXP, mRegExp.getText().toString());
        prefsEditor.putBoolean(PREFS_NOTIFY, mNotify.isChecked());
        prefsEditor.commit();
    }

    public void saveUserLookupEntries() {
        try {
            FileOutputStream file = getApplicationContext().openFileOutput(SAVED_FILE, MODE_PRIVATE);
            JSONArray userLookupEntries = new JSONArray();
            for (String lookupEntryName : mUserLookupEntries.keySet()) {
                try {
                    userLookupEntries.put(mUserLookupEntries.get(lookupEntryName).toJSONObject());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            OutputStreamWriter content = new OutputStreamWriter(file);
            content.write(userLookupEntries.toString());
            content.flush();
            content.close();
            file.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void doCustomize() {
        mIgnoreItemSelection = true;
        mLookup.setSelection(0);
        mURL.setEnabled(true);
        mURL.setFocusableInTouchMode(true);
        mRegExp.setEnabled(true);
        mRegExp.setFocusableInTouchMode(true);
    }

    public void doSave() {
        final Context context = this;
        final EditText input = new EditText(context);
        input.setHint(R.string.Name);

        AlertDialog.Builder alert = new AlertDialog.Builder(context);
        alert.setTitle(R.string.SaveTitle);
        alert.setMessage(R.string.SaveMessage);
        alert.setView(input);

        alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @SuppressWarnings("unchecked")
            @Override
            public void onClick(DialogInterface dialog, int which) {
                final String name = SAVED_PREFIX + input.getText().toString().trim();
                if (name.length() <= SAVED_PREFIX.length()) {
                    AlertDialog.Builder error = new AlertDialog.Builder(context);
                    error.setTitle(R.string.NameMissingTitle);
                    error.setMessage(R.string.NameMissingMessage);
                    error.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            doSave();
                        }
                    });
                    error.show();
                    return;
                }
                if (mLookupEntries.containsKey(name)) {
                    AlertDialog.Builder confirm = new AlertDialog.Builder(context);
                    confirm.setTitle(R.string.NameConfirmTitle);
                    confirm.setMessage(R.string.NameConfirmMessage);
                    confirm.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            mLookupEntries.remove(name);
                            mUserLookupEntries.remove(name);
                            addUserLookupEntry(name);

                            int count = mLookup.getCount();
                            for (int i = 1; i < count; i++) {
                                if (mLookup.getItemAtPosition(i).toString().equals(name)) {
                                    mLookup.setSelection(i);
                                    break;
                                }
                            }
                        }
                    });
                    confirm.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            doSave();
                        }
                    });
                    confirm.show();
                    return;
                }

                addUserLookupEntry(name);

                ArrayAdapter<CharSequence> adapter = (ArrayAdapter<CharSequence>) mLookup.getAdapter();
                adapter.add(name);
                mLookup.setSelection(mLookup.getCount() - 1);
            }
        });

        alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });

        alert.show();
    }

    public void doRemove() {
        final Context context = this;
        final String name = mLookup.getSelectedItem().toString();

        AlertDialog.Builder confirm = new AlertDialog.Builder(context);
        confirm.setTitle(R.string.RemoveTitle);
        confirm.setMessage(R.string.RemoveMessage);
        confirm.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            @SuppressWarnings("unchecked")
            @Override
            public void onClick(DialogInterface dialog, int which) {
                removeUserLookupEntry(name);
                doCustomize();

                ArrayAdapter<CharSequence> adapter = (ArrayAdapter<CharSequence>) mLookup.getAdapter();
                adapter.remove(name);
            }
        });
        confirm.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });
        confirm.show();
    }

    public void doSubmit() {
        String entry = "";
        if (mLookup.getSelectedItemPosition() != 0) {
            entry = mLookup.getSelectedItem().toString() + "\n";
        }

        entry += mURL.getText().toString() + "\n";
        entry += mRegExp.getText().toString() + "\n";

        try {
            String[] mailto = { EMAIL_ADDRESS };
            Intent sendIntent = new Intent(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_EMAIL, mailto);
            sendIntent.putExtra(Intent.EXTRA_SUBJECT, EMAIL_SUBJECT);
            sendIntent.putExtra(Intent.EXTRA_TEXT, entry);
            sendIntent.setType("message/rfc822");
            startActivity(sendIntent);
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();

            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.setTitle(R.string.SubmitFailureTitle);
            alert.setMessage(R.string.SubmitFailureMessage);
            alert.setPositiveButton(android.R.string.ok, null);
            alert.show();
        }
    }

    public void doUpdate() {
        showDialog(DIALOG_PROGRESS);
        savePreferences();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL uri = new URL(UPDATE_URL);
                    URLConnection urlc = uri.openConnection();
                    long lastModified = urlc.getLastModified();
                    if ((lastModified == 0) || (lastModified != mPrefs.getLong(PREFS_UPDATE, 0))) {
                        FileOutputStream file = getApplicationContext().openFileOutput(UPDATE_FILE, MODE_PRIVATE);
                        OutputStreamWriter content = new OutputStreamWriter(file);

                        String tmp;
                        InputStream is = urlc.getInputStream();
                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
                        while ((tmp = br.readLine()) != null) {
                            content.write(tmp + "\n");
                        }

                        content.flush();
                        content.close();
                        file.close();

                        SharedPreferences.Editor prefsEditor = mPrefs.edit();
                        prefsEditor.putLong(PREFS_UPDATE, lastModified);
                        prefsEditor.commit();

                        Message message = mUpdateHandler.obtainMessage();
                        message.what = MESSAGE_UPDATE_FINISHED;
                        mUpdateHandler.sendMessage(message);
                    } else {
                        Message message = mUpdateHandler.obtainMessage();
                        message.what = MESSAGE_UPDATE_UNNECESSARY;
                        mUpdateHandler.sendMessage(message);
                    }
                } catch (MalformedURLException e) {
                    System.out.println(e.getMessage());
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }).start();
    }

    public void doHelp() {
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle(R.string.HelpTitle);
        alert.setMessage(R.string.HelpMessage);
        alert.setPositiveButton(android.R.string.ok, null);
        alert.show();
    }
}