I'm using Mono for Android (latest version as of this post) with the Visual Studio plugin to build an Android application. It targets API Level 8, Android 2.2 framework.
The app runs fine on a Motorola Droid running Android version 2.2.2 It crashes with almost no output from the debugger on Motorola Droid X2 running Android 2.3.3
The only output is: The program 'Mono' has exited with code 255 (0xff).
The crash happens in this method on the line that starts with using (Bitmap...
public static Drawable GetDrawable(string url) {
try {
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Bitmap bitmap = Android.Graphics.BitmapFactory.DecodeStream(response.GetResponseStream())) {
Drawable image = (Drawable)(new BitmapDrawable(bitmap));
return image;
}
}
catch {
return null;
}
}
If I set a breakpoint on that line it breaks correctly but I can't find anything wrong. If I set a breakpoint after that line the debugger simply detaches and the app force quits.
I have a similar method that returns an object from JSON and it works fine. So, I'm fairly sure it's related to the dynamic bitmap creation but at this point I've tried everything I can think of.
I just reproduced this problem in a small, self-contained project available here: DrawableTest.zip
Here's the full code:
using System;
using System.Net;
using System.Threading;
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Graphics;
using Android.Graphics.Drawables;
namespace DrawableTest {
[Activity(Label = "DrawableTest", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity {
ImageView mImage;
Button mButton;
public const string mImageUrl = "http://i.stpost.com/erez4/erez?src=ProductImages/3576U_02.tif&tmp=MediumLargeG4&redirect=0&headers=proxy";
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
mImage = FindViewById<ImageView>(Resource.Id.MyImage);
mButton = FindViewById<Button>(Resource.Id.MyButton);
mButton.Click += new EventHandler(mButton_Click);
}
void mButton_Click(object sender, EventArgs e) {
ThreadPool.QueueUserWorkItem(o => AsyncImageLoad());
}
private Drawable GetDrawable(string url) {
try {
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Bitmap bitmap = Android.Graphics.BitmapFactory.DecodeStream(response.GetResponseStream())) {
Drawable image = new BitmapDrawable(bitmap);
return image;
}
}
catch (Exception e) {
return null;
}
}
private void AsyncImageLoad() {
Drawable image = GetDrawable(mImageUrl);
RunOnUiThread(() => {
mImage.SetImageDrawable(image);
});
}
}
}
This is probably a bug in our Stream mapping code, similar to: http://bugzilla.xamarin.com/show_bug.cgi?id=1054
This should be fixed in the next release (1.9.x, probably).
As a workaround, try copying response.GetResponseStream() into a System.IO.MemoryStream, and then pass the MemoryStream to BitmapFactory.DecodeStream().
I had the right idea, but the wrong approach. Instead of using BitmapFactory.DecodeStream(), use BitmapFactory.DecodeByteArray(). The following code works for me in your DrawableTest.zip app:
private Drawable GetDrawable(string url)
{
try {
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(url);
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
using (Stream responseStream = response.GetResponseStream()) {
MemoryStream workaround = new MemoryStream();
responseStream.CopyTo(workaround);
Bitmap bitmap = Android.Graphics.BitmapFactory.DecodeByteArray (
workaround.GetBuffer (), 0, (int) workaround.Length);
Drawable image = new BitmapDrawable(bitmap);
return image;
}
}
catch (Exception e) {
Log.Error("DrawableTest", "Exception: " + e.Message);
return null;
}
}
Note the using blocks to ensure that the resources are disposed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With