WebView.draw(canvas)有时会在某些设备上的Android Lollipop 5.0+中崩溃 - 致命信号11(SIGSEGV)

时间:2014-12-11 19:58:21

标签: android android-ndk android-webview android-canvas android-5.0-lollipop

我有一段代码在UI线程上运行,要求RelativeLayout使用WebView绘制到Canvas

someRelativeLayoutContainingWebView.draw(canvas);

这条确切的线路在一些Android Lollipop 5.0设备(Nexus 4,Nexus 5)上崩溃,但在其他设备(Nexus 7)上运行。崩溃日志显示以下内容:

--------- beginning of crash
F/libc    (20829): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x8d68fc68 in tid 21178 (Thread-860)
W/art     (20829): Attempt to remove local handle scope entry from IRT, ignoring
I/DEBUG   (  184): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (  184): Build fingerprint: 'google/occam/mako:5.0/LRX21T/1576899:user/release-keys'
I/DEBUG   (  184): Revision: '11'
I/DEBUG   (  184): ABI: 'arm'
I/DEBUG   (  184): pid: 20829, tid: 21178, name: Thread-860  >>> com.[censored] <<<
I/DEBUG   (  184): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8d68fc68
I/DEBUG   (  184):     r0 8d68fc68  r1 00000020  r2 000000df  r3 20202020
I/DEBUG   (  184):     r4 00000001  r5 8d68fc68  r6 8d68fc68  r7 a62a0241
I/DEBUG   (  184):     r8 b86f9e13  r9 b86f982a  sl ffffffff  fp 000000ff
I/DEBUG   (  184):     ip 20002000  sp a32988f8  lr a62525f9  pc a62a02bc  cpsr 200b0030
I/DEBUG   (  184): 
I/DEBUG   (  184): backtrace:
I/DEBUG   (  184):     #00 pc 003552bc  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #01 pc 003075f7  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #02 pc 002c450f  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #03 pc 002c4589  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #04 pc 002c6b41  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #05 pc 002c6ffb  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #06 pc 002c4b83  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #07 pc 002c4c51  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #08 pc 002adff5  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #09 pc 002fea4f  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #10 pc 002aa35f  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #11 pc 0032d4ef  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #12 pc 002bd2d1  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #13 pc 00e0ef7b  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #14 pc 00e14a4d  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #15 pc 00e14af3  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #16 pc 00e4cbd1  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #17 pc 00e1ccd1  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #18 pc 00e1ce17  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #19 pc 00204333  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #20 pc 0020458d  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #21 pc 002023cb  /system/lib/libwebviewchromium.so
I/DEBUG   (  184):     #22 pc 000158a7  /system/lib/libc.so (__pthread_start(void*)+30)
I/DEBUG   (  184):     #23 pc 0001387b  /system/lib/libc.so (__start_thread+6)

每隔一秒左右调用一次绘图。直到第40到第120次在我的应用程序的单次运行中调用draw()时才会发生崩溃。我没有安装Lollipop的所有测试设备工作正常,不会崩溃。

如果我从WebView删除RelativeLayout,但保留所有其他元素,也不会发生崩溃。 WebView确实会加载网站并正常运行一段时间,直到崩溃发生。如果我不调用loadUrl(),则不会发生崩溃。无论我加载哪个网站,都会发生崩溃。

我能做些什么来解决这个问题吗?

我在这里找到了解决问题的一些资源:https://groups.google.com/forum/#!topic/android-developers/W6smaM1atE8

但是,在这种情况下使用的函数已经被弃用了很长时间。

编辑:

以下是回应@ marcin.kosiba的问题的其他信息:

  1. 你传递的Canvas是一个支持Bitmap的Canvas,对吗?它有多大?它是否应用了任何变换?
  2. 是的,这是前面几行:

    Bitmap bmp = Bitmap.createBitmap(someRelativeLayoutContainingWebView.getWidth(), someRelativeLayoutContainingWebView.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bmp);
    someRelativeLayoutContainingWebView.draw(canvas);
    

    正如您所看到的,它是RelativeLayout的整个宽度和高度,占据设备的整个屏幕,减去设备的状态栏和软后退/主页按钮栏。我的应用程序无法以全屏模式运行。

    1. WebView是否显示在屏幕上并呈现在此画布中,或者WebView是否未附加到视图层次结构并在后台运行?
    2. WebView附加到视图层次结构并显示在屏幕上。它占据了屏幕的大部分,减去了顶部的一个小条。

      1. 如果您直接调用WebView.onDraw,是否会发生这种情况?
      2. 除非我覆盖onDraw()类,否则我无法直接调用WebView。但是,在这样做时,没有发生崩溃。

        1. 如果您可以创建一个带有repro的APK并将其附加到该bug,那么对于看这个的人来说会更容易。你愿意这样做吗?如果没有,你能提供一些关于RelativeLayout中其他元素的细节吗?
        2. 不幸的是,这是一个非常大的项目,Activity中有很多事情发生了这个问题。我无法公开分享整个源代码,我知道,这使得解决问题变得更加困难。以下是视图层次结构的框架:

          <RelativeLayout android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:id="@+id/someRelativeLayoutContainingWebView">
              <DrawerLayout
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:layout_below="@+id/topRelativeLayout">
          
                  <!-- Main content -->
                  <RelativeLayout
                          android:layout_width="match_parent"
                          android:layout_height="match_parent">
          
                      <RelativeLayout
                          android:layout_width="match_parent"
                          android:layout_height="match_parent">
          
                          <WebView
                                  android:layout_width="match_parent"
                                  android:layout_height="match_parent"
                                  android:id="@+id/primaryWebView"
                                  android:scrollbarStyle="insideOverlay"
                                  android:fadeScrollbars="true"
                                  android:scrollbarThumbVertical="@drawable/scrollbar"
                                  android:scrollbarSize="@dimen/scroll_bar_size"/>
          
                          <RelativeLayout>
                              <EditText/>
                              <Button/>
                              <View/>
                              <Button/>
                          </RelativeLayout>
                      </RelativeLayout>
          
                      <View/>
                  </RelativeLayout>
          
                  <!-- Navigation drawer -->
                  <RelativeLayout
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:layout_gravity="left">
          
                      <RelativeLayout>
                          <TextView/>
                          <ViewPager/>
                          <View/>
          
                          <LinearLayout>
                              <Button/>
                              <View/>
                              <Button/>
                          </LinearLayout>
          
                          <LinearLayout>
                              <Button/>
                          </LinearLayout>
          
                          <Button/>
                          <Button/>
                          <Button/>
                      </RelativeLayout>
          
                      <View/>
                  </RelativeLayout>
          
              </DrawerLayout>
          
              <!-- Top bar -->
              <RelativeLayout android:layout_width="match_parent"
                              android:layout_height="@dimen/some_height"
                              id="@+id/topRelativeLayout">
          
                  <RelativeLayout>
                      <SurfaceView/>
                      <TextView/>
                  </RelativeLayout>
          
                  <Button/>
          
                  <RelativeLayout>
                          <EditText/>
                          <Button/>
                  </RelativeLayout>
          
              </RelativeLayout>
          
              <View/>
              <ProgressBar/>
              <TextView/>
          </RelativeLayout>
          

2 个答案:

答案 0 :(得分:1)

此时不确定是否有任何可以做的事情。我代表您提交了http://crbug.com/441707。了解问题的原因可以更容易地提出解决方法。如果你能澄清一些事情(最好是关于bug)会很有帮助:

  1. 你传递的Canvas是一个支持Bitmap的Canvas,对吗?它有多大?它是否应用了任何变换?
  2. WebView显示在屏幕上呈现在此画布中,或者WebView未附加到视图层次结构并在后台运行?
  3. 如果你直接调用WebView.onDraw会发生这种情况吗?
  4. 如果您可以创建一个带有repro的APK并将其附加到该bug,那么对于看这个的人来说会更容易。你愿意这样做吗?如果没有,你能提供一些关于RelativeLayout中其他元素的细节吗?

答案 1 :(得分:0)

问题来自竞争条件,有时会导致我的代码吸引属于回收Canvas的{​​{1}}。可以使用以下代码重现崩溃:

Bitmap

修复竞争条件并确保永远不会使用回收的Bitmap bmp = Bitmap.createBitmap(someRelativeLayoutContainingWebView.getWidth(), someRelativeLayoutContainingWebView.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bmp); bmp.recycle(); someRelativeLayoutContainingWebView.draw(canvas); // SIGSEGV will happen here Bitmap来解决问题。

另一个有趣的细节是,如果从视图层次结构中删除了Canvas,则会抛出WebView而不是RuntimeException。异常的重要部分如下所示:

SIGSEGV

这比E/AndroidRuntime( 7052): Caused by: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@1cb64604 E/AndroidRuntime( 7052): at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1225) E/AndroidRuntime( 7052): at android.graphics.Canvas.<init>(Canvas.java:152) 崩溃更有用。