一个回归错误出现在Android 4.3中。在之前的版本中运行良好的代码现在会导致本地崩溃,从而关闭进程。
当将一个大于32kb的图像绘制到由一个Picture对象记录的Canvas中,并通过writeToStream()写入流时,就会发生崩溃。
当尝试写入一个字符串(我相信这是图像对象的Uri)时,崩溃发生在Skia中。
以下程序演示如何重现此问题。所需的是具有ID“button”的按钮的布局。
设置BitmapFactory.Options的这两行是必需的,以便让Skia平坦化代码写出图像数据(否则将发射图像)。
我知道Picture方法中的
我需要将Picture对象写入文件,以便将其从主应用程序传递到服务进程。我不能使用文档中推荐的解决方法,即“将图片绘制到位图” ,原因如下:
当将一个大于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对象写入文件,以便将其从主应用程序传递到服务进程。我不能使用文档中推荐的解决方法,即“将图片绘制到位图” ,原因如下:
- 在写入时无法确定所需的Picture分辨率。
- 在恢复后,需要通过矩阵将Picture对象进行缩放。
- 保存为非常高分辨率的位图在内存和处理时间方面效率低下。