| /* |
| * Copyright (C) 2011 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.settings.inputmethod; |
| |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.content.pm.ApplicationInfo; |
| import android.os.Bundle; |
| import android.provider.Settings; |
| import android.util.Log; |
| import android.view.textservice.SpellCheckerInfo; |
| import android.view.textservice.SpellCheckerSubtype; |
| import android.view.textservice.TextServicesManager; |
| import android.widget.Switch; |
| |
| import androidx.appcompat.app.AlertDialog; |
| import androidx.preference.Preference; |
| import androidx.preference.Preference.OnPreferenceChangeListener; |
| import androidx.preference.Preference.OnPreferenceClickListener; |
| import androidx.preference.PreferenceScreen; |
| |
| import com.android.internal.logging.nano.MetricsProto.MetricsEvent; |
| import com.android.settings.R; |
| import com.android.settings.SettingsActivity; |
| import com.android.settings.SettingsPreferenceFragment; |
| import com.android.settings.widget.SwitchBar; |
| import com.android.settings.widget.SwitchBar.OnSwitchChangeListener; |
| |
| public class SpellCheckersSettings extends SettingsPreferenceFragment |
| implements OnSwitchChangeListener, OnPreferenceClickListener, OnPreferenceChangeListener { |
| private static final String TAG = SpellCheckersSettings.class.getSimpleName(); |
| private static final boolean DBG = false; |
| |
| private static final String KEY_SPELL_CHECKER_LANGUAGE = "spellchecker_language"; |
| private static final String KEY_DEFAULT_SPELL_CHECKER = "default_spellchecker"; |
| private static final int ITEM_ID_USE_SYSTEM_LANGUAGE = 0; |
| |
| private SwitchBar mSwitchBar; |
| private Preference mSpellCheckerLanaguagePref; |
| private AlertDialog mDialog = null; |
| private SpellCheckerInfo mCurrentSci; |
| private SpellCheckerInfo[] mEnabledScis; |
| private TextServicesManager mTsm; |
| |
| @Override |
| public int getMetricsCategory() { |
| return MetricsEvent.INPUTMETHOD_SPELL_CHECKERS; |
| } |
| |
| @Override |
| public void onCreate(final Bundle icicle) { |
| super.onCreate(icicle); |
| |
| addPreferencesFromResource(R.xml.spellchecker_prefs); |
| mSpellCheckerLanaguagePref = findPreference(KEY_SPELL_CHECKER_LANGUAGE); |
| mSpellCheckerLanaguagePref.setOnPreferenceClickListener(this); |
| |
| mTsm = (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); |
| mCurrentSci = mTsm.getCurrentSpellChecker(); |
| mEnabledScis = mTsm.getEnabledSpellCheckers(); |
| populatePreferenceScreen(); |
| } |
| |
| private void populatePreferenceScreen() { |
| final SpellCheckerPreference pref = new SpellCheckerPreference(getPrefContext(), |
| mEnabledScis); |
| pref.setTitle(R.string.default_spell_checker); |
| final int count = (mEnabledScis == null) ? 0 : mEnabledScis.length; |
| if (count > 0) { |
| pref.setSummary("%s"); |
| } else { |
| pref.setSummary(R.string.spell_checker_not_selected); |
| } |
| pref.setKey(KEY_DEFAULT_SPELL_CHECKER); |
| pref.setOnPreferenceChangeListener(this); |
| getPreferenceScreen().addPreference(pref); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); |
| mSwitchBar.setSwitchBarText( |
| R.string.spell_checker_master_switch_title, |
| R.string.spell_checker_master_switch_title); |
| mSwitchBar.show(); |
| mSwitchBar.addOnSwitchChangeListener(this); |
| updatePreferenceScreen(); |
| } |
| |
| @Override |
| public void onPause() { |
| super.onPause(); |
| mSwitchBar.removeOnSwitchChangeListener(this); |
| } |
| |
| @Override |
| public void onSwitchChanged(final Switch switchView, final boolean isChecked) { |
| Settings.Secure.putInt(getContentResolver(), Settings.Secure.SPELL_CHECKER_ENABLED, |
| isChecked ? 1 : 0); |
| updatePreferenceScreen(); |
| } |
| |
| private void updatePreferenceScreen() { |
| mCurrentSci = mTsm.getCurrentSpellChecker(); |
| final boolean isSpellCheckerEnabled = mTsm.isSpellCheckerEnabled(); |
| mSwitchBar.setChecked(isSpellCheckerEnabled); |
| |
| final SpellCheckerSubtype currentScs; |
| if (mCurrentSci != null) { |
| currentScs = mTsm.getCurrentSpellCheckerSubtype( |
| false /* allowImplicitlySelectedSubtype */); |
| } else { |
| currentScs = null; |
| } |
| mSpellCheckerLanaguagePref.setSummary(getSpellCheckerSubtypeLabel(mCurrentSci, currentScs)); |
| |
| final PreferenceScreen screen = getPreferenceScreen(); |
| final int count = screen.getPreferenceCount(); |
| for (int index = 0; index < count; index++) { |
| final Preference preference = screen.getPreference(index); |
| preference.setEnabled(isSpellCheckerEnabled); |
| if (preference instanceof SpellCheckerPreference) { |
| final SpellCheckerPreference pref = (SpellCheckerPreference) preference; |
| pref.setSelected(mCurrentSci); |
| } |
| } |
| mSpellCheckerLanaguagePref.setEnabled(isSpellCheckerEnabled && mCurrentSci != null); |
| } |
| |
| private CharSequence getSpellCheckerSubtypeLabel(final SpellCheckerInfo sci, |
| final SpellCheckerSubtype subtype) { |
| if (sci == null) { |
| return getString(R.string.spell_checker_not_selected); |
| } |
| if (subtype == null) { |
| return getString(R.string.use_system_language_to_select_input_method_subtypes); |
| } |
| return subtype.getDisplayName( |
| getActivity(), sci.getPackageName(), sci.getServiceInfo().applicationInfo); |
| } |
| |
| @Override |
| public boolean onPreferenceClick(final Preference pref) { |
| if (pref == mSpellCheckerLanaguagePref) { |
| showChooseLanguageDialog(); |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean onPreferenceChange(Preference preference, Object newValue) { |
| final SpellCheckerInfo sci = (SpellCheckerInfo) newValue; |
| final boolean isSystemApp = |
| (sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; |
| if (isSystemApp) { |
| changeCurrentSpellChecker(sci); |
| return true; |
| } else { |
| showSecurityWarnDialog(sci); |
| return false; |
| } |
| } |
| |
| private static int convertSubtypeIndexToDialogItemId(final int index) { |
| return index + 1; |
| } |
| |
| private static int convertDialogItemIdToSubtypeIndex(final int item) { |
| return item - 1; |
| } |
| |
| private void showChooseLanguageDialog() { |
| if (mDialog != null && mDialog.isShowing()) { |
| mDialog.dismiss(); |
| } |
| final SpellCheckerInfo currentSci = mTsm.getCurrentSpellChecker(); |
| if (currentSci == null) { |
| // This can happen in some situations. One example is that the package that the current |
| // spell checker belongs to was uninstalled or being in background. |
| return; |
| } |
| final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype( |
| false /* allowImplicitlySelectedSubtype */); |
| final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| builder.setTitle(R.string.phone_language); |
| final int subtypeCount = currentSci.getSubtypeCount(); |
| final CharSequence[] items = new CharSequence[subtypeCount + 1 /* default */]; |
| items[ITEM_ID_USE_SYSTEM_LANGUAGE] = getSpellCheckerSubtypeLabel(currentSci, null); |
| int checkedItemId = ITEM_ID_USE_SYSTEM_LANGUAGE; |
| for (int index = 0; index < subtypeCount; ++index) { |
| final SpellCheckerSubtype subtype = currentSci.getSubtypeAt(index); |
| final int itemId = convertSubtypeIndexToDialogItemId(index); |
| items[itemId] = getSpellCheckerSubtypeLabel(currentSci, subtype); |
| if (subtype.equals(currentScs)) { |
| checkedItemId = itemId; |
| } |
| } |
| builder.setSingleChoiceItems(items, checkedItemId, new AlertDialog.OnClickListener() { |
| @Override |
| public void onClick(final DialogInterface dialog, final int item) { |
| final int subtypeId; |
| if (item == ITEM_ID_USE_SYSTEM_LANGUAGE) { |
| subtypeId = SpellCheckerSubtype.SUBTYPE_ID_NONE; |
| } else { |
| final int index = convertDialogItemIdToSubtypeIndex(item); |
| subtypeId = currentSci.getSubtypeAt(index).hashCode(); |
| } |
| |
| Settings.Secure.putInt(getContentResolver(), |
| Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, subtypeId); |
| |
| if (DBG) { |
| final SpellCheckerSubtype subtype = mTsm.getCurrentSpellCheckerSubtype( |
| true /* allowImplicitlySelectedSubtype */); |
| Log.d(TAG, "Current spell check locale is " |
| + subtype == null ? "null" : subtype.getLocale()); |
| } |
| dialog.dismiss(); |
| updatePreferenceScreen(); |
| } |
| }); |
| mDialog = builder.create(); |
| mDialog.show(); |
| } |
| |
| private void showSecurityWarnDialog(final SpellCheckerInfo sci) { |
| if (mDialog != null && mDialog.isShowing()) { |
| mDialog.dismiss(); |
| } |
| final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| builder.setTitle(android.R.string.dialog_alert_title); |
| builder.setMessage(getString(R.string.spellchecker_security_warning, |
| sci.loadLabel(getPackageManager()))); |
| builder.setCancelable(true); |
| builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(final DialogInterface dialog, final int which) { |
| changeCurrentSpellChecker(sci); |
| } |
| }); |
| builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(final DialogInterface dialog, final int which) { |
| } |
| }); |
| mDialog = builder.create(); |
| mDialog.show(); |
| } |
| |
| private void changeCurrentSpellChecker(final SpellCheckerInfo sci) { |
| Settings.Secure.putString(getContentResolver(), Settings.Secure.SELECTED_SPELL_CHECKER, |
| sci.getId()); |
| // Reset the spell checker subtype |
| Settings.Secure.putInt(getContentResolver(), Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, |
| SpellCheckerSubtype.SUBTYPE_ID_NONE); |
| if (DBG) { |
| Log.d(TAG, "Current spell check is " + mTsm.getCurrentSpellChecker().getId()); |
| } |
| updatePreferenceScreen(); |
| } |
| } |