在Espresso android中获取当前活动

fen*_*123 41 android ui-automation android-espresso

如果测试跨越多个活动,是否有办法获得当前活动?

getActivtiy()方法只提供一个用于启动测试的活动.

我尝试过类似下面的内容,

public Activity getCurrentActivity() {
    Activity activity = null;
    ActivityManager am = (ActivityManager) this.getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    try {
        Class<?> myClass = taskInfo.get(0).topActivity.getClass();
        activity = (Activity) myClass.newInstance();
    }
    catch (Exception e) {

    }
    return activity;
}
Run Code Online (Sandbox Code Playgroud)

但我得到了空对象.

lac*_*ton 29

在Espresso中,您可以使用,ActivityLifecycleMonitorRegistry但它不受官方支持,因此在将来的版本中可能无法使用.

下面是它的工作原理:

Activity getCurrentActivity() throws Throwable {
  getInstrumentation().waitForIdleSync();
  final Activity[] activity = new Activity[1];
  runTestOnUiThread(new Runnable() {
    @Override
    public void run() {
      java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
      activity[0] = Iterables.getOnlyElement(activities);
  }});
  return activity[0];
}
Run Code Online (Sandbox Code Playgroud)

  • 这种方法与 AndroidX 测试相关吗? (4认同)
  • 这是 Kotlin 中的类似解决方案:/sf/answers/4107946041/ (3认同)

riw*_*nyk 28

如果你需要的只是对当前进行检查Activity,使用可能会与原生Espresso单行相关,以检查是否已启动预期意图:

intended(hasComponent(new ComponentName(getTargetContext(), ExpectedActivity.class)));
Run Code Online (Sandbox Code Playgroud)

如果不匹配,Espresso也会向您显示同时触发的意图.

您需要的唯一设置是在测试中替换ActivityTestRule,IntentsTestRule以便跟踪启动的意图.并确保此库位于您的build.gradle依赖项中:

androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1'
Run Code Online (Sandbox Code Playgroud)

  • 这如何回答这里的问题? (3认同)

Fab*_*tel 12

我喜欢@ Ryan的版本,因为它不使用无证书的内部,但你可以写得更短:

private Activity getCurrentActivity() {
    final Activity[] activity = new Activity[1];
    onView(isRoot()).check(new ViewAssertion() {
        @Override
        public void check(View view, NoMatchingViewException noViewFoundException) {
            activity[0] = (Activity) view.getContext();
        }
    });
    return activity[0];
}
Run Code Online (Sandbox Code Playgroud)

请注意,虽然在Firebase测试实验室中运行测试时这不起作用.那失败了

java.lang.ClassCastException: com.android.internal.policy.DecorContext cannot be cast to android.app.Activity
Run Code Online (Sandbox Code Playgroud)

  • 关于FireBase问题,请使用:activity [0] =(Activity)view.findViewById(android.R.id.content).getContext(); (5认同)

Tan*_*nin 8

Android团队已替换ActivityTestRuleActivityScenario。我们可以activityTestRule.getActivity()ActivityTestRule但不能用ActivityScenario做。这是我围绕ActivityActivityScenario获取解决方案的工作(受@Ryan和@Fabian解决方案启发)

@get:Rule
var activityRule = ActivityScenarioRule(MainActivity::class.java)
...
private fun getActivity(): Activity? {
  var activity: Activity? = null
  activityRule.scenario.onActivity {
    activity = it
  }
  return activity
}
Run Code Online (Sandbox Code Playgroud)

  • 使用此方法获取活动时要小心线程 (2认同)

Rya*_*yan 5

public static Activity getActivity() {
    final Activity[] currentActivity = new Activity[1];
    Espresso.onView(AllOf.allOf(ViewMatchers.withId(android.R.id.content), isDisplayed())).perform(new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isAssignableFrom(View.class);
        }

        @Override
        public String getDescription() {
            return "getting text from a TextView";
        }

        @Override
        public void perform(UiController uiController, View view) {
            if (view.getContext() instanceof Activity) {
                Activity activity1 = ((Activity)view.getContext());
                currentActivity[0] = activity1;
            }
        }
    });
    return currentActivity[0];
}
Run Code Online (Sandbox Code Playgroud)

  • @GabrielBB 因为 currentActivity 在匿名函数中使用,因此必须是最终的,如果是最终的,则只能在构造函数中对其进行初始化,因此,您使用“数组”。 (3认同)

Bil*_*ner 5

我无法使用其他任何解决方案,因此最终不得不这样做:

声明您的ActivityTestRule

@Rule
public ActivityTestRule<MainActivity> mainActivityTestRule =
        new ActivityTestRule<>(MainActivity.class);
Run Code Online (Sandbox Code Playgroud)

声明一个finalActivity数组来存储您的活动:

private final Activity[] currentActivity = new Activity[1];
Run Code Online (Sandbox Code Playgroud)

添加一个帮助程序方法来向应用程序上下文注册以获取生命周期更新:

private void monitorCurrentActivity() {
    mainActivityTestRule.getActivity().getApplication()
            .registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(final Activity activity, final Bundle savedInstanceState) { }

                @Override
                public void onActivityStarted(final Activity activity) { }

                @Override
                public void onActivityResumed(final Activity activity) {
                    currentActivity[0] = activity;
                }

                @Override
                public void onActivityPaused(final Activity activity) { }

                @Override
                public void onActivityStopped(final Activity activity) { }

                @Override
                public void onActivitySaveInstanceState(final Activity activity, final Bundle outState) { }

                @Override
                public void onActivityDestroyed(final Activity activity) { }
            });
}
Run Code Online (Sandbox Code Playgroud)

添加助手方法以获取当前活动

private Activity getCurrentActivity() {
    return currentActivity[0];
}
Run Code Online (Sandbox Code Playgroud)

因此,启动第一个活动后,只需调用monitorCurrentActivity(),然后在需要引用当前活动时就调用getCurrentActivity()