/* * Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com> * * This file is part of Loop Habit Tracker. * * Loop Habit Tracker 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. * * Loop Habit Tracker 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.isoron.uhabits.activities; import android.content.*; import android.os.*; import android.support.annotation.*; import android.support.v7.app.*; import android.view.*; import org.isoron.uhabits.*; import org.isoron.uhabits.activities.habits.list.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.models.sqlite.*; import static android.R.anim.*; /** * Base class for all activities in the application. * <p> * This class delegates the responsibilities of an Android activity to other * classes. For example, callbacks related to menus are forwarded to a {@link * BaseMenu}, while callbacks related to activity results are forwarded to a * {@link BaseScreen}. * <p> * A BaseActivity also installs an {@link java.lang.Thread.UncaughtExceptionHandler} * to the main thread that logs the exception to the disk before the application * crashes. */ abstract public class BaseActivity extends AppCompatActivity implements Thread.UncaughtExceptionHandler { @Nullable private BaseMenu baseMenu; @Nullable private Thread.UncaughtExceptionHandler androidExceptionHandler; @Nullable private BaseScreen screen; private ActivityComponent component; public ActivityComponent getComponent() { return component; } @Override public boolean onCreateOptionsMenu(@Nullable Menu menu) { if (menu == null) return true; if (baseMenu == null) return true; baseMenu.onCreate(getMenuInflater(), menu); return true; } @Override public boolean onOptionsItemSelected(@Nullable MenuItem item) { if (item == null) return false; if (baseMenu == null) return false; return baseMenu.onItemSelected(item); } public void restartWithFade() { new Handler().postDelayed(() -> { Intent intent = new Intent(this, ListHabitsActivity.class); finish(); overridePendingTransition(fade_in, fade_out); startActivity(intent); }, 500); // HACK: Let the menu disappear first } public void setBaseMenu(@Nullable BaseMenu baseMenu) { this.baseMenu = baseMenu; } public void setScreen(@Nullable BaseScreen screen) { this.screen = screen; } public void showDialog(AppCompatDialogFragment dialog, String tag) { dialog.show(getSupportFragmentManager(), tag); } public void showDialog(AppCompatDialog dialog) { dialog.show(); } @Override public void uncaughtException(@Nullable Thread thread, @Nullable Throwable ex) { if (ex == null) return; try { ex.printStackTrace(); new BaseSystem(this).dumpBugReportToFile(); } catch (Exception e) { // ignored } if (ex.getCause() instanceof InconsistentDatabaseException) { HabitsApplication app = (HabitsApplication) getApplication(); HabitList habits = app.getComponent().getHabitList(); habits.repair(); System.exit(0); } if (androidExceptionHandler != null) androidExceptionHandler.uncaughtException(thread, ex); else System.exit(1); } @Override protected void onActivityResult(int request, int result, Intent data) { if (screen == null) super.onActivityResult(request, result, data); else screen.onResult(request, result, data); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); androidExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); HabitsApplication app = (HabitsApplication) getApplicationContext(); component = DaggerActivityComponent .builder() .activityModule(new ActivityModule(this)) .appComponent(app.getComponent()) .build(); component.getThemeSwitcher().apply(); } }