package com.frogermcs.androiddevmetrics; import android.app.Application; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.v4.app.NotificationCompat; import com.frogermcs.androiddevmetrics.aspect.ActivityLifecycleAnalyzer; import com.frogermcs.androiddevmetrics.aspect.Dagger2GraphAnalyzer; import com.frogermcs.androiddevmetrics.internal.MethodsTracingManager; import com.frogermcs.androiddevmetrics.internal.metrics.ActivityLaunchMetrics; import com.frogermcs.androiddevmetrics.internal.metrics.ChoreographerMetrics; import com.frogermcs.androiddevmetrics.internal.metrics.InitManager; import com.frogermcs.androiddevmetrics.internal.ui.MetricsActivity; import com.frogermcs.androiddevmetrics.internal.ui.interceptor.DefaultInterceptor; import com.frogermcs.androiddevmetrics.internal.ui.interceptor.UIInterceptor; import java.util.ArrayList; import java.util.List; /** * Created by Miroslaw Stanek on 25.01.2016. */ public class AndroidDevMetrics { private static int DAGGER2_WARNING_1_LIMIT_MILLIS = 30; private static int DAGGER2_WARNING_2_LIMIT_MILLIS = 50; private static int DAGGER2_WARNING_3_LIMIT_MILLIS = 100; private static int FRAME_DROPS_DEFAULT_INTERVAL_MS = 500; private static double FRAME_DROPS_FPS_LIMIT = 40; static volatile AndroidDevMetrics singleton; private Context context; private int dagger2WarningLevel1, dagger2WarningLevel2, dagger2WarningLevel3; private boolean enableAcitivtyMetrics; private boolean showNotification; private boolean autoCancelNotification; private boolean enableDagger2Metrics; private int intervalMillis; private double maxFpsForFrameDrop; private List<UIInterceptor> interceptors; /** * Enable Activity and Dagger 2 metrics * */ public static AndroidDevMetrics initWith(Context context) { Builder androidDevMetricsBuilder = new Builder(context) .enableActivityMetrics(true) .enableDagger2Metrics(true) .showNotification(true) .autoCancelNotification(false); return initWith(androidDevMetricsBuilder); } public static AndroidDevMetrics initWith(Builder builder) { return initWith(builder.build()); } public static AndroidDevMetrics initWith(AndroidDevMetrics androidDevMetrics) { if (singleton == null) { synchronized (AndroidDevMetrics.class) { if (singleton == null) { setAndroidDevMetrics(androidDevMetrics); } } } return singleton; } private static void setAndroidDevMetrics(AndroidDevMetrics androidDevMetrics) { singleton = androidDevMetrics; singleton.setupMetrics(); } public static AndroidDevMetrics singleton() { if (singleton == null) { throw new IllegalStateException("Must Initialize Dagger2Metrics before using singleton()"); } else { return singleton; } } AndroidDevMetrics(Context context) { this.context = context; } public int dagger2WarningLevel1() { return dagger2WarningLevel1; } public int dagger2WarningLevel2() { return dagger2WarningLevel2; } public int dagger2WarningLevel3() { return dagger2WarningLevel3; } private void setupMetrics() { Dagger2GraphAnalyzer.setEnabled(enableDagger2Metrics); InitManager.getInstance().initializedMetrics.clear(); ActivityLifecycleAnalyzer.setEnabled(true); if (enableAcitivtyMetrics) { MethodsTracingManager.getInstance().init(context); ActivityLaunchMetrics activityLaunchMetrics = ActivityLaunchMetrics.getInstance(); ((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks(activityLaunchMetrics); ChoreographerMetrics.getInstance().setMaxFpsForFrameDrop(maxFpsForFrameDrop); ChoreographerMetrics.getInstance().setIntervalMillis(intervalMillis); ChoreographerMetrics.getInstance().start(); } if (showNotification) { showNotification(); } } private void showNotification() { NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_timeline_white_18dp) .setContentTitle(context.getString(R.string.adm_name)) .setContentText("Click to see current metrics") .setAutoCancel(autoCancelNotification); Intent resultIntent = new Intent(context, MetricsActivity.class); PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify("AndroidDevMetrics".hashCode(), mBuilder.build()); } public List<UIInterceptor> interceptors() { return interceptors; } public static class Builder { private final Context context; private int dagger2WarningLevel1 = DAGGER2_WARNING_1_LIMIT_MILLIS; private int dagger2WarningLevel2 = DAGGER2_WARNING_2_LIMIT_MILLIS; private int dagger2WarningLevel3 = DAGGER2_WARNING_3_LIMIT_MILLIS; private boolean enableAcitivtyMetrics = true; private boolean enableDagger2Metrics = true; private boolean showNotification = true; private boolean autoCancelNotification = false; private int intervalMillis = FRAME_DROPS_DEFAULT_INTERVAL_MS; private double maxFpsForFrameDrop = FRAME_DROPS_FPS_LIMIT; private List<UIInterceptor> interceptors; public Builder(Context context) { if (context == null) { throw new IllegalArgumentException("Context must not be null."); } else { this.context = context.getApplicationContext(); this.interceptors = new ArrayList<>(); this.interceptors.add(new DefaultInterceptor()); } } public Builder dagger2WarningLevelsMs(int warning1, int warning2, int warning3) { if (warning1 > warning2 || warning2 > warning3) { throw new IllegalArgumentException("Warning levels should be ascending"); } else { this.dagger2WarningLevel1 = warning1; this.dagger2WarningLevel2 = warning2; this.dagger2WarningLevel3 = warning3; } return this; } public Builder frameDropsLimits(int measureIntervalMillis, double maxFpsForFrameDrop) { if (maxFpsForFrameDrop > 60) { throw new IllegalArgumentException("Max fps cannot be bigger than 60fps"); } this.intervalMillis = measureIntervalMillis; this.maxFpsForFrameDrop = maxFpsForFrameDrop; return this; } public Builder enableActivityMetrics(boolean enable) { this.enableAcitivtyMetrics = enable; return this; } public Builder showNotification(boolean show) { this.showNotification = show; return this; } public Builder enableDagger2Metrics(boolean enable) { this.enableDagger2Metrics = enable; return this; } public Builder autoCancelNotification(boolean autoCancelNotification) { this.autoCancelNotification = autoCancelNotification; return this; } public Builder addUIInterceptor(UIInterceptor interceptor) { this.interceptors.add(interceptor); return this; } public AndroidDevMetrics build() { AndroidDevMetrics androidDevMetrics = new AndroidDevMetrics(context); androidDevMetrics.dagger2WarningLevel1 = this.dagger2WarningLevel1; androidDevMetrics.dagger2WarningLevel2 = this.dagger2WarningLevel2; androidDevMetrics.dagger2WarningLevel3 = this.dagger2WarningLevel3; androidDevMetrics.enableAcitivtyMetrics = this.enableAcitivtyMetrics; androidDevMetrics.showNotification = this.showNotification; androidDevMetrics.enableDagger2Metrics = this.enableDagger2Metrics; androidDevMetrics.maxFpsForFrameDrop = this.maxFpsForFrameDrop; androidDevMetrics.intervalMillis = this.intervalMillis; androidDevMetrics.autoCancelNotification = this.autoCancelNotification; androidDevMetrics.interceptors = this.interceptors; return androidDevMetrics; } } }