aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/res/xml/spellchecker.xml2
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java145
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/WordListPreference.java6
3 files changed, 149 insertions, 4 deletions
diff --git a/java/res/xml/spellchecker.xml b/java/res/xml/spellchecker.xml
index 813319c7b..13e6132f1 100644
--- a/java/res/xml/spellchecker.xml
+++ b/java/res/xml/spellchecker.xml
@@ -21,7 +21,7 @@
for the spell checker -->
<spell-checker xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/aosp_spell_checker_service_name"
+ android:label="@string/spell_checker_service_name"
android:settingsActivity="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity">
<subtype
android:label="@string/subtype_generic"
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
index 39cfb60ff..307749121 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
@@ -16,11 +16,28 @@
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;
import android.widget.ProgressBar;
public class DictionaryDownloadProgressBar extends ProgressBar {
+ @SuppressWarnings("unused")
+ private static final String TAG = DictionaryDownloadProgressBar.class.getSimpleName();
+ private static final int NOT_A_DOWNLOADMANAGER_PENDING_ID = 0;
+
+ private String mClientId;
+ private String mWordlistId;
+ private boolean mIsCurrentlyAttachedToWindow = false;
+ private Thread mReporterThread = null;
+
public DictionaryDownloadProgressBar(final Context context) {
super(context);
}
@@ -28,4 +45,132 @@ public class DictionaryDownloadProgressBar extends ProgressBar {
public DictionaryDownloadProgressBar(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
+
+ public void setIds(final String clientId, final String wordlistId) {
+ mClientId = clientId;
+ mWordlistId = wordlistId;
+ }
+
+ static private int getDownloadManagerPendingIdFromWordlistId(final Context context,
+ final String clientId, final String wordlistId) {
+ final SQLiteDatabase db = MetadataDbHelper.getDb(context, clientId);
+ final ContentValues wordlistValues =
+ MetadataDbHelper.getContentValuesOfLatestAvailableWordlistById(db, wordlistId);
+ if (null == wordlistValues) {
+ // We don't know anything about a word list with this id. Bug? This should never
+ // happen, but still return to prevent a crash.
+ Log.e(TAG, "Unexpected word list ID: " + wordlistId);
+ return NOT_A_DOWNLOADMANAGER_PENDING_ID;
+ }
+ return wordlistValues.getAsInteger(MetadataDbHelper.PENDINGID_COLUMN);
+ }
+
+ /*
+ * This method will stop any running updater thread for this progress bar and create and run
+ * a new one only if the progress bar is visible.
+ * Hence, as a result of calling this method, the progress bar will have an updater thread
+ * running if and only if the progress bar is visible.
+ */
+ private void updateReporterThreadRunningStatusAccordingToVisibility() {
+ if (null != mReporterThread) mReporterThread.interrupt();
+ if (mIsCurrentlyAttachedToWindow && View.VISIBLE == getVisibility()) {
+ final int downloadManagerPendingId =
+ getDownloadManagerPendingIdFromWordlistId(getContext(), mClientId, mWordlistId);
+ if (NOT_A_DOWNLOADMANAGER_PENDING_ID == downloadManagerPendingId) {
+ // Can't get the ID. This is never supposed to happen, but still clear the updater
+ // thread and return to avoid a crash.
+ mReporterThread = null;
+ return;
+ }
+ final UpdaterThread updaterThread =
+ new UpdaterThread(getContext(), downloadManagerPendingId);
+ updaterThread.start();
+ mReporterThread = updaterThread;
+ } else {
+ // We're not going to restart the thread anyway, so we may as well garbage collect it.
+ mReporterThread = null;
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ mIsCurrentlyAttachedToWindow = true;
+ updateReporterThreadRunningStatusAccordingToVisibility();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mIsCurrentlyAttachedToWindow = false;
+ updateReporterThreadRunningStatusAccordingToVisibility();
+ }
+
+ 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 Context context, final int id) {
+ super();
+ mDownloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
+ mId = id;
+ }
+ @Override
+ public void run() {
+ try {
+ // 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;
+ 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() {
+ 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/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index 1340a41fc..29015d61b 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -24,7 +24,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ListView;
-import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.inputmethod.latin.R;
@@ -195,9 +194,10 @@ public final class WordListPreference extends Preference {
super.onBindView(view);
((ViewGroup)view).setLayoutTransition(null);
- final ProgressBar progressBar =
- (ProgressBar)view.findViewById(R.id.dictionary_line_progress_bar);
+ final DictionaryDownloadProgressBar progressBar =
+ (DictionaryDownloadProgressBar)view.findViewById(R.id.dictionary_line_progress_bar);
final TextView status = (TextView)view.findViewById(android.R.id.summary);
+ progressBar.setIds(mClientId, mWordlistId);
progressBar.setMax(mFilesize);
final boolean showProgressBar = (MetadataDbHelper.STATUS_DOWNLOADING == mStatus);
status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);