/* * Calendula - An assistant for personal medication management. * Copyright (C) 2016 CITIUS - USC * * Calendula is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software. If not, see <http://www.gnu.org/licenses/>. */ package es.usc.citius.servando.calendula.activities; import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import com.mikepenz.google_material_typeface_library.GoogleMaterial; import com.mikepenz.iconics.IconicsDrawable; import java.sql.SQLException; import java.util.List; import es.usc.citius.servando.calendula.CalendulaApp; import es.usc.citius.servando.calendula.R; import es.usc.citius.servando.calendula.database.DB; import es.usc.citius.servando.calendula.scheduling.AlarmScheduler; import es.usc.citius.servando.calendula.services.PopulatePrescriptionDBService; import es.usc.citius.servando.calendula.util.PermissionUtils; import es.usc.citius.servando.calendula.util.ScreenUtils; /** * A {@link PreferenceActivity} that presents a set of application settings. On * handset devices, settings are presented as a single list. On tablets, * settings are split by category, with category headers shown to the left of * the list of settings. * <p/> * See <a href="http://developer.android.com/design/patterns/settings.html"> * Android Design: Settings</a> for design guidelines and the <a * href="http://developer.android.com/guide/topics/ui/settings.html">Settings * API Guide</a> for more information on developing a Settings UI. */ public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { /** * Determines whether to always show the simplified settings UI, where * settings are presented in a single list. When false, settings are shown * as a master/detail two-pane view on tablets. When true, a single pane is * shown on tablets. */ private static final boolean ALWAYS_SIMPLE_PREFS = false; public static final int REQ_CODE_EXTERNAL_STORAGE = 20; static Context ctx; static Activity activity; /** * A preference value change listener that updates the preference's summary * to reflect its new value. */ private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object value) { String stringValue = value.toString(); if (preference instanceof es.usc.citius.servando.calendula.util.RingtonePreference) { String p = Manifest.permission.WRITE_EXTERNAL_STORAGE; if(PermissionUtils.useRunTimePermissions() && !PermissionUtils.hasPermission(activity, p)){ preference.setSummary(""); }else{ Uri ringtoneUri = Uri.parse(stringValue); Ringtone ringtone = RingtoneManager.getRingtone(ctx, ringtoneUri); String name = ringtone!=null ? ringtone.getTitle(ctx) :ctx.getString(R.string.pref_notification_tone_sum); preference.setSummary(name); } } else if (preference instanceof ListPreference) { // For list preferences, look up the correct display value in // the preference's 'entries' list. ListPreference listPreference = (ListPreference) preference; int index = listPreference.findIndexOfValue(stringValue); // Set the summary to reflect the new value. preference.setSummary( index >= 0 ? listPreference.getEntries()[index] : null); } else { // For all other preferences, set the summary to the value's // simple string representation. preference.setSummary(stringValue); } return true; } }; /** * Helper method to determine if the device has an extra-large screen. For * example, 10" tablets are extra-large. */ private static boolean isXLargeTablet(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; } /** * Determines whether the simplified settings UI should be shown. This is * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device * doesn't have newer APIs like {@link PreferenceFragment}, or the device * doesn't have an extra-large screen. In these cases, a single-pane * "simplified" settings UI should be shown. */ private static boolean isSimplePreferences(Context context) { return ALWAYS_SIMPLE_PREFS || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB || !isXLargeTablet(context); } /** * Binds a preference's summary to its value. More specifically, when the * preference's value is changed, its summary (line of text below the * preference title) is updated to reflect the value. The summary is also * immediately updated upon calling this method. The exact display format is * dependent on the type of preference. * * @see #sBindPreferenceSummaryToValueListener */ private static void bindPreferenceSummaryToValue(Preference preference) { // Set the listener to watch for value changes. preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); // Trigger the listener immediately with the preference's // current value. sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, PreferenceManager .getDefaultSharedPreferences(preference.getContext()) .getString(preference.getKey(), "")); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); ScreenUtils.setStatusBarColor(this, getResources().getColor(R.color.dark_grey_home)); LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent(); Toolbar toolbar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false); toolbar.setBackgroundColor(getResources().getColor(R.color.dark_grey_home)); toolbar.setNavigationIcon(getNavigationIcon()); toolbar.setTitleTextColor(getResources().getColor(R.color.white)); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { finish(); } }); root.addView(toolbar, 0); // insert at top activity = this; ctx = getBaseContext(); setupSimplePreferencesScreen(); } protected Drawable getNavigationIcon(){ return new IconicsDrawable(this, GoogleMaterial.Icon.gmd_arrow_back) .sizeDp(24) .paddingDp(2) .colorRes(R.color.white); } /** * Shows the simplified settings UI if the device configuration if the * device configuration dictates that a simplified, single-pane UI should be * shown. */ private void setupSimplePreferencesScreen() { if (!isSimplePreferences(this)) { return; } // Add 'general' preferences. addPreferencesFromResource(R.xml.pref_general); // Add 'notifications' preferences, and a corresponding header. PreferenceCategory fakeHeader2 = new PreferenceCategory(this); fakeHeader2.setTitle(R.string.pref_header_notifications); getPreferenceScreen().addPreference(fakeHeader2); addPreferencesFromResource(R.xml.pref_notification); // Add 'data and sync' preferences, and a corresponding header. //fakeHeader = new PreferenceCategory(this); //fakeHeader.setTitle(R.string.pref_header_data_sync); //getPreferenceScreen().addPreference(fakeHeader); //addPreferencesFromResource(R.xml.pref_data_sync); // Bind the summaries of EditText/List/Dialog/Ringtone preferences to // their values. When their values change, their summaries are updated // to reflect the new value, per the Android Design guidelines. bindPreferenceSummaryToValue(findPreference("display_name")); bindPreferenceSummaryToValue(findPreference("alarm_repeat_frequency")); bindPreferenceSummaryToValue(findPreference("alarm_reminder_window")); bindPreferenceSummaryToValue(findPreference("pref_notification_tone")); //bindPreferenceSummaryToValue(findPreference("check_window_margin")); findPreference("enable_prescriptions_db").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { Boolean checked = (Boolean) newValue; if (checked) { new PopulatePrescriptionDatabaseTask().execute(""); }else{ try { DB.prescriptions().executeRaw("DELETE FROM Prescriptions;"); } catch (SQLException e) { e.printStackTrace(); } } return true; } }); findPreference("alarm_insistent").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object o) { boolean val = (boolean) o; String p = Manifest.permission.WRITE_EXTERNAL_STORAGE; if(val && PermissionUtils.useRunTimePermissions() && !PermissionUtils.hasPermission(activity,p)) { if(PermissionUtils.shouldAskForPermission(activity,p)) PermissionUtils.requestPermissions(activity, new String[]{p}, REQ_CODE_EXTERNAL_STORAGE); else showStupidUserDialog(); return false; } return true; } }); if(!CalendulaApp.isPharmaModeEnabled(this)){ Preference alarmPk = findPreference("alarm_pickup_notifications"); PreferenceScreen preferenceScreen = getPreferenceScreen(); preferenceScreen.removePreference(alarmPk); } } private void showStupidUserDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(activity); // "Remove " + m.name() + "?" builder.setMessage(getString(R.string.permission_dialog_go_to_settings)) .setCancelable(true) .setPositiveButton(getString(R.string.permission_dialog_ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { PermissionUtils.goToAppSettings(activity); } }) .setNegativeButton(getString(R.string.dialog_no_option), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } /** * {@inheritDoc} */ @Override public boolean onIsMultiPane() { return isXLargeTablet(this) && !isSimplePreferences(this); } /** * {@inheritDoc} */ @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void onBuildHeaders(List<Header> target) { if (!isSimplePreferences(this)) { loadHeadersFromResource(R.xml.pref_headers, target); } } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if ("alarm_repeat_frequency".equals(key)) { Log.d("SettingsActivity", "Update " + key); AlarmScheduler.instance().updateAllAlarms(this); } } @Override protected void onResume() { super.onResume(); PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); } @Override protected void onPause() { super.onPause(); PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); } /** * This fragment shows general preferences only. It is used when the * activity is showing a two-pane settings UI. */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class GeneralPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_general); // Bind the summaries of EditText/List/Dialog/Ringtone preferences // to their values. When their values change, their summaries are // updated to reflect the new value, per the Android Design // guidelines. bindPreferenceSummaryToValue(findPreference("example_text")); bindPreferenceSummaryToValue(findPreference("example_list")); } } /** * This fragment shows notification preferences only. It is used when the * activity is showing a two-pane settings UI. */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class NotificationPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.pref_notification); // Bind the summaries of EditText/List/Dialog/Ringtone preferences // to their values. When their values change, their summaries are // updated to reflect the new value, per the Android Design // guidelines. bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone")); } } public class PopulatePrescriptionDatabaseTask extends AsyncTask<String, String, Void> { ProgressDialog dialog; @Override protected Void doInBackground(String... params) { new PopulatePrescriptionDBService().updateIfNeeded(SettingsActivity.this); return null; } @Override protected void onPreExecute() { super.onPreExecute(); dialog = new ProgressDialog(SettingsActivity.this); dialog.setIndeterminate(true); dialog.setCancelable(false); dialog.setMessage(getString(R.string.enable_prescriptions_progress_messgae)); dialog.show(); } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (dialog.isShowing()) { dialog.dismiss(); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case REQ_CODE_EXTERNAL_STORAGE: { PermissionUtils.markedPermissionAsAsked(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { CheckBoxPreference ins = (CheckBoxPreference)findPreference("alarm_insistent"); ins.setChecked(true); } return; } } } }