C# Xamarin Recieve and Display image from Stream Byte Array with TCP Sockets

John Sp 96 Reputation points
2021-04-16T13:14:25.02+00:00

I am currently working on a project that I send an Image through TCP using sockets from a WinForm Application to a Xamarin Android App in the same network.

I've tested the Server ( WinForms ) code using a client ( also Winforms) and managed it to work. But the problem comes, when I code for Android client in Xamarin I find out that I cannot use Bitmap the same way, so I tried to find other ways.

The problem is with the android Client code. Everywhere I search everyone suggests to use the code below. But It looks that I am missing something. I've checked in debugging that the image bytes get all through from Server -> Client.
I am not an expert on these matters so feel free to suggest any corrections

 Stream stream = new MemoryStream(buffer);  
                   PhotoStream = ImageSource.FromStream(() => new MemoryStream(buffer));  
                   imgXam.Source = PhotoStream;  

EDIT 1:
If I remove the while loop and start playing with the Send button ( server) and Connect Button(Client) some images show up on the clients side. That's odd
EDIT 2.
It seems that with the while loop removed. And move the code to the main-thread it works but, I still can't use the while loop without block the UI thread

The codes that I use

The Code in my WinForms Server is this.

 private void StartServer_Click(object sender, EventArgs e)  
    {  
        IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 9999);  
        Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
        server.Bind(iep);  
        server.Listen(100);  
        Console.WriteLine("Waiting for client....");  
        client = server.Accept();  
    }  
    private void SendImage_Click(object sender, EventArgs e)  
    {  
        Bitmap bmp = TakingScreenshotEx1(); // method for taking screenshot  
        bmp.Save("1.jpeg", ImageFormat.Jpeg); // the name of the screenshot taken, just before   
  
        byte[] buffer = ReadImageFile("1.jpeg"); // read the saved image file   
        int v = client.Send(buffer, buffer.Length, SocketFlags.None); // send the image   
        Console.WriteLine("Image SENT!");  
    }  

My WinForms Client ( newbie but working method )

 IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 9999);  
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
    byte[] buffer = new byte[1000000];  
  
    private async void Connect_Click(object sender, EventArgs e)  
    {    
       if(client.Connected != true)  
        client.Connect(iep);  
  
        await Task.Run(() => DoSomethingLong());  
    }  
   private async void DoSomethingLong()  
    {  
        while (true)  
        {  
            int v = client.Receive(buffer, buffer.Length, SocketFlags.None);  
            Console.WriteLine("Data Received!");  
  
            Stream stream = new MemoryStream(buffer);  
            var img = Bitmap.FromStream(stream);  
            pictureBox1.Image = img;  
        }  
    }  

The problematic Android Client

        IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 9999);  
        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
        byte[] buffer = new byte[1000000];  
        private async void Connect_Clicked(object sender, EventArgs e)  
        {  
            if (client.Connected != true)  
                client.Connect(iep);  
  
            await Task.Run(() => DoSomethingLong());  
        }  
        public Xamarin.Forms.ImageSource PhotoStream { get; set; }  
        private async void DoSomethingLong()  
        {  
  
            while(true){  
                int v = client.Receive(buffer, buffer.Length, SocketFlags.None);  
                    Console.WriteLine("Data Received!");  

                    Stream stream = new MemoryStream(buffer);  
                   PhotoStream = ImageSource.FromStream(() => new MemoryStream(buffer));  
                   imgXam.Source = PhotoStream; // load the PhotoStream to Image (aka imgXam)  
            }  
}  
Developer technologies .NET Xamarin
Developer technologies C#
{count} votes

Accepted answer
  1. John Sp 96 Reputation points
    2021-04-25T07:44:20.503+00:00

    If I use a while loop to keep 'doing stuff' it blocks the Main UI Thread.

    SOLVED

    If I Invoke the MainThread Method inside a Timer . I was able to solve the problem

     Device.StartTimer(TimeSpan.FromMilliseconds(500), () =>
            {
                // called every 1 second
    
                MainThread.BeginInvokeOnMainThread(() =>
                {
    
                });
    
                return true; // return true to repeat counting, false to stop timer
    
            });
    
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.