Java tutorial
/* * Copyright (C) 2015 Google Inc. * * 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.switchaccess; import android.content.Context; import android.content.SharedPreferences; import android.preference.ListPreference; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; import android.support.v4.os.BuildCompat; import android.text.TextUtils; import com.android.talkback.R; import com.android.utils.SharedPreferencesUtils; import android.os.Bundle; import java.util.ArrayList; import java.util.Arrays; /** * Preference activity for switch access. * * PreferenceActivity contains various deprecated methods because * PreferenceFragment is preferred. PreferenceFragment, however, * can only be added to activities, not services. */ @SuppressWarnings("deprecation") public class SwitchAccessPreferenceActivity extends PreferenceActivity implements OnPreferenceChangeListener { private static final int SINGLE_VALUE = 1; private static final int MANY_VALUE = 2; private static final double PRECISION = 0.01; /** * Check if option scanning is enabled * * @param context The current context * @return {@code true} if option scanning is enabled in the preferences, {@code false} * otherwise */ public static boolean isOptionScanningEnabled(Context context) { String optionScanKey = context.getString(R.string.option_scanning_key); String scanPref = SharedPreferencesUtils.getSharedPreferences(context).getString( context.getString(R.string.pref_scanning_methods_key), context.getString(R.string.pref_scanning_methods_default)); return TextUtils.equals(scanPref, optionScanKey); } /** * Check if auto-scanning is enabled * * @param context The current context * @return {@code true} if auto scan is enabled in the preferences, {@code false} otherwise */ public static boolean isAutoScanEnabled(Context context) { final SharedPreferences prefs = SharedPreferencesUtils.getSharedPreferences(context); return prefs.getBoolean(context.getString(R.string.pref_key_auto_scan_enabled), Boolean.parseBoolean(context.getString(R.string.pref_auto_scan_default_value))); } /** * Check the global menu preference for auto-select * * @param context The current context * @return {@code true} auto-selecting is controlled from the auto-scan menu, * {@code false} otherwise */ public static boolean isGlobalMenuAutoselectOn(Context context) { SharedPreferences prefs = SharedPreferencesUtils.getSharedPreferences(context); String autoselectGlobalMenuPrefValue = prefs.getString( context.getString(R.string.switch_access_choose_action_global_menu_behavior_key), context.getString(R.string.switch_access_pref_choose_action_behavior_default)); return TextUtils.equals(autoselectGlobalMenuPrefValue, context.getString(R.string.switch_access_choose_action_auto_select_key)); } /** * Set the global menu preference for auto-select * * @param context The current context * @param autoselectOn {@code true} to enable auto-select when the global menu controls * the preference, {@code false} to disable it. */ public static void setGlobalMenuAutoselectOn(Context context, boolean autoselectOn) { SharedPreferences prefs = SharedPreferencesUtils.getSharedPreferences(context); String newStringValue = (autoselectOn) ? context.getString(R.string.switch_access_choose_action_auto_select_key) : context.getString(R.string.switch_access_choose_action_show_menu_key); prefs.edit().putString(context.getString(R.string.switch_access_choose_action_global_menu_behavior_key), newStringValue).apply(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (BuildCompat.isAtLeastN()) { getPreferenceManager().setStorageDeviceProtected(); } addPreferencesFromResource(R.xml.switch_access_preferences); /* Set the summary to be the current value of the preference */ final Preference autoScanDelayPref = findPreference(getString(R.string.pref_key_auto_scan_time_delay)); double currentValue; try { SharedPreferences prefs = SharedPreferencesUtils.getSharedPreferences(this); currentValue = Double.parseDouble(prefs.getString(getString(R.string.pref_key_auto_scan_time_delay), getString(R.string.pref_auto_scan_time_delay_default_value))); } catch (NumberFormatException e) { currentValue = Double.parseDouble(getString(R.string.pref_auto_scan_time_delay_default_value)); } final int count = Math.abs(currentValue - SINGLE_VALUE) < PRECISION ? SINGLE_VALUE : MANY_VALUE; autoScanDelayPref.setSummary(getResources().getQuantityString(R.plurals.auto_scan_time_delay_summary_format, count, currentValue)); autoScanDelayPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { /** * Update the current summary of the delay preference. The newValue for the delay is * guaranteed to be an integer (or an empty string which is not handled). */ @Override public boolean onPreferenceChange(Preference preference, Object newValue) { final String newValueString = newValue.toString(); if (TextUtils.isEmpty(newValueString)) { return false; } try { final double value = Double.parseDouble(newValueString); final int count = Math.abs(value - SINGLE_VALUE) < PRECISION ? SINGLE_VALUE : MANY_VALUE; preference.setSummary(getResources() .getQuantityString(R.plurals.auto_scan_time_delay_summary_format, count, value)); return true; } catch (NumberFormatException e) { return false; } } }); int[] prefsToListenTo = { R.string.pref_scanning_methods_key, R.string.pref_key_auto_scan_enabled, R.string.pref_key_mapped_to_click_key, R.string.pref_key_mapped_to_next_key, R.string.pref_key_mapped_to_switch_3_key, R.string.pref_key_mapped_to_switch_4_key, R.string.pref_key_mapped_to_switch_5_key }; for (int prefToListenTo : prefsToListenTo) { findPreference(getString(prefToListenTo)).setOnPreferenceChangeListener(this); } adjustHighlightingPrefs(); adjustKeysForScanning(); adjustAutoscanPrefs(); // Add listener to "Help & feedback" preference. Preference helpAndFeedbackPreference = findPreference(getString(R.string.pref_help_feedback_key)); helpAndFeedbackPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { HelpUtils.launchHelp(SwitchAccessPreferenceActivity.this); return true; } }); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { recreate(); return true; } /* * Adjust the highlighting preferences to show appropriate values for option scanning or * row-column. */ private void adjustHighlightingPrefs() { PreferenceScreen mainPrefScreen = (PreferenceScreen) findPreference( getString(R.string.main_pref_screen_key)); if (isOptionScanningEnabled(this)) { // Configure the switch names. User-facing numbers start at 1 int[] highlightPrefKeys = { R.string.pref_highlight_0_key, R.string.pref_highlight_1_key, R.string.pref_highlight_2_key, R.string.pref_highlight_3_key, R.string.pref_highlight_4_key }; for (int i = 0; i < highlightPrefKeys.length; i++) { findPreference(getString(highlightPrefKeys[i])) .setTitle(String.format(getString(R.string.option_scan_switch_format), i + 1)); } mainPrefScreen.removePreference(findPreference(getString(R.string.pref_standard_highlight_key))); } else { mainPrefScreen.removePreference(findPreference(getString(R.string.pref_highlights_key))); } } /* * If option scanning is disabled, remove all keys related to it. Keep all preferences with * keys assigned (otherwise there's no way to clear those assignments). If option scanning * is enabled, assign all titles for the applicable key assignments. */ private void adjustKeysForScanning() { int[] optionScanKeyAssignmentKeys = { R.string.pref_key_mapped_to_click_key, R.string.pref_key_mapped_to_next_key, R.string.pref_key_mapped_to_switch_3_key, R.string.pref_key_mapped_to_switch_4_key, R.string.pref_key_mapped_to_switch_5_key }; PreferenceScreen keyAssignmentScreen = (PreferenceScreen) findPreference( getString(R.string.pref_category_scan_mappings_key)); if (!isOptionScanningEnabled(this)) { for (int i = 2; i < optionScanKeyAssignmentKeys.length; i++) { findPreference(getString(optionScanKeyAssignmentKeys[i])) .setTitle(String.format(getString(R.string.option_scan_switch_format), i + 1)); removeKeyAssignmentPressIfEmpty(keyAssignmentScreen, optionScanKeyAssignmentKeys[i]); } } else { int numSwitchesConfigured = 0; for (int i = 0; i < optionScanKeyAssignmentKeys.length; i++) { int key = optionScanKeyAssignmentKeys[i]; numSwitchesConfigured += prefHasKeyAssigned(key) ? 1 : 0; findPreference(getString(key)) .setTitle(String.format(getString(R.string.option_scan_switch_format), i + 1)); /* Limit key assignment options to those that are useful given current config */ if ((i >= 2) && (numSwitchesConfigured < i)) { removeKeyAssignmentPressIfEmpty(keyAssignmentScreen, key); } } } } /* * If auto-scanning is disabled, remove all preferences related to it except for key assignment * for actions that are already configured. * If auto-scannning is enabled, don't allow option scanning to be enabled. * If option scanning is enabled, don't allow auto-scanning to be enabled. * If both are enabled (which shouldn't be possible, disable option scanning). */ private void adjustAutoscanPrefs() { if (isAutoScanEnabled(this)) { ListPreference scanMethodsPref = (ListPreference) findPreference( getString(R.string.pref_scanning_methods_key)); String optionScanKey = getString(R.string.option_scanning_key); if (isOptionScanningEnabled(this)) { /* If somehow both autoscan and option scan are enabled, turn off option scan */ scanMethodsPref.setValue(getString(R.string.row_col_scanning_key)); SharedPreferencesUtils.getSharedPreferences(this).edit() .putString(getString(R.string.pref_scanning_methods_key), getString(R.string.row_col_scanning_key)) .commit(); } ArrayList<String> entries = new ArrayList<>( Arrays.asList(getResources().getStringArray(R.array.switch_access_scanning_methods_entries))); ArrayList<String> entryValues = new ArrayList<>( Arrays.asList(getResources().getStringArray(R.array.switch_access_scanning_methods_values))); int optionScanIndex = entryValues.indexOf(optionScanKey); entries.remove(optionScanIndex); entryValues.remove(optionScanIndex); scanMethodsPref.setEntries(entries.toArray(new String[entries.size()])); scanMethodsPref.setEntryValues(entryValues.toArray(new String[entries.size()])); } else { PreferenceScreen mainPrefScreen = (PreferenceScreen) findPreference( getString(R.string.main_pref_screen_key)); PreferenceScreen keyAssignmentScreen = (PreferenceScreen) findPreference( getString(R.string.pref_category_scan_mappings_key)); mainPrefScreen.removePreference(findPreference(getString(R.string.pref_key_auto_scan_time_delay))); removeKeyAssignmentPressIfEmpty(keyAssignmentScreen, R.string.pref_key_mapped_to_auto_scan_key); removeKeyAssignmentPressIfEmpty(keyAssignmentScreen, R.string.pref_key_mapped_to_reverse_auto_scan_key); if (isOptionScanningEnabled(this)) { mainPrefScreen.removePreference(findPreference(getString(R.string.pref_key_auto_scan_enabled))); } } } /** * @return {@code true} if preference was empty and has been removed */ private void removeKeyAssignmentPressIfEmpty(PreferenceScreen keyAssignmentScreen, int prefKeyStringId) { if (!prefHasKeyAssigned(prefKeyStringId)) { keyAssignmentScreen.removePreference(findPreference(getString(prefKeyStringId))); } } private boolean prefHasKeyAssigned(int prefKeyStringId) { return (KeyComboPreference.getKeyCodesForPreference(this, getString(prefKeyStringId)).size() != 0); } }