Java tutorial
/** * RxDroid - A Medication Reminder * Copyright (C) 2011-2013 Joseph Lehner <joseph.c.lehner@gmail.com> * * * RxDroid 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. * * RxDroid 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 RxDroid. If not, see <http://www.gnu.org/licenses/>. * * */ package at.jclehner.rxdroid; import java.io.File; import java.util.Date; import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.support.v4.content.LocalBroadcastManager; import android.text.SpannableString; import android.text.style.RelativeSizeSpan; import android.text.style.UnderlineSpan; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import at.jclehner.rxdroid.db.Database; import at.jclehner.rxdroid.db.DatabaseHelper; import at.jclehner.rxdroid.db.DatabaseHelper.DatabaseError; import at.jclehner.rxdroid.db.Drug; import at.jclehner.rxdroid.util.DateTime; import at.jclehner.rxdroid.util.Util; import at.jclehner.rxdroid.util.WrappedCheckedException; import com.actionbarsherlock.app.SherlockActivity; public class SplashScreenActivity extends SherlockActivity implements OnClickListener { @SuppressWarnings("unused") private static final boolean USE_MSG_HANDLER = BuildConfig.DEBUG; public class DatabaseStatusReceiver extends BroadcastReceiver { public static final String EXTRA_MESSAGE = "at.jclehner.rxdroid.extra.MESSAGE"; public static final String EXTRA_PROGRESS = "at.jclehner.rxdroid.extra.PROGRESS"; @Override public void onReceive(Context context, Intent intent) { if (intent == null) return; final TextView msg = (TextView) SplashScreenActivity.this.findViewById(R.id.text_loading); if (msg == null) return; final int msgResId = intent.getIntExtra(EXTRA_MESSAGE, R.string._title_db_status_loading); msg.setText(getString(R.string._title_database) + ": " + getString(msgResId)); } } public class DatabaseStatusHandler extends Handler { public static final int MSG_SET_TEXT = 0; @Override public void handleMessage(Message msg) { if (msg.what == MSG_SET_TEXT) { final TextView text = (TextView) findViewById(R.id.text_loading); if (text != null) { final int textResId = msg.arg1; text.setText(getString(R.string._title_database) + ": " + getString(textResId)); return; } } super.handleMessage(msg); } } private static final String TAG = SplashScreenActivity.class.getSimpleName(); private static final String ARG_EXCEPTION = "exception"; private final BroadcastReceiver mReceiver = new DatabaseStatusReceiver(); private Date mDate; private WrappedCheckedException mException = null; @TargetApi(11) @Override protected void onCreate(Bundle savedInstanceState) { Settings.init(); setTheme(Theme.get()); setContentView(R.layout.loader); mDate = Settings.getActiveDate(); final SpannableString dateString = new SpannableString(DateTime.toNativeDate(mDate)); Util.applyStyle(dateString, new RelativeSizeSpan(0.75f)); Util.applyStyle(dateString, new UnderlineSpan()); getSupportActionBar().setSubtitle(dateString); try { Class.forName(com.michaelnovakjr.numberpicker.NumberPicker.class.getName()); } catch (ClassNotFoundException e) { throw new WrappedCheckedException("NumberPicker library is missing", e); } super.onCreate(savedInstanceState); } @Override protected void onResume() { //registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_MAIN)); RxDroid.getLocalBroadcastManager().registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_MAIN)); loadDatabaseAndLaunchMainActivity(); super.onResume(); } @Override protected void onPause() { super.onPause(); RxDroid.getLocalBroadcastManager().unregisterReceiver(mReceiver); } @Override public void onClick(DialogInterface dialog, int which) { if (which == Dialog.BUTTON_POSITIVE) { if (deleteDatabase()) { Toast.makeText(this, R.string._toast_db_reset_success, Toast.LENGTH_SHORT).show(); loadDatabaseAndLaunchMainActivity(); } else Toast.makeText(this, R.string._toast_db_reset_failure, Toast.LENGTH_LONG).show(); } else if (which == Dialog.BUTTON_NEGATIVE && mException != null) throw mException; finish(); } public static void setStatusMessage(int msgResId) { final Context context = RxDroid.getContext(); final Intent intent = new Intent(context, DatabaseStatusReceiver.class); intent.setAction(Intent.ACTION_MAIN); intent.putExtra(DatabaseStatusReceiver.EXTRA_MESSAGE, msgResId); LocalBroadcastManager bm = RxDroid.getLocalBroadcastManager(); bm.sendBroadcast(intent); } @SuppressWarnings("deprecation") @Override protected Dialog onCreateDialog(int id, Bundle args) { if (id == R.id.db_error_dialog) { final AlertDialog.Builder ab = new AlertDialog.Builder(SplashScreenActivity.this); ab.setTitle(R.string._title_error); ab.setIcon(android.R.drawable.ic_dialog_alert); ab.setCancelable(false); ab.setNegativeButton(R.string._btn_exit, SplashScreenActivity.this); ab.setPositiveButton(R.string._btn_reset, SplashScreenActivity.this); ab.setMessage(""); return ab.create(); } return super.onCreateDialog(id, args); } @SuppressWarnings("deprecation") @Override protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { if (id == R.id.db_error_dialog) { // final WrappedCheckedException exception = mException = (WrappedCheckedException) args.getSerializable(ARG_EXCEPTION); final StringBuilder sb = new StringBuilder(); if (mException.getCauseType() == DatabaseError.class) { switch (((DatabaseError) mException.getCause()).getType()) { case DatabaseError.E_GENERAL: sb.append(getString(R.string._msg_db_error_general)); break; case DatabaseError.E_UPGRADE: sb.append(getString(R.string._msg_db_error_upgrade)); break; case DatabaseError.E_DOWNGRADE: sb.append(getString(R.string._msg_db_error_downgrade)); break; } } else sb.append(getString(R.string._msg_db_error_general)); sb.append(" " + getString(R.string._msg_db_error_footer, getString(R.string._btn_reset))); ((AlertDialog) dialog).setMessage(sb); } else super.onPrepareDialog(id, dialog, args); } private void loadDatabaseAndLaunchMainActivity() { new DatabaseIntializerTask().execute(0); } private boolean deleteDatabase() { final String packageName = getApplicationInfo().packageName; final File dbDir = new File(Environment.getDataDirectory(), "data/" + packageName + "/databases"); final File currentDb = new File(dbDir, DatabaseHelper.DB_NAME); Log.d(TAG, "deleteDatabase: "); Log.d(TAG, " dbDir=" + dbDir); Log.d(TAG, " currentDb=" + currentDb); Log.d(TAG, " dbDir.canWrite() = " + dbDir.canWrite()); Log.d(TAG, " currentDb.exists() = " + currentDb.exists()); Log.d(TAG, " currentDb.canWrite() = " + currentDb.canWrite()); if (!dbDir.canWrite() || !currentDb.exists() || !currentDb.canWrite()) return false; return currentDb.delete(); } private void launchMainActivity() { (new Thread() { @SuppressWarnings("unused") @Override public void run() { while (Database.hasPendingOperations()) { Log.i(TAG, "Waiting for database to settle"); try { Thread.sleep(50); } catch (InterruptedException e) { Log.w(TAG, e); break; } } final boolean isFirstLaunch; if (!BuildConfig.DEBUG && Database.countAll(Drug.class) != 0) { isFirstLaunch = false; Settings.putBoolean(Settings.Keys.IS_FIRST_LAUNCH, false); } else isFirstLaunch = Settings.getBoolean(Settings.Keys.IS_FIRST_LAUNCH, true); final Class<?> intentClass = isFirstLaunch ? DoseTimePreferenceActivity.class : DrugListActivity.class; Intent intent = new Intent(getBaseContext(), intentClass); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_ANIMATION); intent.putExtra(DoseTimePreferenceActivity.EXTRA_IS_FIRST_LAUNCH, isFirstLaunch); intent.putExtra(DrugListActivity.EXTRA_DATE, mDate); startActivity(intent); finish(); } }).start(); } private class DatabaseIntializerTask extends AsyncTask<Integer, Void, WrappedCheckedException> { //private boolean mAttemptedDatabaseReload = false; @Override protected WrappedCheckedException doInBackground(Integer... params) { int count = (params == null || params.length == 0) ? 0 : params[0]; try { if (count == 0) Database.init(); else Database.reload(RxDroid.getContext()); } catch (Exception e) { if (count < Database.TABLE_COUNT) return doInBackground(++count); return new WrappedCheckedException(e); } return null; } @SuppressWarnings("deprecation") @Override protected void onPostExecute(WrappedCheckedException result) { setStatusMessage(R.string._title_db_status_loading); if (result == null) launchMainActivity(); else { Log.w(TAG, result.getRootCause()); Bundle args = new Bundle(); args.putSerializable(ARG_EXCEPTION, result); showDialog(R.id.db_error_dialog, args); } } } }