src/main/java/nitezh/ministock/activities/PreferencesActivity.java
/*
The MIT License
Copyright (c) 2013 Nitesh Patel http://niteshpatel.github.io/ministocks
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package nitezh.ministock.activities;
import android.app.AlertDialog;
import android.app.SearchManager;
import android.app.TimePickerDialog;
import android.appwidget.AppWidgetManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.widget.RemoteViews;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TimePicker;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import nitezh.ministock.DialogTools;
import nitezh.ministock.MimeSendTask;
import nitezh.ministock.R;
import nitezh.ministock.SaveFile;
import nitezh.ministock.UserData;
import nitezh.ministock.activities.widget.Bonobo_widget_service;
import nitezh.ministock.activities.widget.WidgetProviderBase;
import nitezh.ministock.utils.DateTools;
import nitezh.ministock.utils.VersionTools;
import static android.content.SharedPreferences.Editor;
import static android.content.SharedPreferences.OnSharedPreferenceChangeListener;
public class PreferencesActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
// Constants
private static final int STRING_TYPE = 0;
private static final int LIST_TYPE = 1;
private static final int CHECKBOX_TYPE = 2;
// Public variables
public static int mAppWidgetId = 0;
// Private
private static boolean mPendingUpdate = false;
private static String mSymbolSearchKey = "";
private final String CHANGE_LOG = "";
// TODO: Allow comma when entering numbers;
private final Pattern VALID_EMAIL_ADDRESS_REGEX =
Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
// Fields for time pickers
private TimePickerDialog.OnTimeSetListener mTimeSetListener;
private String mTimePickerKey = null;
private int mHour = 0;
private int mMinute = 0;
//usedforImport
private List<String> csvSymbols;
private boolean isValidEmail(String emailStr) {
Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(emailStr);
return matcher.find();
}
private String getChangeLog() {
return CHANGE_LOG;
}
@Override
public void onNewIntent(Intent intent) {
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
setPreference(mSymbolSearchKey, intent.getDataString(), intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
} else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
startSearch(query, false, null, false);
} else if (Intent.ACTION_EDIT.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
startSearch(query, false, null, false);
}
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
// Each widget has its own set of preferences
return super.getSharedPreferences(name + mAppWidgetId, mode);
}
private SharedPreferences getAppPreferences() {
// Convenience method to get global preferences
return super.getSharedPreferences(getString(R.string.prefs_name), 0);
}
@Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
private void removePref(PreferenceScreen screen, String name) {
try {
screen.removePreference(findPreference(name));
} catch (Exception ignored) {
}
}
private void removePref(String screenName, String name) {
PreferenceScreen screen = (PreferenceScreen) findPreference(screenName);
try {
screen.removePreference(findPreference(name));
} catch (Exception ignored) {
}
}
private void showRecentChanges() {
// Return if the change log has already been viewed
if (getAppPreferences().getString("change_log_viewed", "").equals(VersionTools.BUILD)) {
return;
}
// Cleanup preferences files
UserData.cleanupPreferenceFiles(getApplicationContext());
@SuppressWarnings("rawtypes") Callable callable = new Callable() {
@Override
public Object call() throws Exception {
// Ensure we don't show this again
SharedPreferences preferences = getAppPreferences();
Editor editor = preferences.edit();
editor.putString("change_log_viewed", VersionTools.BUILD);
// Set first install if not set
if (preferences.getString("install_date", "").equals("")) {
editor.putString("install_date", new SimpleDateFormat("yyyyMMdd").format(new Date()).toUpperCase());
}
editor.apply();
return new Object();
}
};
DialogTools.alertWithCallback(this, "BUILD " + VersionTools.BUILD,
getChangeLog(), "Close", null, callable, null);
}
@Override
protected void onResume() {
super.onResume();
showRecentChanges();
PreferenceScreen screen = getPreferenceScreen();
SharedPreferences sharedPreferences = screen.getSharedPreferences();
// Hide preferences for certain widget sizes
int widgetSize = sharedPreferences.getInt("widgetSize", 0);
// Remove extra stocks
if (widgetSize == 0 || widgetSize == 1) {
PreferenceScreen stock_setup = (PreferenceScreen) findPreference("stock_setup");
for (int i = 5; i < 11; i++)
removePref(stock_setup, "Stock" + i);
}
// Remove extra widget views
if (widgetSize == 1 || widgetSize == 3) {
PreferenceScreen widget_views = (PreferenceScreen) findPreference("widget_views");
removePref(widget_views, "show_percent_change");
removePref(widget_views, "show_portfolio_change");
removePref(widget_views, "show_profit_daily_change");
removePref(widget_views, "show_profit_change");
}
// Hide Feedback option if not relevant
String install_date = getAppPreferences().getString("install_date", null);
if (DateTools.elapsedDays(install_date) < 30)
removePref("about_menu", "rate_app");
// Initialise the summaries when the preferences screen loads
Map<String, ?> map = sharedPreferences.getAll();
for (String key : map.keySet())
updateSummaries(sharedPreferences, key);
// Update version number
findPreference("version").setSummary("BUILD " + VersionTools.BUILD);
// Force update of global preferences
// TODO Ensure the items below are included in the above list
// rather than updating these items twice (potentially)
updateSummaries(sharedPreferences, "update_interval");
updateSummaries(sharedPreferences, "update_start");
updateSummaries(sharedPreferences, "update_end");
updateSummaries(sharedPreferences, "update_weekend");
// Set up a listener whenever a key changes
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// Perform some custom handling of some values
if (key.startsWith("Stock") && !key.endsWith("_summary")) {
updateStockValue(sharedPreferences, key);
// Mark stock changed as dirty
mPendingUpdate = true;
} else if (key.equals("update_interval")) {
updateGlobalPref(sharedPreferences, key, LIST_TYPE);
// Warning massage if necessary
if (sharedPreferences.getString(key, "").equals("900000") || sharedPreferences.getString(key, "").equals("300000")) {
String title = "Short update interval";
String body = "Note that choosing a short update interval may drain your battery faster.";
DialogTools.showSimpleDialog(this, title, body);
}
} else if (key.equals("update_start") || key.equals("update_end")) {
updateGlobalPref(sharedPreferences, key, STRING_TYPE);
} else if (key.equals("update_weekend")) {
updateGlobalPref(sharedPreferences, key, CHECKBOX_TYPE);
}
// Update the summary whenever the preference is changed
updateSummaries(sharedPreferences, key);
}
private void updateStockValue(SharedPreferences sharedPreferences, String key) {
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
// Massages the value: remove whitespace and upper-case
String value = sharedPreferences.getString(key, "");
value = value.replace(" ", "");
value = value.toUpperCase();
Editor editor = sharedPreferences.edit();
editor.putString(key, value);
editor.apply();
// Also update the UI
EditTextPreference preference = (EditTextPreference) findPreference(key);
preference.setText(value);
// Set up a listener whenever a key changes
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
private void updateFromGlobal(SharedPreferences sharedPreferences, String key, int valType) {
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
// Update the widget preferences with the interval
Editor editor = sharedPreferences.edit();
if (valType == STRING_TYPE) {
String value = getAppPreferences().getString(key, "");
if (!value.equals("")) {
editor.putString(key, value);
}
} else if (valType == LIST_TYPE) {
String value = getAppPreferences().getString(key, "");
if (!value.equals("")) {
editor.putString(key, value);
((ListPreference) findPreference(key)).setValue(value);
}
} else if (valType == CHECKBOX_TYPE) {
Boolean value = getAppPreferences().getBoolean(key, false);
editor.putBoolean(key, value);
((CheckBoxPreference) findPreference(key)).setChecked(value);
}
editor.apply();
// Set up a listener whenever a key changes
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
private void updateGlobalPref(SharedPreferences sharedPreferences, String key, int valType) {
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
// Update the global preferences with the widget update interval
Editor editor = getAppPreferences().edit();
if (valType == STRING_TYPE || valType == LIST_TYPE)
editor.putString(key, sharedPreferences.getString(key, ""));
else if (valType == CHECKBOX_TYPE)
editor.putBoolean(key, sharedPreferences.getBoolean(key, false));
editor.apply();
// Set up a listener whenever a key changes
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
private void showDisclaimer() {
String title = "License";
String body = "The MIT License (MIT)<br/><br/>Copyright © 2013 Nitesh Patel<br/><br />Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:<br /><br />The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.<br/><br/>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.";
DialogTools.showSimpleDialog(this, title, body);
}
private void showAttributions() {
String title = "Attributions";
String body = "Data provided for free by IEX (https://iextrading.com/developer).";
DialogTools.showSimpleDialog(this, title, body);
}
private void showTermsOfService() {
String title = "Terms of Service (data)";
String body = "See https://iextrading.com/api-exhibit-a";
DialogTools.showSimpleDialog(this, title, body);
}
private void showHelp() {
String title = "Entering stocks";
String body = "<b>Entering stock symbols</b><br/><br />Stock symbols must be in the Yahoo format, which you can look up on the Yahoo Finance website.";
DialogTools.showSimpleDialog(this, title, body);
}
private void showHelpPrices() {
String title = "Updating prices";
String body = "You can set how often, and when the widget updates in the Advanced settings menu. The setting applies globally to all the widgets.<br /><br />Stock price information is provided by Yahoo Finance, and there may be a delay (from real-time prices, to up to 30 minutes) for some exchanges.<br /><br />Note that the time in the lower-left of the widget is the time that the data was retrieved from Yahoo, not the time of the live price.<br /><br />If an internet connection is not present when an update occurs, the widget will just use the last shown data, and the time for that data.<br /><br /><b>Update prices now feature</b><br /><br />This will update the prices in all your widgets, if there is an internet connection available.";
DialogTools.showSimpleDialog(this, title, body);
}
private void showTimePickerDialog(Preference preference, String defaultValue) {
// Get the raw value from the preferences
String value = preference.getSharedPreferences().getString(preference.getKey(), defaultValue);
mHour = 0;
mMinute = 0;
if (value != null && !value.equals("")) {
String[] items = value.split(":");
mHour = Integer.parseInt(items[0]);
mMinute = Integer.parseInt(items[1]);
}
mTimePickerKey = preference.getKey();
new TimePickerDialog(this, mTimeSetListener, mHour, mMinute, true).show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != 1) {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void setTimePickerPreference(int hourOfDay, int minute) {
// Set the preference value
SharedPreferences preferences = getPreferenceScreen().getSharedPreferences();
Editor editor = preferences.edit();
editor.putString(mTimePickerKey, String.valueOf(hourOfDay) + ":" + String.valueOf(minute));
editor.apply();
// Also update the UI
updateSummaries(getPreferenceScreen().getSharedPreferences(), mTimePickerKey);
}
private void setPreference(String key, String value, String summary) {
// Return if no key
if (key.equals("")) {
return;
}
// Set the stock value
SharedPreferences preferences = getPreferenceScreen().getSharedPreferences();
// Ignore the remove and manual entry options
if (value.endsWith("and close")) {
value = "";
} else if (value.startsWith("Use ")) {
value = value.replace("Use ", "");
}
// Set dirty
mPendingUpdate = true;
Editor editor = preferences.edit();
editor.putString(key, value);
editor.putString(key + "_summary", summary);
editor.apply();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// Hook the About preference to the About (MinistocksActivity) activity
Preference about = findPreference("about");
about.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showDisclaimer();
return true;
}
});
// Hook up the help preferences
Preference help = findPreference("help");
help.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showHelp();
return true;
}
});
// Hook up the symbol search for the stock preferences
for (int i = 1; i < 11; i++) {
String key = "Stock" + i;
findPreference(key).setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
mSymbolSearchKey = preference.getKey();
// Start search with current value as query
String query = preference.getSharedPreferences().getString(mSymbolSearchKey, "");
startSearch(query, false, null, false);
return true;
}
});
}
// Hook up the help preferences
Preference help_usage = findPreference("help_usage");
help_usage.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showHelpUsage();
return true;
}
});
// Hook the Help preference to the Help activity
Preference help_portfolio = findPreference("help_portfolio");
help_portfolio.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showHelpPortfolio();
return true;
}
});
// Hook the Help preference to the Help activity
Preference help_prices = findPreference("help_prices");
help_prices.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showHelpPrices();
return true;
}
});
// Hook the Update preference to the Help activity
Preference updateNow = findPreference("update_now");
updateNow.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
mPendingUpdate = true;
finish();
return true;
}
});
final Preference sendEmail = findPreference("send_email");
sendEmail.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
sendEmailToUser();
return true;
}
});
final Preference importFile = findPreference("open_file");
importFile.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
try {
importStocks();
} catch (IOException e) {
e.printStackTrace();
}
//Toast.makeText(PreferencesActivity.this, "This is my import message!", Toast.LENGTH_LONG).show();
return true;
}
});
// Hook the PortfolioActivity preference to the PortfolioActivity activity
Preference portfolio = findPreference("portfolio");
portfolio.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(PreferencesActivity.this, PortfolioActivity.class);
startActivity(intent);
return true;
}
});
// Hook the Backup widget option to the backup widget method
Preference backup_widget = findPreference("backup_widget");
backup_widget.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
DialogTools.InputAlertCallable callable = new DialogTools.InputAlertCallable() {
@Override
public Object call() throws Exception {
UserData.backupWidget(PreferencesActivity.this, mAppWidgetId, this.getInputValue());
return new Object();
}
};
DialogTools.inputWithCallback(PreferencesActivity.this,
"Backup this widget", "Please enter a name for this backup:",
"OK", "Cancel",
"Widget <" + mAppWidgetId + "> from " + DateTools.getNowAsString(),
callable);
return true;
}
});
// Hook the Restore widget option to the restore widget method
Preference restore_widget = findPreference("restore_widget");
restore_widget.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
CharSequence[] backupNames = UserData.getWidgetBackupNames(PreferencesActivity.this);
// If there are no backups show an appropriate dialog
if (backupNames == null) {
DialogTools.showSimpleDialog(PreferencesActivity.this,
"No backups available", "There were no widget backups to restore.");
return true;
}
// If there are backups then show the list
DialogTools.InputAlertCallable callable = new DialogTools.InputAlertCallable() {
@Override
public Object call() throws Exception {
UserData.restoreWidget(PreferencesActivity.this, mAppWidgetId, this.getInputValue());
return new Object();
}
};
DialogTools.choiceWithCallback(PreferencesActivity.this,
"Select a widget backup to restore", "Cancel", backupNames, callable);
return true;
}
});
// Hook the Delete widget backup option to the delete widget backup method
Preference delete_widget_backup = findPreference("delete_widget_backup");
delete_widget_backup.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
CharSequence[] backupNames = UserData.getWidgetBackupNames(PreferencesActivity.this);
// If there are no backups show an appropriate dialog
if (backupNames == null) {
DialogTools.showSimpleDialog(PreferencesActivity.this,
"No backups available to delete", "There were no widget backups to delete.");
return true;
}
// If there are backups then show the list
DialogTools.InputAlertCallable callable = new DialogTools.InputAlertCallable() {
@Override
public Object call() throws Exception {
UserData.deleteWidgetBackup(PreferencesActivity.this, this.getInputValue());
return new Object();
}
};
DialogTools.choiceWithCallback(PreferencesActivity.this,
"Select a widget backup to delete", "Cancel", backupNames, callable);
return true;
}
});
// Hook Rate MinistocksActivity preference to the market link
Preference rate_app = findPreference("rate_app");
rate_app.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showFeedbackOption();
return true;
}
});
// Hook the Online help preference to the online help link
Preference online_help = findPreference("online_help");
online_help.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showOnlineHelp();
return true;
}
});
// Hook the Online faqs preference to the online faqs link
Preference online_faqs = findPreference("online_faqs");
online_faqs.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showOnlineFaqs();
return true;
}
});
// Hook the Feedback preference to the PortfolioActivity activity
Preference feedback = findPreference("feedback");
feedback.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
// Open the e-mail client with destination and subject
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("message/rfc822");
String[] toAddress = {"nitezh@gmail.com"};
intent.putExtra(Intent.EXTRA_EMAIL, toAddress);
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name) + " BUILD " + VersionTools.BUILD);
intent.setType("message/rfc822");
// In case we can't launch e-mail, show a dialog
try {
startActivity(intent);
return true;
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Show dialog if launching e-mail fails
DialogTools.showSimpleDialog(getApplicationContext(), "Launching e-mail failed", "We were unable to launch your e-mail client automatically.<br /><br />Our e-mail address for support and feedback is nitezh@gmail.com");
return true;
}
});
// Hook the Change history preference to the Change history dialog
Preference change_history = findPreference("change_history");
change_history.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showChangeLog();
return true;
}
});
// Hook the Attributions preference to the Attributions dialog
Preference attributions = findPreference("attributions");
attributions.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showAttributions();
return true;
}
});
// Hook the Terms of Service preference to the Terms of Service dialog
Preference termsOfService = findPreference("termsOfService");
termsOfService.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showTermsOfService();
return true;
}
});
// Callback received when the user sets the time in the dialog
mTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
setTimePickerPreference(hourOfDay, minute);
}
};
// Hook the Update schedule preferences up
Preference update_start = findPreference("update_start");
update_start.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showTimePickerDialog(preference, "00:00");
return true;
}
});
Preference update_end = findPreference("update_end");
update_end.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showTimePickerDialog(preference, "23:59");
return true;
}
});
}
private void updateSummaries(SharedPreferences sharedPreferences, String key) {
Preference preference = findPreference(key);
if (preference != null) {
// Initialise the Stock summaries
if (sharedPreferences.contains(key) && key.startsWith("Stock") && !key.endsWith("_summary")) {
// Update the summary based on the stock value
String value = sharedPreferences.getString(key, "");
String summary = sharedPreferences.getString(key + "_summary", "");
// Set the title
if (value.equals("")) {
value = key.replace("Stock", "Stock ");
summary = "Set symbol";
}
// Set the summary appropriately
else if (summary.equals("")) {
summary = "No description";
}
preference.setTitle(value);
preference.setSummary(summary);
}
// Initialise the ListPreference summaries
else if (key.startsWith("background") || key.startsWith("updated_colour") || key.startsWith("updated_display") || key.startsWith("text_style")) {
String value = sharedPreferences.getString(key, "");
preference.setSummary("Selected: " + value.substring(0, 1).toUpperCase() + value.substring(1));
}
// Initialise the Update interval
else if (key.startsWith("update_interval")) {
// Update summary based on selected value
String displayValue = "30 minutes";
String value = getAppPreferences().getString(key, "1800000");
switch (value) {
case "300000":
displayValue = "5 minutes";
break;
case "900000":
displayValue = "15 minutes";
break;
case "1800000":
displayValue = "30 minutes";
break;
case "3600000":
displayValue = "One hour";
break;
case "10800000":
displayValue = "Three hours";
break;
case "86400000":
displayValue = "Daily";
break;
}
preference.setSummary("Selected: " + displayValue);
// Update the value of the update interval
updateFromGlobal(sharedPreferences, "update_interval", LIST_TYPE);
}
// Update time picker summaries
else if (key.equals("update_start") || key.equals("update_end")) {
String value = getAppPreferences().getString(key, null);
mHour = 0;
mMinute = 0;
if (value != null) {
String[] items = value.split(":");
mHour = Integer.parseInt(items[0]);
mMinute = Integer.parseInt(items[1]);
}
preference.setSummary("Time set: " + DateTools.timeDigitPad(mHour) + ":" + DateTools.timeDigitPad(mMinute));
// Update the value of the update limits
updateFromGlobal(sharedPreferences, key, STRING_TYPE);
} else if (key.equals("update_weekend")) {
updateFromGlobal(sharedPreferences, key, CHECKBOX_TYPE);
}
}
}
@Override
protected void onStop() {
super.onStop();
// Update the widget when we quit the preferences, and if the dirty,
// flag is true then do a web update, otherwise do a regular update
if (mPendingUpdate) {
mPendingUpdate = false;
WidgetProviderBase.updateWidgets(getApplicationContext(),
WidgetProviderBase.UpdateType.VIEW_UPDATE);
} else {
WidgetProviderBase.updateWidgetAsync(getApplicationContext(), mAppWidgetId,
WidgetProviderBase.UpdateType.VIEW_NO_UPDATE);
}
finish();
}
private void showHelpUsage() {
String title = "Selecting widget views";
String body = "The widget has multiple views that display different information.<br /><br />These views can be turned on from the AppWidgetProvider views menu in settings.<br /><br />Once selected, the views can be changed on your home screen by touching the right-side of the widget.<br /><br />If a stock does not have information for a particular view, then the daily percentage change will instead be displayed for that stock in blue.<br /><br /><b>Daily change %</b><br /><br />Shows the current stock price with the daily percentage change.<br /><br /><b>Daily change (DA)</b><br /><br />Shows the current stock price with the daily price change.<br /><br /><b>Total change % (PF T%)</b><br /><br />Shows the current stock price with the total percentage change from the buy price in the portfolio.<br /><br /><b>Total change (PF TA)</b><br /><br />Shows the current stock price with the total price change from the buy price in the portfolio.<br /><br /><b>Total change AER % (PF AER)</b><br /><br />Shows the current stock price with the annualised percentage change using the buy price in the portfolio.<br /><br /><b>P/L daily change % (P/L D%)</b><br /><br />Shows your current holding value with the daily percentage change.<br /><br /><b>P/L daily change (P/L DA)</b><br /><br />Shows your current holding value with the daily price change.<br /><br /><b>P/L total change % (P/L T%)</b><br /><br />Shows your current holding value with the total percentage change from the buy cost in the portfolio.<br /><br /><b>P/L total change (P/L TA)</b><br /><br />Shows your current holding value with the total value change from the buy cost in the portfolio.<br /><br /><b>P/L total change AER (P/L AER)</b><br /><br />Shows your current holding value with the annualised percentage change using the buy cost in the portfolio.";
DialogTools.showSimpleDialog(this, title, body);
}
private void showHelpPortfolio() {
String title = "Using the portfolio";
String body = "On the portfolio screen you will see all the stocks that you have entered in your widgets in one list.<br /><br />You can touch an item to enter your stock purchase details.<br /><br /><b>Entering purchase details</b><br /><br />Enter the price that you bought the stock for, this will then be used for the PortfolioActivity and Profit and loss widget views.<br /><br />The Date is optional, and will be used for the AER rate on the portfolio AER and profit and loss AER views.<br /><br />The Quantity is optional, and will be used to calculate your holdings for the profit and loss views. You may use negative values to simulate a short position.<br /><br />The High price limit and Low price limit are optional. When the current price hits these limits, the price color will change in the widget.<br /><br /><b>Removing purchase details</b><br /><br />To remove purchase and alert details, long press the portfolio item and then choose the Clear details option.";
DialogTools.showSimpleDialog(this, title, body);
}
private void sendEmailToUser() {
// Set up the input
final EditText input = new EditText(this);
input.setId(R.id.emailFieldID);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
CharSequence colors[] = new CharSequence[] {"Save File On Device", "Send File to Email"};
AlertDialog.Builder fileOrEmailAlert = new AlertDialog.Builder(this);
fileOrEmailAlert.setTitle("Export Method");
fileOrEmailAlert.setItems(colors, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 1)
{
AlertDialog builder = new AlertDialog.Builder(PreferencesActivity.this)
.setTitle("Enter Destination E-mail Address")
.setPositiveButton("Send", null)
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setView(input)
.create();
builder.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(final DialogInterface dialogInterface) {
Button button = ((AlertDialog) dialogInterface).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String email = input.getText().toString();
if (email.length() > 0 && isValidEmail(email)) {
new MimeSendTask(PreferencesActivity.this, email).execute();
dialogInterface.dismiss();
} else {
new AlertDialog.Builder(PreferencesActivity.this)
.setTitle("Verify Input")
.setMessage("Please enter a valid e-mail address format")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
}
})
.show();
}
}
});
}
});
builder.show();
}
else{
AlertDialog alertUserOfFileDialog = new AlertDialog.Builder(PreferencesActivity.this).create();
alertUserOfFileDialog.setTitle("File Save");
alertUserOfFileDialog.setMessage("File Has Been Saved in DataFolder.");
alertUserOfFileDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
System.out.println("it works");
new SaveFile().execute();
dialog.dismiss();
}
});
alertUserOfFileDialog.show();
}
}
});
fileOrEmailAlert.show();
}
private void showChangeLog() {
String title = "BUILD " + VersionTools.BUILD;
String body = CHANGE_LOG;
DialogTools.showSimpleDialog(this, title, body);
}
private void showOnlineHelp() {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://niteshpatel.github.io/ministocks/help.html"));
startActivity(browserIntent);
}
private void showOnlineFaqs() {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://niteshpatel.github.io/ministocks/faq.html"));
startActivity(browserIntent);
}
private void showFeedbackOption() {
@SuppressWarnings("rawtypes") Callable callable = new Callable() {
@Override
public Object call() throws Exception {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=nitezh.ministock")));
return new Object();
}
};
DialogTools.alertWithCallback(this, "Rate MinistocksActivity",
"Please support MinistocksActivity by giving the application a 5 star rating in the android market.<br /><br />Motivation to continue to improve the product and add new features comes from positive feedback and ratings.",
"Rate it!", "Close", callable, null);
}
private List <String> openStocksFile()throws IOException {
List <String> symbols = new ArrayList<String>();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "stocks.csv");
if(file.exists()) {
FileInputStream fis = new FileInputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "stocks.csv"));
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
String line;
while ((line = bufferedReader.readLine()) != null) {
symbols.add(line);
}
bufferedReader.close();
}
else {
Toast.makeText(PreferencesActivity.this, "FILE <<stocks.cvs>> DOES NOT EXIST",
Toast.LENGTH_LONG).show();
}
return symbols;
}
private void createQuotesFromCSV(List<String> csvSymbols) {
String first;
int i = 1;
for(String s : csvSymbols){
first = s;
try{
setPreference("Stock"+i,s , "");
i++;
}
catch(Exception e){
e.printStackTrace();
setPreference("Stock"+csvSymbols.size(), first, "");
}
}
}
private void importStocks() throws IOException {
RemoteViews remoteViews= new RemoteViews(getApplicationContext().getPackageName(),R.layout.bonobo_widget_layout);
csvSymbols = openStocksFile();
createQuotesFromCSV(csvSymbols);
Intent intent = new Intent(getApplicationContext(), Bonobo_widget_service.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setRemoteAdapter( R.id.widgetCollectionList, intent);
// Updates the widget ListView immediately
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
appWidgetManager.notifyAppWidgetViewDataChanged(mAppWidgetId, R.id.widgetCollectionList);
}
}