package com.vpedak.testsrecorder.core; import android.app.Activity; import android.app.Instrumentation; import android.content.IntentFilter; import android.os.Looper; import android.util.Log; import android.util.Printer; import com.vpedak.testsrecorder.core.events.PressBackAction; import com.vpedak.testsrecorder.core.events.RecordingEvent; import java.lang.reflect.Field; import java.util.EmptyStackException; import java.util.Stack; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; public class ActivityListener implements EventWriter.EventWriterListener { private Instrumentation instr; private volatile Instrumentation.ActivityMonitor monitor; private Activity activity = null; private ActivityProcessor activityProcessor; private long uniqueId; private boolean wasEvent = false; private EventWriter eventWriter; private Stack<Activity> stack = new Stack<Activity>(); private Field fResumed; private Field fStopped; public ActivityListener(Instrumentation instr, Activity activity, long uniqueId) { this.instr = instr; IntentFilter filter = null; this.monitor = instr.addMonitor(filter, null, false); this.activity = activity; this.uniqueId = uniqueId; eventWriter = new EventWriter(uniqueId, this); activityProcessor = new ActivityProcessor(uniqueId, instr, eventWriter); activityProcessor.processActivity(activity); try { fResumed = Activity.class.getDeclaredField("mResumed"); fResumed.setAccessible(true); fStopped = Activity.class.getDeclaredField("mStopped"); fStopped.setAccessible(true); } catch (NoSuchFieldException e) { Log.e(ActivityProcessor.ANDRIOD_TEST_RECORDER, "NoSuchFieldException", e); } } public void start() { new Timer().schedule(new ActivityTask(this), 300L, 300L); } public synchronized void check() { Activity test = monitor.getLastActivity(); if (test != null && test != activity && !isStopped(test)) { boolean push = true; if (isResumed(test)) { try { if (stack.peek().equals(test) ) { stack.pop(); push = false; if (!wasEvent) { eventWriter.writeEvent(new RecordingEvent(new Espresso(), new PressBackAction(), "Press on the back button")); } } } catch (EmptyStackException e) { //no op; } } if (push) { stack.push(activity); } activity = test; //Log.i("12345", activity.getLocalClassName()); activityProcessor.processActivity(activity); } wasEvent = false; activityProcessor.processAllViews(); } @Override public synchronized void onEventWritten() { wasEvent = true; } public static class ActivityTask extends TimerTask { private ActivityListener checker; public ActivityTask(ActivityListener checker) { this.checker = checker; } @Override public void run() { checker.check(); } } private boolean isResumed(Activity activity) { try { return (Boolean) fResumed.get(activity); } catch (IllegalAccessException e) { Log.e(ActivityProcessor.ANDRIOD_TEST_RECORDER, "IllegalAccessException", e); return false; } } private boolean isStopped(Activity activity) { try { return (Boolean) fStopped.get(activity); } catch (IllegalAccessException e) { Log.e(ActivityProcessor.ANDRIOD_TEST_RECORDER, "IllegalAccessException", e); return false; } } }