Android: java.lang.SecurityException: для ввода в другое приложение требуется разрешение INJECT_EVENTS

Привет, я новичок в тестировании 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

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

 TouchUtils.clickView(this, view);

Пожалуйста, помогите

Ответы

Ответ 1

У меня была такая же проблема, и мой код был чем-то вроде этого (для обычной активности входа):

    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());

Это сработало отлично.

Ответ 2

У меня была такая же проблема, и добавление метода closeSoftKeyboard() разрешило это для меня.

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

Ответ 3

Это потому, что ваше устройство заблокировано/любое другое открытое диалоговое окно открыто/все, что мешает тестовой способности нажать на кнопку. Например. если телефон заблокирован - когда тест пытается нажать на кнопку, он не может этого сделать, потому что устройство заблокировано.

У меня были проблемы с эмулятором, потому что он всегда отображал "лаунчер разбился". Поэтому всякий раз, когда он пытался нажать на кнопку, он не мог, потому что диалоговое окно оповещения было открыто.

Короче говоря, убедитесь, что ваш экран разблокирован и никакие окна сообщений не мешают тесту и возможности нажатия на кнопку.

Ответ 4

Я сам столкнулся с этой же проблемой, и вот что я нашел по этой проблеме.

  1. Добавление разрешения INJECT_EVENTS к вашему приложению заставляет Android Studio указать, что такое разрешение "Предоставляется только системным приложениям". Более того, в справочном руководстве Google для manifest.permissions указано, что это разрешение "Не для использования сторонними приложениями".

    Теперь, скорее всего, ваше приложение, как мое, не является системным приложением. Поэтому добавление этого разрешения определенно не очень хорошая вещь, и, к счастью, не будет применяться в вашем стороннем проекте. По крайней мере, при разработке под Android Studio.

  2. Я вижу, что в вашем методе setUp вы вызвали setActivityInitialTouchMode (false); Как указано в рекомендациях Google по тестированию пользовательского интерфейса, при тестировании пользовательского интерфейса необходимо установить для сенсорного режима значение true. В противном случае ваш тестовый прибор не сможет взаимодействовать с элементами пользовательского интерфейса.

  3. Еще одна вещь. Это автоматический тест, который эмулирует действия пользователя над вашим приложением. Если мы будем взаимодействовать с устройством (реальным или виртуальным, не имеет значения), мы, скорее всего, сделаем все, чтобы сфокусироваться (даже внутри тестируемого приложения), и тогда возникнет конфликт с настройками сенсорного режима, которые вызывает метод setUp выполнил.

В конечном итоге это то, что происходило со мной. Я решил свою проблему, просто не щелкая/не касаясь/не взаимодействуя с устройством, на котором проводился тест.

Ответ 5

for a rooted device, этот файл мне очень помог. Имеет:

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

Ответ 6

У меня была точно такая же проблема и сообщение об ошибке при запуске эспрессо-тестов. Один из них всегда терпел неудачу при запуске всего пакета, однако он всегда проходил, когда я запускал его один. Интересно то, что проблема произошла, потому что я добавил следующую строку в одну из своих операций в AndroidManifest.xml:

android:windowSoftInputMode="stateUnchanged|adjustResize"

После удаления или изменения вышеуказанной строки:

android:windowSoftInputMode="stateHidden"

упомянутый тест проходил также при запуске всего пакета.

Ответ 7

Я решил использовать 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())

Ответ 8

Еще несколько способов исправить "Инъекция в другое приложение требует разрешения INJECT_EVENTS", происходящего с TouchUtils...

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() в промежутке появляется, чтобы исправить * проблему (обратите внимание, что здесь здесь управляет имя метода, поскольку тесты выполняются в алфавитном порядке):

* это все равно может завершиться неудачей после того, как было вызвано намерение, но больше не происходит после того, как финал был вызван

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);

}

Интересно, что вставлять то, что в setUp() перед тем, как TouchUtils может и работать, и работать:

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);
}

Вы также можете попробовать тайм-аут waitForActivity непосредственно перед TouchUtils, который может * исправить его в другое время, например, после того, как было вызвано намерение:

* Ошибка ввода может все же произойти, если она используется в том же методе тестирования... потребуется разделить на другой метод, как показано выше.

    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);

Ответ 9

Когда вы тестируете много функций в одном и том же упражнении, рекомендуется добавить следующий код:

SystemClock.sleep(800);

в начале каждой функции. Вы можете настроить его, но идея состоит в том, чтобы подождать определенное количество раз перед обработкой.