我有一个基于Romain Guy的示例的TextureView,可以找到here。在Android 4.3和4.4上,经过几轮暂停和恢复应用程序后,应用程序崩溃,唯一的错误痕迹是LogCat中的致命信号11。我创建了一个测试应用程序,它使用Romain Guy的确切代码来查看它是否是我在代码中所做的事情,而Romain的代码也与致命信号11一起崩溃。
我已经确定如果我使用Handler而不是Thread运行代码,它似乎不会使应用程序崩溃。 Handler应该在主UI线程上运行(或者至少我相信它),这可能暗示它是一个线程问题。
我还确定在调用canvas.drawX(drawColor,drawBitmap,drawRect等等)期间发生了崩溃。锁定和解锁画布似乎不是问题。我怀疑线程正在被取消,而其他一些代码仍在使用画布,但由于没有任何真正的异常被抛出而且崩溃相当不一致,我很难跟踪问题。
非常感谢任何见解。
答案 0 :(得分:2)
当TextureView
失去可见性时(因为屏幕旋转,其他Activity
出现在前面或您按下主页按钮),它会使其SurfaceTexture.OnFrameAvailableListener
无效({{3} }})。看起来当这种情况发生时,Canvas
实例正在C ++代码本身执行drawX()
方法,应用程序将崩溃,因为由于某种原因,在方法完成之前清除包含该画布的内存。但是,因为Canvas.drawX()
方法使用Android本机C ++代码,所以C ++不会抛出NullPointerException
(GrepCode),因此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);