/* * This source is part of the * _____ ___ ____ * __ / / _ \/ _ | / __/___ _______ _ * / // / , _/ __ |/ _/_/ _ \/ __/ _ `/ * \___/_/|_/_/ |_/_/ (_)___/_/ \_, / * /___/ * repository. * * Copyright (C) 2014-2017 Carmen Alvarez (c@rmen.ca) * * 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 ca.rmen.android.networkmonitor.app.prefs; import android.app.Notification; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.preference.PreferenceManager; import android.text.TextUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import ca.rmen.android.networkmonitor.R; import ca.rmen.android.networkmonitor.app.prefs.SortPreferences.SortOrder; import ca.rmen.android.networkmonitor.app.service.scheduler.AlarmManagerScheduler; import ca.rmen.android.networkmonitor.app.service.scheduler.ExecutorServiceScheduler; import ca.rmen.android.networkmonitor.app.service.scheduler.NetworkChangeScheduler; import ca.rmen.android.networkmonitor.app.service.scheduler.Scheduler; import ca.rmen.android.networkmonitor.provider.NetMonColumns; /** * Convenience methods for getting/setting shared preferences. */ public class NetMonPreferences { public enum CellIdFormat { DECIMAL, HEX, DECIMAL_HEX } public enum LocationFetchingStrategy { SAVE_POWER, HIGH_ACCURACY, SAVE_POWER_GMS, HIGH_ACCURACY_GMS } public enum NetMonTheme { DAY, NIGHT, AUTO } static final String PREF_TEST_SERVER = "PREF_TEST_SERVER"; public static final int PREF_MIN_POLLING_INTERVAL = 10000; public static final String PREF_UPDATE_INTERVAL = "PREF_UPDATE_INTERVAL"; public static final int PREF_UPDATE_ON_NETWORK_CHANGE = -1; public static final String PREF_SERVICE_ENABLED = "PREF_SERVICE_ENABLED"; public static final boolean PREF_SERVICE_ENABLED_DEFAULT = false; public static final String PREF_SCHEDULER = "PREF_SCHEDULER"; public static final String PREF_SORT_ORDER = "PREF_SORT_ORDER"; public static final String PREF_SORT_COLUMN_NAME = "PREF_SORT_COLUMN_NAME"; public static final String PREF_KML_EXPORT_COLUMN = "PREF_KML_EXPORT_COLUMN"; public static final String PREF_FILTER_RECORD_COUNT = "PREF_FILTER_RECORD_COUNT"; public static final String PREF_FILTER_RECORD_COUNT_DEFAULT = "100"; static final String PREF_DB_RECORD_COUNT = "PREF_DB_RECORD_COUNT"; static final String PREF_ENABLE_CONNECTION_TEST = "PREF_ENABLE_CONNECTION_TEST"; public static final String PREF_CELL_ID_FORMAT = "PREF_CELL_ID_FORMAT"; public static final String PREF_CELL_ID_FORMAT_DEFAULT = "decimal"; public static final String PREF_LOCATION_FETCHING_STRATEGY = "PREF_LOCATION_FETCHING_STRATEGY"; static final String PREF_NOTIFICATION_RINGTONE = "PREF_NOTIFICATION_RINGTONE"; static final String PREF_NOTIFICATION_ENABLED = "PREF_NOTIFICATION_ENABLED"; public static final String PREF_EXPORT_GNUPLOT_SERIES = "PREF_EXPORT_GNUPLOT_SERIES"; public static final String PREF_EXPORT_GNUPLOT_Y_AXIS = "PREF_EXPORT_GNUPLOT_Y_AXIS"; static final String PREF_THEME = "PREF_THEME"; public static final String PREF_NOTIFICATION_PRIORITY = "PREF_NOTIFICATION_PRIORITY"; private static final String PREF_NOTIFICATION_PRIORITY_MAX = "max"; private static final String PREF_NOTIFICATION_PRIORITY_HIGH = "high"; private static final String PREF_NOTIFICATION_PRIORITY_DEFAULT = "default"; private static final String PREF_NOTIFICATION_PRIORITY_LOW = "low"; private static final String PREF_NOTIFICATION_PRIORITY_MIN = "min"; private static final String PREF_FREEZE_HTML_TABLE_HEADER = "PREF_FREEZE_HTML_TABLE_HEADER"; private static final boolean PREF_FREEZE_HTML_TABLE_HEADER_DEFAULT = false; private static final String PREF_WAKE_INTERVAL = "PREF_WAKE_INTERVAL"; private static final String PREF_UPDATE_INTERVAL_DEFAULT = "10000"; private static final String PREF_DB_RECORD_COUNT_DEFAULT = "-1"; private static final boolean PREF_ENABLE_CONNECTION_TEST_DEFAULT = true; private static final String PREF_TEST_SERVER_DEFAULT = "216.58.208.206"; private static final String PREF_WAKE_INTERVAL_DEFAULT = "0"; private static final String PREF_SCHEDULER_DEFAULT = ExecutorServiceScheduler.class.getSimpleName(); private static final String PREF_SELECTED_COLUMNS = "PREF_SELECTED_COLUMNS"; private static final String PREF_SORT_COLUMN_NAME_DEFAULT = NetMonColumns.TIMESTAMP; private static final String PREF_SORT_ORDER_DEFAULT = SortOrder.DESC.name(); private static final String PREF_FILTER_PREFIX = "PREF_FILTERED_VALUES_"; private static final String PREF_EXPORT_GNUPLOT_SERIES_DEFAULT = "wifi_ssid"; private static final String PREF_EXPORT_GNUPLOT_Y_AXIS_DEFAULT = "wifi_rssi"; private static final String PREF_SHOW_APP_WARNING = "show_app_warning"; private static final boolean PREF_SHOW_APP_WARNING_DEFAULT = true; private static NetMonPreferences INSTANCE = null; private final SharedPreferences mSharedPrefs; private final Context mContext; public static synchronized NetMonPreferences getInstance(Context context) { if (INSTANCE == null) { INSTANCE = new NetMonPreferences(context.getApplicationContext()); } return INSTANCE; } private NetMonPreferences(Context context) { mContext = context; mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); } /** * @return The server we try to reach to test connectivity. */ public String getTestServer() { return mSharedPrefs.getString(NetMonPreferences.PREF_TEST_SERVER, NetMonPreferences.PREF_TEST_SERVER_DEFAULT); } /** * Use the default test server. */ void resetTestServer() { setStringPreference(NetMonPreferences.PREF_TEST_SERVER, NetMonPreferences.PREF_TEST_SERVER_DEFAULT); } /** * @return the interval between log entries, in millis */ public int getUpdateInterval() { return getIntPreference(NetMonPreferences.PREF_UPDATE_INTERVAL, NetMonPreferences.PREF_UPDATE_INTERVAL_DEFAULT); } /** * @return true if we're polling quickly */ public boolean isFastPollingEnabled() { int updateInterval = getUpdateInterval(); return updateInterval > 0 && updateInterval < NetMonPreferences.PREF_MIN_POLLING_INTERVAL; } /** * @return the interval, in milliseconds, between forced waking up the device (by turning the screen on). If not positive, we will never force wake up the * device. */ public int getWakeInterval() { return getIntPreference(NetMonPreferences.PREF_WAKE_INTERVAL, NetMonPreferences.PREF_WAKE_INTERVAL_DEFAULT); } /** * @return true if we are currently collecting and logging data. */ public boolean isServiceEnabled() { return mSharedPrefs.getBoolean(NetMonPreferences.PREF_SERVICE_ENABLED, NetMonPreferences.PREF_SERVICE_ENABLED_DEFAULT); } /** * @param value true if we should collect and log data, false otherwise. */ public void setServiceEnabled(boolean value) { setBooleanPreference(NetMonPreferences.PREF_SERVICE_ENABLED, value); } /** * @return the number of rows we should display in the log view. This is only for display: we always export all rows. */ public int getFilterRecordCount() { return getIntPreference(NetMonPreferences.PREF_FILTER_RECORD_COUNT, NetMonPreferences.PREF_FILTER_RECORD_COUNT_DEFAULT); } /** * @return true if we should keep the column headings in the log view in a fixed position, while the table body scrolls. */ public boolean getFreezeHtmlTableHeader() { return mSharedPrefs.getBoolean(NetMonPreferences.PREF_FREEZE_HTML_TABLE_HEADER, NetMonPreferences.PREF_FREEZE_HTML_TABLE_HEADER_DEFAULT); } /** * @param value if true, we should keep the column headings in the log view in a fixed position, while the table body scrolls. */ public void setFreezeHtmlTableHeader(boolean value) { setBooleanPreference(NetMonPreferences.PREF_FREEZE_HTML_TABLE_HEADER, value); } /** * @return the number of rows we should store in the database */ public int getDBRecordCount() { return getIntPreference(NetMonPreferences.PREF_DB_RECORD_COUNT, NetMonPreferences.PREF_DB_RECORD_COUNT_DEFAULT); } public void setDBRecordCount(int recordCount) { setIntPreference(NetMonPreferences.PREF_DB_RECORD_COUNT, recordCount); } /** * @return true if we should do connection tests with each test. */ public boolean isConnectionTestEnabled() { return mSharedPrefs.getBoolean(NetMonPreferences.PREF_ENABLE_CONNECTION_TEST, NetMonPreferences.PREF_ENABLE_CONNECTION_TEST_DEFAULT); } /** * Enable or disable the data connection tests. */ public void setConnectionTestEnabled(boolean enabled) { setBooleanPreference(NetMonPreferences.PREF_ENABLE_CONNECTION_TEST, enabled); } /** * @return the format in which numeric cell id fields should be displayed and exported. */ public CellIdFormat getCellIdFormat() { String cellIdFormat = mSharedPrefs.getString(NetMonPreferences.PREF_CELL_ID_FORMAT, NetMonPreferences.PREF_CELL_ID_FORMAT_DEFAULT); if ("decimal".equals(cellIdFormat)) return CellIdFormat.DECIMAL; if ("hex".equals(cellIdFormat)) return CellIdFormat.HEX; return CellIdFormat.DECIMAL_HEX; } /** * @return the implementation of the {@link Scheduler} interface which schedules each logging of data. */ public Class<?> getSchedulerClass() { int updateInterval = getUpdateInterval(); if (updateInterval == PREF_UPDATE_ON_NETWORK_CHANGE) return NetworkChangeScheduler.class; String schedulerPref = mSharedPrefs.getString(NetMonPreferences.PREF_SCHEDULER, NetMonPreferences.PREF_SCHEDULER_DEFAULT); if (schedulerPref.equals(AlarmManagerScheduler.class.getSimpleName())) return AlarmManagerScheduler.class; else return ExecutorServiceScheduler.class; } /** * @return the list of columns which will appear in the log view. This is only for display. All columns will be exported. */ public List<String> getSelectedColumns() { String selectedColumnsString = mSharedPrefs.getString(NetMonPreferences.PREF_SELECTED_COLUMNS, null); final String[] selectedColumns; if (TextUtils.isEmpty(selectedColumnsString)) selectedColumns = NetMonColumns.getDefaultVisibleColumnNames(mContext); else selectedColumns = selectedColumnsString.split(","); return Arrays.asList(selectedColumns); } /** * set the list of columns to appear in the log view. This is only for display. All columns will be exported. */ void setSelectedColumns(List<String> selectedColumns) { String selectedColumnsString = TextUtils.join(",", selectedColumns); setStringPreference(NetMonPreferences.PREF_SELECTED_COLUMNS, selectedColumnsString); } /** * The report will only show rows where the given column has one of the given values. */ void setColumnFilterValues(String columnName, List<String> filteredValues) { String filteredValuesString = TextUtils.join(",", filteredValues); setStringPreference(NetMonPreferences.PREF_FILTER_PREFIX + columnName, filteredValuesString); } /** * Get the list of values for this column on which we'll filter the report. */ public List<String> getColumnFilterValues(String columnName) { String filteredValuesString = mSharedPrefs.getString(PREF_FILTER_PREFIX + columnName, ""); if (TextUtils.isEmpty(filteredValuesString)) return new ArrayList<>(); return Arrays.asList(filteredValuesString.split(",")); } /** * Clear any filtering preferences the user has set. */ public void resetColumnFilters() { String[] filterableColumns = mContext.getResources().getStringArray(R.array.filterable_columns); Editor editor = mSharedPrefs.edit(); for (String filterableColumn : filterableColumns) editor.putString(PREF_FILTER_PREFIX + filterableColumn, null); editor.apply(); } /** * @return true if the user has chosen to filter at least one column. */ public boolean hasColumnFilters() { String[] filterableColumns = mContext.getResources().getStringArray(R.array.filterable_columns); for (String filterableColumn : filterableColumns) if (!TextUtils.isEmpty(mSharedPrefs.getString(PREF_FILTER_PREFIX + filterableColumn, null))) return true; return false; } /** * @return the settings for how rows in the log view or table export formats are sorted. */ public SortPreferences getSortPreferences() { String sortColumnName = mSharedPrefs.getString(PREF_SORT_COLUMN_NAME, PREF_SORT_COLUMN_NAME_DEFAULT); SortOrder sortOrder = SortOrder.valueOf(mSharedPrefs.getString(PREF_SORT_ORDER, PREF_SORT_ORDER_DEFAULT)); return new SortPreferences(sortColumnName, sortOrder); } /** * set the settings for how rows in the log view or table export formats should be sorted. */ public void setSortPreferences(SortPreferences sortPreferences) { Editor editor = mSharedPrefs.edit(); editor.putString(PREF_SORT_COLUMN_NAME, sortPreferences.sortColumnName); editor.putString(PREF_SORT_ORDER, sortPreferences.sortOrder.name()); editor.apply(); } public String getExportGnuplotSeriesField() { return mSharedPrefs.getString(PREF_EXPORT_GNUPLOT_SERIES, PREF_EXPORT_GNUPLOT_SERIES_DEFAULT); } public String getExportGnuplotYAxisField() { return mSharedPrefs.getString(PREF_EXPORT_GNUPLOT_Y_AXIS, PREF_EXPORT_GNUPLOT_Y_AXIS_DEFAULT); } /** * @return the strategy we should use for requesting location updates. */ public LocationFetchingStrategy getLocationFetchingStrategy() { String value = mSharedPrefs.getString(PREF_LOCATION_FETCHING_STRATEGY, LocationFetchingStrategy.SAVE_POWER.name()); return LocationFetchingStrategy.valueOf(value); } /** * Set the strategy we should use for requesting location updates. */ private void setLocationFetchingStrategy(LocationFetchingStrategy strategy) { setStringPreference(PREF_LOCATION_FETCHING_STRATEGY, strategy.name()); } /** * Don't use Google Play Services for requesting location. */ public void forceFossLocationFetchingStrategy() { LocationFetchingStrategy strategy = getLocationFetchingStrategy(); if (strategy == LocationFetchingStrategy.HIGH_ACCURACY_GMS) { setLocationFetchingStrategy(LocationFetchingStrategy.HIGH_ACCURACY); } else if (strategy == LocationFetchingStrategy.SAVE_POWER_GMS) { setLocationFetchingStrategy(LocationFetchingStrategy.SAVE_POWER); } } /** * @return true if we should display a warning notification when a network test fails. */ public boolean getShowNotificationOnTestFailure() { return mSharedPrefs.getBoolean(PREF_NOTIFICATION_ENABLED, false); } /** * @return the Uri of the sound to play when a notification is created. */ public Uri getNotificationSoundUri() { String soundUriStr = mSharedPrefs.getString(PREF_NOTIFICATION_RINGTONE, null); if (TextUtils.isEmpty(soundUriStr)) return null; return Uri.parse(soundUriStr); } /** * Set the Uri of the sound to play when a notification is created. */ void setNotificationSoundUri(Uri uri) { if (uri == null) setStringPreference(PREF_NOTIFICATION_RINGTONE, null); else setStringPreference(PREF_NOTIFICATION_RINGTONE, uri.toString()); } /** * Set the ringtone Uri to the default ringtone Uri. */ void setDefaultNotificationSoundUri() { Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); if (defaultSoundUri != null) setStringPreference(PREF_NOTIFICATION_RINGTONE, defaultSoundUri.toString()); } public boolean getShowAppWarning() { return mSharedPrefs.getBoolean(PREF_SHOW_APP_WARNING, PREF_SHOW_APP_WARNING_DEFAULT); } public void setShowAppWarning(boolean value) { setBooleanPreference(PREF_SHOW_APP_WARNING, value); } public NetMonTheme getTheme() { String themeStr = mSharedPrefs.getString(PREF_THEME, NetMonTheme.DAY.name()); return NetMonTheme.valueOf(themeStr); } public int getNotificationPriority() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return 0; String priorityPref = mSharedPrefs.getString(PREF_NOTIFICATION_PRIORITY, PREF_NOTIFICATION_PRIORITY_DEFAULT); if (priorityPref.equals(PREF_NOTIFICATION_PRIORITY_MAX)) return Notification.PRIORITY_MAX; if (priorityPref.equals(PREF_NOTIFICATION_PRIORITY_HIGH)) return Notification.PRIORITY_HIGH; if (priorityPref.equals(PREF_NOTIFICATION_PRIORITY_LOW)) return Notification.PRIORITY_LOW; if (priorityPref.equals(PREF_NOTIFICATION_PRIORITY_MIN)) return Notification.PRIORITY_MIN; return Notification.PRIORITY_DEFAULT; } private int getIntPreference(String key, String defaultValue) { String valueStr = mSharedPrefs.getString(key, defaultValue); return Integer.valueOf(valueStr); } private void setIntPreference(String key, int value) { setStringPreference(key, String.valueOf(value)); } private void setStringPreference(final String key, final String value) { mSharedPrefs.edit().putString(key, value).apply(); } private void setBooleanPreference(final String key, final Boolean value) { mSharedPrefs.edit().putBoolean(key, value).apply(); } }