Android :java.lang.SecurityException: Injecting to

2019-01-14 15:37发布

问题:

Hi there I am new to Android Junit testing:

I have written some test code in MainActivityFunctionalTest.java file

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

  }


    }

However,I get an error: java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission

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

 TouchUtils.clickView(this, view);

Please help

回答1:

I had the same problem, and my code was something like this (for a normal login activity):

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

The last line was crashing with SecurityException. Turned out after the last text typing, the keyboard was left open, hence the next click was considered on a different application.

To fix this, I simply had to close the keyboard after typing. I also had to add some sleep to make sure the keyboard is closed, otherwise the test would break every now and then. So the final code looked like this:

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

This worked just fine.



回答2:

I had the same issue and adding the closeSoftKeyboard() method resolved it for me.

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


回答3:

I was facing this very same problem myself, and here is what I found about this issue.

  1. Adding INJECT_EVENTS permission to your app, makes Android Studio point out that such permission "Is only granted to system apps". Moreover, Google's reference guide for manifest.permissions states that this permission is "Not for use by third-party applications."

    Now, chances are that your app, as mine, is not a system app. So adding this permission is definitely not a good thing to do, and luckily will not be apply on your 3rd party project. At least when developing on Android Studio.

  2. I can see that in your setUp method, you have called setActivityInitialTouchMode(false); As pointed out by Google's best practices for UI testing, when testing UI one must set Touch Mode to true. Otherwise, your test fixture will not be able to interact with UI elements.

  3. Just one more thing. This is an automated test that emulates user actions upon your app. If we interact with the device (real or virtual, doesn't matter), we will most likely make other things gain focus (even inside the app under test) and then there will be a conflict with the touch mode settings that the setUp method had performed.

Ultimately, that is what was happening to me. I solved my problem simply by not clicking/touching/interacting with the device where the test was being ran.



回答4:

It's because your device is locked/any other open dialog box is open /anything preventing the test's ability to click on the button. Eg. if the phone is locked-when the test tries to click on the button it can't because the device is locked.

I was having troubles on the emulator because it always displayed "launcher has crashed". So whenever it tried to click the button, it couldn't because the alert dialog box was open.

In short. Make sure your screen is unlocked and no message boxes are interfering with the test and it's ability to click on a button.



回答5:

for a rooted device, this file helped me a lot. It has:

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


回答6:

I had exactly the same problem and error message when running espresso tests. One of them was always failing when running whole package, however it always passed when I was running it alone. Interesting thing was that the problem happened because I had added following line to one of my Activities in AndroidManifest.xml:

android:windowSoftInputMode="stateUnchanged|adjustResize"

After removing or changing above line to:

android:windowSoftInputMode="stateHidden"

mentioned test was passing also when running whole package.



回答7:

Some more ways to fix "Injecting to another application requires INJECT_EVENTS permission" happening with TouchUtils...

Eg. the official android developer site shows:

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

Yet, this can cause the error if in the test method this is followed directly by a 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);

However, splitting it into two test methods and allowing setUp() to run in-between appears to fix* the problem (Note this is controlled here by the method name as tests are run alphabetically):

*this still might fail after an intent was called but no longer does after finish was called

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

}

Interestingly, putting what's in setUp() before the TouchUtils can both fail and work:

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

You can also try the waitForActivity timeout directly before the TouchUtils which can* fix it at other times such as after an intent was called:

*Inject error can still occur if used within the same test method... will need to split out into another method as I show above.

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


标签: android junit