在恢复应用后,TextureView抛出致命信号11

时间:2013-12-20 00:05:56

标签: android textureview

我有一个基于Romain Guy的示例的TextureView,可以找到here。在Android 4.3和4.4上,经过几轮暂停和恢复应用程序后,应用程序崩溃,唯一的错误痕迹是LogCat中的致命信号11。我创建了一个测试应用程序,它使用Romain Guy的确切代码来查看它是否是我在代码中所做的事情,而Romain的代码也与致命信号11一起崩溃。

我已经确定如果我使用Handler而不是Thread运行代码,它似乎不会使应用程序崩溃。 Handler应该在主UI线程上运行(或者至少我相信它),这可能暗示它是一个线程问题。

我还确定在调用canvas.drawX(drawColor,drawBitmap,drawRect等等)期间发生了崩溃。锁定和解锁画布似乎不是问题。我怀疑线程正在被取消,而其他一些代码仍在使用画布,但由于没有任何真正的异常被抛出而且崩溃相当不一致,我很难跟踪问题。

非常感谢任何见解。

3 个答案:

答案 0 :(得分:2)

TextureView失去可见性时(因为屏幕旋转,其他Activity出现在前面或您按下主页按钮),它会使其SurfaceTexture.OnFrameAvailableListener无效({{3} }})。看起来当这种情况发生时,Canvas实例正在C ++代码本身执行drawX()方法,应用程序将崩溃,因为由于某种原因,在方法完成之前清除包含该画布的内存。但是,因为Canvas.drawX()方法使用Android本机C ++代码,所以C ++不会抛出NullPointerExceptionGrepCode),因此Java异常处理系统在这种情况下是无用的。

只要您多次调用TextureView方法或者在drawX()上绘制一些复杂的内容,此问题就会导致Canvas类无法使用。

非常类似于线程和/或C ++代码方面的错误。我已经打开了一个报告此问题的问题:How to catch the null pointer exception?

编辑:我已找到一种可靠的方法,可以避免在drawX()不再可见时调用TextureView方法,从而启动应用崩溃:中断在Canvas上绘制的线程,并在每次调用任何drawX()方法之前检查线程是否被中断。之前的onPause()被称为drawX()方法,不会抛出任何错误。

mThread = new Thread() {
    @Override
    public void run() {
        Canvas canvas = mTV.lockCanvas();

        /** Draw your stuff on the canvas but check before every
            single drawX() call whether mThread has been interrupted **/
        Paint p = new Paint();
        p.setColor(Color.RED);
        for (int n=0; n<5000; ++n) {
            if (mThread.isInterrupted())
                break;
            canvas.drawCircle(0, 0, 300, p);
        }
        /** **/

        mTV.unlockCanvasAndPost(canvas);
    };
mThread.start();

然后在onPause() - 正好在调用Canvas.drawX()之前的那一刻开始崩溃应用程序中断线程:

@Override
public void onPause() {
    super.onPause();
    if (mThread != null) {
        mThread.interrupt();
        mThread = null;
    }
}

onStop()onDestroy()添加相同的代码。我还试图通过覆盖它来中断线程来使用TextureView.onVisibilityChanged()方法。但调用onPause()后调用此方法的时间差不多500毫秒,而且drawX()调用开始导致应用程序崩溃。

答案 1 :(得分:0)

我有类似的问题,结果发现在我的代码中是一个微不足道的NullPointerException,它以某种方式导致了整个过程的分段错误(信号11)。显然,SurfaceTextureListener.onSurfaceTextureAvailable()回调中的异常未得到正确处理。这可能是一些JNI问题。

作为一种肮脏的解决方法,您可以使用

捕获SurfaceTextureListener中的所有例外情况
try {
} catch (Throwable t) {
    //do some tear down - better than signal 11
}

我决定不报告Android错误,因为我无法在4.4.2上重现它,所以它可能已修复。

答案 2 :(得分:-1)

if(Build.VERSION.SDK_INT&gt; Build.VERSION_CODES.HONEYCOMB)             webview.setLayerType(View.LAYER_TYPE_SOFTWARE,null);