最近车厂做monkey测试,出现一个很奇怪的问题,具体报错如下:
//monkey KEYCODE_MENU ACTION_UP
22:18:38.115207 6570 6570 I Monkey : :Sending Key (ACTION_UP): 82 // KEYCODE_MENU
//崩溃
--------- switch to crash
22:18:38.133137 16255 16255 E AndroidRuntime: FATAL EXCEPTION: main
22:18:38.133137 16255 16255 E AndroidRuntime: Process: net.easyconn, PID: 16255
22:18:38.133137 16255 16255 E AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl.setView(ViewRootImpl.java:807)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
22:18:38.133137 16255 16255 E AndroidRuntime: at d.b.k.k.G(:15)
22:18:38.133137 16255 16255 E AndroidRuntime: at d.b.k.k.v(:7)
22:18:38.133137 16255 16255 E AndroidRuntime: at d.b.k.k$e.dispatchKeyEvent(Unknown Source:2)
22:18:38.133137 16255 16255 E AndroidRuntime: at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:342)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:5047)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4915)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4436)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4489)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4455)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4595)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4463)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4652)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4436)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4489)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4455)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4463)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4436)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4489)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4455)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4628)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4789)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2571)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:2081)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:2072)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2548)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.os.MessageQueue.nativePollOnce(Native Method)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.os.MessageQueue.next(MessageQueue.java:326)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.os.Looper.loop(Looper.java:160)
22:18:38.133137 16255 16255 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6718)
22:18:38.133137 16255 16255 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
22:18:38.133137 16255 16255 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
22:18:38.133137 16255 16255 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
//中止进程,信号9
22:18:38.229723 16255 16255 I Process : Sending signal. PID: 16255 SIG: 9
系统提示我:Unable to add window -- token null is not valid; is your activity running?
追踪源码发现,报错的位置在ViewRootImpl的setView方法中的
case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
中,可是我的Activity明明好好的在前台放着,应该什么都没干,怎么会setView呢?
由于项目中代码很多,又没有其他错误,于是我决定写一个Helloworld真正什么都不干试一下
1.gradle依赖如下
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
2.MainActivity的代码
public class MainActivity extends AppCompatActivity {
@Overide
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.main_activity);
}
}
然后手动模拟发送EVENT_MENU事件
adb shell input keyevent 82
我靠,果然崩了!
这就奇怪了,HelloWorld里面什么代码都没写,难道系统出bug了?
查阅博客应用错误收集 (thinbug.com)得知,在AppCompatActivity中没能处理EVENT_MENU事件导致的异常,要么升级'androidx.appcompat:appcompat:1.0.0'的版本为最新,要么手动让AppCompatActivity监听EVENT_MENU事件,代码如下:
public class MainActivity extends AppCompatActivity {
@Overide
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.main_activity);
Window window = appCompatActivity.getWindow();
Window.Callback callback = window.getCallback();
MyWindowCallbackWrapper myWindowCallbackWrapper = new MyWindowCallbackWrapper(callback, new WeakReference(this));
window.setCallback(myWindowCallbackWrapper);
}
private static class MyWindowCallbackWrapper extends WindowCallbackWrapper {
private AppCompatActivity activity;
public WindowCallbackWrapper(Window.Callback callback, WeakReference weakactivity) {
super(callback);
this.activity = weakactivity.get();
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
int action = event.getAction();
if (keyCode == KeyEvent.KEYCODE_MENU && action == KeyEvent.ACTION_DOWN) {
if (activity.onKeyDown(event.getKeyCode(), event))
return true;
} else if (keyCode == KeyEvent.KEYCODE_MENU && action == KeyEvent.ACTION_UP) {
if (activity.onKeyUp(event.getKeyCode(), event))
return true;
}
return super.dispatchKeyEvent(event);
}
}
}