Saving images and displaying them in recycler view - xamarin.droid


#1

Hi,

I am building a chat application that displays chat messages in a recycler view. adding and displaying the chats work fine, now I’m working on adding the ability to take photos and display them in the chat activity. I have created a method that creates a new document with a revision where i attach the image:

 public void SaveImage(Bitmap image,string user)
{

	var document = cbDB.CreateDocument();
	var properties = new Dictionary<string,object>()
	{
		{"type","image"},
		{"user",user},
		{"created",DateTime.Now.ToString()}
	};

	var rev = document.PutProperties(properties);
	var newRev = document.CurrentRevision.CreateRevision();

	using(MemoryStream stream = new MemoryStream())
	{
		image.Compress(Bitmap.CompressFormat.Jpeg, 50, stream);
		byte[] imageData = stream.ToArray();
		newRev.SetAttachment("image", "image/jpg", stream);
		newRev.Save();
	}

	var retrieveDocument = cbDB.GetDocument(document.Id);
	foreach (var props in retrieveDocument.Properties)
	{
		Log.Info("--DOCUMENT WITH IMAGE EVENT--", "Document Properties: " + props.Key + " " + props.Value);
	}
}

as far as i can tell this method is working correctly and the attachment is being saved. To display the chats/images in the recycler view i use the following query(docType = message and imgType=image):

public Query GetEquipmentChats()
{
    var view = cbDB.GetView(dbView);

    if (view.Map == null)
    {
        view.SetMap((document, emitter) =>
        {
            object type;
            document.TryGetValue("type", out type);

                if (docType.Equals((string)type) || imgType.Equals((string)type))
                {
                    emitter(document["created"], document);
                }
        }, "2");
	}

    var query = view.CreateQuery();
    query.Descending = true;
    return query;
}

now inside my OnBindViewHolder method i have added the following code as a test to see if i can get the attachement data length but my toast returns 0

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
    AdapterView viewHolder = holder as AdapterView;
    var doc = (Document)GetItem(position);

    Attachment image = doc.CurrentRevision.GetAttachment("image");
    if(image != null)
    {
        using(var sr = new StreamReader(image.ContentStream))
        {
            var data = sr.ReadToEnd();
            Toast.MakeText(Application.Context, data.Length.ToString(), ToastLength.Long).Show();
        }
    }
                
    viewHolder.mMsg.Text = ((string)doc.GetProperty("message"));
    viewHolder.mSdr.Text = ((string)doc.GetProperty("user"));
    viewHolder.mDte.Text = ((string)doc.GetProperty("created"));
}

my ultimate goal is to get the image displaying in the recycler view but for now i want to make sure my steps so far are right (which i dont think they are) can anyone confirm what my error is ie why im getting 0 for my data length


#2

I have just found this post which explains how to attach a photo and save it to couchbase: http://developer.couchbase.com/documentation/mobile/current/get-started/get-started-mobile/todo-lite/attach-a-photo/index.html. I proceeded to update my SaveImage method to be more inline with the documentation:

public void SaveImage(Bitmap image,string user)
{
    var document = cbDB.CreateDocument();
    var properties = new Dictionary<string,object>()
    {
        {"type","image"},
        {"user",user},
        {"created",DateTime.Now.ToString()}
    };

    var rev = document.PutProperties(properties);
    var newRev = document.CurrentRevision.CreateRevision();

    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    image.Compress(Bitmap.CompressFormat.Jpeg,50,outStream);

    ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.ToByteArray());

    newRev.SetAttachment("image","image/jpg",inStream);
    newRev.Save();


    // For testing purposes - remove when going live
    var retrieveDocument = cbDB.GetDocument(document.Id);
    foreach (var props in retrieveDocument.Properties)
    {
        Log.Info("--DOCUMENT WITH IMAGE EVENT--", "Document Properties: " + props.Key + " " + props.Value);
    }
}

but i get errors on

 image.Compress(Bitmap.CompressFormat.Jpeg,50,outStream); 

Error 3 Argument 3: cannot convert from ‘Java.IO.ByteArrayOutputStream’ to ‘System.IO.Stream’ C:\Users\Admin\Documents\Visual Studio 2013\Projects\K-Rith Chat\K-Rith Chat\K_Rith_Chat.Droid\CBase.cs 80 58 K_Rith_Chat.Droid

and

newRev.SetAttachment("image","image/jpg",inStream);

Error 5 Argument 3: cannot convert from ‘Java.IO.ByteArrayInputStream’ to ‘System.Collections.Generic.IEnumerable’ C:\Users\Admin\Documents\Visual Studio 2013\Projects\K-Rith Chat\K-Rith Chat\K_Rith_Chat.Droid\CBase.cs 84 54 K_Rith_Chat.Droid


#3

Hi @Gareth_Price

Which CBL SDK are you using? The code samples are in Java but you say it’s a Xamarin app. Shouldn’t it be written in C#? Sorry I’m no expert in Xamarin :]
It looks like the type castings are failing.

James