/* * This program is part of the OpenLMIS logistics management information * system platform software. * * Copyright © 2015 ThoughtWorks, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. This program 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 Affero General Public License for more details. You should * have received a copy of the GNU Affero General Public License along with * this program. If not, see http://www.gnu.org/licenses. For additional * information contact info@OpenLMIS.org */ package org.openlmis.core.view.activity; import android.app.FragmentManager; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.StyleRes; import android.util.Log; import android.view.MenuItem; import android.view.MotionEvent; import android.view.inputmethod.InputMethodManager; import com.google.inject.Inject; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import org.openlmis.core.LMISApp; import org.openlmis.core.R; import org.openlmis.core.exceptions.ViewNotMatchException; import org.openlmis.core.googleAnalytics.ScreenName; import org.openlmis.core.manager.SharedPreferenceMgr; import org.openlmis.core.presenter.DummyPresenter; import org.openlmis.core.presenter.Presenter; import org.openlmis.core.utils.InjectPresenter; import org.openlmis.core.utils.ToastUtil; import org.openlmis.core.view.BaseView; import org.openlmis.core.view.fragment.RetainedFragment; import org.roboguice.shaded.goole.common.base.Optional; import org.roboguice.shaded.goole.common.base.Predicate; import org.roboguice.shaded.goole.common.collect.FluentIterable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import roboguice.RoboGuice; import roboguice.activity.RoboActionBarActivity; import rx.Subscription; import static org.roboguice.shaded.goole.common.collect.Lists.newArrayList; public abstract class BaseActivity extends RoboActionBarActivity implements BaseView { @Inject SharedPreferenceMgr preferencesMgr; protected RetainedFragment dataFragment; protected Presenter presenter; protected List<Subscription> subscriptions = new ArrayList<>(); protected Class<? extends Presenter> presenterClass; protected ProgressDialog loadingDialog; protected boolean isLoading = false; private long APP_TIMEOUT; private long onCreateStartMili; private boolean isPageLoadTimerInProgress; public void injectPresenter() { Field[] fields = FieldUtils.getAllFields(this.getClass()); Optional<Field> annotatedFiled = FluentIterable.from(newArrayList(fields)).firstMatch(new Predicate<Field>() { @Override public boolean apply(Field field) { return field.getAnnotation(InjectPresenter.class) != null; } }); if (annotatedFiled.isPresent()) { InjectPresenter annotation = annotatedFiled.get().getAnnotation(InjectPresenter.class); if (!Presenter.class.isAssignableFrom(annotation.value())) { throw new RuntimeException("Invalid InjectPresenter class :" + annotation.value()); } presenter = initPresenter(annotation.value()); try { annotatedFiled.get().setAccessible(true); annotatedFiled.get().set(this, presenter); } catch (IllegalAccessException e) { throw new RuntimeException("InjectPresenter type cast failed :" + annotation.value().getSimpleName()); } } if (presenter == null) { presenter = new DummyPresenter(); } } @Override protected void onStart() { super.onStart(); presenter.onStart(); sendScreenToGoogleAnalytics(); } protected abstract ScreenName getScreenName(); protected void sendScreenToGoogleAnalytics() { ScreenName screenName = getScreenName(); if (screenName != null) { LMISApp.getInstance().trackScreen(screenName); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (LMISApp.lastOperateTime > 0L && alreadyTimeOuted() && !isLoginActivityActive()) { logout(); return true; } else { LMISApp.lastOperateTime = LMISApp.getInstance().getCurrentTimeMillis(); return super.dispatchTouchEvent(ev); } } protected void logout() { startActivity(new Intent(this, LoginActivity.class)); LMISApp.lastOperateTime = 0L; } private boolean isLoginActivityActive() { return this instanceof LoginActivity; } private boolean alreadyTimeOuted() { Long currentTimeMillis = LMISApp.getInstance().getCurrentTimeMillis(); return currentTimeMillis - LMISApp.lastOperateTime > APP_TIMEOUT; } @Override protected void onCreate(Bundle savedInstanceState) { isPageLoadTimerInProgress = true; onCreateStartMili = LMISApp.getInstance().getCurrentTimeMillis(); setTheme(getThemeRes()); super.onCreate(savedInstanceState); initDataFragment(); injectPresenter(); try { presenter.attachView(BaseActivity.this); } catch (ViewNotMatchException e) { e.reportToFabric(); ToastUtil.show(e.getMessage()); return; } if (getSupportActionBar() != null) { getSupportActionBar().setHomeButtonEnabled(false); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } APP_TIMEOUT = Long.parseLong(getResources().getString(R.string.app_time_out)); } protected @StyleRes int getThemeRes() { return R.style.AppTheme; } @Override protected void onDestroy() { if (presenter != null && presenterClass != null) { presenter.onStop(); dataFragment.putData(presenterClass.getSimpleName(), presenter); } unSubscribeSubscriptions(); super.onDestroy(); } private void unSubscribeSubscriptions() { for (Subscription subscription : subscriptions) { if (subscription != null) { subscription.unsubscribe(); } } } private void initDataFragment() { FragmentManager fm = getFragmentManager(); dataFragment = (RetainedFragment) fm.findFragmentByTag("RetainedFragment"); if (dataFragment == null) { dataFragment = new RetainedFragment(); fm.beginTransaction().add(dataFragment, "RetainedFragment").commit(); } } protected Presenter initPresenter(Class<? extends Presenter> clazz) { // find the retained fragment on activity restarts presenterClass = clazz; Presenter presenter = (Presenter) dataFragment.getData(presenterClass.getSimpleName()); if (presenter == null) { presenter = RoboGuice.getInjector(getApplicationContext()).getInstance(presenterClass); dataFragment.putData(presenterClass.getSimpleName(), presenter); } return presenter; } @Override public void loading() { loading(StringUtils.EMPTY); } @Override public void loading(String message) { loaded(); loadingDialog = new ProgressDialog(this); loadingDialog.setMessage(message); loadingDialog.setIndeterminate(false); loadingDialog.setCanceledOnTouchOutside(false); if (!isFinishing()) { loadingDialog.show(); } isLoading = true; } @Override public void loaded() { try { if (loadingDialog != null && !isFinishing()) { loadingDialog.dismiss(); loadingDialog = null; isLoading = false; if (isPageLoadTimerInProgress) { Log.d(this.getTitle() + " page", "load time " + (System.currentTimeMillis() - onCreateStartMili) + " ms"); isPageLoadTimerInProgress = false; } } } catch (IllegalArgumentException e) { Log.d("View", "loaded -> dialog already dismissed"); } } public void saveString(String key, String value) { preferencesMgr.getPreference().edit().putString(key, value).apply(); } public void startActivity(Class activityName, boolean closeThis) { Intent intent = new Intent(); intent.setClass(this, activityName); startActivity(intent); if (closeThis) this.finish(); } public void startActivity(Class activityName) { startActivity(activityName, false); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; default: return super.onOptionsItemSelected(item); } } public void hideImm() { InputMethodManager mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (mImm != null && mImm.isActive() && this.getCurrentFocus() != null) { mImm.hideSoftInputFromWindow(this.getCurrentFocus() .getWindowToken(), 0); } } }