diff --git a/api-logansquare/build.gradle b/api-logansquare/build.gradle index 9daa9da..3e774b1 100644 --- a/api-logansquare/build.gradle +++ b/api-logansquare/build.gradle @@ -13,10 +13,6 @@ android { } } -repositories { - maven { url "http://dl.bintray.com/touchin/touchin-tools" } -} - dependencies { api project(":storable") api 'net.danlew:android.joda:2.9.9.4' diff --git a/build.gradle b/build.gradle index d489a4e..ae4e81d 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ allprojects { repositories { google() jcenter() + maven { url "http://dl.bintray.com/touchin/touchin-tools" } } } @@ -31,6 +32,7 @@ ext { dagger : '2.16', retrofit : '2.4.0', rxJava : '2.1.17', - rxAndroid : '2.0.2' + rxAndroid : '2.0.2', + crashlytics : '2.9.4' ] } diff --git a/modules.gradle b/modules.gradle index 9b11a59..750126e 100644 --- a/modules.gradle +++ b/modules.gradle @@ -15,6 +15,7 @@ include ':lifecycle-rx' include ':views' include ':recyclerview-adapters' include ':kotlin-extensions' +include ':templates' project(':utils').projectDir = new File(rootDir, 'utils') project(':logging').projectDir = new File(rootDir, 'logging') @@ -26,3 +27,4 @@ project(':lifecycle-rx').projectDir = new File(rootDir, 'lifecycle-rx') project(':views').projectDir = new File(rootDir, 'views') project(':recyclerview-adapters').projectDir = new File(rootDir, 'recyclerview-adapters') project(':kotlin-extensions').projectDir = new File(rootDir, 'kotlin-extensions') +project(':templates').projectDir = new File(rootDir, 'templates') diff --git a/templates/.gitignore b/templates/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/templates/.gitignore @@ -0,0 +1 @@ +/build diff --git a/templates/build.gradle b/templates/build.gradle new file mode 100644 index 0000000..1ee1e3b --- /dev/null +++ b/templates/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion versions.compileSdk + + defaultConfig { + minSdkVersion versions.minSdk + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + api project(":utils") + api project(":logging") + api project(":api-logansquare") + api project(":navigation") + + api 'com.android.support:multidex:1.0.3' + + api 'net.danlew:android.joda:2.9.9.4' + + implementation "com.android.support:appcompat-v7:$versions.supportLibrary" + + implementation("com.crashlytics.sdk.android:crashlytics:$versions.crashlytics@aar") { + transitive = true + } +} diff --git a/templates/src/main/AndroidManifest.xml b/templates/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ad64e1e --- /dev/null +++ b/templates/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + diff --git a/templates/src/main/java/ru/touchin/templates/TouchinActivity.java b/templates/src/main/java/ru/touchin/templates/TouchinActivity.java new file mode 100644 index 0000000..41b2e28 --- /dev/null +++ b/templates/src/main/java/ru/touchin/templates/TouchinActivity.java @@ -0,0 +1,70 @@ +/* + * 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.ActivityManager; +import android.content.Intent; +import android.graphics.drawable.BitmapDrawable; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.ColorRes; +import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; + +import ru.touchin.roboswag.components.navigation.activities.BaseActivity; +import ru.touchin.roboswag.core.log.Lc; + +/** + * Created by Gavriil Sitnikov on 11/03/16. + * Base class of activity to extends for Touch Instinct related projects. + */ +public abstract class TouchinActivity extends BaseActivity { + + @Override + protected void onCreate(@Nullable final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Possible work around for market launches. See http://code.google.com/p/android/issues/detail?id=2373 + // for more details. Essentially, the market launches the main activity on top of other activities. + // we never want this to happen. Instead, we check if we are the root and if not, we finish. + if (!isTaskRoot() && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(getIntent().getAction())) { + Lc.e("Finishing activity as it is launcher but not root"); + finish(); + } + } + + /** + * Setup task description of application for Android 5.0 and later. It is showing when user opens task bar. + * + * @param label Name of application to show in task bar; + * @param iconRes Icon of application to show in task bar; + * @param primaryColorRes Color of application to show in task bar. + */ + protected void setupTaskDescriptor(@NonNull final String label, @DrawableRes final int iconRes, @ColorRes final int primaryColorRes) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + final ActivityManager.TaskDescription taskDescription = new ActivityManager.TaskDescription(label, + ((BitmapDrawable) ContextCompat.getDrawable(this, iconRes)).getBitmap(), + ContextCompat.getColor(this, primaryColorRes)); + setTaskDescription(taskDescription); + } + } + +} diff --git a/templates/src/main/java/ru/touchin/templates/TouchinApp.java b/templates/src/main/java/ru/touchin/templates/TouchinApp.java new file mode 100644 index 0000000..8d33cb0 --- /dev/null +++ b/templates/src/main/java/ru/touchin/templates/TouchinApp.java @@ -0,0 +1,146 @@ +/* + * 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.StrictMode; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.multidex.MultiDex; +import android.util.Log; + +import com.crashlytics.android.Crashlytics; + +import net.danlew.android.joda.JodaTimeAndroid; + +import java.util.ArrayList; +import java.util.List; + +import io.fabric.sdk.android.Fabric; +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; + +/** + * 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 { + + @Override + protected void attachBaseContext(@NonNull final Context base) { + super.attachBaseContext(base); + MultiDex.install(base); + } + + @Override + public void onCreate() { + super.onCreate(); + JodaTimeAndroid.init(this); + if (BuildConfig.DEBUG) { + enableStrictMode(); + Lc.initialize(new ConsoleLogProcessor(LcLevel.VERBOSE), true); + LcGroup.UI_LIFECYCLE.disable(); + } else { + try { + final Crashlytics crashlytics = new Crashlytics(); + Fabric.with(this, crashlytics); + Fabric.getLogger().setLogLevel(Log.ERROR); + Lc.initialize(new CrashlyticsLogProcessor(crashlytics), false); + } catch (final NoClassDefFoundError error) { + Lc.initialize(new ConsoleLogProcessor(LcLevel.INFO), false); + Lc.e("Crashlytics initialization error! Did you forget to add\n" + + "compile('com.crashlytics.sdk.android:crashlytics:+@aar') {\n" + + " transitive = true;\n" + + "}\n" + + "to your build.gradle?", error); + } + } + } + + 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.INFO); + 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 (group == LcGroup.UI_LIFECYCLE) { + crashlytics.core.log(level.getPriority(), tag, message); + } else if (!level.lessThan(LcLevel.ASSERT) + || (group == ApiModel.API_VALIDATION_LC_GROUP && level == LcLevel.ERROR)) { + Log.e(tag, message); + if (throwable != null) { + crashlytics.core.log(level.getPriority(), tag, message); + crashlytics.core.logException(throwable); + } else { + final ShouldNotHappenException exceptionToLog = new ShouldNotHappenException(tag + ':' + message); + reduceStackTrace(exceptionToLog); + crashlytics.core.logException(exceptionToLog); + } + } + } + + private void reduceStackTrace(@NonNull final Throwable throwable) { + final StackTraceElement[] stackTrace = throwable.getStackTrace(); + final List reducedStackTraceList = new ArrayList<>(); + for (int i = stackTrace.length - 1; i >= 0; i--) { + final StackTraceElement stackTraceElement = stackTrace[i]; + if (stackTraceElement.getClassName().contains(getClass().getSimpleName()) + || stackTraceElement.getClassName().contains(LcGroup.class.getName()) + || stackTraceElement.getClassName().contains(Lc.class.getName())) { + break; + } + reducedStackTraceList.add(0, stackTraceElement); + } + StackTraceElement[] reducedStackTrace = new StackTraceElement[reducedStackTraceList.size()]; + reducedStackTrace = reducedStackTraceList.toArray(reducedStackTrace); + throwable.setStackTrace(reducedStackTrace); + } + + } + +} diff --git a/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedEditText.java b/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedEditText.java index d556a81..ceac558 100644 --- a/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedEditText.java +++ b/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedEditText.java @@ -43,11 +43,6 @@ import ru.touchin.defaults.DefaultTextWatcher; import ru.touchin.roboswag.components.views.internal.AttributesUtils; import ru.touchin.roboswag.core.log.Lc; -/** - * Created by Gavriil Sitnikov on 18/07/2014. - * TextView that supports fonts from Typefaces class - */ - /** * Created by Gavriil Sitnikov on 18/07/2014. * EditText that supports custom typeface and forces developer to specify if this view multiline or not. @@ -57,15 +52,6 @@ import ru.touchin.roboswag.core.log.Lc; //ConstructorCallsOverridableMethod: it's ok as we need to setTypeface public class TypefacedEditText extends AppCompatEditText { - private static boolean inDebugMode; - - /** - * Enables debugging features like checking attributes on inflation. - */ - public static void setInDebugMode() { - inDebugMode = true; - } - private boolean multiline; private boolean constructed; @@ -100,7 +86,7 @@ public class TypefacedEditText extends AppCompatEditText { setSingleLine(); } typedArray.recycle(); - if (inDebugMode) { + if (BuildConfig.DEBUG) { checkAttributes(context, attrs); } } diff --git a/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedTextView.java b/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedTextView.java index 188686c..702342d 100644 --- a/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedTextView.java +++ b/views/src/main/java/ru/touchin/roboswag/components/views/TypefacedTextView.java @@ -51,15 +51,6 @@ public class TypefacedTextView extends AppCompatTextView { private static final int UNSPECIFIED_MEASURE_SPEC = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); private static final int START_SCALABLE_DIFFERENCE = 4; - private static boolean inDebugMode; - - /** - * Enables debugging features like checking attributes on inflation. - */ - public static void setInDebugMode() { - inDebugMode = true; - } - private boolean constructed; @NonNull private LineStrategy lineStrategy = LineStrategy.SINGLE_LINE_ELLIPSIZE; @@ -92,7 +83,7 @@ public class TypefacedTextView extends AppCompatTextView { setLineStrategy(lineStrategy); } typedArray.recycle(); - if (inDebugMode) { + if (BuildConfig.DEBUG) { checkAttributes(context, attrs); } }