Android 4.3中调用Picture.writeToStream()时发生本地崩溃

6
一个回归错误出现在Android 4.3中。在之前的版本中运行良好的代码现在会导致本地崩溃,从而关闭进程。
当将一个大于32kb的图像绘制到由一个Picture对象记录的Canvas中,并通过writeToStream()写入流时,就会发生崩溃。
当尝试写入一个字符串(我相信这是图像对象的Uri)时,崩溃发生在Skia中。
I/DEBUG(122):     #00  pc 0001e3bc  /system/lib/libc.so (strlen+72)    
I/DEBUG(122):     #01  pc 000d9858  /system/lib/libskia.so (SkWriter32::writeString(char const*, unsigned int)+256)    
I/DEBUG(122):     #02  pc 00113d68  /system/lib/libskia.so (SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer&) const+44)

以下程序演示如何重现此问题。所需的是具有ID“button”的按钮的布局。
    public class MainActivity extends Activity {

    static final String IMAGE_FILE = Environment.getExternalStorageDirectory() + "/test.jpg";
    static final String SKIA_FILE = Environment.getExternalStorageDirectory() + "/test.skia";

    private static Bitmap loadBitmap(final String filename) {
        Bitmap bitmap = null;
        FileInputStream is;
        try {
            is = new FileInputStream(filename);
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inInputShareable = true;
            options.inPurgeable = true;
            bitmap = BitmapFactory.decodeFileDescriptor(is.getFD(), null, options);
            is.close();
        } catch (final FileNotFoundException e) {
            e.printStackTrace();
        } catch (final IOException ex) {
            ex.printStackTrace();
        }
        return bitmap;
    }

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(final View v) {

                final Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        // Create a Canvas and begin recording
                        final Picture picture = new Picture();
                        final Canvas canvas = picture.beginRecording(1024, 1024);
                        // De-compress an image from file
                        final Bitmap bitmap = loadBitmap(IMAGE_FILE);
                        // If present draw the image to the canvas and end
                        // recording
                        if (bitmap != null) {
                            canvas.drawBitmap(bitmap, new Matrix(), null);
                        }
                        picture.endRecording();

                        // Write out the Picture object to a Skia File.
                        FileOutputStream os;
                        try {
                            os = new FileOutputStream(SKIA_FILE);
                            picture.writeToStream(os);
                            os.close();
                        } catch (final FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (final IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                };
                new Thread(runnable).start();
            }
        });
    }
}

设置BitmapFactory.Options的这两行是必需的,以便让Skia平坦化代码写出图像数据(否则将发射图像)。
options.inInputShareable = true;
options.inPurgeable = true;

我知道Picture方法中的writeToStream()createFromStream()已经被弃用,但我不认为这会导致稳定性问题。
我需要将Picture对象写入文件,以便将其从主应用程序传递到服务进程。我不能使用文档中推荐的解决方法,即“将图片绘制到位图” ,原因如下:
  1. 在写入时无法确定所需的Picture分辨率。
  2. 在恢复后,需要通过矩阵将Picture对象进行缩放。
  3. 保存为非常高分辨率的位图在内存和处理时间方面效率低下。
有没有人知道一种解决方法,可以允许将图像写入流而不会导致崩溃?
1个回答

4

我本想将这个发表为评论,但我的声誉值不够...

Skia中的重大变化似乎出现在SkImageRef_ashmem.cpp文件的更改中:

https://code.google.com/p/skia/source/detail?r=4980

flatten方法用于检查空URI,如果uri为空,则会将0写入输出流。将null传递给SkFlattenableWriteBuffer::writeString()会导致strlen()崩溃。


1
已将此问题报告给Skia项目,编号为1457:https://code.google.com/p/skia/issues/detail?id=1457 - CAB
这个问题现在应该已经在未来版本的Android中得到了修复,因为核心Skia团队已经提交了一个修复,请参见https://code.google.com/p/android/issues/detail?id=58257。 - quickdraw mcgraw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接