Android:java.lang.SecurityException:注入另一个应用程序需要INJECT_EVENTS权限

时间:2014-03-04 05:09:54

标签: android junit

您好,我是Android Junit测试新手:

我在MainActivityFunctionalTest.java文件中编写了一些测试代码

MainActivityFunctionalTest.java:

package com.example.myfirstapp2.test;

public class MainActivityFunctionalTest extends ActivityInstrumentationTestCase2<Login>{

private static final String TAG = "MainActivityFunctionalTest";
private Login activity;

  public MainActivityFunctionalTest() {
    super(Login.class);
  }


  @Override
  protected void setUp() throws Exception {
     Log.d(TAG,"Set-Up");
     super.setUp();
    setActivityInitialTouchMode(false);
    activity = getActivity();
  }

  public void testStartSecondActivity() throws Exception {
      // add monitor to check for the second activity
        ActivityMonitor monitor =
            getInstrumentation().
              addMonitor(DisplayMessageActivity.class.getName(), null, false);
        //addMonitor(MainActivity.class.getName(), null, false);
     // find button and click it
        Button view = (Button) activity.findViewById(R.id.btnLogin);

        // TouchUtils handles the sync with the main thread internally
        TouchUtils.clickView(this, view);

        // to click on a click, e.g., in a listview
        // listView.getChildAt(0);

        // wait 2 seconds for the start of the activity
        DisplayMessageActivity startedActivity = (DisplayMessageActivity) 

     monitor
            .waitForActivityWithTimeout(5000);
        assertNotNull(startedActivity);

        // search for the textView
        TextView textView = (TextView) startedActivity.findViewById(R.id.Email);

        // check that the TextView is on the screen
        ViewAsserts.assertOnScreen(startedActivity.getWindow().getDecorView(),
            textView);
        // validate the text on the TextView
        assertEquals("Text incorrect", "1http://www.vogella.com", 

         textView.getText().toString());

        // press back and click again
        this.sendKeys(KeyEvent.KEYCODE_BACK);

        TouchUtils.clickView(this, view);

  }


    }

然而,我收到一个错误: java.lang.SecurityException:注入另一个应用程序需要INJECT_EVENTS权限

at com.example.myfirstapp2.test.MainActivityFunctionalTest.testStartSecondActivity(MainActivityFunctionalTest.java:70)

 TouchUtils.clickView(this, view);

请帮忙

11 个答案:

答案 0 :(得分:40)

我遇到了同样的问题,我的代码是这样的(对于正常的登录活动):

    onView(withId(R.id.username))
            .perform(new TypeTextAction("test_user"));
    onView(withId(R.id.password))
            .perform(new TypeTextAction("test123"));
    onView(withId(R.id.login)).perform(click());

最后一行是使用SecurityException崩溃的。在最后一次输入文字后输出,键盘处于打开状态,因此在另一个应用程序中考虑了下一次点击。

要解决此问题,我只需在打字后关闭键盘即可。我还必须添加一些睡眠以确保键盘关闭,否则测试会不时地中断。所以最终的代码看起来像这样:

    onView(withId(R.id.username))
            .perform(new TypeTextAction("test_user"));
    onView(withId(R.id.password))
            .perform(new TypeTextAction("test123")).perform(closeSoftKeyboard());
    Thread.sleep(250);
    onView(withId(R.id.login)).perform(click());

这很好用。

答案 1 :(得分:27)

我遇到了同样的问题,并且添加了closeSoftKeyboard()方法为我解决了这个问题。

onView(withId(R.id.view)).perform(typeText(text_to_be_typed), closeSoftKeyboard());

答案 2 :(得分:7)

我自己也遇到了同样的问题,这就是我发现的关于这个问题的内容。

  1. 向您的应用添加INJECT_EVENTS权限,使Android Studio指出此类权限“仅授予系统应用”。此外,manifest.permissions的Google's reference guide表明此权限是“不供第三方应用程序使用。”

    现在,您的应用程序可能不是系统应用程序。因此,添加此权限绝对不是一件好事,幸运的是不适用于您的第三方项目。至少在Android Studio上开发时。

  2. 我可以看到你在setUp方法中调用了 setActivityInitialTouchMode(false); 正如Google's best practices for UI testing所指出的那样,在测试用户界面时必须将触摸模式设置为<强>真即可。否则,您的测试夹具将无法与UI元素交互。

  3. 还有一件事。这是一个自动化测试,可模拟用户对您应用的操作。如果我们与设备交互(真实或虚拟,无关紧要),我们很可能会让其他事情获得焦点(即使在被测试的应用内),然后与setUp方法的触摸模式设置会发生冲突已经表演了。

  4. 最终,这就是发生在我身上的事情。我只是通过不点击/触摸/与正在运行测试的设备进行交互来解决我的问题。

答案 3 :(得分:7)

这是因为您的设备已锁定/任何其他打开的对话框已打开 /任何阻止测试能够点击按钮的东西。例如。如果手机被锁定 - 当测试试图点击按钮时,它不能,因为设备已被锁定。

我在模拟器上遇到了麻烦,因为它总是显示“启动器已经崩溃”。因此,无论何时尝试单击该按钮,都不能,因为警报对话框已打开。

简而言之,请确保您的屏幕已解锁且没有消息框干扰测试,并且可以点击按钮。

答案 4 :(得分:5)

对于有根设备,this file帮助了我很多。 它有:

 Injector.pressBackButton();
 Injector.pressHomeButton();
 Injector.pressPowerButton();
 Injector.showNotificationCenter();
 Injector.swipeLeftRight();
 Injector.swipeRightLeft();
 Injector.touch(x, y);

答案 5 :(得分:2)

我的代码是使用replaceText而不是TypeText动作解决的:

onView(withId(R.id.username_edit_text)).perform(ViewActions.replaceText("user123"))

onView(withId(R.id.password_edit_text)).perform(ViewActions.replaceText("pass123"), closeSoftKeyboard())

答案 6 :(得分:1)

运行espresso测试时,我遇到了完全相同的问题和错误消息。其中一个在运行整个包时总是失败,但是当我独自运行它时它总是通过。有趣的是,问题发生了,因为我在AndroidManifest.xml中的一个活动中添加了以下行:

android:windowSoftInputMode="stateUnchanged|adjustResize"

删除或更改以上行后:

android:windowSoftInputMode="stateHidden"

提到测试在运行整个包时也正在通过。

答案 7 :(得分:0)

上下文:这可能是一个奇怪的利基问题,但我也遇到了这个失败,然后我意识到这是因为我有一个 Facebook Messenger 聊天头正好浮动在它试图点击的位置。

在关闭 FB Messenger 聊天头后,我的测试通过了。

并不是说这是适合所有人的 #1 解决方案,但绝对解决了我的问题。

答案 8 :(得分:0)

对我来说,我在 UI 测试中遇到了这个问题。我通过这样做在运行时将活动设置为全屏:

systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION

我通过简单地再添加一个标志 View.SYSTEM_UI_FLAG_IMMERSIVE 解决了这个问题。

systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
                        View.SYSTEM_UI_FLAG_IMMERSIVE

答案 9 :(得分:-2)

使用TouchUtils修复“注入其他应用程序需要INJECT_EVENTS权限”的更多方法......

EG。官方android开发者网站显示:

// Stop the activity - The onDestroy() method should save the state of the Spinner
mActivity.finish();

// Re-start the Activity - the onResume() method should restore the state of the Spinner
mActivity = getActivity();

然而,如果在测试方法中直接跟随TouchUtils.clickView,则会导致错误:

// Stop the activity - The onDestroy() method should save the state of the Spinner
mActivity.finish();

// Re-start the Activity - the onResume() method should restore the state of the Spinner
mActivity = getActivity();

// Possible inject error!
TouchUtils.clickView(this, someView);

然而,将其拆分为两个测试方法并允许setUp()在中间运行似乎可以解决问题(注意这是由方法名控制的,因为测试是按字母顺序运行的):

*调用一个intent后仍然可能会失败但是在调用完成后不再会这样做

public void testYTestFinishing() {

    TouchUtils.clickView(this, someView);

    // Finish & restart the activity
    activity.finish();
}

// -------------------------------------------
// Called before every test case method
@Override
protected void setUp() throws Exception {
    super.setUp();

    setActivityInitialTouchMode(true);

    activity = getActivity();

    getViews();
}
// -------------------------------------------

public void testZOnReturn() {

    TouchUtils.clickView(this, someView);

}

有趣的是,在TouchUtils之前放置setUp()中的内容可能会失败并且有效:

public void testYTestFinishing() {

    TouchUtils.clickView(this, someView);

    // Finish & restart the activity
    activity.finish();

    setActivityInitialTouchMode(true);

    activity = getActivity();

    getViews();

    // SORRY, this fails here on some builds and succeeds on others
    TouchUtils.clickView(this, someView);
}

您也可以在TouchUtils之前直接尝试waitForActivity超时,它可以在其他时间修复它,例如在调用intent之后:

*如果在同一测试方法中使用,仍会出现注入错误...需要拆分为另一种方法,如上所示。

    Instrumentation.ActivityMonitor monitor = getInstrumentation()
        .addMonitor(Instrumentation.ActivityMonitor.class.getName(),
        null, false);

    // Wait for activity to fix inject error; Increase or decrease as needed
    monitor.waitForActivityWithTimeout(2000);

    // Should no longer fail
    TouchUtils.clickView(this, someView);

答案 10 :(得分:-2)

在同一活动中测试许多功能时,建议输入以下代码:

SystemClock.sleep(800);

在每个函数的开头。您可以对其进行自定义,但想法是要等待一定次数才能进行处理。