Add crashlytics (#47)

This commit is contained in:
Mikołaj Pich 2018-01-11 21:57:41 +01:00 committed by Rafał Borcz
parent 23ac726d3c
commit be161cf161
6 changed files with 69 additions and 6 deletions

View File

@ -33,7 +33,7 @@ jobs:
command: ./gradlew dependencies --no-daemon --stacktrace --console=plain -PdisablePreDex || true command: ./gradlew dependencies --no-daemon --stacktrace --console=plain -PdisablePreDex || true
- run: - run:
name: Initial build name: Initial build
command: ./gradlew -x test -x lint build assembleDebug --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew build assembleDebug -x test -x lint -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
- store_artifacts: - store_artifacts:
path: ./app/build/outputs/apk/ path: ./app/build/outputs/apk/
destination: apks/ destination: apks/
@ -54,7 +54,7 @@ jobs:
<<: *general_cache_key <<: *general_cache_key
- run: - run:
name: Run lint name: Run lint
command: ./gradlew lint --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew lint -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
- store_artifacts: - store_artifacts:
path: ./app/build/reports/ path: ./app/build/reports/
destination: lint_reports/app/ destination: lint_reports/app/
@ -73,7 +73,7 @@ jobs:
<<: *general_cache_key <<: *general_cache_key
- run: - run:
name: Run app tests name: Run app tests
command: ./gradlew :app:test :app:jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex command: ./gradlew :app:test :app:jacocoTestReport -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: - run:
name: Upload unit code coverage to codecov name: Upload unit code coverage to codecov
command: bash <(curl -s https://codecov.io/bash) -F app command: bash <(curl -s https://codecov.io/bash) -F app

View File

@ -1,5 +1,22 @@
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
classpath 'io.fabric.tools:gradle:1.25.1'
}
}
repositories {
maven { url 'https://maven.fabric.io/public' }
}
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' apply plugin: 'org.greenrobot.greendao'
apply plugin: 'io.fabric'
apply from: '../jacoco.gradle' apply from: '../jacoco.gradle'
apply from: '../android-sonarqube.gradle' apply from: '../android-sonarqube.gradle'
@ -17,6 +34,9 @@ android {
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
buildConfigField "String", "UPDATE_URL", "\"https://bitrise-redirector.herokuapp.com" + buildConfigField "String", "UPDATE_URL", "\"https://bitrise-redirector.herokuapp.com" +
"/v0.1/apps/daeff1893f3c8128/builds/" + "${getCurrentGitBranch()}" + "/artifacts/app-release-bitrise-signed.apk/info\"" "/v0.1/apps/daeff1893f3c8128/builds/" + "${getCurrentGitBranch()}" + "/artifacts/app-release-bitrise-signed.apk/info\""
manifestPlaceholders = [
fabricApiKey: System.getenv("FABRIC_API_KEY") ?: "null"
]
} }
buildTypes { buildTypes {
@ -66,6 +86,13 @@ dependencies {
implementation 'com.google.dagger:dagger-android:2.14.1' implementation 'com.google.dagger:dagger-android:2.14.1'
implementation 'com.google.dagger:dagger-android-support:2.14.1' implementation 'com.google.dagger:dagger-android-support:2.14.1'
implementation('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') {
transitive = true
}
implementation('com.crashlytics.sdk.android:answers:1.4.1@aar') {
transitive = true
}
annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1' annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

View File

@ -59,6 +59,9 @@
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" /> android:resource="@xml/provider_paths" />
</provider> </provider>
<meta-data
android:name="io.fabric.ApiKey"
android:value="${fabricApiKey}" />
</application> </application>
</manifest> </manifest>

View File

@ -4,10 +4,14 @@ import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.core.CrashlyticsCore;
import org.greenrobot.greendao.query.QueryBuilder; import org.greenrobot.greendao.query.QueryBuilder;
import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.utils.Log; import eu.davidea.flexibleadapter.utils.Log;
import io.fabric.sdk.android.Fabric;
import io.github.wulkanowy.db.dao.entities.DaoMaster; import io.github.wulkanowy.db.dao.entities.DaoMaster;
import io.github.wulkanowy.db.dao.entities.DaoSession; import io.github.wulkanowy.db.dao.entities.DaoSession;
@ -25,6 +29,8 @@ public class WulkanowyApp extends Application {
enableDebugLog(); enableDebugLog();
} }
initializeFabric();
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "wulkanowy-db"); DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "wulkanowy-db");
daoSession = new DaoMaster(devOpenHelper.getWritableDb()).newSession(); daoSession = new DaoMaster(devOpenHelper.getWritableDb()).newSession();
@ -46,6 +52,15 @@ public class WulkanowyApp extends Application {
FlexibleAdapter.enableLogs(Log.Level.DEBUG); FlexibleAdapter.enableLogs(Log.Level.DEBUG);
} }
private void initializeFabric() {
Fabric.with(new Fabric.Builder(this)
.kits(new Crashlytics.Builder()
.core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
.build())
.debuggable(BuildConfig.DEBUG)
.build());
}
public DaoSession getDaoSession() { public DaoSession getDaoSession() {
return daoSession; return daoSession;
} }

View File

@ -13,6 +13,10 @@ import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
@ -53,7 +57,7 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
private WeakReference<TextView> showText; private WeakReference<TextView> showText;
public LoginTask(Activity activity, String email, String password, String symbol) { LoginTask(Activity activity, String email, String password, String symbol) {
this.activity = new WeakReference<>(activity); this.activity = new WeakReference<>(activity);
this.email = email; this.email = email;
this.password = password; this.password = password;
@ -93,6 +97,9 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
return R.string.error_host_offline; return R.string.error_host_offline;
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
return -1; return -1;
} catch (Throwable e) {
Crashlytics.logException(e);
return R.string.login_denied_text;
} }
new FullSyncJob().scheduledJob(activity.get()); new FullSyncJob().scheduledJob(activity.get());
@ -116,6 +123,7 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
switch (messageID) { switch (messageID) {
// if success // if success
case R.string.login_accepted_text: case R.string.login_accepted_text:
logFirstLoginAction(true, activity.get().getString(messageID));
Intent intent = new Intent(activity.get(), DashboardActivity.class); Intent intent = new Intent(activity.get(), DashboardActivity.class);
activity.get().finish(); activity.get().finish();
activity.get().startActivity(intent); activity.get().startActivity(intent);
@ -123,6 +131,7 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
// if bad credentials entered // if bad credentials entered
case R.string.login_bad_credentials_text: case R.string.login_bad_credentials_text:
logFirstLoginAction(false, activity.get().getString(messageID));
EditText passwordView = activity.get().findViewById(R.id.password); EditText passwordView = activity.get().findViewById(R.id.password);
passwordView.setError(activity.get().getString(R.string.error_incorrect_password)); passwordView.setError(activity.get().getString(R.string.error_incorrect_password));
passwordView.requestFocus(); passwordView.requestFocus();
@ -131,6 +140,7 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
// if no permission // if no permission
case R.string.error_bad_account_permission: case R.string.error_bad_account_permission:
logFirstLoginAction(false, activity.get().getString(messageID));
// Change to visible symbol input view // Change to visible symbol input view
TextInputLayout symbolLayout = activity.get().findViewById(R.id.to_symbol_input_layout); TextInputLayout symbolLayout = activity.get().findViewById(R.id.to_symbol_input_layout);
symbolLayout.setVisibility(View.VISIBLE); symbolLayout.setVisibility(View.VISIBLE);
@ -143,6 +153,7 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
// if rooted and SDK < 18 // if rooted and SDK < 18
case -1: case -1:
logFirstLoginAction(false, "Device rooted");
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity.get()) final AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity.get())
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.alert_dialog_blocked_app) .setTitle(R.string.alert_dialog_blocked_app)
@ -157,12 +168,20 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
break; break;
default: default:
logFirstLoginAction(false, activity.get().getString(messageID));
Snackbar.make(activity.get().findViewById(R.id.fragment_container), Snackbar.make(activity.get().findViewById(R.id.fragment_container),
messageID, Snackbar.LENGTH_LONG).show(); messageID, Snackbar.LENGTH_LONG).show();
break; break;
} }
} }
private void logFirstLoginAction(boolean success, String message) {
Answers.getInstance().logCustom(new CustomEvent("First login")
.putCustomAttribute("Symbol", symbol)
.putCustomAttribute("Success", success ? 1 : 0)
.putCustomAttribute("Message", message));
}
@Override @Override
protected void onCancelled() { protected void onCancelled() {
showProgress(false); showProgress(false);
@ -171,7 +190,7 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
/** /**
* Shows the progress UI and hides the login form. * Shows the progress UI and hides the login form.
*/ */
public void showProgress(final boolean show) { void showProgress(final boolean show) {
loginFormView = new WeakReference<>(activity.get().findViewById(R.id.login_form)); loginFormView = new WeakReference<>(activity.get().findViewById(R.id.login_form));
progressView = new WeakReference<>(activity.get().findViewById(R.id.login_progress)); progressView = new WeakReference<>(activity.get().findViewById(R.id.login_progress));

View File

@ -7,7 +7,6 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files