package com.nuscomputing.ivle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
import android.provider.Settings;
@TargetApi(11)
public class SettingsFragment extends PreferenceFragment {
// {{{ properties
/** TAG for logging */
public static final String TAG = "SettingsFragment";
/** The "Check for Updates" alert dialog */
private AlertDialog mCheckForUpdatesDialog;
/** The "Check for Updates" preference */
private Preference mCheckForUpdatesPreference;
// }}}
// {{{ methods
/** Called when the activity is first created. */
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Set up the preferences tree.
addPreferencesFromResource(R.layout.settings_fragment);
// Set up some options in the preferences tree.
setUpAccount();
setUpAddAccount();
setUpManageAccounts();
setUpAbout();
setUpCheckForUpdates();
setUpSendFeedback();
// Create an AlertDialog for "Check for Updates".
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.settings_fragment_update_available_body)
.setCancelable(true)
.setTitle(R.string.settings_fragment_update_available)
.setNegativeButton(R.string.cancel, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
mCheckForUpdatesDialog = builder.create();
// Was the "Check for Updates" dialog being shown?
if (savedInstanceState != null && savedInstanceState.getBoolean("checkForUpdatesDialog", false)) {
getLoaderManager().initLoader(DataLoader.LOADER_CHECK_FOR_UPDATES, new Bundle(), new CheckForUpdatesLoaderCallbacks());
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Is the "Check for Updates" dialog being shown?
outState.putBoolean("checkForUpdatesDialog", mCheckForUpdatesDialog.isShowing());
mCheckForUpdatesDialog.dismiss();
}
@Override
public void onResume() {
super.onResume();
// Reload the accounts list.
setUpAccount();
}
/**
* Method: setUpAccounts
* Populates the accounts list.
*/
private void setUpAccount() {
// Obtain an instance of AccountManager.
AccountManager am = AccountManager.get(getActivity());
Account[] accounts = am.getAccountsByType(Constants.ACCOUNT_TYPE);
// Obtain the accounts preference.
ListPreference accountsPreference = (ListPreference) findPreference("account");
// Reset the state of the preference.
accountsPreference.setEnabled(true);
// Populate the list.
String[] accountEntries = new String[accounts.length];
for (int i = 0; i < accounts.length; i++) {
accountEntries[i] = accounts[i].name;
}
accountsPreference.setEntries(accountEntries);
accountsPreference.setEntryValues(accountEntries);
// There are no accounts, disable this.
if (accounts.length == 0) {
accountsPreference.setSummary(getString(R.string.settings_fragment_no_accounts_configured));
accountsPreference.setEnabled(false);
}
// If there is only one account, it should be the current and default one.
if (accounts.length == 1) {
accountsPreference.setSummary(accounts[0].name);
}
// If is more than one account, search for the current active one.
if (accounts.length > 1) {
Account currentAccount = AccountUtils.getActiveAccount(getActivity());
if (currentAccount == null) {
accountsPreference.setSummary(accounts[0].name);
} else {
accountsPreference.setSummary(currentAccount.name);
}
}
// When the preference is changed, update the summary too.
final Context context = getActivity();
accountsPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String oldPref = preference.getSharedPreferences().getString("account", null);
if (oldPref.equals(newValue)) {
return false;
}
// Change the summary value.
preference.setSummary(newValue.toString());
// Build a dialog to inform the user that we need to restart.
AlertDialog dialog = new AlertDialog.Builder(context).create();
dialog.setMessage(getString(R.string.settings_fragment_app_will_restart));
// Set button parameters and show the dialog.
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, getText(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
// Restart the application.
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
dialog.show();
return true;
}
});
}
/**
* Method: setUpAddAccount
* Action for adding an account.
*/
private void setUpAddAccount() {
// Set up new intent to launch the authenticator activity.
Intent intent = new Intent();
intent.setClass(getActivity(), AuthenticatorActivity.class);
// Obtain the add_account preference.
Preference addAccountPreference = findPreference("add_account");
addAccountPreference.setIntent(intent);
}
/**
* Method: setUpManageAccounts
* Action for managing accounts.
*/
private void setUpManageAccounts() {
// Set up new intent to launch the "Accounts and Sync Settings" screen.
Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] { Constants.PROVIDER_AUTHORITY });
// Obtain the manage_accounts preference.
Preference manageAccountsPreference = findPreference("manage_accounts");
manageAccountsPreference.setIntent(intent);
}
/**
* Method: setUpAbout
* Action for the about dialog.
*/
private void setUpAbout() {
Preference aboutPreference = findPreference("about");
aboutPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
// Get the fragment manager.
DialogFragment fragment = new AboutApplicationDialogFragment();
FragmentManager manager = getActivity().getFragmentManager();
fragment.show(manager, null);
return true;
}
});
// Get the information about this package.
String version = MainApplication.getVersionString();
aboutPreference.setTitle(getString(R.string.settings_fragment_about_title, version));
aboutPreference.setSummary(getString(R.string.settings_fragment_about_summary));
}
/**
* Method: setUpCheckForUpdates
* Action for checking updates.
*/
private void setUpCheckForUpdates() {
mCheckForUpdatesPreference = findPreference("check_updates");
mCheckForUpdatesPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
preference.setSummary(getString(R.string.settings_fragment_checking_for_updates));
// Load the update information.
getLoaderManager().initLoader(DataLoader.LOADER_CHECK_FOR_UPDATES, new Bundle(), new CheckForUpdatesLoaderCallbacks());
return true;
}
});
}
/**
* Method: setUpSendFeedback
* Action for sending feedback.
*/
private void setUpSendFeedback() {
// Get the application version.
String version = MainApplication.getVersionString();
// Set up the email intent.
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("message/rfc822");
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.settings_fragment_send_feedback_subject, getString(R.string.app_name), version));
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { "yjwong92@gmail.com" });
// Find the preference.
Preference sendFeedbackPreference = findPreference("send_feedback");
sendFeedbackPreference.setIntent(Intent.createChooser(intent, getString(R.string.settings_fragment_send_feedback_via)));
}
// }}}
// {{{ classes
/**
* Loader callbacks to check for updates.
* @author yjwong
*/
class CheckForUpdatesLoaderCallbacks implements LoaderManager.LoaderCallbacks<UpdateInfo> {
// {{{ methods
@Override
public Loader<UpdateInfo> onCreateLoader(int id, Bundle args) {
return new CheckForUpdatesLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<UpdateInfo> loader, final UpdateInfo updateInfo) {
// Hide any progress.
mCheckForUpdatesPreference.setSummary("");
// We now have the update info.
if (updateInfo == null) {
mCheckForUpdatesPreference.setSummary(R.string.settings_fragment_update_check_failed);
} else if (updateInfo.currentVersionCode >= updateInfo.updateVersionCode) {
mCheckForUpdatesPreference.setSummary(R.string.settings_fragment_update_latest_version);
} else {
// Update the dialog with newest URL.
mCheckForUpdatesDialog.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.ok), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
// Open a browser to download the update.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(updateInfo.updateAPK));
startActivity(Intent.createChooser(intent, getString(R.string.settings_fragment_update_download_via)));
}
});
// Prompt to download newer version.
mCheckForUpdatesDialog.show();
}
}
@Override
public void onLoaderReset(Loader<UpdateInfo> loader) {
// Do nothing.
}
// }}}
}
/**
* AsyncTaskLoader to check for updates.
* @author yjwong
*/
static class CheckForUpdatesLoader extends AsyncTaskLoader<UpdateInfo> {
// {{{ properties
/** The context */
private Context mContext;
/** The update information */
private UpdateInfo mUpdateInfo;
// }}}
// {{{ methods
public CheckForUpdatesLoader(Context context) {
super(context);
mContext = context;
}
@Override
public void onStartLoading() {
if (mUpdateInfo != null) {
deliverResult(mUpdateInfo);
}
if (takeContentChanged() || mUpdateInfo == null) {
forceLoad();
}
}
@Override
public UpdateInfo loadInBackground() {
try {
// Get the current version code.
PackageInfo info = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
int versionCode = info.versionCode;
// Get the online source.
URL url = new URL("http://ivle.nuscomputing.com/versionCode");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder response = new StringBuilder();
String buf = null;
while ((buf = reader.readLine()) != null) {
response.append(buf);
}
reader.close();
// Parse the new version code.
int updateVersionCode = Integer.parseInt(response.toString());
// Create new update info.
UpdateInfo updateInfo = new UpdateInfo();
updateInfo.currentVersionCode = versionCode;
updateInfo.updateVersionCode = updateVersionCode;
updateInfo.updateAPK = "http://ivle.nuscomputing.com/com.nuscomputing.ivle-".concat(Integer.toString(updateVersionCode)).concat(".apk");
return updateInfo;
} catch (NameNotFoundException e) {
return null;
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
}
// }}}
}
/**
* Class containing update information.
* @author yjwong
*/
static class UpdateInfo {
// {{{ properties
/** The current version code */
public int currentVersionCode;
/** The update version code */
public int updateVersionCode;
/** The URL to the update APK */
public String updateAPK;
// }}}
}
// }}}
}