Java tutorial
/* * Copyright (c) 2012, Robert von Burg * * All rights reserved. * * This file is part of the XXX. * * XXX 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. * * XXX 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 XXX. If not, see * <http://www.gnu.org/licenses/>. */ package ch.eitchnet.android.mabea.activity; import android.app.ProgressDialog; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.text.method.ScrollingMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.ToggleButton; import ch.eitchnet.android.mabea.MabeaApplication; import ch.eitchnet.android.mabea.MabeaConnection; import ch.eitchnet.android.mabea.R; import ch.eitchnet.android.mabea.model.MabeaContext; import ch.eitchnet.android.mabea.model.MabeaState; import ch.eitchnet.android.mabea.model.MabeaState.State; import ch.eitchnet.android.mabea.model.Setting; import ch.eitchnet.android.mabea.persistence.SettingsTable; import ch.eitchnet.android.mabea.provider.SettingsContentProvider; import ch.eitchnet.android.util.DialogUtil; import ch.eitchnet.android.util.JodaHelper; import ch.eitchnet.android.util.Logger; import ch.eitchnet.android.util.SyncExec; /** * @author Robert von Burg <eitch@eitchnet.ch> * */ public class SettingsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { private static final String TAG = SettingsFragment.class.getSimpleName(); private static final Uri ITEM_URI = Uri.parse(SettingsContentProvider.CONTENT_URI + "/0"); private static final Uri ANY_URI = Uri.parse(SettingsContentProvider.CONTENT_URI.toString()); private static final String[] PROJECTION = new String[] { SettingsTable.COLUMN_NAME, SettingsTable.COLUMN_URL, SettingsTable.COLUMN_USERNAME, SettingsTable.COLUMN_ID }; private View rootView; private ToggleButton debugChk; private TextView statusTxt; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Logger.i(TAG, "onCreateView", "called"); this.rootView = inflater.inflate(R.layout.fragment_settings_layout, container, false); this.rootView.setVisibility(View.INVISIBLE); this.statusTxt = ((TextView) this.rootView.findViewById(R.id.statusTxt)); this.statusTxt.setMovementMethod(new ScrollingMovementMethod()); initContentProvider(); registerObservers(); return this.rootView; } // Creates a new loader after the initLoader () call @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { Logger.i(TAG, "onCreateLoader", id); String selection = null; String[] selectionArgs = null; return new CursorLoader(getActivity(), ITEM_URI, PROJECTION, selection, selectionArgs, null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { Logger.i(TAG, "onLoadFinished", data.getColumnCount() + ", " + data.getCount()); this.rootView.setVisibility(View.VISIBLE); if (data.getCount() == 0) { Logger.i(TAG, "onLoadFinished", "Loaded unpersisted setting to context."); Setting setting = MabeaApplication.getContext().getSetting(); setting.setPersisted(false); return; } data.moveToFirst(); Setting setting = MabeaApplication.getContext().getSetting(); setting.setPersisted(true); int columnIndex; columnIndex = data.getColumnIndex(SettingsTable.COLUMN_ID); setting.setId(data.getInt(columnIndex)); columnIndex = data.getColumnIndex(SettingsTable.COLUMN_NAME); setting.setName(data.getString(columnIndex)); columnIndex = data.getColumnIndex(SettingsTable.COLUMN_URL); setting.setUrl(data.getString(columnIndex)); columnIndex = data.getColumnIndex(SettingsTable.COLUMN_USERNAME); setting.setUsername(data.getString(columnIndex)); Logger.i(TAG, "onLoadFinished", "Loaded persisted setting to context."); updateUi(); } @Override public void onLoaderReset(Loader<Cursor> loader) { Logger.i(TAG, "onLoaderReset", loader); } private void initContentProvider() { Logger.i(TAG, "initContentProvider", "called"); getLoaderManager().initLoader(0, null, this); } /** * @param rootView */ private void registerObservers() { Button checkConnectionBtn = (Button) this.rootView.findViewById(R.id.checkConnectionBtn); checkConnectionBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { checkConnection(); } }, "checkConnection").start(); } }); debugChk = (ToggleButton) this.rootView.findViewById(R.id.debugChk); debugChk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { toggleDebug(); } }); } private void toggleDebug() { MabeaApplication.getContext().toggleDebug(); updateUi(); } ProgressDialog progressDlg; private void checkConnection() { Logger.i(TAG, "checkConnection", "called"); try { String msg = updateModel(); if (msg != null) { DialogUtil.showErrorDialog(getActivity(), "Missing input", msg); return; } // show progress dialog SyncExec action = new SyncExec() { @Override protected void execute() { Setting setting = MabeaApplication.getContext().getSetting(); progressDlg = ProgressDialog.show(getActivity(), "Checking input", "Connecting to " + setting.getUrl() + " for user " + setting.getUsername() + "..."); } }; action.runOnUiThread(getActivity()); Logger.i(TAG, "run", "Starting..."); MabeaConnection connection = MabeaApplication.getContext().getConnection(); connection.checkConnection(); if (!connection.hasError()) { persist(); } String statusMsg = createStatusMsg(connection); MabeaApplication.getContext().setConnectionStateMsg(statusMsg); getActivity().runOnUiThread(new Runnable() { @Override public void run() { updateUi(); if (progressDlg != null) progressDlg.dismiss(); } }); Logger.i(TAG, "checkConnection", "Done."); } catch (Exception e) { Logger.e(TAG, "checkConnection", e.getMessage(), e); DialogUtil.showExceptionDialog(getActivity(), TAG, e); } } private String createStatusMsg(MabeaConnection mabeaConnection) { StringBuilder sb = new StringBuilder(); if (mabeaConnection.hasError()) { Throwable e = mabeaConnection.getConnectionError(); String msg = mabeaConnection.getErrorMsg(); if (msg == null && e == null) { sb.append("Connection invalid but no error message available"); } else if (msg == null) { sb.append("Connection invalid: \n\n" + DialogUtil.toString(e)); } else if (e == null) { sb.append("Connection invalid: " + msg); } else { sb.append("Connection invalid: " + msg + "\n\n" + DialogUtil.toString(e)); } } else { sb.append("Connection valid and tested.\n\n"); MabeaState state = mabeaConnection.getMabeaState(); sb.append("Name: "); sb.append(state.getName()); sb.append("\nBalance: "); sb.append(JodaHelper.toHourMinute(state.getBalance())); sb.append("\nRemaining Vacation: "); sb.append(JodaHelper.toDays(state.getRemainingVacation())); sb.append("\n"); String time = JodaHelper.toHourMinute(state.getStateTime()); if (state.getState() == State.LOGGED_OUT) sb.append("Logged out since " + time); else if (state.getState() == State.LOGGED_IN) sb.append("Logged in since " + time); else sb.append("Unknown state since " + time); } sb.append("\n"); sb.append("\n"); if (MabeaApplication.getContext().isDebugEnabled()) sb.append("Debugging is enabled"); else sb.append("Debugging is disabled"); return sb.toString(); } public void updateUi() { if (this.rootView == null) return; MabeaContext context = MabeaApplication.getContext(); Setting setting = context.getSetting(); TextView textView; textView = (TextView) this.rootView.findViewById(R.id.settingMabeaName); textView.clearFocus(); textView.setText(setting.getName()); textView = (TextView) this.rootView.findViewById(R.id.settingMabeaUrl); textView.setText(setting.getUrl()); textView = (TextView) this.rootView.findViewById(R.id.settingMabeaUsername); textView.setText(setting.getUsername()); debugChk.setChecked(context.isDebugEnabled()); statusTxt.setText(context.getConnectionStateMsg()); statusTxt.requestFocus(); } private void persist() { Logger.i(TAG, "persist", "Starting..."); try { Setting setting = MabeaApplication.getContext().getSetting(); ContentValues values = new ContentValues(); values.put(SettingsTable.COLUMN_ID, setting.getId()); values.put(SettingsTable.COLUMN_NAME, setting.getName()); values.put(SettingsTable.COLUMN_URL, setting.getUrl()); values.put(SettingsTable.COLUMN_USERNAME, setting.getUsername()); if (setting.isPersisted()) { getActivity().getContentResolver().update(ITEM_URI, values, null, null); } else { getActivity().getContentResolver().insert(ANY_URI, values); setting.setPersisted(true); } Logger.i(TAG, "persist", "Done."); } catch (Exception e) { Logger.e(TAG, "persist", e.getMessage(), e); DialogUtil.showExceptionDialog(getActivity(), TAG, e); } } /** * */ private String updateModel() { TextView textView; textView = (TextView) this.rootView.findViewById(R.id.settingMabeaName); String name = textView.getText().toString(); if (name == null || name.isEmpty()) return "Name is not set!"; textView = (TextView) this.rootView.findViewById(R.id.settingMabeaUrl); String url = textView.getText().toString(); if (url == null || url.isEmpty()) return "url is not set!"; textView = (TextView) this.rootView.findViewById(R.id.settingMabeaUsername); String username = textView.getText().toString(); if (username == null || username.isEmpty()) return "username is not set!"; Setting setting = MabeaApplication.getContext().getSetting(); setting.setName(name); setting.setUrl(url); setting.setUsername(username); return null; } }