android-templates/src/main/java/ru/touchin/templates/TouchinApp.java

184 lines
6.2 KiB
Java

/*
* Copyright (c) 2016 Touch Instinct
*
* This file is part of RoboSwag library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package ru.touchin.templates;
import android.app.Application;
import android.content.Context;
import android.os.Looper;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.multidex.MultiDex;
import com.crashlytics.android.Crashlytics;
import net.danlew.android.joda.JodaTimeAndroid;
import java.util.concurrent.TimeUnit;
import io.fabric.sdk.android.Fabric;
import ru.touchin.roboswag.components.navigation.fragments.ViewControllerFragment;
import ru.touchin.roboswag.components.views.TypefacedEditText;
import ru.touchin.roboswag.components.views.TypefacedTextView;
import ru.touchin.roboswag.core.log.ConsoleLogProcessor;
import ru.touchin.roboswag.core.log.Lc;
import ru.touchin.roboswag.core.log.LcGroup;
import ru.touchin.roboswag.core.log.LcLevel;
import ru.touchin.roboswag.core.log.LogProcessor;
import ru.touchin.roboswag.core.utils.ShouldNotHappenException;
import rx.Scheduler;
import rx.Subscription;
import rx.android.plugins.RxAndroidPlugins;
import rx.android.plugins.RxAndroidSchedulersHook;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.subscriptions.Subscriptions;
/**
* Created by Gavriil Sitnikov on 10/03/16.
* Base class of application to extends for Touch Instinct related projects.
*/
public abstract class TouchinApp extends Application {
/**
* Returns if application runs in debug mode or not.
* In most cases it should return BuildConfig.DEBUG.
* If it will returns true then debug options for RoboSwag components will be enabled.
* In non-debug mode it will also enables Crashlitycs.
*
* @return True if application runs in debug mode.
*/
protected abstract boolean isDebug();
@Override
protected void attachBaseContext(@NonNull final Context base) {
super.attachBaseContext(base);
MultiDex.install(base);
}
@Override
public void onCreate() {
super.onCreate();
RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() {
@Override
public Scheduler getMainThreadScheduler() {
return new MainThreadScheduler();
}
});
JodaTimeAndroid.init(this);
if (isDebug()) {
enableStrictMode();
ViewControllerFragment.setInDebugMode();
TypefacedEditText.setInDebugMode();
TypefacedTextView.setInDebugMode();
Lc.initialize(new ConsoleLogProcessor(LcLevel.VERBOSE), true);
} else {
final Crashlytics crashlytics = new Crashlytics();
Fabric.with(this, crashlytics);
Lc.initialize(new CrashlyticsLogProcessor(crashlytics), false);
}
}
private void enableStrictMode() {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.permitDiskReads()
.permitDiskWrites()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
}
private static class CrashlyticsLogProcessor extends LogProcessor {
@NonNull
private final Crashlytics crashlytics;
public CrashlyticsLogProcessor(@NonNull final Crashlytics crashlytics) {
super(LcLevel.ASSERT);
this.crashlytics = crashlytics;
}
@Override
public void processLogMessage(@NonNull final LcGroup group,
@NonNull final LcLevel level,
@NonNull final String tag,
@NonNull final String message,
@Nullable final Throwable throwable) {
if (!level.lessThan(LcLevel.ASSERT)) {
if (throwable != null) {
crashlytics.core.log(tag + ':' + message);
crashlytics.core.logException(throwable);
} else {
crashlytics.core.logException(new ShouldNotHappenException(tag + ':' + message));
}
}
}
}
/**
* This hacky class is needed to execute actions immediately on main thread but not schedule on main thread handler with 0 delay instead.
*/
private static class MainThreadScheduler extends Scheduler {
@Override
public Worker createWorker() {
return new WrapperMainThreadWorker();
}
private class WrapperMainThreadWorker extends Worker {
@NonNull
private final Worker parentWorker = AndroidSchedulers.from(Looper.getMainLooper()).createWorker();
@Override
public Subscription schedule(@NonNull final Action0 action) {
if (Looper.getMainLooper().equals(Looper.myLooper())) {
action.call();
return Subscriptions.unsubscribed();
}
return parentWorker.schedule(action);
}
@Override
public Subscription schedule(@NonNull final Action0 action, final long delayTime, @NonNull final TimeUnit unit) {
return parentWorker.schedule(action, delayTime, unit);
}
@Override
public void unsubscribe() {
parentWorker.unsubscribe();
}
@Override
public boolean isUnsubscribed() {
return parentWorker.isUnsubscribed();
}
}
}
}