Merge "Remove ref to LatinImeLogger preference."
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index e39ca18..fb973f3 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -57,14 +57,22 @@
<activity android:name=".setup.SetupActivity"
android:label="@string/english_ime_name"
android:icon="@mipmap/ic_launcher_keyboard"
- android:launchMode="singleTop"
- android:clearTaskOnLaunch="true">
+ android:launchMode="singleTask"
+ android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name=".setup.SetupWizardActivity"
+ android:label="@string/english_ime_name"
+ android:clearTaskOnLaunch="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+
<receiver android:name=".setup.LauncherIconVisibilityManager">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
diff --git a/java/res/layout/setup_wizard.xml b/java/res/layout/setup_wizard.xml
index 176f836..87db4d0 100644
--- a/java/res/layout/setup_wizard.xml
+++ b/java/res/layout/setup_wizard.xml
@@ -19,6 +19,7 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/setup_wizard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/setup_background"
diff --git a/java/res/layout/user_dictionary_add_word_fullscreen.xml b/java/res/layout/user_dictionary_add_word_fullscreen.xml
index 75e86c5..219485b 100644
--- a/java/res/layout/user_dictionary_add_word_fullscreen.xml
+++ b/java/res/layout/user_dictionary_add_word_fullscreen.xml
@@ -19,12 +19,6 @@
android:layout_height="wrap_content"
android:orientation="vertical" >
- <TextView
- style="?android:attr/listSeparatorTextViewStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/user_dict_settings_add_screen_title" />
-
<EditText
android:id="@+id/user_dictionary_add_word_text"
android:layout_width="match_parent"
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index dbf39c5..502355e 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -57,7 +57,7 @@
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"همیشه نمایش داده شود"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"نمایش در حالت عمودی"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"همیشه پنهان شود"</string>
- <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"مسدودکردن کلمات توهینآمیز"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"عدم نمایش کلمات توهینآمیز"</string>
<string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"کلمات توهینآمیز احتمالی پیشنهاد نشود"</string>
<string name="auto_correction" msgid="7630720885194996950">"تصحیح خودکار"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"کلید فاصله و علائم نگارشی به صورت خودکار کلماتی را که غلط تایپ شدهاند تصحیح میکنند"</string>
@@ -181,7 +181,7 @@
<string name="setup_steps_title" msgid="6400373034871816182">"راهاندازی <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step1_title" msgid="3147967630253462315">"فعالسازی <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step1_instruction" msgid="2578631936624637241">"لطفاً «<xliff:g id="APPLICATION_NAME">%s</xliff:g>» را در تنظیمات زبان و ورودی خود علامت بزنید. این کار مجوز اجرای آن در دستگاه شما است."</string>
- <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> در حال حاضر در تنظیمات زبان و ورودی شما فعال است، بنابراین این مرحله انجام شده است. به مرحله بعدی بروید!"</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> در حال حاضر در تنظیمات زبان و ورودی شما فعال است، بنابراین این مرحله انجام شده است. به مرحله بعد بروید!"</string>
<string name="setup_step1_action" msgid="4366513534999901728">"فعالسازی در تنظیمات"</string>
<string name="setup_step2_title" msgid="6860725447906690594">"جابجایی به <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step2_instruction" msgid="9141481964870023336">"در مرحله بعد، با انتخاب «<xliff:g id="APPLICATION_NAME">%s</xliff:g>» به عنوان روش ورودی نوشتار خود آن را فعال نمایید."</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index b12c36e..167b43b 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -24,9 +24,9 @@
<string name="english_ime_research_log" msgid="8492602295696577851">"Naplózási parancsok"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string>
<string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"A helyesírás-ellenőrző használja a névjegyek bejegyzéseit"</string>
- <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés billentyű megnyomása esetén"</string>
- <string name="sound_on_keypress" msgid="6093592297198243644">"Hangjelzés billentyű megnyomása esetén"</string>
- <string name="popup_on_keypress" msgid="123894815723512944">"Legyen nagyobb billentyű lenyomásakor"</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés gombnyomásra"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"Hangjelzés gombnyomásra"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"Nagyobb billentyű gombnyomásra"</string>
<string name="general_category" msgid="1859088467017573195">"Általános"</string>
<string name="correction_category" msgid="2236750915056607613">"Szövegjavítás"</string>
<string name="gesture_typing_category" msgid="497263612130532630">"Kézmozdulatokkal történő gépelés"</string>
@@ -124,7 +124,7 @@
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"A fő billentyűzeten"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Szimbólumoknál"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Ki"</string>
- <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. a billentyűzeten"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon a billentyűzeten"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. a szimbólumoknál"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hangbevivel KI"</string>
<string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string>
diff --git a/java/res/values-ms/strings-appname.xml b/java/res/values-ms/strings-appname.xml
new file mode 100644
index 0000000..1f9501a
--- /dev/null
+++ b/java/res/values-ms/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"Papan kekunci Android (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"Penyemak Ejaan Android (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"Tetapan Papan Kekunci Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Tetapan Penyemak Ejaan Android (AOSP)"</string>
+</resources>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index 6b6df5d..fe1a3cd 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -57,10 +57,8 @@
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Sentiasa tunjukkan"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Tunjukkan dalam mod potret"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sentiasa sembunyikan"</string>
- <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) -->
- <skip />
- <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) -->
- <skip />
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Sekat perkataan yg menyinggung"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Jangan cadangkan perkataan yang boleh menyinggung"</string>
<string name="auto_correction" msgid="7630720885194996950">"Auto pembetulan"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Bar ruang dan tanda baca secara automatik membetulkan perkataan yang ditaip salah"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Matikan"</string>
@@ -179,8 +177,7 @@
<string name="setup_steps_title" msgid="6400373034871816182">"Menyediakan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step1_title" msgid="3147967630253462315">"Dayakan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step1_instruction" msgid="2578631936624637241">"Sila semak \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" dlm ttpn Bhs & input. Ini mbnarkn apl djlnkn pd pranti anda."</string>
- <!-- no translation found for setup_step1_finished_instruction (10761482004957994) -->
- <skip />
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> sudah didayakan dlm ttpn Bahasa & input anda, jd langkah ini tlh selesai. Beralih ke langkah seterusnya!"</string>
<string name="setup_step1_action" msgid="4366513534999901728">"Dayakan dalam Tetapan"</string>
<string name="setup_step2_title" msgid="6860725447906690594">"Beralih ke <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step2_instruction" msgid="9141481964870023336">"Seterusnya, pilih \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" sebagai kaedah input teks aktif anda."</string>
@@ -222,42 +219,23 @@
<string name="dict_available_notification_description" msgid="1075194169443163487">"Tekan untuk mengulas dan memuat turun"</string>
<string name="toast_downloading_suggestions" msgid="1313027353588566660">"Memuat turun: cadangan untuk <xliff:g id="LANGUAGE">%1$s</xliff:g> akan sedia tidak lama lagi."</string>
<string name="version_text" msgid="2715354215568469385">"Versi <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
- <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) -->
- <skip />
- <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) -->
- <skip />
- <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) -->
- <skip />
- <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) -->
- <skip />
- <!-- no translation found for user_dict_settings_empty_text (558499587532668203) -->
- <skip />
- <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) -->
- <skip />
- <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) -->
- <skip />
- <!-- no translation found for user_dict_settings_delete (110413335187193859) -->
- <skip />
- <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) -->
- <skip />
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Tambah"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Tambah ke kamus"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Frasa"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Lagi pilihan"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Kurang pilihan"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OK"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Perkataan:"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Pintasan:"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Bahasa:"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Taip perkataan"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Pintasan pilihan"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Edit perkataan"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Edit"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Padam"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Anda tidak mempunyai sebarang perkataan dalam kamus pengguna. Tambah perkataan dengan menyentuh butang Tambah (+)."</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Untuk semua bahasa"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Lebih banyak bahasa..."</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"Padam"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
</resources>
diff --git a/java/res/values-pt/strings-appname.xml b/java/res/values-pt/strings-appname.xml
new file mode 100644
index 0000000..7180a0c
--- /dev/null
+++ b/java/res/values-pt/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"Teclado Android (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"Corretor ortográfico do Android (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"Configurações de teclado Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Configurações de corretor ortográfico do Android (AOSP)"</string>
+</resources>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index a58d16d..25592b1 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -57,10 +57,8 @@
<string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string>
<string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostrar em modo de retrato"</string>
<string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sempre ocultar"</string>
- <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) -->
- <skip />
- <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) -->
- <skip />
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquear palavras ofensivas"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Não sugerir palavras potencialmente ofensivas"</string>
<string name="auto_correction" msgid="7630720885194996950">"Correção automática"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"A barra de espaço e a pontuação corrigem automaticamente palavras com erro de digitação"</string>
<string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desativado"</string>
@@ -179,8 +177,7 @@
<string name="setup_steps_title" msgid="6400373034871816182">"Configurando o <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step1_title" msgid="3147967630253462315">"Ative o <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step1_instruction" msgid="2578631936624637241">"Marque \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" em \"Configurações de idioma e entrada\" para autorizar a execução."</string>
- <!-- no translation found for setup_step1_finished_instruction (10761482004957994) -->
- <skip />
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> já está ativado em suas configurações de idioma e entrada. Esta estapa está concluída. Vamos avançar para a próxima!"</string>
<string name="setup_step1_action" msgid="4366513534999901728">"Ativar em \"Configurações\""</string>
<string name="setup_step2_title" msgid="6860725447906690594">"Abra o <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="setup_step2_instruction" msgid="9141481964870023336">"Em seguida, selecione \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" como o método de entrada de texto ativo."</string>
@@ -222,42 +219,23 @@
<string name="dict_available_notification_description" msgid="1075194169443163487">"Pressione para consultar e fazer o download"</string>
<string name="toast_downloading_suggestions" msgid="1313027353588566660">"Download em andamento: as sugestões para <xliff:g id="LANGUAGE">%1$s</xliff:g> estarão prontas em breve."</string>
<string name="version_text" msgid="2715354215568469385">"Versão <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
- <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) -->
- <skip />
- <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) -->
- <skip />
- <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) -->
- <skip />
- <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) -->
- <skip />
- <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) -->
- <skip />
- <!-- no translation found for user_dict_settings_empty_text (558499587532668203) -->
- <skip />
- <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) -->
- <skip />
- <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) -->
- <skip />
- <!-- no translation found for user_dict_settings_delete (110413335187193859) -->
- <skip />
- <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) -->
- <skip />
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Adicionar"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Adicionar ao dicionário"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Frase"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Mais opções"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Menos opções"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"Ok"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Palavra:"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Atalho:"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Idioma:"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Digite uma palavra"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Atalho opcional"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Editar palavra"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Editar"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Excluir"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Você não possui palavras no dicionário do usuário. Adicione uma palavra tocando no botão \"Adicionar\" ou no símbolo \"+\"."</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Para todos os idiomas"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Mais idiomas..."</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"Excluir"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
</resources>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 06b99de..47f2132 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -124,7 +124,7 @@
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На основ. клавіатурі"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Символьна клавіатура"</string>
<string name="voice_input_modes_off" msgid="3745699748218082014">"Вимк."</string>
- <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Miкр. на осн. клав."</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Мікрофон на основній клавіатурі"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Miкр. на симв. клавіат."</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голос. ввід вимкнено"</string>
<string name="configure_input_method" msgid="373356270290742459">"Налаштування методів введення"</string>
diff --git a/java/res/values/keyboard-heights.xml b/java/res/values/keyboard-heights.xml
index 418d3e5..1c0277c 100644
--- a/java/res/values/keyboard-heights.xml
+++ b/java/res/values/keyboard-heights.xml
@@ -19,20 +19,20 @@
-->
<resources>
- <!-- Build.HARDWARE,keyboard_height_in_dp -->
+ <!-- Build condition,keyboard_height_in_dp -->
<string-array name="keyboard_heights" translatable="false">
<!-- Preferable keyboard height in absolute scale: 1.285in -->
<!-- Droid -->
- <item>sholes,227.0167</item>
+ <item>HARDWARE=sholes,227.0167</item>
<!-- Nexus One -->
- <item>mahimahi,217.5932</item>
+ <item>HARDWARE=mahimahi,217.5932</item>
<!-- Nexus S -->
- <item>herring,200.8554</item>
+ <item>HARDWARE=herring,200.8554</item>
<!-- Galaxy Nexus -->
- <item>tuna,202.5869</item>
+ <item>HARDWARE=tuna,202.5869</item>
<!-- Preferable keyboard height in absolute scale: 48.0mm -->
<!-- Xoom -->
- <item>stingray,283.1337</item>
+ <item>HARDWARE=stingray,283.1337</item>
<!-- Default value for unknown device: empty string -->
<item>DEFAULT,</item>
</string-array>
diff --git a/java/res/values/keypress-vibration-durations.xml b/java/res/values/keypress-vibration-durations.xml
index 10400be..45c51e7 100644
--- a/java/res/values/keypress-vibration-durations.xml
+++ b/java/res/values/keypress-vibration-durations.xml
@@ -18,16 +18,16 @@
*/
-->
<resources>
- <!-- Build.HARDWARE,duration_in_milliseconds -->
+ <!-- Build condition,duration_in_milliseconds -->
<string-array name="keypress_vibration_durations" translatable="false">
<!-- Nexus S -->
- <item>herring,5</item>
+ <item>HARDWARE=herring,5</item>
<!-- Galaxy Nexus -->
- <item>tuna,5</item>
+ <item>HARDWARE=tuna,5</item>
<!-- Nexus 4 -->
- <item>mako,5</item>
+ <item>HARDWARE=mako,5</item>
<!-- Nexus 10 -->
- <item>manta,16</item>
+ <item>HARDWARE=manta,16</item>
<!-- Default value for unknown device -->
<item>DEFAULT,20</item>
</string-array>
diff --git a/java/res/values/keypress-volumes.xml b/java/res/values/keypress-volumes.xml
index 047fe0c..7061f13 100644
--- a/java/res/values/keypress-volumes.xml
+++ b/java/res/values/keypress-volumes.xml
@@ -18,14 +18,14 @@
*/
-->
<resources>
+ <!-- Build condition,volume -->
<string-array name="keypress_volumes" translatable="false">
- <!-- Build.HARDWARE,volume -->
- <item>herring,0.5f</item>
- <item>tuna,0.5f</item>
- <item>stingray,0.4f</item>
- <item>grouper,0.3f</item>
- <item>mako,0.3f</item>
- <item>manta,0.2f</item>
+ <item>HARDWARE=herring,0.5f</item>
+ <item>HARDWARE=tuna,0.5f</item>
+ <item>HARDWARE=stingray,0.4f</item>
+ <item>HARDWARE=grouper,0.3f</item>
+ <item>HARDWARE=mako,0.3f</item>
+ <item>HARDWARE=manta,0.2f</item>
<!-- Default value for unknown device -->
<item>DEFAULT,0.2f</item>
</string-array>
diff --git a/java/res/values/phantom-sudden-move-event-device-list.xml b/java/res/values/phantom-sudden-move-event-device-list.xml
index 22f5102..d0895b1 100644
--- a/java/res/values/phantom-sudden-move-event-device-list.xml
+++ b/java/res/values/phantom-sudden-move-event-device-list.xml
@@ -19,10 +19,10 @@
-->
<resources>
<string-array name="phantom_sudden_move_event_device_list" translatable="false">
- <!-- "Build.HARDWARE,true" that needs "phantom sudden move event" hack.
+ <!-- "Build condition,true" that needs "phantom sudden move event" hack.
See {@link com.android.inputmethod.keyboard.PointerTracker}. -->
<!-- Xoom -->
- <item>stingray,true</item>
+ <item>HARDWARE=stingray,true</item>
<!-- Default value for unknown device -->
<item>DEFAULT,false</item>
</string-array>
diff --git a/java/res/values/sudden-jumping-touch-event-device-list.xml b/java/res/values/sudden-jumping-touch-event-device-list.xml
index 3fdc0c7..73e30c1 100644
--- a/java/res/values/sudden-jumping-touch-event-device-list.xml
+++ b/java/res/values/sudden-jumping-touch-event-device-list.xml
@@ -19,12 +19,12 @@
-->
<resources>
<string-array name="sudden_jumping_touch_event_device_list" translatable="false">
- <!-- "Build.HARDWARE,true" that needs "sudden jump touch event" hack.
+ <!-- "Build condition,true" that needs "sudden jump touch event" hack.
See {@link com.android.inputmethod.keyboard.SuddenJumpingTouchEventHandler}. -->
<!-- Nexus One -->
- <item>mahimahi,true</item>
+ <item>HARDWARE=mahimahi,true</item>
<!-- Droid -->
- <item>sholes,true</item>
+ <item>HARDWARE=sholes,true</item>
<!-- Default value for unknown device -->
<item>DEFAULT,false</item>
</string-array>
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index fb75d6d..6183223 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -66,6 +66,8 @@
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 @@
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 @@
// 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 29015d6..451a0fb 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -58,6 +58,8 @@
// 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 @@
mVersion = version;
mWordlistId = wordlistId;
mFilesize = filesize;
+ mLocale = locale;
+ mDescription = description;
setLayoutResource(R.layout.dictionary_line);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
index 7fd1bed..761d9dc 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -18,6 +18,7 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
@@ -35,12 +36,19 @@
* @attr ref R.styleable#MainKeyboardView_gesturePreviewTrailWidth
*/
final class GesturePreviewTrail {
+ public static final boolean DBG_SHOW_POINTS = false;
+ public static final int POINT_TYPE_SAMPLED = 0;
+ public static final int POINT_TYPE_INTERPOLATED = 1;
+ public static final int POINT_TYPE_COMPROMISED = 2;
+
private static final int DEFAULT_CAPACITY = GestureStrokeWithPreviewPoints.PREVIEW_CAPACITY;
// These three {@link ResizableIntArray}s should be synchronized by {@link #mEventTimes}.
private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY);
+ private final ResizableIntArray mPointTypes = new ResizableIntArray(
+ DBG_SHOW_POINTS ? DEFAULT_CAPACITY : 0);
private int mCurrentStrokeId = -1;
// The wall time of the zero value in {@link #mEventTimes}
private long mCurrentTimeBase;
@@ -75,9 +83,9 @@
R.styleable.MainKeyboardView_gesturePreviewTrailShadowRatio, 0);
mTrailShadowEnabled = (trailShadowRatioInt > 0);
mTrailShadowRatio = (float)trailShadowRatioInt / (float)PERCENTAGE_INT;
- mFadeoutStartDelay = mainKeyboardViewAttr.getInt(
+ mFadeoutStartDelay = DBG_SHOW_POINTS ? 2000 : mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_gesturePreviewTrailFadeoutStartDelay, 0);
- mFadeoutDuration = mainKeyboardViewAttr.getInt(
+ mFadeoutDuration = DBG_SHOW_POINTS ? 200 : mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_gesturePreviewTrailFadeoutDuration, 0);
mTrailLingerDuration = mFadeoutStartDelay + mFadeoutDuration;
mUpdateInterval = mainKeyboardViewAttr.getInt(
@@ -125,7 +133,7 @@
final int lastInterpolatedIndex = (strokeId == mCurrentStrokeId)
? mLastInterpolatedDrawIndex : trailSize;
mLastInterpolatedDrawIndex = stroke.interpolateStrokeAndReturnStartIndexOfLastSegment(
- lastInterpolatedIndex, mEventTimes, mXCoordinates, mYCoordinates);
+ lastInterpolatedIndex, mEventTimes, mXCoordinates, mYCoordinates, mPointTypes);
if (strokeId != mCurrentStrokeId) {
final int elapsedTime = (int)(downTime - mCurrentTimeBase);
for (int i = mTrailStartIndex; i < trailSize; i++) {
@@ -204,6 +212,7 @@
final int[] eventTimes = mEventTimes.getPrimitiveArray();
final int[] xCoords = mXCoordinates.getPrimitiveArray();
final int[] yCoords = mYCoordinates.getPrimitiveArray();
+ final int[] pointTypes = mPointTypes.getPrimitiveArray();
final int sinceDown = (int)(SystemClock.uptimeMillis() - mCurrentTimeBase);
int startIndex;
for (startIndex = mTrailStartIndex; startIndex < trailSize; startIndex++) {
@@ -246,6 +255,17 @@
final int alpha = getAlpha(elapsedTime, params);
paint.setAlpha(alpha);
canvas.drawPath(path, paint);
+ if (DBG_SHOW_POINTS) {
+ if (pointTypes[i] == POINT_TYPE_INTERPOLATED) {
+ paint.setColor(Color.RED);
+ } else if (pointTypes[i] == POINT_TYPE_SAMPLED) {
+ paint.setColor(0xFFA000FF);
+ } else {
+ paint.setColor(Color.GREEN);
+ }
+ canvas.drawCircle(p1x - 1, p1y - 1, 2, paint);
+ paint.setColor(params.mTrailColor);
+ }
}
}
p1x = p2x;
@@ -265,6 +285,9 @@
mEventTimes.setLength(newSize);
mXCoordinates.setLength(newSize);
mYCoordinates.setLength(newSize);
+ if (DBG_SHOW_POINTS) {
+ mPointTypes.setLength(newSize);
+ }
// The start index of the last segment of the stroke
// {@link mLastInterpolatedDrawIndex} should also be updated because all array
// elements have just been shifted for compaction or been zeroed.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
index 93ff264..70363e6 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
@@ -145,7 +145,7 @@
public void setKeyboardGeometry(final int keyWidth, final int keyboardHeight) {
mKeyWidth = keyWidth;
mMinYCoordinate = -(int)(keyboardHeight * EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO);
- mMaxYCoordinate = keyboardHeight - 1;
+ mMaxYCoordinate = keyboardHeight;
// TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key?
mDetectFastMoveSpeedThreshold = (int)(keyWidth * mParams.mDetectFastMoveSpeedThreshold);
mGestureDynamicDistanceThresholdFrom =
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
index 312fd21..ccb8802 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
@@ -152,7 +152,7 @@
*/
public int interpolateStrokeAndReturnStartIndexOfLastSegment(final int lastInterpolatedIndex,
final ResizableIntArray eventTimes, final ResizableIntArray xCoords,
- final ResizableIntArray yCoords) {
+ final ResizableIntArray yCoords, final ResizableIntArray types) {
final int size = mPreviewEventTimes.getLength();
final int[] pt = mPreviewEventTimes.getPrimitiveArray();
final int[] px = mPreviewXCoordinates.getPrimitiveArray();
@@ -189,11 +189,17 @@
eventTimes.add(d1, (int)(dt * t) + t1);
xCoords.add(d1, (int)mInterpolator.mInterpolatedX);
yCoords.add(d1, (int)mInterpolator.mInterpolatedY);
+ if (GesturePreviewTrail.DBG_SHOW_POINTS) {
+ types.add(d1, GesturePreviewTrail.POINT_TYPE_INTERPOLATED);
+ }
d1++;
}
eventTimes.add(d1, pt[p2]);
xCoords.add(d1, px[p2]);
yCoords.add(d1, py[p2]);
+ if (GesturePreviewTrail.DBG_SHOW_POINTS) {
+ types.add(d1, GesturePreviewTrail.POINT_TYPE_SAMPLED);
+ }
}
return lastInterpolatedDrawIndex;
}
diff --git a/java/src/com/android/inputmethod/latin/ResourceUtils.java b/java/src/com/android/inputmethod/latin/ResourceUtils.java
index b74b979..f0bfe75 100644
--- a/java/src/com/android/inputmethod/latin/ResourceUtils.java
+++ b/java/src/com/android/inputmethod/latin/ResourceUtils.java
@@ -35,8 +35,7 @@
// This utility class is not publicly instantiable.
}
- private static final String DEFAULT_PREFIX = "DEFAULT,";
- private static final String HARDWARE_PREFIX = Build.HARDWARE + ",";
+ private static final String DEFAULT_KEY = "DEFAULT";
private static final HashMap<String, String> sDeviceOverrideValueMap =
CollectionUtils.newHashMap();
@@ -48,28 +47,29 @@
}
final String[] overrideArray = res.getStringArray(overrideResId);
- final String overrideValue = StringUtils.findPrefixedString(HARDWARE_PREFIX, overrideArray);
+ final String hardwareKey = "HARDWARE=" + Build.HARDWARE;
+ final String overrideValue = StringUtils.findValueOfKey(hardwareKey, overrideArray);
// The overrideValue might be an empty string.
if (overrideValue != null) {
if (DEBUG) {
Log.d(TAG, "Find override value:"
+ " resource="+ res.getResourceEntryName(overrideResId)
- + " Build.HARDWARE=" + Build.HARDWARE + " override=" + overrideValue);
+ + " " + hardwareKey + " override=" + overrideValue);
}
sDeviceOverrideValueMap.put(key, overrideValue);
return overrideValue;
}
- final String defaultValue = StringUtils.findPrefixedString(DEFAULT_PREFIX, overrideArray);
+ final String defaultValue = StringUtils.findValueOfKey(DEFAULT_KEY, overrideArray);
// The defaultValue might be an empty string.
if (defaultValue == null) {
Log.w(TAG, "Couldn't find override value nor default value:"
+ " resource="+ res.getResourceEntryName(overrideResId)
- + " Build.HARDWARE=" + Build.HARDWARE);
+ + " " + hardwareKey);
} else if (DEBUG) {
Log.d(TAG, "Found default value:"
+ " resource="+ res.getResourceEntryName(overrideResId)
- + " Build.HARDWARE=" + Build.HARDWARE + " default=" + defaultValue);
+ + " " + hardwareKey + " " + DEFAULT_KEY + "=" + defaultValue);
}
sDeviceOverrideValueMap.put(key, defaultValue);
return defaultValue;
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index d5ee58a..5ff101f 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -65,17 +65,24 @@
}
/**
- * Find a string that start with specified prefix from an array.
+ * Find a value that has a specified key from an array of key-comma-value.
*
- * @param prefix a prefix string to find.
- * @param array an string array to be searched.
- * @return the rest part of the string that starts with the prefix.
+ * @param key a key string to find.
+ * @param array an array of key-comma-value string to be searched.
+ * @return the value part of the first string that has a specified key.
* Returns null if it couldn't be found.
*/
- public static String findPrefixedString(final String prefix, final String[] array) {
+ public static String findValueOfKey(final String key, final String[] array) {
+ if (array == null) {
+ return null;
+ }
for (final String element : array) {
- if (element.startsWith(prefix)) {
- return element.substring(prefix.length());
+ final int posComma = element.indexOf(',');
+ if (posComma < 0) {
+ throw new RuntimeException("Element has no comma: " + element);
+ }
+ if (element.substring(0, posComma).equals(key)) {
+ return element.substring(posComma + 1);
}
}
return null;
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index acb0766..8a2de88 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -17,265 +17,27 @@
package com.android.inputmethod.latin.setup;
import android.app.Activity;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Resources;
-import android.media.MediaPlayer;
-import android.net.Uri;
import android.os.Bundle;
-import android.os.Message;
import android.provider.Settings;
-import android.util.Log;
-import android.view.View;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.VideoView;
-import com.android.inputmethod.compat.TextViewCompatUtils;
-import com.android.inputmethod.compat.ViewCompatUtils;
-import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.SettingsActivity;
-import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
-import java.util.ArrayList;
-
-// TODO: Use Fragment to implement welcome screen and setup steps.
-public final class SetupActivity extends Activity implements View.OnClickListener {
- private static final String TAG = SetupActivity.class.getSimpleName();
-
- private View mWelcomeScreen;
- private View mSetupScreen;
- private Uri mWelcomeVideoUri;
- private VideoView mWelcomeVideoView;
- private View mActionStart;
- private View mActionNext;
- private TextView mStep1Bullet;
- private TextView mActionFinish;
- private SetupStepGroup mSetupStepGroup;
- private static final String STATE_STEP = "step";
- private int mStepNumber;
- private static final int STEP_WELCOME = 0;
- private static final int STEP_1 = 1;
- private static final int STEP_2 = 2;
- private static final int STEP_3 = 3;
- private boolean mWasLanguageAndInputSettingsInvoked;
-
- private final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this);
-
- static final class SettingsPoolingHandler extends StaticInnerHandlerWrapper<SetupActivity> {
- private static final int MSG_POLLING_IME_SETTINGS = 0;
- private static final long IME_SETTINGS_POLLING_INTERVAL = 200;
-
- public SettingsPoolingHandler(final SetupActivity outerInstance) {
- super(outerInstance);
- }
-
- @Override
- public void handleMessage(final Message msg) {
- final SetupActivity setupActivity = getOuterInstance();
- if (setupActivity == null) {
- return;
- }
- switch (msg.what) {
- case MSG_POLLING_IME_SETTINGS:
- if (SetupActivity.isThisImeEnabled(setupActivity)) {
- setupActivity.invokeSetupWizardOfThisIme();
- return;
- }
- startPollingImeSettings();
- break;
- }
- }
-
- public void startPollingImeSettings() {
- sendMessageDelayed(obtainMessage(MSG_POLLING_IME_SETTINGS),
- IME_SETTINGS_POLLING_INTERVAL);
- }
-
- public void cancelPollingImeSettings() {
- removeMessages(MSG_POLLING_IME_SETTINGS);
- }
- }
-
+public final class SetupActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
- setTheme(android.R.style.Theme_DeviceDefault_Light_NoActionBar);
super.onCreate(savedInstanceState);
-
- setContentView(R.layout.setup_wizard);
-
- RichInputMethodManager.init(this);
-
- if (savedInstanceState == null) {
- mStepNumber = determineSetupStepNumber();
- if (mStepNumber == STEP_1 && !mWasLanguageAndInputSettingsInvoked) {
- mStepNumber = STEP_WELCOME;
- }
- if (mStepNumber == STEP_3) {
- // This IME already has been enabled and set as current IME.
- // TODO: Implement tutorial.
- invokeSettingsOfThisIme();
- finish();
- return;
- }
- } else {
- mStepNumber = savedInstanceState.getInt(STATE_STEP);
- }
-
- final String applicationName = getResources().getString(getApplicationInfo().labelRes);
- mWelcomeScreen = findViewById(R.id.setup_welcome_screen);
- final TextView welcomeTitle = (TextView)findViewById(R.id.setup_welcome_title);
- welcomeTitle.setText(getString(R.string.setup_welcome_title, applicationName));
-
- mSetupScreen = findViewById(R.id.setup_steps_screen);
- final TextView stepsTitle = (TextView)findViewById(R.id.setup_title);
- stepsTitle.setText(getString(R.string.setup_steps_title, applicationName));
-
- final SetupStepIndicatorView indicatorView =
- (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
- mSetupStepGroup = new SetupStepGroup(indicatorView);
-
- mStep1Bullet = (TextView)findViewById(R.id.setup_step1_bullet);
- mStep1Bullet.setOnClickListener(this);
- final SetupStep step1 = new SetupStep(STEP_1, applicationName,
- mStep1Bullet, findViewById(R.id.setup_step1),
- R.string.setup_step1_title, R.string.setup_step1_instruction,
- R.string.setup_step1_finished_instruction, R.drawable.ic_setup_step1,
- R.string.setup_step1_action);
- step1.setAction(new Runnable() {
- @Override
- public void run() {
- invokeLanguageAndInputSettings();
- mHandler.startPollingImeSettings();
- }
- });
- mSetupStepGroup.addStep(step1);
-
- final SetupStep step2 = new SetupStep(STEP_2, applicationName,
- (TextView)findViewById(R.id.setup_step2_bullet), findViewById(R.id.setup_step2),
- R.string.setup_step2_title, R.string.setup_step2_instruction,
- 0 /* finishedInstruction */, R.drawable.ic_setup_step2,
- R.string.setup_step2_action);
- step2.setAction(new Runnable() {
- @Override
- public void run() {
- // Invoke input method picker.
- RichInputMethodManager.getInstance().getInputMethodManager()
- .showInputMethodPicker();
- }
- });
- mSetupStepGroup.addStep(step2);
-
- final SetupStep step3 = new SetupStep(STEP_3, applicationName,
- (TextView)findViewById(R.id.setup_step3_bullet), findViewById(R.id.setup_step3),
- R.string.setup_step3_title, R.string.setup_step3_instruction,
- 0 /* finishedInstruction */, R.drawable.ic_setup_step3,
- R.string.setup_step3_action);
- step3.setAction(new Runnable() {
- @Override
- public void run() {
- invokeSubtypeEnablerOfThisIme();
- }
- });
- mSetupStepGroup.addStep(step3);
-
- mWelcomeVideoUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(getPackageName())
- .path(Integer.toString(R.raw.setup_welcome_video))
- .build();
- mWelcomeVideoView = (VideoView)findViewById(R.id.setup_welcome_video);
- mWelcomeVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(final MediaPlayer mp) {
- // Now VideoView has been laid-out and ready to play, remove background of it to
- // reveal the video.
- mWelcomeVideoView.setBackgroundResource(0);
- mp.setLooping(true);
- }
- });
- final ImageView welcomeImageView = (ImageView)findViewById(R.id.setup_welcome_image);
- mWelcomeVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(final MediaPlayer mp, final int what, final int extra) {
- Log.e(TAG, "Playing welcome video causes error: what=" + what + " extra=" + extra);
- mWelcomeVideoView.setVisibility(View.GONE);
- welcomeImageView.setImageResource(R.raw.setup_welcome_image);
- welcomeImageView.setVisibility(View.VISIBLE);
- return true;
- }
- });
-
- mActionStart = findViewById(R.id.setup_start_label);
- mActionStart.setOnClickListener(this);
- mActionNext = findViewById(R.id.setup_next);
- mActionNext.setOnClickListener(this);
- mActionFinish = (TextView)findViewById(R.id.setup_finish);
- TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mActionFinish,
- getResources().getDrawable(R.drawable.ic_setup_finish), null, null, null);
- mActionFinish.setOnClickListener(this);
- }
-
- @Override
- public void onClick(final View v) {
- if (v == mActionFinish) {
+ final Intent intent = new Intent();
+ intent.setClass(this, SetupWizardActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ if (!isFinishing()) {
finish();
- return;
}
- final int currentStep = determineSetupStepNumber();
- final int nextStep;
- if (v == mActionStart) {
- nextStep = STEP_1;
- } else if (v == mActionNext) {
- nextStep = mStepNumber + 1;
- } else if (v == mStep1Bullet && currentStep == STEP_2) {
- nextStep = STEP_1;
- } else {
- nextStep = mStepNumber;
- }
- if (mStepNumber != nextStep) {
- mStepNumber = nextStep;
- updateSetupStepView();
- }
- }
-
- private void invokeSetupWizardOfThisIme() {
- final Intent intent = new Intent();
- intent.setClass(this, SetupActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- }
-
- private void invokeSettingsOfThisIme() {
- final Intent intent = new Intent();
- intent.setClass(this, SettingsActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- }
-
- private void invokeLanguageAndInputSettings() {
- final Intent intent = new Intent();
- intent.setAction(Settings.ACTION_INPUT_METHOD_SETTINGS);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- startActivity(intent);
- mWasLanguageAndInputSettingsInvoked = true;
- }
-
- private void invokeSubtypeEnablerOfThisIme() {
- final InputMethodInfo imi =
- RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme();
- final Intent intent = new Intent();
- intent.setAction(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imi.getId());
- startActivity(intent);
}
/**
@@ -312,170 +74,4 @@
context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
return myImi.getId().equals(currentImeId);
}
-
- private int determineSetupStepNumber() {
- mHandler.cancelPollingImeSettings();
- if (!isThisImeEnabled(this)) {
- return STEP_1;
- }
- if (!isThisImeCurrent(this)) {
- return STEP_2;
- }
- return STEP_3;
- }
-
- @Override
- protected void onSaveInstanceState(final Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt(STATE_STEP, mStepNumber);
- }
-
- @Override
- protected void onRestoreInstanceState(final Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- mStepNumber = savedInstanceState.getInt(STATE_STEP);
- }
-
- @Override
- protected void onRestart() {
- super.onRestart();
- if (mStepNumber != STEP_WELCOME) {
- mStepNumber = determineSetupStepNumber();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- updateSetupStepView();
- }
-
- @Override
- public void onBackPressed() {
- if (mStepNumber == STEP_1) {
- mStepNumber = STEP_WELCOME;
- updateSetupStepView();
- return;
- }
- super.onBackPressed();
- }
-
- private static void hideAndStopVideo(final VideoView videoView) {
- videoView.stopPlayback();
- videoView.setVisibility(View.INVISIBLE);
- }
-
- @Override
- protected void onPause() {
- hideAndStopVideo(mWelcomeVideoView);
- super.onPause();
- }
-
- @Override
- public void onWindowFocusChanged(final boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- if (hasFocus && mStepNumber != STEP_WELCOME) {
- mStepNumber = determineSetupStepNumber();
- updateSetupStepView();
- }
- }
-
- private void updateSetupStepView() {
- final boolean welcomeScreen = (mStepNumber == STEP_WELCOME);
- mWelcomeScreen.setVisibility(welcomeScreen ? View.VISIBLE : View.GONE);
- mSetupScreen.setVisibility(welcomeScreen ? View.GONE: View.VISIBLE);
- if (welcomeScreen) {
- mWelcomeVideoView.setVisibility(View.VISIBLE);
- mWelcomeVideoView.setVideoURI(mWelcomeVideoUri);
- mWelcomeVideoView.start();
- return;
- }
- hideAndStopVideo(mWelcomeVideoView);
- final boolean isStepActionAlreadyDone = mStepNumber < determineSetupStepNumber();
- mSetupStepGroup.enableStep(mStepNumber, isStepActionAlreadyDone);
- mActionNext.setVisibility(isStepActionAlreadyDone ? View.VISIBLE : View.GONE);
- mActionFinish.setVisibility((mStepNumber == STEP_3) ? View.VISIBLE : View.GONE);
- }
-
- static final class SetupStep implements View.OnClickListener {
- public final int mStepNo;
- private final View mStepView;
- private final TextView mBulletView;
- private final int mActivatedColor;
- private final int mDeactivatedColor;
- private final String mInstruction;
- private final String mFinishedInstruction;
- private final TextView mActionLabel;
- private Runnable mAction;
-
- public SetupStep(final int stepNo, final String applicationName, final TextView bulletView,
- final View stepView, final int title, final int instruction,
- final int finishedInstruction,final int actionIcon, final int actionLabel) {
- mStepNo = stepNo;
- mStepView = stepView;
- mBulletView = bulletView;
- final Resources res = stepView.getResources();
- mActivatedColor = res.getColor(R.color.setup_text_action);
- mDeactivatedColor = res.getColor(R.color.setup_text_dark);
-
- final TextView titleView = (TextView)mStepView.findViewById(R.id.setup_step_title);
- titleView.setText(res.getString(title, applicationName));
- mInstruction = (instruction == 0) ? null
- : res.getString(instruction, applicationName);
- mFinishedInstruction = (finishedInstruction == 0) ? null
- : res.getString(finishedInstruction, applicationName);
-
- mActionLabel = (TextView)mStepView.findViewById(R.id.setup_step_action_label);
- mActionLabel.setText(res.getString(actionLabel));
- if (actionIcon == 0) {
- final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
- ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
- } else {
- TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(
- mActionLabel, res.getDrawable(actionIcon), null, null, null);
- }
- }
-
- public void setEnabled(final boolean enabled, final boolean isStepActionAlreadyDone) {
- mStepView.setVisibility(enabled ? View.VISIBLE : View.GONE);
- mBulletView.setTextColor(enabled ? mActivatedColor : mDeactivatedColor);
- final TextView instructionView = (TextView)mStepView.findViewById(
- R.id.setup_step_instruction);
- instructionView.setText(isStepActionAlreadyDone ? mFinishedInstruction : mInstruction);
- mActionLabel.setVisibility(isStepActionAlreadyDone ? View.GONE : View.VISIBLE);
- }
-
- public void setAction(final Runnable action) {
- mActionLabel.setOnClickListener(this);
- mAction = action;
- }
-
- @Override
- public void onClick(final View v) {
- if (v == mActionLabel && mAction != null) {
- mAction.run();
- return;
- }
- }
- }
-
- static final class SetupStepGroup {
- private final SetupStepIndicatorView mIndicatorView;
- private final ArrayList<SetupStep> mGroup = CollectionUtils.newArrayList();
-
- public SetupStepGroup(final SetupStepIndicatorView indicatorView) {
- mIndicatorView = indicatorView;
- }
-
- public void addStep(final SetupStep step) {
- mGroup.add(step);
- }
-
- public void enableStep(final int enableStepNo, final boolean isStepActionAlreadyDone) {
- for (final SetupStep step : mGroup) {
- step.setEnabled(step.mStepNo == enableStepNo, isStepActionAlreadyDone);
- }
- mIndicatorView.setIndicatorPosition(enableStepNo - STEP_1, mGroup.size());
- }
- }
}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
new file mode 100644
index 0000000..3406ecf
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.android.inputmethod.latin.setup;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.VideoView;
+
+import com.android.inputmethod.compat.TextViewCompatUtils;
+import com.android.inputmethod.compat.ViewCompatUtils;
+import com.android.inputmethod.latin.CollectionUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.SettingsActivity;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+
+import java.util.ArrayList;
+
+// TODO: Use Fragment to implement welcome screen and setup steps.
+public final class SetupWizardActivity extends Activity implements View.OnClickListener {
+ static final String TAG = SetupWizardActivity.class.getSimpleName();
+
+ private View mSetupWizard;
+ private View mWelcomeScreen;
+ private View mSetupScreen;
+ private Uri mWelcomeVideoUri;
+ private VideoView mWelcomeVideoView;
+ private View mActionStart;
+ private View mActionNext;
+ private TextView mStep1Bullet;
+ private TextView mActionFinish;
+ private SetupStepGroup mSetupStepGroup;
+ private static final String STATE_STEP = "step";
+ private int mStepNumber;
+ private static final int STEP_WELCOME = 0;
+ private static final int STEP_1 = 1;
+ private static final int STEP_2 = 2;
+ private static final int STEP_3 = 3;
+ private static final int STEP_LAUNCHING_IME_SETTINGS = 4;
+ private static final int STEP_BACK_FROM_IME_SETTINGS = 5;
+
+ final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this);
+
+ static final class SettingsPoolingHandler
+ extends StaticInnerHandlerWrapper<SetupWizardActivity> {
+ private static final int MSG_POLLING_IME_SETTINGS = 0;
+ private static final long IME_SETTINGS_POLLING_INTERVAL = 200;
+
+ public SettingsPoolingHandler(final SetupWizardActivity outerInstance) {
+ super(outerInstance);
+ }
+
+ @Override
+ public void handleMessage(final Message msg) {
+ final SetupWizardActivity setupWizardActivity = getOuterInstance();
+ if (setupWizardActivity == null) {
+ return;
+ }
+ switch (msg.what) {
+ case MSG_POLLING_IME_SETTINGS:
+ if (SetupActivity.isThisImeEnabled(setupWizardActivity)) {
+ setupWizardActivity.invokeSetupWizardOfThisIme();
+ return;
+ }
+ startPollingImeSettings();
+ break;
+ }
+ }
+
+ public void startPollingImeSettings() {
+ sendMessageDelayed(obtainMessage(MSG_POLLING_IME_SETTINGS),
+ IME_SETTINGS_POLLING_INTERVAL);
+ }
+
+ public void cancelPollingImeSettings() {
+ removeMessages(MSG_POLLING_IME_SETTINGS);
+ }
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ setTheme(android.R.style.Theme_Translucent_NoTitleBar);
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.setup_wizard);
+ mSetupWizard = findViewById(R.id.setup_wizard);
+
+ RichInputMethodManager.init(this);
+
+ if (savedInstanceState == null) {
+ mStepNumber = determineSetupStepNumberFromLauncher();
+ } else {
+ mStepNumber = savedInstanceState.getInt(STATE_STEP);
+ }
+
+ final String applicationName = getResources().getString(getApplicationInfo().labelRes);
+ mWelcomeScreen = findViewById(R.id.setup_welcome_screen);
+ final TextView welcomeTitle = (TextView)findViewById(R.id.setup_welcome_title);
+ welcomeTitle.setText(getString(R.string.setup_welcome_title, applicationName));
+
+ mSetupScreen = findViewById(R.id.setup_steps_screen);
+ final TextView stepsTitle = (TextView)findViewById(R.id.setup_title);
+ stepsTitle.setText(getString(R.string.setup_steps_title, applicationName));
+
+ final SetupStepIndicatorView indicatorView =
+ (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
+ mSetupStepGroup = new SetupStepGroup(indicatorView);
+
+ mStep1Bullet = (TextView)findViewById(R.id.setup_step1_bullet);
+ mStep1Bullet.setOnClickListener(this);
+ final SetupStep step1 = new SetupStep(STEP_1, applicationName,
+ mStep1Bullet, findViewById(R.id.setup_step1),
+ R.string.setup_step1_title, R.string.setup_step1_instruction,
+ R.string.setup_step1_finished_instruction, R.drawable.ic_setup_step1,
+ R.string.setup_step1_action);
+ step1.setAction(new Runnable() {
+ @Override
+ public void run() {
+ invokeLanguageAndInputSettings();
+ mHandler.startPollingImeSettings();
+ }
+ });
+ mSetupStepGroup.addStep(step1);
+
+ final SetupStep step2 = new SetupStep(STEP_2, applicationName,
+ (TextView)findViewById(R.id.setup_step2_bullet), findViewById(R.id.setup_step2),
+ R.string.setup_step2_title, R.string.setup_step2_instruction,
+ 0 /* finishedInstruction */, R.drawable.ic_setup_step2,
+ R.string.setup_step2_action);
+ step2.setAction(new Runnable() {
+ @Override
+ public void run() {
+ // Invoke input method picker.
+ RichInputMethodManager.getInstance().getInputMethodManager()
+ .showInputMethodPicker();
+ }
+ });
+ mSetupStepGroup.addStep(step2);
+
+ final SetupStep step3 = new SetupStep(STEP_3, applicationName,
+ (TextView)findViewById(R.id.setup_step3_bullet), findViewById(R.id.setup_step3),
+ R.string.setup_step3_title, R.string.setup_step3_instruction,
+ 0 /* finishedInstruction */, R.drawable.ic_setup_step3,
+ R.string.setup_step3_action);
+ step3.setAction(new Runnable() {
+ @Override
+ public void run() {
+ invokeSubtypeEnablerOfThisIme();
+ }
+ });
+ mSetupStepGroup.addStep(step3);
+
+ mWelcomeVideoUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(getPackageName())
+ .path(Integer.toString(R.raw.setup_welcome_video))
+ .build();
+ final VideoView welcomeVideoView = (VideoView)findViewById(R.id.setup_welcome_video);
+ welcomeVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(final MediaPlayer mp) {
+ // Now VideoView has been laid-out and ready to play, remove background of it to
+ // reveal the video.
+ welcomeVideoView.setBackgroundResource(0);
+ mp.setLooping(true);
+ }
+ });
+ final ImageView welcomeImageView = (ImageView)findViewById(R.id.setup_welcome_image);
+ welcomeVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+ @Override
+ public boolean onError(final MediaPlayer mp, final int what, final int extra) {
+ Log.e(TAG, "Playing welcome video causes error: what=" + what + " extra=" + extra);
+ welcomeVideoView.setVisibility(View.GONE);
+ welcomeImageView.setImageResource(R.raw.setup_welcome_image);
+ welcomeImageView.setVisibility(View.VISIBLE);
+ return true;
+ }
+ });
+ mWelcomeVideoView = welcomeVideoView;
+
+ mActionStart = findViewById(R.id.setup_start_label);
+ mActionStart.setOnClickListener(this);
+ mActionNext = findViewById(R.id.setup_next);
+ mActionNext.setOnClickListener(this);
+ mActionFinish = (TextView)findViewById(R.id.setup_finish);
+ TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mActionFinish,
+ getResources().getDrawable(R.drawable.ic_setup_finish), null, null, null);
+ mActionFinish.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(final View v) {
+ if (v == mActionFinish) {
+ finish();
+ return;
+ }
+ final int currentStep = determineSetupStepNumber();
+ final int nextStep;
+ if (v == mActionStart) {
+ nextStep = STEP_1;
+ } else if (v == mActionNext) {
+ nextStep = mStepNumber + 1;
+ } else if (v == mStep1Bullet && currentStep == STEP_2) {
+ nextStep = STEP_1;
+ } else {
+ nextStep = mStepNumber;
+ }
+ if (mStepNumber != nextStep) {
+ mStepNumber = nextStep;
+ updateSetupStepView();
+ }
+ }
+
+ void invokeSetupWizardOfThisIme() {
+ final Intent intent = new Intent();
+ intent.setClass(this, SetupWizardActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ }
+
+ private void invokeSettingsOfThisIme() {
+ final Intent intent = new Intent();
+ intent.setClass(this, SettingsActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ }
+
+ void invokeLanguageAndInputSettings() {
+ final Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_INPUT_METHOD_SETTINGS);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ startActivity(intent);
+ }
+
+ void invokeSubtypeEnablerOfThisIme() {
+ final InputMethodInfo imi =
+ RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme();
+ final Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imi.getId());
+ startActivity(intent);
+ }
+
+ private int determineSetupStepNumberFromLauncher() {
+ final int stepNumber = determineSetupStepNumber();
+ if (stepNumber == STEP_1) {
+ return STEP_WELCOME;
+ }
+ if (stepNumber == STEP_3) {
+ return STEP_LAUNCHING_IME_SETTINGS;
+ }
+ return stepNumber;
+ }
+
+ private int determineSetupStepNumber() {
+ mHandler.cancelPollingImeSettings();
+ if (!SetupActivity.isThisImeEnabled(this)) {
+ return STEP_1;
+ }
+ if (!SetupActivity.isThisImeCurrent(this)) {
+ return STEP_2;
+ }
+ return STEP_3;
+ }
+
+ @Override
+ protected void onSaveInstanceState(final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_STEP, mStepNumber);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(final Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ mStepNumber = savedInstanceState.getInt(STATE_STEP);
+ }
+
+ private static boolean isInSetupSteps(final int stepNumber) {
+ return stepNumber >= STEP_1 && stepNumber <= STEP_3;
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ if (isInSetupSteps(mStepNumber)) {
+ mStepNumber = determineSetupStepNumber();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mStepNumber == STEP_LAUNCHING_IME_SETTINGS) {
+ // Prevent white screen flashing while launching settings activity.
+ mSetupWizard.setVisibility(View.INVISIBLE);
+ invokeSettingsOfThisIme();
+ mStepNumber = STEP_BACK_FROM_IME_SETTINGS;
+ return;
+ }
+ if (mStepNumber == STEP_BACK_FROM_IME_SETTINGS) {
+ finish();
+ return;
+ }
+ updateSetupStepView();
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (mStepNumber == STEP_1) {
+ mStepNumber = STEP_WELCOME;
+ updateSetupStepView();
+ return;
+ }
+ super.onBackPressed();
+ }
+
+ private static void hideAndStopVideo(final VideoView videoView) {
+ videoView.stopPlayback();
+ videoView.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ protected void onPause() {
+ hideAndStopVideo(mWelcomeVideoView);
+ super.onPause();
+ }
+
+ @Override
+ public void onWindowFocusChanged(final boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (hasFocus && isInSetupSteps(mStepNumber)) {
+ mStepNumber = determineSetupStepNumber();
+ updateSetupStepView();
+ }
+ }
+
+ private void updateSetupStepView() {
+ mSetupWizard.setVisibility(View.VISIBLE);
+ final boolean welcomeScreen = (mStepNumber == STEP_WELCOME);
+ mWelcomeScreen.setVisibility(welcomeScreen ? View.VISIBLE : View.GONE);
+ mSetupScreen.setVisibility(welcomeScreen ? View.GONE : View.VISIBLE);
+ if (welcomeScreen) {
+ mWelcomeVideoView.setVisibility(View.VISIBLE);
+ mWelcomeVideoView.setVideoURI(mWelcomeVideoUri);
+ mWelcomeVideoView.start();
+ return;
+ }
+ hideAndStopVideo(mWelcomeVideoView);
+ final boolean isStepActionAlreadyDone = mStepNumber < determineSetupStepNumber();
+ mSetupStepGroup.enableStep(mStepNumber, isStepActionAlreadyDone);
+ mActionNext.setVisibility(isStepActionAlreadyDone ? View.VISIBLE : View.GONE);
+ mActionFinish.setVisibility((mStepNumber == STEP_3) ? View.VISIBLE : View.GONE);
+ }
+
+ static final class SetupStep implements View.OnClickListener {
+ public final int mStepNo;
+ private final View mStepView;
+ private final TextView mBulletView;
+ private final int mActivatedColor;
+ private final int mDeactivatedColor;
+ private final String mInstruction;
+ private final String mFinishedInstruction;
+ private final TextView mActionLabel;
+ private Runnable mAction;
+
+ public SetupStep(final int stepNo, final String applicationName, final TextView bulletView,
+ final View stepView, final int title, final int instruction,
+ final int finishedInstruction, final int actionIcon, final int actionLabel) {
+ mStepNo = stepNo;
+ mStepView = stepView;
+ mBulletView = bulletView;
+ final Resources res = stepView.getResources();
+ mActivatedColor = res.getColor(R.color.setup_text_action);
+ mDeactivatedColor = res.getColor(R.color.setup_text_dark);
+
+ final TextView titleView = (TextView)mStepView.findViewById(R.id.setup_step_title);
+ titleView.setText(res.getString(title, applicationName));
+ mInstruction = (instruction == 0) ? null
+ : res.getString(instruction, applicationName);
+ mFinishedInstruction = (finishedInstruction == 0) ? null
+ : res.getString(finishedInstruction, applicationName);
+
+ mActionLabel = (TextView)mStepView.findViewById(R.id.setup_step_action_label);
+ mActionLabel.setText(res.getString(actionLabel));
+ if (actionIcon == 0) {
+ final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
+ ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
+ } else {
+ TextViewCompatUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ mActionLabel, res.getDrawable(actionIcon), null, null, null);
+ }
+ }
+
+ public void setEnabled(final boolean enabled, final boolean isStepActionAlreadyDone) {
+ mStepView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ mBulletView.setTextColor(enabled ? mActivatedColor : mDeactivatedColor);
+ final TextView instructionView = (TextView)mStepView.findViewById(
+ R.id.setup_step_instruction);
+ instructionView.setText(isStepActionAlreadyDone ? mFinishedInstruction : mInstruction);
+ mActionLabel.setVisibility(isStepActionAlreadyDone ? View.GONE : View.VISIBLE);
+ }
+
+ public void setAction(final Runnable action) {
+ mActionLabel.setOnClickListener(this);
+ mAction = action;
+ }
+
+ @Override
+ public void onClick(final View v) {
+ if (v == mActionLabel && mAction != null) {
+ mAction.run();
+ return;
+ }
+ }
+ }
+
+ static final class SetupStepGroup {
+ private final SetupStepIndicatorView mIndicatorView;
+ private final ArrayList<SetupStep> mGroup = CollectionUtils.newArrayList();
+
+ public SetupStepGroup(final SetupStepIndicatorView indicatorView) {
+ mIndicatorView = indicatorView;
+ }
+
+ public void addStep(final SetupStep step) {
+ mGroup.add(step);
+ }
+
+ public void enableStep(final int enableStepNo, final boolean isStepActionAlreadyDone) {
+ for (final SetupStep step : mGroup) {
+ step.setEnabled(step.mStepNo == enableStepNo, isStepActionAlreadyDone);
+ }
+ mIndicatorView.setIndicatorPosition(enableStepNo - STEP_1, mGroup.size());
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index cd2f994..c8242c8 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -149,18 +149,18 @@
private static final ResearchLogger sInstance = new ResearchLogger();
private static String sAccountType = null;
private static String sAllowedAccountDomain = null;
- /* package */ ResearchLog mMainResearchLog;
+ private ResearchLog mMainResearchLog; // always non-null after init() is called
// mFeedbackLog records all events for the session, private or not (excepting
// passwords). It is written to permanent storage only if the user explicitly commands
// the system to do so.
// LogUnits are queued in the LogBuffers and published to the ResearchLogs when words are
// complete.
- /* package */ MainLogBuffer mMainLogBuffer;
+ /* package for test */ MainLogBuffer mMainLogBuffer; // always non-null after init() is called
// TODO: Remove the feedback log. The feedback log continuously captured user data in case the
// user wanted to submit it. We now use the mUserRecordingLogBuffer to allow the user to
// explicitly reproduce a problem.
- /* package */ ResearchLog mFeedbackLog;
- /* package */ LogBuffer mFeedbackLogBuffer;
+ private ResearchLog mFeedbackLog;
+ private LogBuffer mFeedbackLogBuffer;
/* package */ ResearchLog mUserRecordingLog;
/* package */ LogBuffer mUserRecordingLogBuffer;
private File mUserRecordingFile = null;
@@ -240,6 +240,9 @@
mResearchLogDirectory = new ResearchLogDirectory(mLatinIME);
cleanLogDirectoryIfNeeded(mResearchLogDirectory, System.currentTimeMillis());
+ // Initialize log buffers
+ resetLogBuffers();
+
// Initialize external services
mUploadIntent = new Intent(mLatinIME, UploaderService.class);
mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
@@ -251,6 +254,39 @@
mReplayer.setKeyboardSwitcher(keyboardSwitcher);
}
+ private void resetLogBuffers() {
+ mMainResearchLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
+ System.currentTimeMillis(), System.nanoTime()), mLatinIME);
+ final int numWordsToIgnore = new Random().nextInt(NUMBER_OF_WORDS_BETWEEN_SAMPLES + 1);
+ mMainLogBuffer = new MainLogBuffer(NUMBER_OF_WORDS_BETWEEN_SAMPLES, numWordsToIgnore,
+ mSuggest) {
+ @Override
+ protected void publish(final ArrayList<LogUnit> logUnits,
+ boolean canIncludePrivateData) {
+ canIncludePrivateData |= IS_LOGGING_EVERYTHING;
+ for (final LogUnit logUnit : logUnits) {
+ if (DEBUG) {
+ final String wordsString = logUnit.getWordsAsString();
+ Log.d(TAG, "onPublish: '" + wordsString
+ + "', hc: " + logUnit.containsCorrection()
+ + ", cipd: " + canIncludePrivateData);
+ }
+ for (final String word : logUnit.getWordsAsStringArray()) {
+ final Dictionary dictionary = getDictionary();
+ mStatistics.recordWordEntered(
+ dictionary != null && dictionary.isValidWord(word),
+ logUnit.containsCorrection());
+ }
+ }
+ publishLogUnits(logUnits, mMainResearchLog, canIncludePrivateData);
+ }
+ };
+
+ mFeedbackLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
+ System.currentTimeMillis(), System.nanoTime()), mLatinIME);
+ mFeedbackLogBuffer = new FixedLogBuffer(FEEDBACK_WORD_BUFFER_SIZE);
+ }
+
private void cleanLogDirectoryIfNeeded(final ResearchLogDirectory researchLogDirectory,
final long now) {
final long lastCleanupTime = ResearchSettings.readResearchLastDirCleanupTime(mPrefs);
@@ -379,49 +415,6 @@
requestIndicatorRedraw();
mStatistics.reset();
checkForEmptyEditor();
- if (mFeedbackLogBuffer == null) {
- resetFeedbackLogging();
- }
- if (!isAllowedToLog()) {
- // Log.w(TAG, "not in usability mode; not logging");
- return;
- }
- if (mMainLogBuffer == null) {
- mMainResearchLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
- System.currentTimeMillis(), System.nanoTime()), mLatinIME);
- final int numWordsToIgnore = new Random().nextInt(NUMBER_OF_WORDS_BETWEEN_SAMPLES + 1);
- mMainLogBuffer = new MainLogBuffer(NUMBER_OF_WORDS_BETWEEN_SAMPLES, numWordsToIgnore,
- mSuggest) {
- @Override
- protected void publish(final ArrayList<LogUnit> logUnits,
- boolean canIncludePrivateData) {
- canIncludePrivateData |= IS_LOGGING_EVERYTHING;
- for (final LogUnit logUnit : logUnits) {
- if (DEBUG) {
- final String wordsString = logUnit.getWordsAsString();
- Log.d(TAG, "onPublish: '" + wordsString
- + "', hc: " + logUnit.containsCorrection()
- + ", cipd: " + canIncludePrivateData);
- }
- for (final String word : logUnit.getWordsAsStringArray()) {
- final Dictionary dictionary = getDictionary();
- mStatistics.recordWordEntered(
- dictionary != null && dictionary.isValidWord(word),
- logUnit.containsCorrection());
- }
- }
- if (mMainResearchLog != null) {
- publishLogUnits(logUnits, mMainResearchLog, canIncludePrivateData);
- }
- }
- };
- }
- }
-
- private void resetFeedbackLogging() {
- mFeedbackLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
- System.currentTimeMillis(), System.nanoTime()), mLatinIME);
- mFeedbackLogBuffer = new FixedLogBuffer(FEEDBACK_WORD_BUFFER_SIZE);
}
/* package */ void stop() {
@@ -431,35 +424,27 @@
// Commit mCurrentLogUnit before closing.
commitCurrentLogUnit();
- if (mMainLogBuffer != null) {
- mMainLogBuffer.shiftAndPublishAll();
- logStatistics();
- commitCurrentLogUnit();
- mMainLogBuffer.setIsStopping();
- mMainLogBuffer.shiftAndPublishAll();
- mMainResearchLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
- mMainLogBuffer = null;
- }
- if (mFeedbackLogBuffer != null) {
- mFeedbackLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
- mFeedbackLogBuffer = null;
- }
+ mMainLogBuffer.shiftAndPublishAll();
+ logStatistics();
+ commitCurrentLogUnit();
+ mMainLogBuffer.setIsStopping();
+ mMainLogBuffer.shiftAndPublishAll();
+ mMainResearchLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
+ mFeedbackLog.blockingClose(RESEARCHLOG_CLOSE_TIMEOUT_IN_MS);
+
+ resetLogBuffers();
}
public void abort() {
if (DEBUG) {
Log.d(TAG, "abort called");
}
- if (mMainLogBuffer != null) {
- mMainLogBuffer.clear();
- mMainResearchLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
- mMainLogBuffer = null;
- }
- if (mFeedbackLogBuffer != null) {
- mFeedbackLogBuffer.clear();
- mFeedbackLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
- mFeedbackLogBuffer = null;
- }
+ mMainLogBuffer.clear();
+ mMainResearchLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
+ mFeedbackLogBuffer.clear();
+ mFeedbackLog.blockingAbort(RESEARCHLOG_ABORT_TIMEOUT_IN_MS);
+
+ resetLogBuffers();
}
private void restart() {
@@ -740,8 +725,8 @@
public void initSuggest(final Suggest suggest) {
mSuggest = suggest;
- // MainLogBuffer has out-of-date Suggest object. Need to close it down and create a new
- // one.
+ // MainLogBuffer now has an out-of-date Suggest object. Close down MainLogBuffer and create
+ // a new one.
if (mMainLogBuffer != null) {
stop();
start();
@@ -852,9 +837,7 @@
": " + mCurrentLogUnit.getWordsAsString() : ""));
}
if (!mCurrentLogUnit.isEmpty()) {
- if (mMainLogBuffer != null) {
- mMainLogBuffer.shiftIn(mCurrentLogUnit);
- }
+ mMainLogBuffer.shiftIn(mCurrentLogUnit);
if (mFeedbackLogBuffer != null) {
mFeedbackLogBuffer.shiftIn(mCurrentLogUnit);
}
@@ -882,9 +865,6 @@
//
// Note that we don't use mLastLogUnit here, because it only goes one word back and is only
// needed for reverts, which only happen one back.
- if (mMainLogBuffer == null) {
- return;
- }
final LogUnit oldLogUnit = mMainLogBuffer.peekLastLogUnit();
// Check that expected word matches.
@@ -938,6 +918,7 @@
final ResearchLog researchLog, final boolean canIncludePrivateData) {
final LogUnit openingLogUnit = new LogUnit();
if (logUnits.isEmpty()) return;
+ if (!isAllowedToLog()) return;
// LogUnits not containing private data, such as contextual data for the log, do not require
// logSegment boundary statements.
if (canIncludePrivateData) {
@@ -1371,11 +1352,7 @@
public static void latinIME_promotePhantomSpace() {
final ResearchLogger researchLogger = getInstance();
final LogUnit logUnit;
- if (researchLogger.mMainLogBuffer == null) {
- logUnit = researchLogger.mCurrentLogUnit;
- } else {
- logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
- }
+ logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_PROMOTEPHANTOMSPACE);
}
@@ -1392,11 +1369,7 @@
final String charactersAfterSwap) {
final ResearchLogger researchLogger = getInstance();
final LogUnit logUnit;
- if (researchLogger.mMainLogBuffer == null) {
- logUnit = null;
- } else {
- logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
- }
+ logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
if (logUnit != null) {
researchLogger.enqueueEvent(logUnit, LOGSTATEMENT_LATINIME_SWAPSWAPPERANDSPACE,
originalCharacters, charactersAfterSwap);
@@ -1469,11 +1442,7 @@
final ResearchLogger researchLogger = getInstance();
// TODO: Verify that mCurrentLogUnit has been restored and contains the reverted word.
final LogUnit logUnit;
- if (researchLogger.mMainLogBuffer == null) {
- logUnit = null;
- } else {
- logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
- }
+ logUnit = researchLogger.mMainLogBuffer.peekLastLogUnit();
if (originallyTypedWord.length() > 0 && hasLetters(originallyTypedWord)) {
if (logUnit != null) {
logUnit.setWords(originallyTypedWord);
diff --git a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
index 1e3cc8a..b6a17a3 100644
--- a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
@@ -237,4 +237,63 @@
// code for now True is acceptable.
assertTrue(StringUtils.lastPartLooksLikeURL(".abc/def"));
}
+
+ public void testFindValueOfKey() {
+ final String nullKey = null;
+ final String emptyKey = "";
+
+ final String[] nullArray = null;
+ assertNull(StringUtils.findValueOfKey("anyKey", nullArray));
+ assertNull(StringUtils.findValueOfKey(emptyKey, nullArray));
+ assertNull(StringUtils.findValueOfKey(nullKey, nullArray));
+
+ final String[] emptyArray = {};
+ assertNull(StringUtils.findValueOfKey("anyKey", emptyArray));
+ assertNull(StringUtils.findValueOfKey(emptyKey, emptyArray));
+ assertNull(StringUtils.findValueOfKey(nullKey, emptyArray));
+
+ final String[] array = {
+ "DEFAULT,defaultValue",
+ "HARDWARE=grouper,0.3",
+ "HARDWARE=mako,0.4",
+ "HARDWARE=manta,0.2"
+ };
+ assertEquals(StringUtils.findValueOfKey("HARDWARE=grouper", array), "0.3");
+ assertEquals(StringUtils.findValueOfKey("HARDWARE=mako", array), "0.4");
+ assertEquals(StringUtils.findValueOfKey("HARDWARE=manta", array), "0.2");
+ assertEquals(StringUtils.findValueOfKey("DEFAULT", array), "defaultValue");
+
+ assertNull(StringUtils.findValueOfKey("hardware=grouper", array));
+ assertNull(StringUtils.findValueOfKey("HARDWARE=MAKO", array));
+ assertNull(StringUtils.findValueOfKey("HARDWARE=mantaray", array));
+ assertNull(StringUtils.findValueOfKey(emptyKey, array));
+ assertNull(StringUtils.findValueOfKey(nullKey, array));
+
+ final String[] containsNullKey = {
+ "DEFAULT,defaultValue",
+ ",emptyValue"
+ };
+ assertEquals(StringUtils.findValueOfKey(emptyKey, containsNullKey), "emptyValue");
+
+ final String[] containsMultipleSameKeys = {
+ "key1,value1",
+ "key2,value2",
+ "key3,value3",
+ "key2,value4"
+ };
+ assertEquals(StringUtils.findValueOfKey("key2", containsMultipleSameKeys), "value2");
+
+ final String[] containNoCommaElement = {
+ "key1,value1",
+ "key2-and-value2",
+ "key3,value3"
+ };
+ assertEquals(StringUtils.findValueOfKey("key1", containNoCommaElement), "value1");
+ try {
+ final String valueOfKey3 = StringUtils.findValueOfKey("key3", containNoCommaElement);
+ fail("finding valueOfKey3=" + valueOfKey3 + " must fail");
+ } catch (final RuntimeException e) {
+ assertEquals(e.getMessage(), "Element has no comma: key2-and-value2");
+ }
+ }
}