Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  Remove extra logs at CrashHandler
  Notification channels added with name and description.
  LogScreen: fix scroll issues and flicks.
  Notification only pop up after welcome accepted
  Notification intrusion fix. Added 3 notification channels
  CrashHandler stacktraceAt fix.
  CrashHandler fix: internal exception when stacktrace.lenght is 0.
  Increase versions and light internal refactor at plugin
  • Loading branch information
rafaco committed Sep 30, 2019
2 parents 07b251c + 5c1e943 commit 3a3fc93
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 63 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -56,7 +58,7 @@ public void uncaughtException(final Thread thread, final Throwable ex) {

try {
friendlyLogId = FriendlyLog.logCrash(ex.getMessage());
//stopDevToolsServices();
stopAnrDetector();
Crash crash = buildCrash(thread, ex);
printLogcatError(thread, crash);
long crashId = storeCrash(crash);
Expand All @@ -68,7 +70,7 @@ public void uncaughtException(final Thread thread, final Throwable ex) {
saveDetailReport();
saveStacktrace(crashId, ex);

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);
}
catch (Exception e) {
Expand All @@ -79,6 +81,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");
Expand All @@ -102,15 +111,18 @@ private Crash buildCrash(Thread thread, Throwable ex) {
final Crash crash = new Crash();
crash.setDate(new Date().getTime());
crash.setException(ex.getClass().getSimpleName());
crash.setExceptionAt(ex.getStackTrace()[1].toString());
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());
}
crash.setMessage(ex.getMessage());

Throwable cause = ex.getCause();
if (cause != null){
crash.setCauseException(cause.getClass().getSimpleName());
crash.setCauseMessage(cause.getMessage());
if (cause.getStackTrace() != null && cause.getStackTrace().length > 1){
crash.setCauseExceptionAt(cause.getStackTrace()[1].toString());
if (cause.getStackTrace() != null && cause.getStackTrace().length > 0){
crash.setCauseExceptionAt(cause.getStackTrace()[0].toString());
}
}
ActivityEventDetector activityWatcher = (ActivityEventDetector) IadtController.get().getEventManager()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,24 @@
public class PendingCrashUtil {

public static final String PREF_VALUE_KEY = "PENDING_CRASH";
private static Boolean iSessionFromPending;

public static void savePending(){
DevToolsPrefs.setBoolean(PREF_VALUE_KEY, true);
}

public static boolean isPending(){
if (iSessionFromPending == null){
return isSessionFromPending();
}
return DevToolsPrefs.getBoolean(PREF_VALUE_KEY, false);
}

public static void savePending(){
DevToolsPrefs.setBoolean(PREF_VALUE_KEY, true);
public static boolean isSessionFromPending() {
if (iSessionFromPending == null){
iSessionFromPending = DevToolsPrefs.getBoolean(PREF_VALUE_KEY, false);
}
return iSessionFromPending;
}

public static void clearPending(){
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,7 +41,6 @@
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 int SUMMARY_ID = 0;

Expand Down Expand Up @@ -122,7 +122,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,
Expand All @@ -135,7 +135,7 @@ private void startForegroundService() {


Notification notification = buildMainNotification(pendingIntent,
PendingCrashUtil.isPending() ? new Crash() : null);
PendingCrashUtil.isSessionFromPending() ? new Crash() : null);

//createNotificationGroup();
//createNotificationSummary();
Expand Down Expand Up @@ -190,14 +190,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)
Expand All @@ -209,9 +207,30 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr
//.setSubText("setSubText") //Group second
.setWhen(System.currentTimeMillis()); //Group third

builder.setChannelId(getCurrentChannel().getId());
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){
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));
}

Expand All @@ -231,14 +250,23 @@ private Notification buildMainNotification(PendingIntent pendingIntent, Crash cr
return builder.build();
}

private IadtChannel getCurrentChannel() {
if (FirstStartUtil.isSessionFromFirstStart())
return IadtChannel.CHANNEL_PRIORITY;
else if (PendingCrashUtil.isSessionFromPending())
return IadtChannel.CHANNEL_STANDARD;
else
return IadtChannel.CHANNEL_SILENT;
}

//TODO: delete?
private Notification buildCrashNotification(PendingIntent pendingIntent) {

AppInfoReporter infoHelper = new AppInfoReporter(getApplicationContext());
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().getId())
.setGroup(GROUP_ID)
.setPriority(Notification.PRIORITY_MAX)
.setVisibility(Notification.VISIBILITY_PRIVATE)
Expand Down Expand Up @@ -305,25 +333,31 @@ private NotificationCompat.Action buildAction(String action) {
return new NotificationCompat.Action(0, title, pendingPrevIntent);
}

private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
private void createNotificationChannels() {
createNotificationChannel(IadtChannel.CHANNEL_PRIORITY);
createNotificationChannel(IadtChannel.CHANNEL_STANDARD);
createNotificationChannel(IadtChannel.CHANNEL_SILENT);
}

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(CHANNEL_ID);
NotificationChannel channel = notificationManager.getNotificationChannel(channelData.getId());
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.setDescription(description);
channel = new NotificationChannel(channelData.getId(), channelData.getName(), channelData.getPriority());
if (channelData.getPriority() == NotificationManager.IMPORTANCE_LOW){
channel.setSound(null, null);
}
channel.setDescription(channelData.getDescription());
notificationManager.createNotificationChannel(channel);
}
}
}

private void createNotificationGroup() {
Notification summaryNotification = new NotificationCompat.Builder(this, CHANNEL_ID)
Notification summaryNotification = new NotificationCompat.Builder(this, getCurrentChannel().getId())
.setSmallIcon(UiUtils.getAppIconResourceId())
.setContentTitle("Group Title")
.setContentText("Group text")
Expand All @@ -339,7 +373,7 @@ private void createNotificationGroup() {

private void createNotificationSummary() {
Notification summaryNotification =
new NotificationCompat.Builder(this, CHANNEL_ID)
new NotificationCompat.Builder(this, getCurrentChannel().getId())
.setContentTitle("Summary Title")
.setContentText("Summary text")
.setSmallIcon(UiUtils.getAppIconResourceId())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,31 +143,24 @@ 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();
}
}
});

PagedList.Config myPagingConfig = new PagedList.Config.Builder()
.setEnablePlaceholders(true)
.setInitialLoadSizeHint(4)
.setPageSize(20)
.setPrefetchDistance(60)
.setPageSize(25*2)
.build();

initLiveDataWithFriendlyLog(myPagingConfig);

logList.observe(ProcessLifecycleOwner.get(), new Observer<PagedList<Friendly>>() {
@Override
public void onChanged(PagedList<Friendly> 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);
Expand Down
Loading

0 comments on commit 3a3fc93

Please sign in to comment.