diff options
Diffstat (limited to 'java')
20 files changed, 149 insertions, 64 deletions
diff --git a/java/proguard.flags b/java/proguard.flags index 4da182b1f..c08a968bc 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -1,16 +1,16 @@ # Keep classes and methods that have the @UsedForTesting annotation -keep @com.android.inputmethod.annotations.UsedForTesting class * -keepclassmembers class * { -@com.android.inputmethod.annotations.UsedForTesting *; + @com.android.inputmethod.annotations.UsedForTesting *; } # Keep classes and methods that have the @ExternallyReferenced annotation -keep @com.android.inputmethod.annotations.ExternallyReferenced class * -keepclassmembers class * { -@com.android.inputmethod.annotations.ExternallyReferenced *; + @com.android.inputmethod.annotations.ExternallyReferenced *; } # Keep native methods --keep class * { -native <methods>; +-keepclassmembers class * { + native <methods>; } diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict Binary files differindex a59f7823e..5d35e64a2 100644 --- a/java/res/raw/main_de.dict +++ b/java/res/raw/main_de.dict diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict Binary files differindex 086874dd6..120e19b60 100644 --- a/java/res/raw/main_en.dict +++ b/java/res/raw/main_en.dict diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict Binary files differindex ac15d3992..efc507532 100644 --- a/java/res/raw/main_es.dict +++ b/java/res/raw/main_es.dict diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict Binary files differindex 9044c7e9e..fb43a1a18 100644 --- a/java/res/raw/main_fr.dict +++ b/java/res/raw/main_fr.dict diff --git a/java/res/raw/main_it.dict b/java/res/raw/main_it.dict Binary files differindex e289cefbe..523f645c7 100644 --- a/java/res/raw/main_it.dict +++ b/java/res/raw/main_it.dict diff --git a/java/res/raw/main_ru.dict b/java/res/raw/main_ru.dict Binary files differindex 3e23617c2..86c368eb9 100644 --- a/java/res/raw/main_ru.dict +++ b/java/res/raw/main_ru.dict diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 321e80611..4b5d02716 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -439,7 +439,6 @@ public final class BinaryDictionaryFileDumper { final ContentProviderClient client, final String clientId) throws RemoteException { final String metadataFileUri = MetadataFileUriGetter.getMetadataUri(context); final String metadataAdditionalId = MetadataFileUriGetter.getMetadataAdditionalId(context); - if (TextUtils.isEmpty(metadataFileUri)) return; // Tell the content provider to reset all information about this client id final Uri metadataContentUri = getProviderUriBuilder(clientId) .appendPath(QUERY_PATH_METADATA) diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index d0af59db0..51dc85295 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -19,11 +19,9 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetFileDescriptor; import android.util.Log; -import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.utils.CollectionUtils; @@ -293,13 +291,8 @@ final public class BinaryDictionaryGetter { final Context context) { final boolean hasDefaultWordList = DictionaryFactory.isDictionaryAvailable(context, locale); - // We need internet access to do the following. Only do this if the package actually - // has the permission. - if (context.checkCallingOrSelfPermission(android.Manifest.permission.INTERNET) - == PackageManager.PERMISSION_GRANTED) { - BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context, - hasDefaultWordList); - } + BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context, + hasDefaultWordList); final File[] cachedWordLists = getCachedWordLists(locale.toString(), context); final String mainDictId = DictionaryInfoUtils.getMainDictId(locale); final DictPackSettings dictPackSettings = new DictPackSettings(context); diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index d1cb39cd9..01ec7f9a7 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -16,21 +16,16 @@ package com.android.inputmethod.latin; -import android.content.Context; import android.content.SharedPreferences; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.Process; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; -import android.util.Log; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.latin.utils.Utils; -import com.android.inputmethod.research.ResearchLogger; public final class DebugSettings extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { diff --git a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java index 18f4920d9..47d9bf34d 100644 --- a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java +++ b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.os.Environment; @@ -59,7 +60,7 @@ public class ExternalDictionaryGetterForDebug { if (0 == fileNames.length) { showNoFileDialog(context); } else if (1 == fileNames.length) { - askInstallFile(context, fileNames[0]); + askInstallFile(context, SOURCE_FOLDER, fileNames[0], null /* completeRunnable */); } else { showChooseFileDialog(context, fileNames); } @@ -82,14 +83,19 @@ public class ExternalDictionaryGetterForDebug { .setItems(fileNames, new OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { - askInstallFile(context, fileNames[which]); + askInstallFile(context, SOURCE_FOLDER, fileNames[which], + null /* completeRunnable */); } }) .create().show(); } - private static void askInstallFile(final Context context, final String fileName) { - final File file = new File(SOURCE_FOLDER, fileName.toString()); + /** + * Shows a dialog which offers the user to install the external dictionary. + */ + public static void askInstallFile(final Context context, final String dirPath, + final String fileName, final Runnable completeRunnable) { + final File file = new File(dirPath, fileName.toString()); final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file); final StringBuilder message = new StringBuilder(); final String locale = header.getLocaleString(); @@ -109,12 +115,26 @@ public class ExternalDictionaryGetterForDebug { @Override public void onClick(final DialogInterface dialog, final int which) { dialog.dismiss(); + if (completeRunnable != null) { + completeRunnable.run(); + } } }).setPositiveButton(android.R.string.ok, new OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { installFile(context, file, header); dialog.dismiss(); + if (completeRunnable != null) { + completeRunnable.run(); + } + } + }).setOnCancelListener(new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + // Canceled by the user by hitting the back key + if (completeRunnable != null) { + completeRunnable.run(); + } } }).create().show(); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c867436e5..0560cf528 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -43,7 +43,6 @@ import android.os.Message; import android.os.SystemClock; import android.preference.PreferenceManager; import android.text.InputType; -import android.text.Spanned; import android.text.TextUtils; import android.text.style.SuggestionSpan; import android.util.Log; @@ -778,6 +777,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // span, so we should reset our state unconditionally, even if restarting is true. mEnteredText = null; resetComposingState(true /* alsoResetLastComposedWord */); + if (isDifferentTextField) mHandler.postResumeSuggestions(); mDeleteCount = 0; mSpaceState = SPACE_STATE_NONE; mRecapitalizeStatus.deactivate(); @@ -2522,21 +2522,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int numberOfCharsInWordBeforeCursor = range.getNumberOfCharsInWordBeforeCursor(); if (numberOfCharsInWordBeforeCursor > mLastSelectionStart) return; final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); - final CharSequence word = range.mWord; - final String typedWord = word.toString(); - if (word instanceof Spanned) { - final Spanned spanned = (Spanned)word; - int i = 0; - for (Object object : spanned.getSpans(0, spanned.length(), - SuggestionSpan.class)) { - SuggestionSpan span = (SuggestionSpan)object; - for (String s : span.getSuggestions()) { - ++i; - if (!TextUtils.equals(s, typedWord)) { - suggestions.add(new SuggestedWordInfo(s, - SuggestionStripView.MAX_SUGGESTIONS - i, - SuggestedWordInfo.KIND_RESUMED, Dictionary.TYPE_RESUMED)); - } + final String typedWord = range.mWord.toString(); + int i = 0; + for (final SuggestionSpan span : range.getSuggestionSpansAtWord()) { + for (final String s : span.getSuggestions()) { + ++i; + if (!TextUtils.equals(s, typedWord)) { + suggestions.add(new SuggestedWordInfo(s, + SuggestionStripView.MAX_SUGGESTIONS - i, + SuggestedWordInfo.KIND_RESUMED, Dictionary.TYPE_RESUMED)); } } } diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 5391b1303..6b22cb12e 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -17,7 +17,9 @@ package com.android.inputmethod.latin; import android.inputmethodservice.InputMethodService; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.SuggestionSpan; import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; @@ -32,6 +34,7 @@ import com.android.inputmethod.latin.utils.DebugLogUtils; import com.android.inputmethod.latin.utils.StringUtils; import com.android.inputmethod.research.ResearchLogger; +import java.util.Arrays; import java.util.Locale; import java.util.regex.Pattern; @@ -457,6 +460,66 @@ public final class RichInputConnection { return mWordAtCursorEndIndex - mCursorIndex; } + /** + * Gets the suggestion spans that are put squarely on the word, with the exact start + * and end of the span matching the boundaries of the word. + * @return the list of spans. + */ + public SuggestionSpan[] getSuggestionSpansAtWord() { + if (!(mTextAtCursor instanceof Spanned && mWord instanceof Spanned)) { + return new SuggestionSpan[0]; + } + final Spanned text = (Spanned)mTextAtCursor; + // Note: it's fine to pass indices negative or greater than the length of the string + // to the #getSpans() method. The reason we need to get from -1 to +1 is that, the + // spans were cut at the cursor position, and #getSpans(start, end) does not return + // spans that end at `start' or begin at `end'. Consider the following case: + // this| is (The | symbolizes the cursor position + // ---- --- + // In this case, the cursor is in position 4, so the 0~7 span has been split into + // a 0~4 part and a 4~7 part. + // If we called #getSpans(0, 4) in this case, we would only get the part from 0 to 4 + // of the span, and not the part from 4 to 7, so we would not realize the span actually + // extends from 0 to 7. But if we call #getSpans(-1, 5) we'll get both the 0~4 and + // the 4~7 spans and we can merge them accordingly. + // Any span starting more than 1 char away from the word boundaries in any direction + // does not touch the word, so we don't need to consider it. That's why requesting + // -1 ~ +1 is enough. + // Of course this is only relevant if the cursor is at one end of the word. If it's + // in the middle, the -1 and +1 are not necessary, but they are harmless. + final SuggestionSpan[] spans = text.getSpans(mWordAtCursorStartIndex - 1, + mWordAtCursorEndIndex + 1, SuggestionSpan.class); + int readIndex = 0; + int writeIndex = 0; + for (; readIndex < spans.length; ++readIndex) { + final SuggestionSpan span = spans[readIndex]; + // The span may be null, as we null them when we find duplicates. Cf a few lines + // down. + if (null == span) continue; + // Tentative span start and end. This may be modified later if we realize the + // same span is also applied to other parts of the string. + int spanStart = text.getSpanStart(span); + int spanEnd = text.getSpanEnd(span); + for (int i = readIndex + 1; i < spans.length; ++i) { + if (span.equals(spans[i])) { + // We found the same span somewhere else. Read the new extent of this + // span, and adjust our values accordingly. + spanStart = Math.min(spanStart, text.getSpanStart(spans[i])); + spanEnd = Math.max(spanEnd, text.getSpanEnd(spans[i])); + // ...and mark the span as processed. + spans[i] = null; + } + } + if (spanStart == mWordAtCursorStartIndex && spanEnd == mWordAtCursorEndIndex) { + // If the span does not start and stop here, we ignore it. It probably extends + // past the start or end of the word, as happens in missing space correction + // or EasyEditSpans put by voice input. + spans[writeIndex++] = spans[readIndex]; + } + } + return writeIndex == readIndex ? spans : Arrays.copyOfRange(spans, 0, writeIndex); + } + public Range(final CharSequence textAtCursor, final int wordAtCursorStartIndex, final int wordAtCursorEndIndex, final int cursorIndex) { if (wordAtCursorStartIndex < 0 || cursorIndex < wordAtCursorStartIndex diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java index 46fa1913c..f52e56441 100644 --- a/java/src/com/android/inputmethod/latin/SettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java @@ -25,6 +25,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.media.AudioManager; +import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; @@ -51,7 +52,10 @@ import java.util.TreeSet; public final class SettingsFragment extends InputMethodSettingsFragment implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = SettingsFragment.class.getSimpleName(); - private static final boolean DBG_USE_INTERNAL_USER_DICTIONARY_SETTINGS = false; + private static final boolean DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = false; + private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS = + DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS + || Build.VERSION.SDK_INT <= 18 /* Build.VERSION.JELLY_BEAN_MR2 */; private ListPreference mVoicePreference; private ListPreference mShowCorrectionSuggestionsPreference; @@ -212,10 +216,11 @@ public final class SettingsFragment extends InputMethodSettingsFragment final Preference editPersonalDictionary = findPreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY); final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent(); - final ResolveInfo ri = context.getPackageManager().resolveActivity( - editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY); - if (DBG_USE_INTERNAL_USER_DICTIONARY_SETTINGS || ri == null) { - updateUserDictionaryPreference(editPersonalDictionary); + final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS ? null + : context.getPackageManager().resolveActivity( + editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY); + if (ri == null) { + overwriteUserDictionaryPreference(editPersonalDictionary); } if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) { @@ -470,7 +475,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment }); } - private void updateUserDictionaryPreference(Preference userDictionaryPreference) { + private void overwriteUserDictionaryPreference(Preference userDictionaryPreference) { final Activity activity = getActivity(); final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity); if (null == localeList) { diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 8eadf73b2..2d325a482 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -34,7 +34,7 @@ import java.util.Arrays; /** * When you call the constructor of this class, you may want to change the current system locale by - * using {@link LocaleUtils.RunInLocale}. + * using {@link com.android.inputmethod.latin.utils.LocaleUtils.RunInLocale}. */ public final class SettingsValues { private static final String TAG = SettingsValues.class.getSimpleName(); diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java index e7cf0d3af..37c390d13 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin.userdictionary; import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; @@ -25,10 +26,14 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.provider.UserDictionary; import android.text.TextUtils; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.utils.LocaleUtils; +import java.util.List; import java.util.Locale; import java.util.TreeSet; @@ -52,8 +57,7 @@ public class UserDictionaryList extends PreferenceFragment { final Cursor cursor = activity.managedQuery(UserDictionary.Words.CONTENT_URI, new String[] { UserDictionary.Words.LOCALE }, null, null, null); - final TreeSet<String> localeList = new TreeSet<String>(); - boolean addedAllLocale = false; + final TreeSet<String> localeSet = new TreeSet<String>(); if (null == cursor) { // The user dictionary service is not present or disabled. Return null. return null; @@ -61,20 +65,39 @@ public class UserDictionaryList extends PreferenceFragment { final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE); do { final String locale = cursor.getString(columnIndex); - final boolean allLocale = TextUtils.isEmpty(locale); - localeList.add(allLocale ? "" : locale); - if (allLocale) { - addedAllLocale = true; - } + localeSet.add(null != locale ? locale : ""); } while (cursor.moveToNext()); } - if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED && !addedAllLocale) { + if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { // For ICS, we need to show "For all languages" in case that the keyboard locale // is different from the system locale - localeList.add(""); + localeSet.add(""); + } + + final InputMethodManager imm = + (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); + final List<InputMethodInfo> imis = imm.getEnabledInputMethodList(); + for (final InputMethodInfo imi : imis) { + final List<InputMethodSubtype> subtypes = + imm.getEnabledInputMethodSubtypeList( + imi, true /* allowsImplicitlySelectedSubtypes */); + for (InputMethodSubtype subtype : subtypes) { + final String locale = subtype.getLocale(); + if (!TextUtils.isEmpty(locale)) { + localeSet.add(locale); + } + } + } + + // We come here after we have collected locales from existing user dictionary entries and + // enabled subtypes. If we already have the locale-without-country version of the system + // locale, we don't add the system locale to avoid confusion even though it's technically + // correct to add it. + if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) { + localeSet.add(Locale.getDefault().toString()); } - localeList.add(Locale.getDefault().toString()); - return localeList; + + return localeSet; } /** diff --git a/java/src/com/android/inputmethod/research/FeedbackActivity.java b/java/src/com/android/inputmethod/research/FeedbackActivity.java index b985fda21..520b88d2f 100644 --- a/java/src/com/android/inputmethod/research/FeedbackActivity.java +++ b/java/src/com/android/inputmethod/research/FeedbackActivity.java @@ -18,7 +18,6 @@ package com.android.inputmethod.research; import android.app.Activity; import android.os.Bundle; -import android.widget.CheckBox; import com.android.inputmethod.latin.R; diff --git a/java/src/com/android/inputmethod/research/FeedbackFragment.java b/java/src/com/android/inputmethod/research/FeedbackFragment.java index a0738292e..75fbbf1ba 100644 --- a/java/src/com/android/inputmethod/research/FeedbackFragment.java +++ b/java/src/com/android/inputmethod/research/FeedbackFragment.java @@ -16,7 +16,6 @@ package com.android.inputmethod.research; -import android.app.Activity; import android.app.Fragment; import android.os.Bundle; import android.text.Editable; diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java index fde2798e1..88207c024 100644 --- a/java/src/com/android/inputmethod/research/ResearchLog.java +++ b/java/src/com/android/inputmethod/research/ResearchLog.java @@ -27,7 +27,6 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.concurrent.Callable; import java.util.concurrent.Executors; diff --git a/java/src/com/android/inputmethod/research/UploaderService.java b/java/src/com/android/inputmethod/research/UploaderService.java index d2db34927..8bd46c19e 100644 --- a/java/src/com/android/inputmethod/research/UploaderService.java +++ b/java/src/com/android/inputmethod/research/UploaderService.java @@ -24,8 +24,6 @@ import android.content.Intent; import android.os.Bundle; import android.os.SystemClock; -import com.android.inputmethod.latin.define.ProductionFlag; - /** * Service to invoke the uploader. * @@ -33,8 +31,6 @@ import com.android.inputmethod.latin.define.ProductionFlag; */ public final class UploaderService extends IntentService { private static final String TAG = UploaderService.class.getSimpleName(); - private static final boolean DEBUG = false - && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG; public static final long RUN_INTERVAL = AlarmManager.INTERVAL_HOUR; public static final String EXTRA_UPLOAD_UNCONDITIONALLY = UploaderService.class.getName() + ".extra.UPLOAD_UNCONDITIONALLY"; |