diff options
Diffstat (limited to 'java/src/com/android/inputmethod/dictionarypack')
3 files changed, 90 insertions, 12 deletions
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java index a6376a54c..88b5032e3 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java @@ -16,9 +16,13 @@ package com.android.inputmethod.dictionarypack; +import android.app.DownloadManager; +import android.app.DownloadManager.Query; import android.content.ContentValues; import android.content.Context; +import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -78,7 +82,8 @@ public class DictionaryDownloadProgressBar extends ProgressBar { mReporterThread = null; return; } - final UpdaterThread updaterThread = new UpdaterThread(downloadManagerPendingId); + final UpdaterThread updaterThread = + new UpdaterThread(getContext(), downloadManagerPendingId); updaterThread.start(); mReporterThread = updaterThread; } else { @@ -99,23 +104,75 @@ public class DictionaryDownloadProgressBar extends ProgressBar { updateReporterThreadRunningStatusAccordingToVisibility(); } - private static class UpdaterThread extends Thread { - private final static int REPORT_PERIOD = 1000; // how often to report progress + private class UpdaterThread extends Thread { + private final static int REPORT_PERIOD = 150; // how often to report progress, in ms + final DownloadManager mDownloadManager; final int mId; - public UpdaterThread(final int id) { + public UpdaterThread(final Context context, final int id) { super(); + mDownloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); mId = id; } @Override public void run() { try { - // TODO: implement the actual query and reporting + // It's almost impossible that mDownloadManager is null (it would mean it has been + // disabled between pressing the 'install' button and displaying the progress + // bar), but just in case. + if (null == mDownloadManager) return; + final UpdateHelper updateHelper = new UpdateHelper(); + final Query query = new Query().setFilterById(mId); + int lastProgress = 0; + setIndeterminate(true); while (!isInterrupted()) { + final Cursor cursor = mDownloadManager.query(query); + if (null == cursor) { + // Can't contact DownloadManager: this should never happen. + return; + } + try { + if (cursor.moveToNext()) { + final int columnBytesDownloadedSoFar = cursor.getColumnIndex( + DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR); + final int bytesDownloadedSoFar = + cursor.getInt(columnBytesDownloadedSoFar); + updateHelper.setProgressFromAnotherThread(bytesDownloadedSoFar); + } else { + // Download has finished and DownloadManager has already been asked to + // clean up the db entry. + updateHelper.setProgressFromAnotherThread(getMax()); + return; + } + } finally { + cursor.close(); + } Thread.sleep(REPORT_PERIOD); } } catch (InterruptedException e) { // Do nothing and terminate normally. } } + + private class UpdateHelper implements Runnable { + private int mProgress; + @Override + public void run() { + setIndeterminate(false); + setProgress(mProgress); + } + public void setProgressFromAnotherThread(final int progress) { + if (mProgress != progress) { + mProgress = progress; + // For some unknown reason, setProgress just does not work from a separate + // thread, although the code in ProgressBar looks like it should. Thus, we + // resort to a runnable posted to the handler of the view. + final Handler handler = getHandler(); + // It's possible to come here before this view has been laid out. If so, + // just ignore the call - it will be updated again later. + if (null == handler) return; + handler.post(this); + } + } + } } } diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java index fb75d6dc0..618322357 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java @@ -66,6 +66,8 @@ public final class DictionarySettingsFragment extends PreferenceFragment private boolean mChangedSettings; private DictionaryListInterfaceState mDictionaryListInterfaceState = new DictionaryListInterfaceState(); + private TreeMap<String, WordListPreference> mCurrentPreferenceMap = + new TreeMap<String, WordListPreference>(); // never null private final BroadcastReceiver mConnectivityChangedReceiver = new BroadcastReceiver() { @Override @@ -278,7 +280,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment return result; } else { final String systemLocaleString = Locale.getDefault().toString(); - final TreeMap<String, WordListPreference> prefList = + final TreeMap<String, WordListPreference> prefMap = new TreeMap<String, WordListPreference>(); final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN); final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN); @@ -299,16 +301,31 @@ public final class DictionarySettingsFragment extends PreferenceFragment // The key is sorted in lexicographic order, according to the match level, then // the description. final String key = matchLevelString + "." + description + "." + wordlistId; - final WordListPreference existingPref = prefList.get(key); + final WordListPreference existingPref = prefMap.get(key); if (null == existingPref || hasPriority(status, existingPref.mStatus)) { - final WordListPreference pref = new WordListPreference(activity, - mDictionaryListInterfaceState, mClientId, wordlistId, version, locale, - description, status, filesize); - prefList.put(key, pref); + final WordListPreference oldPreference = mCurrentPreferenceMap.get(key); + final WordListPreference pref; + if (null != oldPreference + && oldPreference.mVersion == version + && oldPreference.mLocale.equals(locale)) { + // If the old preference has all the new attributes, reuse it. We test + // for version and locale because although attributes other than status + // need to be the same, others have been tested through the key of the + // map. Also, status may differ so we don't want to use #equals() here. + pref = oldPreference; + pref.mStatus = status; + } else { + // Otherwise, discard it and create a new one instead. + pref = new WordListPreference(activity, mDictionaryListInterfaceState, + mClientId, wordlistId, version, locale, description, status, + filesize); + } + prefMap.put(key, pref); } } while (cursor.moveToNext()); cursor.close(); - return prefList.values(); + mCurrentPreferenceMap = prefMap; + return prefMap.values(); } } diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java index 29015d61b..451a0fb82 100644 --- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java +++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java @@ -58,6 +58,8 @@ public final class WordListPreference extends Preference { // The metadata word list id and version of this word list. public final String mWordlistId; public final int mVersion; + public final Locale mLocale; + public final String mDescription; // The status public int mStatus; // The size of the dictionary file @@ -80,6 +82,8 @@ public final class WordListPreference extends Preference { mVersion = version; mWordlistId = wordlistId; mFilesize = filesize; + mLocale = locale; + mDescription = description; setLayoutResource(R.layout.dictionary_line); |