/* * Copyright 2018 Google LLC * * 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 * * https://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 com.google.android.gnd; import android.content.Context; import android.os.StrictMode; import android.util.Log; import androidx.annotation.NonNull; import androidx.multidex.MultiDex; import androidx.work.Configuration; import androidx.work.WorkManager; import com.akaita.java.rxjava2debug.RxJava2Debug; import com.facebook.stetho.Stetho; import com.google.android.gnd.inject.GndWorkerFactory; import com.google.android.gnd.rx.RxDebug; import com.google.firebase.crashlytics.FirebaseCrashlytics; import dagger.android.AndroidInjector; import dagger.android.support.DaggerApplication; import io.reactivex.plugins.RxJavaPlugins; import javax.inject.Inject; import timber.log.Timber; // TODO: When implementing background data sync service, we'll need to inject a Service here; we // should then extend DaggerApplication instead. If MultiDex is still needed, we can install it // without extending MultiDexApplication. public class GndApplication extends DaggerApplication { @Inject GndWorkerFactory workerFactory; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); } @Override public void onCreate() { if (BuildConfig.DEBUG) { Timber.d("DEBUG build config active; enabling debug tooling"); // Debug bridge for Android applications. Enables network and database debugging for the app // accessible under chrome://inspect in Chrome desktop browser. Must be done before calling // setStrictMode(). Stetho.initializeWithDefaults(this); // Log failures when trying to do work in the UI thread. setStrictMode(); } super.onCreate(); // Enable RxJava assembly stack collection for more useful stack traces. RxJava2Debug.enableRxJava2AssemblyTracking(new String[] {getClass().getPackage().getName()}); // Prevent RxJava from force-quitting on unhandled errors. RxJavaPlugins.setErrorHandler(RxDebug::logEnhancedStackTrace); // Set custom worker factory that allow Workers to use Dagger injection. // TODO(github.com/google/dagger/issues/1183): Remove once Workers support injection. WorkManager.initialize( this, new Configuration.Builder().setWorkerFactory(workerFactory).build()); if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); } else { Timber.plant(new CrashReportingTree()); } } @Override protected AndroidInjector<? extends DaggerApplication> applicationInjector() { // Root of dependency injection. return DaggerGndApplicationComponent.factory().create(this); } private void setStrictMode() { StrictMode.setThreadPolicy( new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); StrictMode.setVmPolicy( new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().penaltyLog().build()); } private static class CrashReportingTree extends Timber.Tree { @Override protected void log(int priority, String tag, @NonNull String message, Throwable throwable) { if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) { return; } FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); crashlytics.log(message); if (throwable != null && priority == Log.ERROR) { crashlytics.recordException(throwable); } } } }