AbstractMethodError:抽象方法未实现

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之后,重新运行,就没有上面的问题了。

屏幕快照 2018-10-25 20.42.52.png

你可能感兴趣的:(AbstractMethodError:抽象方法未实现)