From 630e548a0ed02dce17794d5fe983d3caadc174cf Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 11:15:02 +0200 Subject: [PATCH 1/8] Increase versions and light internal refactor at plugin --- build.gradle | 6 ++-- .../inappdevtools/InAppDevToolsPlugin.groovy | 36 ++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index 727acd1c..c864ee98 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { plugins { // Declare our plugin (make it available at subprojects) - id "es.rafaco.inappdevtools" version "0.0.14" apply false + id "es.rafaco.inappdevtools" version "0.0.15" apply false id "org.sonarqube" version "2.7" } @@ -34,10 +34,10 @@ allprojects { } ext { - pluginVersionName = '0.0.14' + pluginVersionName = '0.0.15' libraryPublishedVersion = '0.0.51' - libraryWorkingVersion = '0.0.51' + libraryWorkingVersion = '0.0.52' libraryVersionCode = 1 libraryMinSdkVersion = 16 diff --git a/plugin/src/main/groovy/es/rafaco/inappdevtools/InAppDevToolsPlugin.groovy b/plugin/src/main/groovy/es/rafaco/inappdevtools/InAppDevToolsPlugin.groovy index 5ddf551b..823c4607 100644 --- a/plugin/src/main/groovy/es/rafaco/inappdevtools/InAppDevToolsPlugin.groovy +++ b/plugin/src/main/groovy/es/rafaco/inappdevtools/InAppDevToolsPlugin.groovy @@ -24,11 +24,12 @@ class InAppDevToolsPlugin implements Plugin { void apply(Project project) { - if(!isAndroidApplication(project) && !isAndroidLibrary(project)){ + if(!isAndroidApplication(project) && !isAndroidLibrary(project) && !isAndroidFeature(project)){ if (isRoot(project)) - println "IATD: Skipped root project" + println "IATD skipped for root project" else - println "IATD: Skipped NOT root project" + println "IATD skipped for ${project.name} project. " + + "Only Android application, library or feature project are currently allowed." return } @@ -47,13 +48,13 @@ class InAppDevToolsPlugin implements Plugin { project.android.defaultConfig.buildConfigField("String", "INTERNAL_PACKAGE", "\"${internalPackage}\"") } - //Add tasks - project.task(CONFIG_TASK, type:GenerateConfigsTask) + // Add all our tasks to project + addGenerateConfigTask(project) addPackSourcesTask(project, outputFolder) addPackResourcesTask(project, outputFolder) addCleanTask(project, outputFolder) - // Link tasks on project + // Selectively link our tasks to each BuildVariant project.tasks.whenTaskAdded { theTask -> if (theTask.name.contains("generate") & theTask.name.contains("ResValues")) { @@ -62,20 +63,25 @@ class InAppDevToolsPlugin implements Plugin { && isSourceInclusion(project) && isSourceInspection(project)){ - if (isDebug(project)){ println "IADT will include your sources in your apk before " + theTask.name } + if (isDebug(project)){ + println "IADT will include your sources in your apk before " + theTask.name + } + theTask.dependsOn += [ project.tasks.getByName(SOURCES_TASK), project.tasks.getByName(RESOURCES_TASK)] } else{ - if (isDebug(project)){ println "IADT will not add your sources - Added clean sources tasks before " + theTask.name } - //project.android.sourceSets.main.assets.srcDirs -= "${project.buildDir}${ASSETS_PATH}" - //delete(project.file("${project.buildDir}\\generated\\assets\\inappdevtools")) + if (isDebug(project)){ + println "IADT will not add your sources - Added clean sources tasks before " + theTask.name + } + theTask.dependsOn += [ project.tasks.getByName(CLEAN_TASK)] } - //Include CONFIG_TASK for all compilations + //TODO: do we need it when disabled? + // Link CONFIG_TASK theTask.dependsOn += [ project.tasks.getByName(CONFIG_TASK)] } @@ -87,8 +93,8 @@ class InAppDevToolsPlugin implements Plugin { } } - static boolean isRoot(Project project){ - return project.name.equals(project.rootProject.name) + private Task addGenerateConfigTask(Project project) { + project.task(CONFIG_TASK, type: GenerateConfigsTask) } private Task addCleanTask(Project project, outputFolder) { @@ -216,6 +222,10 @@ class InAppDevToolsPlugin implements Plugin { return true } + static boolean isRoot(Project project){ + return project.name.equals(project.rootProject.name) + } + static boolean isAndroidApplication(Project project){ return project.plugins.hasPlugin('com.android.application') } From d006f7108d7ba9e656378b0a26e323f4288caf1e Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 12:41:00 +0200 Subject: [PATCH 2/8] CrashHandler fix: internal exception when stacktrace.lenght is 0. * TODO RELEASE: remove extra logs. Leaved to keep observation a bit. --- .../events/detectors/crash/CrashHandler.java | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java index 127e7a71..3ac4ae46 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java @@ -17,6 +17,8 @@ import es.rafaco.inappdevtools.library.Iadt; import es.rafaco.inappdevtools.library.IadtController; import es.rafaco.inappdevtools.library.logic.config.BuildConfig; +import es.rafaco.inappdevtools.library.logic.events.EventDetector; +import es.rafaco.inappdevtools.library.logic.events.detectors.app.ErrorAnrEventDetector; import es.rafaco.inappdevtools.library.logic.events.detectors.lifecycle.ActivityEventDetector; import es.rafaco.inappdevtools.library.storage.prefs.utils.PendingCrashUtil; import es.rafaco.inappdevtools.library.logic.log.FriendlyLog; @@ -56,20 +58,31 @@ public void uncaughtException(final Thread thread, final Throwable ex) { try { friendlyLogId = FriendlyLog.logCrash(ex.getMessage()); - //stopDevToolsServices(); + Log.v(Iadt.TAG, "CrashHandler: logCrash done"); + stopAnrDetector(); Crash crash = buildCrash(thread, ex); + Log.v(Iadt.TAG, "CrashHandler: buildCrash done"); printLogcatError(thread, crash); + Log.v(Iadt.TAG, "CrashHandler: printLogcatError done"); long crashId = storeCrash(crash); + Log.v(Iadt.TAG, "CrashHandler: printLogcatError done"); PendingCrashUtil.savePending(); + Log.v(Iadt.TAG, "CrashHandler: savePending done"); IadtController.get().beforeClose(); + Log.v(Iadt.TAG, "CrashHandler: beforeClose done"); saveLogcat(crashId); + Log.v(Iadt.TAG, "CrashHandler: saveLogcat done"); saveScreenshot(); + Log.v(Iadt.TAG, "CrashHandler: saveScreenshot done"); saveDetailReport(); + Log.v(Iadt.TAG, "CrashHandler: saveDetailReport done"); saveStacktrace(crashId, ex); + Log.v(Iadt.TAG, "CrashHandler: saveStacktrace done"); Log.v(Iadt.TAG, "CrashHandler: process finished on " + (new Date().getTime() - startTime) + " ms"); onCrashStored( thread, ex); + Log.v(Iadt.TAG, "CrashHandler: onCrashStored done"); } catch (Exception e) { Log.e(Iadt.TAG, "CrashHandler: exception while processing uncaughtException on " + Humanizer.getElapsedTime(startTime)); @@ -79,6 +92,13 @@ public void uncaughtException(final Thread thread, final Throwable ex) { } } + private void stopAnrDetector() { + // Early stop of AnrDetector, other get stopped later on by IadtController.beforeClose(). + // Reason: AnrDetector start new threads which is currently forbidden. + EventDetector anrDetector = IadtController.get().getEventManager().getEventDetectorsManager().get(ErrorAnrEventDetector.class); + anrDetector.stop(); + } + private void onCrashStored(Thread thread, Throwable ex) { if (IadtController.get().getConfig().getBoolean(BuildConfig.CALL_DEFAULT_CRASH_HANDLER)){ Log.i(Iadt.TAG, "CrashHandler: Let the exception propagate to default handler"); @@ -100,19 +120,33 @@ private void stopDevToolsServices() { @NonNull private Crash buildCrash(Thread thread, Throwable ex) { final Crash crash = new Crash(); + Log.v(Iadt.TAG, "CrashHandler: 0.1 done"); crash.setDate(new Date().getTime()); + Log.v(Iadt.TAG, "CrashHandler: 0.2 done"); crash.setException(ex.getClass().getSimpleName()); - crash.setExceptionAt(ex.getStackTrace()[1].toString()); + Log.v(Iadt.TAG, "CrashHandler: 0.3 done"); + if (ex.getStackTrace()!=null && ex.getStackTrace().length>0) { + crash.setExceptionAt(ex.getStackTrace()[1].toString()); + } + else{ + //TODO: REPORTS - Research why this happen, getExceptionAt and getCauseExceptionAt is only used by crash report + // i.e: InflateException -> Binary XML file ... You must supply a layout_height attribute. + Log.v(Iadt.TAG, "CrashHandler: 0.4 FIX!"); + } + Log.v(Iadt.TAG, "CrashHandler: 0.4 done"); crash.setMessage(ex.getMessage()); - + Log.v(Iadt.TAG, "CrashHandler: 1 done"); Throwable cause = ex.getCause(); if (cause != null){ crash.setCauseException(cause.getClass().getSimpleName()); crash.setCauseMessage(cause.getMessage()); - if (cause.getStackTrace() != null && cause.getStackTrace().length > 1){ + if (cause.getStackTrace() != null && cause.getStackTrace().length > 0){ + //TODO: REPORTS - Research why this happen, getExceptionAt and getCauseExceptionAt is only used by crash report + // i.e: InflateException -> Binary XML file ... You must supply a layout_height attribute. crash.setCauseExceptionAt(cause.getStackTrace()[1].toString()); } } + Log.v(Iadt.TAG, "CrashHandler: 2 done"); ActivityEventDetector activityWatcher = (ActivityEventDetector) IadtController.get().getEventManager() .getEventDetectorsManager().get(ActivityEventDetector.class); crash.setStacktrace(Log.getStackTraceString(ex)); @@ -122,6 +156,7 @@ private Crash buildCrash(Thread thread, Throwable ex) { crash.setThreadGroupName(thread.getThreadGroup().getName()); crash.setForeground(!activityWatcher.isInBackground()); crash.setLastActivity(activityWatcher.getLastActivityResumed()); + Log.v(Iadt.TAG, "CrashHandler: 3 done"); return crash; } From d6b97b206f3ba3cb8623ad27c848023935c5431c Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 12:54:49 +0200 Subject: [PATCH 3/8] CrashHandler stacktraceAt fix. --- .../events/detectors/crash/CrashHandler.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java index 3ac4ae46..68caedef 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java @@ -125,13 +125,10 @@ private Crash buildCrash(Thread thread, Throwable ex) { Log.v(Iadt.TAG, "CrashHandler: 0.2 done"); crash.setException(ex.getClass().getSimpleName()); Log.v(Iadt.TAG, "CrashHandler: 0.3 done"); - if (ex.getStackTrace()!=null && ex.getStackTrace().length>0) { - crash.setExceptionAt(ex.getStackTrace()[1].toString()); - } - else{ - //TODO: REPORTS - Research why this happen, getExceptionAt and getCauseExceptionAt is only used by crash report - // i.e: InflateException -> Binary XML file ... You must supply a layout_height attribute. - Log.v(Iadt.TAG, "CrashHandler: 0.4 FIX!"); + if (ex.getStackTrace()!=null && ex.getStackTrace().length > 0) { + // Some exceptions doesn't have stacktrace + // i.e. Binary XML file ... You must supply a layout_height attribute. + crash.setExceptionAt(ex.getStackTrace()[0].toString()); } Log.v(Iadt.TAG, "CrashHandler: 0.4 done"); crash.setMessage(ex.getMessage()); @@ -141,9 +138,7 @@ private Crash buildCrash(Thread thread, Throwable ex) { crash.setCauseException(cause.getClass().getSimpleName()); crash.setCauseMessage(cause.getMessage()); if (cause.getStackTrace() != null && cause.getStackTrace().length > 0){ - //TODO: REPORTS - Research why this happen, getExceptionAt and getCauseExceptionAt is only used by crash report - // i.e: InflateException -> Binary XML file ... You must supply a layout_height attribute. - crash.setCauseExceptionAt(cause.getStackTrace()[1].toString()); + crash.setCauseExceptionAt(cause.getStackTrace()[0].toString()); } } Log.v(Iadt.TAG, "CrashHandler: 2 done"); From 0737e72b9b57ad530b5fe78c020beb03bb93e8e8 Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 13:56:14 +0200 Subject: [PATCH 4/8] Notification intrusion fix. Added 3 notification channels --- .../detectors/app/InitialEventDetector.java | 2 +- .../storage/prefs/utils/PendingCrashUtil.java | 19 ++++-- .../notifications/NotificationService.java | 68 +++++++++++++++---- 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/InitialEventDetector.java b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/InitialEventDetector.java index 2ab1ae3a..8412bc4a 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/InitialEventDetector.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/InitialEventDetector.java @@ -68,7 +68,7 @@ public void onEvent(Event event, Object param) { eventManager.subscribe(Event.APP_START, new EventManager.Listener(){ @Override public void onEvent(Event event, Object param) { - if (PendingCrashUtil.isPending()) { + if (PendingCrashUtil.isSessionFromPending()) { FriendlyLog.log(new Date().getTime(), "W", "App", "Restart", "App restarted after a crash"); } else if (FirstStartUtil.isFirstStart()) { diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java b/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java index 8682f182..a68cb299 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java @@ -5,10 +5,7 @@ public class PendingCrashUtil { public static final String PREF_VALUE_KEY = "PENDING_CRASH"; - - public static boolean isPending(){ - return DevToolsPrefs.getBoolean(PREF_VALUE_KEY, false); - } + private static Boolean iSessionFromPending; public static void savePending(){ DevToolsPrefs.setBoolean(PREF_VALUE_KEY, true); @@ -17,4 +14,18 @@ public static void savePending(){ public static void clearPending(){ DevToolsPrefs.setBoolean(PREF_VALUE_KEY, false); } + + public static boolean isPending(){ + if (iSessionFromPending == null){ + isSessionFromPending(); + } + return DevToolsPrefs.getBoolean(PREF_VALUE_KEY, false); + } + + public static boolean isSessionFromPending() { + if (iSessionFromPending == null){ + iSessionFromPending = DevToolsPrefs.getBoolean(PREF_VALUE_KEY, false); + } + return iSessionFromPending; + } } diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java index 441224ec..df2141a7 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java @@ -31,6 +31,7 @@ import es.rafaco.inappdevtools.library.logic.info.reporters.BuildInfoReporter; import es.rafaco.inappdevtools.library.logic.utils.AppUtils; import es.rafaco.inappdevtools.library.storage.db.entities.Crash; +import es.rafaco.inappdevtools.library.storage.prefs.utils.FirstStartUtil; import es.rafaco.inappdevtools.library.storage.prefs.utils.PendingCrashUtil; import es.rafaco.inappdevtools.library.view.overlay.OverlayService; import es.rafaco.inappdevtools.library.logic.info.reporters.AppInfoReporter; @@ -40,8 +41,10 @@ public class NotificationService extends Service { private static final int NOTIFICATION_ID = 3002; - private static final String CHANNEL_ID = "es.rafaco.iadt"; private static final String GROUP_ID = "es.rafaco.iadt.foreground_service"; + private static final String CHANNEL_PRIORITY = "es.rafaco.iadt.priority"; + private static final String CHANNEL_STANDARD = "es.rafaco.iadt.standard"; + private static final String CHANNEL_SILENT = "es.rafaco.iadt.silent"; private static final int SUMMARY_ID = 0; public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE"; @@ -122,7 +125,7 @@ private void startForegroundService() { if (IadtController.get().isDebug()) Log.d(Iadt.TAG, "Start foreground service."); - createNotificationChannel(); + createNotificationChannels(); /*Intent intent = AppUtils.getAppLauncherIntent(getApplicationContext()); PendingIntent pendingIntent = PendingIntent.getActivity(this, @@ -135,7 +138,7 @@ private void startForegroundService() { Notification notification = buildMainNotification(pendingIntent, - PendingCrashUtil.isPending() ? new Crash() : null); + PendingCrashUtil.isSessionFromPending() ? new Crash() : null); //createNotificationGroup(); //createNotificationSummary(); @@ -190,14 +193,12 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr title = "Open developer tools"; subTitle = overview; }else{ - title = "Ups, your app crashed"; + title = "Restarted from crashed, please report"; subTitle = "Expand me for options..."; } - NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) + NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setGroup(GROUP_ID) - .setDefaults(Notification.DEFAULT_VIBRATE) - .setPriority(Notification.PRIORITY_MAX) .setVisibility(Notification.VISIBILITY_PRIVATE) .setOnlyAlertOnce(true) .setSmallIcon(R.drawable.ic_bug_report_white_24dp) @@ -209,9 +210,29 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr //.setSubText("setSubText") //Group second .setWhen(System.currentTimeMillis()); //Group third + builder.setChannelId(getCurrentChannel()); + if (FirstStartUtil.isFirstStart()){ + Log.w("RAFA", "Notification isFirstStart"); + builder.setDefaults(Notification.DEFAULT_VIBRATE) + .setPriority(Notification.PRIORITY_MAX); + } + else if (crash == null){ + Log.w("RAFA", "Notification crash"); + builder.setDefaults(Notification.DEFAULT_VIBRATE) + .setPriority(Notification.PRIORITY_MIN); + } + else{ + Log.w("RAFA", "Notification not isFirstStart"); + builder.setDefaults(Notification.DEFAULT_LIGHTS) + .setPriority(Notification.PRIORITY_MIN); + } + if (crash == null){ + Log.w("RAFA", "Notification not crash"); builder.setColor(getResources().getColor(R.color.rally_blue_med)); - }else{ + } + else{ + Log.w("RAFA", "Notification crash"); builder.setColor(getResources().getColor(R.color.rally_orange)); } @@ -231,6 +252,15 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr return builder.build(); } + private String getCurrentChannel() { + if (FirstStartUtil.isFirstStart()) + return CHANNEL_PRIORITY; + else if (PendingCrashUtil.isSessionFromPending()) + return CHANNEL_STANDARD; + else + return CHANNEL_SILENT; + } + //TODO: delete? private Notification buildCrashNotification(PendingIntent pendingIntent) { @@ -238,7 +268,7 @@ private Notification buildCrashNotification(PendingIntent pendingIntent) { Bitmap largeIconBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_error_orange_24dp); String title = String.format("Ups, %s crashed", infoHelper.getAppName()); - NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getCurrentChannel()) .setGroup(GROUP_ID) .setPriority(Notification.PRIORITY_MAX) .setVisibility(Notification.VISIBILITY_PRIVATE) @@ -305,17 +335,25 @@ private NotificationCompat.Action buildAction(String action) { return new NotificationCompat.Action(0, title, pendingPrevIntent); } - private void createNotificationChannel() { + private void createNotificationChannels() { + createNotificationChannel(CHANNEL_PRIORITY, NotificationManager.IMPORTANCE_HIGH); + createNotificationChannel(CHANNEL_STANDARD, NotificationManager.IMPORTANCE_DEFAULT); + createNotificationChannel(CHANNEL_SILENT, NotificationManager.IMPORTANCE_LOW); + } + + private void createNotificationChannel(String notificationId, int importance) { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = getSystemService(NotificationManager.class); - NotificationChannel channel = notificationManager.getNotificationChannel(CHANNEL_ID); + NotificationChannel channel = notificationManager.getNotificationChannel(notificationId); if(channel==null){ CharSequence name = "NotificationService"; String description = "To showMain Iadt report notification"; - int importance = NotificationManager.IMPORTANCE_HIGH; - channel = new NotificationChannel(CHANNEL_ID, name, importance); + channel = new NotificationChannel(notificationId, name, importance); + if (importance == NotificationManager.IMPORTANCE_LOW){ + channel.setSound(null, null); + } channel.setDescription(description); notificationManager.createNotificationChannel(channel); } @@ -323,7 +361,7 @@ private void createNotificationChannel() { } private void createNotificationGroup() { - Notification summaryNotification = new NotificationCompat.Builder(this, CHANNEL_ID) + Notification summaryNotification = new NotificationCompat.Builder(this, getCurrentChannel()) .setSmallIcon(UiUtils.getAppIconResourceId()) .setContentTitle("Group Title") .setContentText("Group text") @@ -339,7 +377,7 @@ private void createNotificationGroup() { private void createNotificationSummary() { Notification summaryNotification = - new NotificationCompat.Builder(this, CHANNEL_ID) + new NotificationCompat.Builder(this, getCurrentChannel()) .setContentTitle("Summary Title") .setContentText("Summary text") .setSmallIcon(UiUtils.getAppIconResourceId()) From 3d35babdd67f33e144b708cbd2fcb4f50124a2ea Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 14:15:58 +0200 Subject: [PATCH 5/8] Notification only pop up after welcome accepted --- .../library/storage/prefs/utils/FirstStartUtil.java | 11 +++++++++++ .../library/storage/prefs/utils/PendingCrashUtil.java | 10 +++++----- .../view/notifications/NotificationService.java | 7 ++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/FirstStartUtil.java b/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/FirstStartUtil.java index 0e6c28b7..53c70b42 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/FirstStartUtil.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/FirstStartUtil.java @@ -5,11 +5,22 @@ public class FirstStartUtil { public static final String PREF_VALUE_KEY = "IS_FIRST_START"; + private static Boolean isSessionFromFirstStart; public static boolean isFirstStart(){ + if (isSessionFromFirstStart == null){ + return isSessionFromFirstStart(); + } return DevToolsPrefs.getBoolean(PREF_VALUE_KEY, true); } + public static boolean isSessionFromFirstStart() { + if (isSessionFromFirstStart == null){ + isSessionFromFirstStart = DevToolsPrefs.getBoolean(PREF_VALUE_KEY, true); + } + return isSessionFromFirstStart; + } + public static void saveFirstStart(){ DevToolsPrefs.setBoolean(PREF_VALUE_KEY, false); } diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java b/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java index a68cb299..a920f44d 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/storage/prefs/utils/PendingCrashUtil.java @@ -11,13 +11,9 @@ public static void savePending(){ DevToolsPrefs.setBoolean(PREF_VALUE_KEY, true); } - public static void clearPending(){ - DevToolsPrefs.setBoolean(PREF_VALUE_KEY, false); - } - public static boolean isPending(){ if (iSessionFromPending == null){ - isSessionFromPending(); + return isSessionFromPending(); } return DevToolsPrefs.getBoolean(PREF_VALUE_KEY, false); } @@ -28,4 +24,8 @@ public static boolean isSessionFromPending() { } return iSessionFromPending; } + + public static void clearPending(){ + DevToolsPrefs.setBoolean(PREF_VALUE_KEY, false); + } } diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java index df2141a7..a8facf32 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java @@ -211,12 +211,13 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr .setWhen(System.currentTimeMillis()); //Group third builder.setChannelId(getCurrentChannel()); - if (FirstStartUtil.isFirstStart()){ + Log.w("RAFA", "Notification channel: " + getCurrentChannel()); + if (FirstStartUtil.isSessionFromFirstStart()){ Log.w("RAFA", "Notification isFirstStart"); builder.setDefaults(Notification.DEFAULT_VIBRATE) .setPriority(Notification.PRIORITY_MAX); } - else if (crash == null){ + else if (crash != null){ Log.w("RAFA", "Notification crash"); builder.setDefaults(Notification.DEFAULT_VIBRATE) .setPriority(Notification.PRIORITY_MIN); @@ -253,7 +254,7 @@ else if (crash == null){ } private String getCurrentChannel() { - if (FirstStartUtil.isFirstStart()) + if (FirstStartUtil.isSessionFromFirstStart()) return CHANNEL_PRIORITY; else if (PendingCrashUtil.isSessionFromPending()) return CHANNEL_STANDARD; From c652508b66debda1e9b5f2418d44cf047d2e235d Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 18:37:49 +0200 Subject: [PATCH 6/8] LogScreen: fix scroll issues and flicks. --- .../detectors/app/ErrorAnrEventDetector.java | 2 +- .../view/overlay/screens/log/LogAdapter.java | 5 +++++ .../view/overlay/screens/log/LogScreen.java | 10 ++-------- .../overlay/screens/log/LogViewHolder.java | 9 +++++---- library/src/main/res/layout/tool_log_item.xml | 19 ++++++++++++++----- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/ErrorAnrEventDetector.java b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/ErrorAnrEventDetector.java index 099ef766..9e3daebf 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/ErrorAnrEventDetector.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/app/ErrorAnrEventDetector.java @@ -35,7 +35,7 @@ public void subscribe() { @Override public void start() { - watchDog = new ANRWatchDog() + watchDog = new ANRWatchDog(2*1000) .setANRListener(new ANRWatchDog.ANRListener() { @Override public void onAppNotResponding(ANRError error) { diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogAdapter.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogAdapter.java index 64b3a297..4d8cf174 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogAdapter.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogAdapter.java @@ -43,6 +43,11 @@ protected LogAdapter() { setClickListener(); } + @Override + public long getItemId(int position) { + return getItem(position).getDate(); + } + @NonNull @Override public LogViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java index a2869674..63dddbe1 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java @@ -2,6 +2,7 @@ import android.content.DialogInterface; import android.content.Intent; +import android.support.v7.widget.SimpleItemAnimator; import android.util.Log; import android.view.MenuItem; import android.view.View; @@ -143,9 +144,6 @@ private void initAdapter(){ public void onItemRangeInserted(int positionStart, int itemCount) { super.onItemRangeInserted(positionStart, itemCount); if (positionStart != 0 && !recyclerView.canScrollVertically(1)){ - //Log.v(Iadt.TAG, "Scrolling onItemRangeInserted( positionStart="+positionStart - // +" itemCount="+itemCount+" size="+adapter.getItemCount() - // +" isBottom="+!recyclerView.canScrollVertically(1) + ")"); scrollToBottom(); } } @@ -153,9 +151,7 @@ public void onItemRangeInserted(int positionStart, int itemCount) { PagedList.Config myPagingConfig = new PagedList.Config.Builder() .setEnablePlaceholders(true) - .setInitialLoadSizeHint(4) - .setPageSize(20) - .setPrefetchDistance(60) + .setPageSize(25*2) .build(); initLiveDataWithFriendlyLog(myPagingConfig); @@ -163,11 +159,9 @@ public void onItemRangeInserted(int positionStart, int itemCount) { logList.observe(ProcessLifecycleOwner.get(), new Observer>() { @Override public void onChanged(PagedList pagedList) { - //FriendlyLog.log("V", "Iadt", "IadtLiveData", "Observer onChanged"); adapter.submitList(pagedList); } }); - //Log.d("IadtLiveData", "Observer registered to PagedList from FriendlyDao"); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext()); ((LinearLayoutManager) mLayoutManager).setStackFromEnd(true); diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogViewHolder.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogViewHolder.java index 83e14809..54036dca 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogViewHolder.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogViewHolder.java @@ -168,13 +168,14 @@ else if(data.getCategory().equals("Network")){ public void showPlaceholder(int position) { int color = ContextCompat.getColor(title.getContext(), R.color.rally_gray); + decorator.setVisibility(View.VISIBLE); + //decorator.setBackgroundColor(color); + title.setVisibility(View.VISIBLE); - title.setText(""); - title.setBackgroundColor(color); - decorator.setBackgroundColor(color); + //title.setBackgroundColor(color); icon.setVisibility(View.VISIBLE); - icon.setBackgroundColor(color); + //icon.setBackgroundColor(color); extra_wrapper.setVisibility(View.GONE); overTitleWrapper.setVisibility(View.GONE); diff --git a/library/src/main/res/layout/tool_log_item.xml b/library/src/main/res/layout/tool_log_item.xml index 81172ce4..2406bb85 100644 --- a/library/src/main/res/layout/tool_log_item.xml +++ b/library/src/main/res/layout/tool_log_item.xml @@ -15,8 +15,9 @@ android:layout_gravity="left" android:textAlignment="center" android:textColor="@color/iadt_background" + android:text=" " android:textStyle="bold" - android:background="@color/rally_green" + android:background="@color/iadt_background" android:layout_marginLeft="4dp"/> + + + android:padding="4dp" + android:visibility="gone"> + android:padding="4dp" + android:visibility="gone"> + android:text="Details" + android:visibility="gone"/> From eaaff2854fbc21b759558bfa1e2809f32bc66708 Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 19:06:44 +0200 Subject: [PATCH 7/8] Notification channels added with name and description. --- .../view/notifications/IadtChannel.java | 41 +++++++++++++++++++ .../notifications/NotificationService.java | 41 ++++++++----------- .../view/overlay/screens/log/LogScreen.java | 1 - 3 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/IadtChannel.java diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/IadtChannel.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/IadtChannel.java new file mode 100644 index 00000000..535a0ff3 --- /dev/null +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/IadtChannel.java @@ -0,0 +1,41 @@ +package es.rafaco.inappdevtools.library.view.notifications; + +import android.app.NotificationManager; + +public enum IadtChannel { + + CHANNEL_PRIORITY("es.rafaco.iadt.priority", "Iadt Priority", NotificationManager.IMPORTANCE_HIGH, + "Notifications pop up over other screens"), + CHANNEL_STANDARD("es.rafaco.iadt.standard", "Iadt Standard", NotificationManager.IMPORTANCE_DEFAULT, + "Non intrusive notifications, they use device settings for sound and vibrate"), + CHANNEL_SILENT("es.rafaco.iadt.silent", "Iadt Silent", NotificationManager.IMPORTANCE_LOW, + "Non intrusive and always silent notifications"); + + private String id; + private String name; + private String description; + private int priority; + + IadtChannel(String id, String name, int priority, String description) { + this.id = id; + this.name = name; + this.priority = priority; + this.description = description; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public int getPriority() { + return priority; + } + + public String getDescription() { + return description; + } +} diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java index a8facf32..4dd11d3c 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/notifications/NotificationService.java @@ -42,9 +42,6 @@ public class NotificationService extends Service { private static final int NOTIFICATION_ID = 3002; private static final String GROUP_ID = "es.rafaco.iadt.foreground_service"; - private static final String CHANNEL_PRIORITY = "es.rafaco.iadt.priority"; - private static final String CHANNEL_STANDARD = "es.rafaco.iadt.standard"; - private static final String CHANNEL_SILENT = "es.rafaco.iadt.silent"; private static final int SUMMARY_ID = 0; public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE"; @@ -210,7 +207,7 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr //.setSubText("setSubText") //Group second .setWhen(System.currentTimeMillis()); //Group third - builder.setChannelId(getCurrentChannel()); + builder.setChannelId(getCurrentChannel().getId()); Log.w("RAFA", "Notification channel: " + getCurrentChannel()); if (FirstStartUtil.isSessionFromFirstStart()){ Log.w("RAFA", "Notification isFirstStart"); @@ -253,13 +250,13 @@ else if (crash != null){ return builder.build(); } - private String getCurrentChannel() { + private IadtChannel getCurrentChannel() { if (FirstStartUtil.isSessionFromFirstStart()) - return CHANNEL_PRIORITY; + return IadtChannel.CHANNEL_PRIORITY; else if (PendingCrashUtil.isSessionFromPending()) - return CHANNEL_STANDARD; + return IadtChannel.CHANNEL_STANDARD; else - return CHANNEL_SILENT; + return IadtChannel.CHANNEL_SILENT; } //TODO: delete? @@ -269,7 +266,7 @@ private Notification buildCrashNotification(PendingIntent pendingIntent) { Bitmap largeIconBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_error_orange_24dp); String title = String.format("Ups, %s crashed", infoHelper.getAppName()); - NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getCurrentChannel()) + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getCurrentChannel().getId()) .setGroup(GROUP_ID) .setPriority(Notification.PRIORITY_MAX) .setVisibility(Notification.VISIBILITY_PRIVATE) @@ -337,32 +334,30 @@ private NotificationCompat.Action buildAction(String action) { } private void createNotificationChannels() { - createNotificationChannel(CHANNEL_PRIORITY, NotificationManager.IMPORTANCE_HIGH); - createNotificationChannel(CHANNEL_STANDARD, NotificationManager.IMPORTANCE_DEFAULT); - createNotificationChannel(CHANNEL_SILENT, NotificationManager.IMPORTANCE_LOW); + createNotificationChannel(IadtChannel.CHANNEL_PRIORITY); + createNotificationChannel(IadtChannel.CHANNEL_STANDARD); + createNotificationChannel(IadtChannel.CHANNEL_SILENT); } - private void createNotificationChannel(String notificationId, int importance) { - // Create the NotificationChannel, but only on API 26+ because - // the NotificationChannel class is new and not in the support library + private void createNotificationChannel(IadtChannel channelData) { + // Create the IadtChannel, but only on API 26+ because + // the IadtChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = getSystemService(NotificationManager.class); - NotificationChannel channel = notificationManager.getNotificationChannel(notificationId); + NotificationChannel channel = notificationManager.getNotificationChannel(channelData.getId()); if(channel==null){ - CharSequence name = "NotificationService"; - String description = "To showMain Iadt report notification"; - channel = new NotificationChannel(notificationId, name, importance); - if (importance == NotificationManager.IMPORTANCE_LOW){ + channel = new NotificationChannel(channelData.getId(), channelData.getName(), channelData.getPriority()); + if (channelData.getPriority() == NotificationManager.IMPORTANCE_LOW){ channel.setSound(null, null); } - channel.setDescription(description); + channel.setDescription(channelData.getDescription()); notificationManager.createNotificationChannel(channel); } } } private void createNotificationGroup() { - Notification summaryNotification = new NotificationCompat.Builder(this, getCurrentChannel()) + Notification summaryNotification = new NotificationCompat.Builder(this, getCurrentChannel().getId()) .setSmallIcon(UiUtils.getAppIconResourceId()) .setContentTitle("Group Title") .setContentText("Group text") @@ -378,7 +373,7 @@ private void createNotificationGroup() { private void createNotificationSummary() { Notification summaryNotification = - new NotificationCompat.Builder(this, getCurrentChannel()) + new NotificationCompat.Builder(this, getCurrentChannel().getId()) .setContentTitle("Summary Title") .setContentText("Summary text") .setSmallIcon(UiUtils.getAppIconResourceId()) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java index 63dddbe1..ed575f4d 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/view/overlay/screens/log/LogScreen.java @@ -2,7 +2,6 @@ import android.content.DialogInterface; import android.content.Intent; -import android.support.v7.widget.SimpleItemAnimator; import android.util.Log; import android.view.MenuItem; import android.view.View; From 5c1e9430fef131fb9eefd2b46236b42dc4039fff Mon Sep 17 00:00:00 2001 From: Rafaco Date: Mon, 30 Sep 2019 19:09:44 +0200 Subject: [PATCH 8/8] Remove extra logs at CrashHandler --- .../events/detectors/crash/CrashHandler.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java index 68caedef..b972ac63 100644 --- a/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java +++ b/library/src/main/java/es/rafaco/inappdevtools/library/logic/events/detectors/crash/CrashHandler.java @@ -58,31 +58,20 @@ public void uncaughtException(final Thread thread, final Throwable ex) { try { friendlyLogId = FriendlyLog.logCrash(ex.getMessage()); - Log.v(Iadt.TAG, "CrashHandler: logCrash done"); stopAnrDetector(); Crash crash = buildCrash(thread, ex); - Log.v(Iadt.TAG, "CrashHandler: buildCrash done"); printLogcatError(thread, crash); - Log.v(Iadt.TAG, "CrashHandler: printLogcatError done"); long crashId = storeCrash(crash); - Log.v(Iadt.TAG, "CrashHandler: printLogcatError done"); PendingCrashUtil.savePending(); - Log.v(Iadt.TAG, "CrashHandler: savePending done"); IadtController.get().beforeClose(); - Log.v(Iadt.TAG, "CrashHandler: beforeClose done"); saveLogcat(crashId); - Log.v(Iadt.TAG, "CrashHandler: saveLogcat done"); saveScreenshot(); - Log.v(Iadt.TAG, "CrashHandler: saveScreenshot done"); saveDetailReport(); - Log.v(Iadt.TAG, "CrashHandler: saveDetailReport done"); saveStacktrace(crashId, ex); - Log.v(Iadt.TAG, "CrashHandler: saveStacktrace done"); - Log.v(Iadt.TAG, "CrashHandler: process finished on " + (new Date().getTime() - startTime) + " ms"); + Log.v(Iadt.TAG, "CrashHandler: processing finished on " + (new Date().getTime() - startTime) + " ms"); onCrashStored( thread, ex); - Log.v(Iadt.TAG, "CrashHandler: onCrashStored done"); } catch (Exception e) { Log.e(Iadt.TAG, "CrashHandler: exception while processing uncaughtException on " + Humanizer.getElapsedTime(startTime)); @@ -120,19 +109,14 @@ private void stopDevToolsServices() { @NonNull private Crash buildCrash(Thread thread, Throwable ex) { final Crash crash = new Crash(); - Log.v(Iadt.TAG, "CrashHandler: 0.1 done"); crash.setDate(new Date().getTime()); - Log.v(Iadt.TAG, "CrashHandler: 0.2 done"); crash.setException(ex.getClass().getSimpleName()); - Log.v(Iadt.TAG, "CrashHandler: 0.3 done"); if (ex.getStackTrace()!=null && ex.getStackTrace().length > 0) { // Some exceptions doesn't have stacktrace // i.e. Binary XML file ... You must supply a layout_height attribute. crash.setExceptionAt(ex.getStackTrace()[0].toString()); } - Log.v(Iadt.TAG, "CrashHandler: 0.4 done"); crash.setMessage(ex.getMessage()); - Log.v(Iadt.TAG, "CrashHandler: 1 done"); Throwable cause = ex.getCause(); if (cause != null){ crash.setCauseException(cause.getClass().getSimpleName()); @@ -141,7 +125,6 @@ private Crash buildCrash(Thread thread, Throwable ex) { crash.setCauseExceptionAt(cause.getStackTrace()[0].toString()); } } - Log.v(Iadt.TAG, "CrashHandler: 2 done"); ActivityEventDetector activityWatcher = (ActivityEventDetector) IadtController.get().getEventManager() .getEventDetectorsManager().get(ActivityEventDetector.class); crash.setStacktrace(Log.getStackTraceString(ex)); @@ -151,7 +134,6 @@ private Crash buildCrash(Thread thread, Throwable ex) { crash.setThreadGroupName(thread.getThreadGroup().getName()); crash.setForeground(!activityWatcher.isInBackground()); crash.setLastActivity(activityWatcher.getLastActivityResumed()); - Log.v(Iadt.TAG, "CrashHandler: 3 done"); return crash; }