boolean dispatchFnKeyEvent(KeyEvent)
看到这个方法,懂的人自然就懂了。
之前有外公司的人询问,这个方法+标题上的错误怎么解决,当时没有怎么研究,现在说明一下,留给以后遇到这个问题的人。
公司之前的研发在做定制功能的开发时,修改了android.view.Window.Callback这个类,在里面增加了几个方法,上面的方法就是其一。
公司内部在做应用开发时,可以直接在Activity下面覆盖这个方法,但是当基于标准sdk做开发时,就找不到这个方法了,当用户触发某些特殊事件时,会导致应用crash。其症结如下:
// PhoneWindow.java
if(event.isFnKey(keyCode)){
handled = cb != null && mFeatureId < 0 ? cb.dispatchFnKeyEvent(event)
: super.dispatchKeyEvent(event);
}
解决方式如下:
public class BaseActivity extends AppCompatActivity {
@SuppressLint("RestrictedApi")
public static abstract class FnKeyCallback extends WindowCallbackWrapper {
public FnKeyCallback(Window.Callback callback) {
super(callback);
}
public FnKeyCallback(Activity activity) {
this(activity.getWindow().getCallback());
}
/**
* Fix FnKey crash error:
* java.lang.AbstractMethodError: abstract method not implemented
* at android.support.v7.view.WindowCallbackWrapper. (WindowCallbackWrapper.java)
* at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1981)
*
* @param event standard KeyEvent
* @return false not handled
*/
public abstract boolean dispatchFnKeyEvent(KeyEvent event);
}
protected void setFnKeyCallback(FnKeyCallback callback) {
getWindow().setCallback(callback);
}
}
继承的Activity只要在合适的地方调用setFnKeyCallback就可以了。
问题到这里即得到解决。
但是今天又碰到了这个问题,找了很久才解决,不得不记录一下。
简单说一下,今天将代码运行到一个研发机上,调整音量时,出现了闪退,并无“停止运行”提示,且必现。
查了log,发现如下输出:
I/am_crash( 1891): [16481,0,package_name,13156166,java.lang.AbstractMethodError,abstract method "boolean android.view.Window$Callback.dispatchFnKeyEvent(android.view.KeyEvent)",PhoneWindow.java,2284]
又仔细翻了翻log,发现如下:
java.lang.AbstractMethodError: abstract method "boolean android.view.Window$Callback.dispatchFnKeyEvent(android.view.KeyEvent)"
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2284)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4020)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3982)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3680)
调试了N次,之后又好好想了想,怀疑应该是我设置进去的Callback包装对象被顶掉了,但是日志输出中,并无明显迹象。
我想看都哪里调用getWindow().setCallback()这个方法了,因为没办法在setCallback方法里添加日志,最后只能在getWindow()里添加日志,打印出调用时的方法栈,尝试找到异常的地方。
运行程序之后,发现getWindow()这个方法被调了20多次,还好不是很多,来回看了几遍,其他地方没发现异常,就是觉得下面的调用有点奇怪:
java.lang.Throwable
at com.pkg.BaseActivity.getWindow(BaseActivity.java:107)
at com.android.tools.profiler.support.profilers.EventProfiler.updateCallback(EventProfiler.java:88)
at com.android.tools.profiler.support.profilers.EventProfiler.onActivityStarted(EventProfiler.java:205)
at android.app.Application.dispatchActivityStarted(Application.java:199)
at android.app.Activity.onStart(Activity.java:1201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:552)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
com.android.tools.profiler.support.profilers.EventProfiler
这是什么鬼?android源码中并没有这个类。
最后在Google上找了一下,才发现应该是Android Studio搞的鬼,关闭Enable advanced profiling
之后,重新运行,就没有上面的问题了。

网友评论