Android :java.lang.SecurityException: 注入到另一个应用程序需要 INJECT_EVENTS 权限
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22163424/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android :java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission
提问by user3238961
Hi there I am new to Android Junit testing:
嗨,我是 Android Junit 测试的新手:
I have written some test code in MainActivityFunctionalTest.java file
我在 MainActivityFunctionalTest.java 文件中编写了一些测试代码
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);
}
}
However,I get an error: java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission
但是,我收到一个错误:java.lang.SecurityException:注入另一个应用程序需要 INJECT_EVENTS 权限
at com.example.myfirstapp2.test.MainActivityFunctionalTest.testStartSecondActivity(MainActivityFunctionalTest.java:70)
在 com.example.myfirstapp2.test.MainActivityFunctionalTest.testStartSecondActivity(MainActivityFunctionalTest.java:70)
TouchUtils.clickView(this, view);
Please help
请帮忙
回答by m.hashemian
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.
最后一行因 SecurityException 而崩溃。原来在最后一次文本输入后,键盘保持打开状态,因此下一次点击被认为是在不同的应用程序上。
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.
这工作得很好。
回答by moyheen
I had the same issue and adding the closeSoftKeyboard() method resolved it for me.
我遇到了同样的问题,添加 closeSoftKeyboard() 方法为我解决了这个问题。
onView(withId(R.id.view)).perform(typeText(text_to_be_typed), closeSoftKeyboard());
回答by Prasanth Louis
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.
简而言之,请确保您的屏幕已解锁并且没有消息框干扰测试,并且可以单击按钮。
回答by Lorenzo Petroli
I was facing this very same problem myself, and here is what I found about this issue.
我自己也面临着同样的问题,这是我对这个问题的发现。
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 guidefor 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.
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.
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.
将 INJECT_EVENTS 权限添加到您的应用程序,使 Android Studio 指出此类权限“仅授予系统应用程序”。此外,Google 的manifest.permissions参考指南指出,此权限“不供第三方应用程序使用”。
现在,很可能你的应用程序,就像我的一样,不是系统应用程序。所以添加这个权限绝对不是一件好事,幸运的是不会应用于你的 3rd 方项目。至少在 Android Studio 上开发时是这样。
我可以看到在你的 setUp 方法中,你已经调用了setActivityInitialTouchMode(false); 正如谷歌 UI 测试最佳实践所指出的,在测试 UI 时,必须将 Touch Mode 设置为true。否则,您的测试装置将无法与 UI 元素进行交互。
还有一件事。这是一个自动化测试,模拟用户对您的应用程序的操作。如果我们与设备交互(真实的或虚拟的,无所谓),我们很可能会让其他东西获得焦点(即使在被测应用程序内部),然后会与 setUp 方法的触摸模式设置发生冲突已经执行。
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.
最终,这就是发生在我身上的事情。我通过不点击/触摸/与运行测试的设备进行交互来解决我的问题。
回答by AbdulMomen ?????????
回答by Jatezzz
I solved using replaceText instead of TypeText action, my code:
我解决了使用 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())
回答by LLL
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:
运行浓缩咖啡测试时,我遇到了完全相同的问题和错误消息。其中一个在运行整个包时总是失败,但是当我单独运行它时它总是通过。有趣的是,问题的发生是因为我在 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.
运行整个包时,提到的测试也通过了。
回答by CmosBattery
Some more ways to fix "Injecting to another application requires INJECT_EVENTS permission" happening with TouchUtils...
修复 TouchUtils 发生的“注入另一个应用程序需要 INJECT_EVENTS 权限”的更多方法...
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:
然而,如果在测试方法中直接跟随一个 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):
但是,将其拆分为两个测试方法并允许 setUp() 在其间运行似乎可以解决*问题(请注意,这里由方法名称控制,因为测试按字母顺序运行):
*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:
有趣的是,将 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);
}
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:
您还可以直接在 TouchUtils 之前尝试 waitForActivity 超时,它可以*在其他时间修复它,例如在调用意图之后:
*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);
回答by Boris
When you test many functions in the same activity, it is recommended to put in this code:
当你在同一个activity中测试多个函数时,建议放入这段代码:
SystemClock.sleep(800);
at the beginning of every function. You can customize it but the idea is to wait a certain number of times before processing.
在每个函数的开头。您可以自定义它,但其想法是在处理前等待一定次数。