Java tutorial
/* * Copyright (C) 2016 University of Washington * * 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 org.opendatakit.services.preferences.fragments; import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlertDialog; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Environment; import android.preference.*; import android.preference.Preference.OnPreferenceChangeListener; import android.text.InputFilter; import android.text.Spanned; import android.widget.Toast; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.io.FileUtils; import org.opendatakit.consts.IntentConsts; import org.opendatakit.services.preferences.activities.IOdkAppPropertiesActivity; import org.opendatakit.properties.CommonToolProperties; import org.opendatakit.properties.PropertiesSingleton; import org.opendatakit.services.preferences.PasswordPreferenceScreen; import org.opendatakit.services.R; import org.opendatakit.services.utilities.SettingsUtils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.StringTokenizer; public class ServerSettingsFragment extends PreferenceFragment implements OnPreferenceChangeListener { private static final String t = "ServerSettingsFragment"; private EditTextPreference mServerUrlPreference; private ListPreference mSignOnCredentialPreference; private EditTextPreference mUsernamePreference; private ListPreference mSelectedGoogleAccountPreference; private EditTextPreference mOfficeId; private SettingsUtils settingsUtils; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PropertiesSingleton props = ((IOdkAppPropertiesActivity) this.getActivity()).getProps(); addPreferencesFromResource(R.xml.server_preferences); // not super safe, but we're just putting in this mode to help // administrate // would require code to access it boolean adminMode; adminMode = (this.getArguments() == null) ? false : (this.getArguments().containsKey(IntentConsts.INTENT_KEY_SETTINGS_IN_ADMIN_MODE) ? this.getArguments().getBoolean(IntentConsts.INTENT_KEY_SETTINGS_IN_ADMIN_MODE) : false); String adminPwd = props.getProperty(CommonToolProperties.KEY_ADMIN_PW); boolean adminConfigured = (adminPwd != null && adminPwd.length() != 0); boolean serverAvailable = !adminConfigured || props.getBooleanProperty(CommonToolProperties.KEY_CHANGE_SYNC_SERVER); PreferenceCategory serverCategory = (PreferenceCategory) findPreference( CommonToolProperties.GROUPING_SERVER_CATEGORY); // Initialize the Server URL Text Preference mServerUrlPreference = (EditTextPreference) findPreference(CommonToolProperties.KEY_SYNC_SERVER_URL); if (props.containsKey(CommonToolProperties.KEY_SYNC_SERVER_URL)) { String url = props.getProperty(CommonToolProperties.KEY_SYNC_SERVER_URL); mServerUrlPreference.setSummary(url); mServerUrlPreference.setText(url); } mServerUrlPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { String url = newValue.toString(); // disallow any whitespace if (url.contains(" ") || !url.equals(url.trim())) { Toast.makeText(getActivity().getApplicationContext(), R.string.url_error_whitespace, Toast.LENGTH_SHORT).show(); return false; } // remove all trailing "/"s while (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } boolean isValid = false; try { new URL(url); isValid = true; } catch (MalformedURLException e) { // ignore } if (isValid) { preference.setSummary(newValue.toString()); PropertiesSingleton props = ((IOdkAppPropertiesActivity) ServerSettingsFragment.this .getActivity()).getProps(); props.setProperty(CommonToolProperties.KEY_SYNC_SERVER_URL, newValue.toString()); props.setProperty(CommonToolProperties.KEY_ROLES_LIST, ""); props.setProperty(CommonToolProperties.KEY_USERS_LIST, ""); return true; } else { Toast.makeText(getActivity().getApplicationContext(), R.string.url_error, Toast.LENGTH_SHORT) .show(); return false; } } }); mServerUrlPreference.setSummary(mServerUrlPreference.getText()); mServerUrlPreference.getEditText().setFilters(new InputFilter[] { getReturnFilter() }); mServerUrlPreference.setEnabled(serverAvailable || adminMode); boolean credentialAvailable = !adminConfigured || props.getBooleanProperty(CommonToolProperties.KEY_CHANGE_AUTHENTICATION_TYPE); mSignOnCredentialPreference = (ListPreference) findPreference(CommonToolProperties.KEY_AUTHENTICATION_TYPE); if (props.containsKey(CommonToolProperties.KEY_AUTHENTICATION_TYPE)) { String chosenFontSize = props.getProperty(CommonToolProperties.KEY_AUTHENTICATION_TYPE); CharSequence entryValues[] = mSignOnCredentialPreference.getEntryValues(); for (int i = 0; i < entryValues.length; i++) { String entry = entryValues[i].toString(); if (entry.equals(chosenFontSize)) { mSignOnCredentialPreference.setValue(entry); mSignOnCredentialPreference.setSummary(mSignOnCredentialPreference.getEntries()[i]); } } } mSignOnCredentialPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int index = ((ListPreference) preference).findIndexOfValue(newValue.toString()); String entry = (String) ((ListPreference) preference).getEntries()[index]; ((ListPreference) preference).setSummary(entry); PropertiesSingleton props = ((IOdkAppPropertiesActivity) ServerSettingsFragment.this.getActivity()) .getProps(); props.setProperty(CommonToolProperties.KEY_AUTHENTICATION_TYPE, newValue.toString()); props.setProperty(CommonToolProperties.KEY_ROLES_LIST, ""); props.setProperty(CommonToolProperties.KEY_USERS_LIST, ""); return true; } }); mSignOnCredentialPreference.setEnabled(credentialAvailable || adminMode); ////////////////// mUsernamePreference = (EditTextPreference) findPreference(CommonToolProperties.KEY_USERNAME); if (props.containsKey(CommonToolProperties.KEY_USERNAME)) { String user = props.getProperty(CommonToolProperties.KEY_USERNAME); mUsernamePreference.setSummary(user); mUsernamePreference.setText(user); } mUsernamePreference.setOnPreferenceChangeListener(this); mUsernamePreference.getEditText().setFilters(new InputFilter[] { getReturnFilter() }); boolean usernamePasswordAvailable = !adminConfigured || props.getBooleanProperty(CommonToolProperties.KEY_CHANGE_USERNAME_PASSWORD); mUsernamePreference.setEnabled(usernamePasswordAvailable || adminMode); PasswordPreferenceScreen passwordScreen = (PasswordPreferenceScreen) this .findPreference(CommonToolProperties.GROUPING_PASSWORD_SCREEN); passwordScreen.setCallback(new PasswordPreferenceScreen.PasswordActionCallback() { @Override public void showPasswordDialog() { // DialogFragment.show() will take care of adding the fragment // in a transaction. We also want to remove any currently showing // dialog, so make our own transaction and take care of that here. FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager() .findFragmentByTag(CommonToolProperties.GROUPING_PASSWORD_SCREEN); if (prev != null) { ft.remove(prev); } // Create and show the dialog. PasswordDialogFragment newFragment = PasswordDialogFragment .newPasswordDialog(CommonToolProperties.KEY_PASSWORD); newFragment.show(ft, CommonToolProperties.GROUPING_PASSWORD_SCREEN); } }); passwordScreen.setEnabled((usernamePasswordAvailable || adminMode)); mSelectedGoogleAccountPreference = (ListPreference) findPreference(CommonToolProperties.KEY_ACCOUNT); // get list of google accounts final Account[] accounts = AccountManager.get(getActivity().getApplicationContext()) .getAccountsByType("com.google"); ArrayList<String> accountEntries = new ArrayList<String>(); ArrayList<String> accountValues = new ArrayList<String>(); for (int i = 0; i < accounts.length; i++) { accountEntries.add(accounts[i].name); accountValues.add(accounts[i].name); } accountEntries.add(getString(R.string.no_account)); accountValues.add(""); mSelectedGoogleAccountPreference.setEntries(accountEntries.toArray(new String[accountEntries.size()])); mSelectedGoogleAccountPreference.setEntryValues(accountValues.toArray(new String[accountValues.size()])); mSelectedGoogleAccountPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int index = ((ListPreference) preference).findIndexOfValue(newValue.toString()); String value = (String) ((ListPreference) preference).getEntryValues()[index]; preference.setSummary(value); PropertiesSingleton props = ((IOdkAppPropertiesActivity) ServerSettingsFragment.this.getActivity()) .getProps(); props.setProperty(CommonToolProperties.KEY_ACCOUNT, value); props.setProperty(CommonToolProperties.KEY_AUTH, ""); props.setProperty(CommonToolProperties.KEY_ROLES_LIST, ""); props.setProperty(CommonToolProperties.KEY_USERS_LIST, ""); return true; } }); String googleAccount = props.getProperty(CommonToolProperties.KEY_ACCOUNT); if (googleAccount == null) { googleAccount = ""; } boolean found = false; for (int i = 0; i < accountValues.size(); ++i) { if (googleAccount.equals(accountValues.get(i))) { mSelectedGoogleAccountPreference.setValue(googleAccount); mSelectedGoogleAccountPreference.setSummary(accountEntries.get(i)); found = true; } } if (!found) { // clear the property (prevents clarice@ from being identified) props.setProperty(CommonToolProperties.KEY_ACCOUNT, ""); // set to "none" mSelectedGoogleAccountPreference.setValue(accountValues.get(accountValues.size() - 1)); mSelectedGoogleAccountPreference.setSummary(accountEntries.get(accountEntries.size() - 1)); } Boolean googleAccountAvailable = props.getBooleanProperty(CommonToolProperties.KEY_CHANGE_GOOGLE_ACCOUNT); mSelectedGoogleAccountPreference.setEnabled(googleAccountAvailable || adminMode); if (!adminMode && (!serverAvailable || !credentialAvailable || !usernamePasswordAvailable || !googleAccountAvailable)) { serverCategory.setTitle(R.string.server_restrictions_apply); } mOfficeId = (EditTextPreference) findPreference("common.officeID"); this.settingsUtils = new SettingsUtils(getActivity().getApplicationContext()); String officeId = settingsUtils.getOfficeIdFromFile(); if (officeId != null && !officeId.equals("null")) { mOfficeId.setSummary(officeId); mOfficeId.setText(officeId); } mOfficeId.setOnPreferenceChangeListener(this); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); PropertiesSingleton props = ((IOdkAppPropertiesActivity) this.getActivity()).getProps(); props.writeProperties(); } @Override public void onPause() { PropertiesSingleton props = ((IOdkAppPropertiesActivity) this.getActivity()).getProps(); props.writeProperties(); super.onPause(); } /** * Disallows whitespace from user entry * * @return */ private InputFilter getWhitespaceFilter() { InputFilter whitespaceFilter = new InputFilter() { public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { for (int i = start; i < end; i++) { if (Character.isWhitespace(source.charAt(i))) { return ""; } } return null; } }; return whitespaceFilter; } /** * Disallows carriage returns from user entry * * @return */ private InputFilter getReturnFilter() { InputFilter returnFilter = new InputFilter() { public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { for (int i = start; i < end; i++) { if (Character.getType((source.charAt(i))) == Character.CONTROL) { return ""; } } return null; } }; return returnFilter; } public void createOfficeIdConfirmChangeDialog(final Preference preference, final Object newValue) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.confirm_change_office_id); builder.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { settingsUtils.deleteAllForms(); settingsUtils.saveOfficeIdToFile(newValue.toString()); preference.setSummary((CharSequence) newValue); mOfficeId.setText(newValue.toString()); dialog.dismiss(); } }); builder.setCancelable(true); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.create().show(); } /** * Generic listener that sets the summary to the newly selected/entered value */ @Override public boolean onPreferenceChange(Preference preference, Object newValue) { PropertiesSingleton props = ((IOdkAppPropertiesActivity) this.getActivity()).getProps(); if (props.containsKey(preference.getKey())) { preference.setSummary((CharSequence) newValue); props.setProperty(preference.getKey(), newValue.toString()); props.setProperty(CommonToolProperties.KEY_ROLES_LIST, ""); props.setProperty(CommonToolProperties.KEY_USERS_LIST, ""); } else if (preference.getKey().equals("common.officeID")) { createOfficeIdConfirmChangeDialog(preference, newValue); return false; } else { throw new IllegalStateException("Unexpected case"); } return true; } }