Wireless TWAIN Document Scanning on Android

If you have a TWAIN-compliant scanner, you can easily control it with Dynamic Web TWAIN or Dynamic .NET TWAIN. Both SDKs can help you create some excellent applications for document scanning and management on PCs. However, have you ever complained that it’s so inconvenient to stay with your scanners and PCs all the time? Since mobile technology is so hot today, why don’t you make TWAIN scan wireless, getting rid of clumsy machines? In this tutorial, I’d like to show you how to create a simple Android application and a .Net TWAIN server to conveniently capture document images from remote TWAIN scanners to your smartphone.

twain_android_client

Document Scanning Server with Dynamic .NET TWAIN

Download Dynamic .NET TWAIN SDK.

Download JSON.NET.

Launch Visual Studio to create a Windows Forms Application:

twain_server_gui

Add references: DynamicDotNetTWAIN and Newtonsoft.Json.

Initialize TWAIN component:

private void initTWAINComponent()
        {
            dynamicDotNetTwain = new Dynamsoft.DotNet.TWAIN.DynamicDotNetTwain();
            dynamicDotNetTwain.IfShowUI = false;
            dynamicDotNetTwain.IfThrowException = true;
            dynamicDotNetTwain.MaxImagesInBuffer = 1;
            dynamicDotNetTwain.IfAppendImage = false;
            dynamicDotNetTwain.IfDisableSourceAfterAcquire = true;

            int iNum;
            dynamicDotNetTwain.OpenSourceManager();
            for (iNum = 0; iNum < dynamicDotNetTwain.SourceCount; iNum++)
            {
                comboBox1.Items.Add(dynamicDotNetTwain.SourceNameItems(Convert.ToInt16(iNum)));
            }
            if (iNum > 0)
                comboBox1.SelectedIndex = 0;

            dynamicDotNetTwain.OnPostAllTransfers += dynamicDotNetTwain_OnPostAllTransfers;
        }

Create a Socket server using TCPListener:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;
using System.Net;
using System.Net.Sockets;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace WirelessTWAIN
{
    class ServerManager
    {

        TcpListener server = null;
        NetworkStream stream = null;
        WirelessTWAIN twain = null;
        Byte[] imageData;

        public ServerManager(WirelessTWAIN twain)
        {
            this.twain = twain;
        }

        public void run()
        {
            try
            {
                // Set the TcpListener on port 13000.
                Int32 port = 2015;
                IPAddress localAddr = IPAddress.Parse("192.168.8.84"); // server IP

                // TcpListener server = new TcpListener(port);
                server = new TcpListener(localAddr, port);

                // Start listening for client requests.
                server.Start();

                // Buffer for reading data
                Byte[] bytes = new Byte[256];
                String data = null;

                // Enter the listening loop.
                while (true)
                {
                    Console.Write("Waiting for a connection... ");

                    // Perform a blocking call to accept requests.
                    // You could also user server.AcceptSocket() here.
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected!");
                    data = null;

                    // Get a stream object for reading and writing
                    stream = client.GetStream();

                    int i;

                    // Loop to receive all the data sent by the client.
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        // Translate data bytes to a ASCII string.
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                        Console.WriteLine("Received: {0}", data);

                        JObject jobj = JObject.Parse(data);
                        JToken token = jobj.GetValue("type");
                        if (token != null)
                        {
                            string result = token.ToString();
                            Console.WriteLine("Received: {0}", result);

                            if (result.Equals("data"))
                            {
                                stream.Write(imageData, 0, imageData.Length);
                                stream.Flush();
                                imageData = null;
                            }
                            else if (result.Equals("info"))
                            {
                                twain.scanImage();
                            }
                        }
                    }

                    stream = null;
                    // Shutdown and end connection
                    Console.WriteLine("close connection");
                    client.Close();
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                // Stop listening for new clients.
                server.Stop();
            }

        }

        public void prepareData(Byte[] data)
        {
            this.imageData = data;
        }

        public void sendData()
        {
            if (stream != null && imageData != null)
            {
                JObject jobj = new JObject();
                jobj.Add("length", imageData.Length);
                string msg = jobj.ToString();
                byte[] msgBytes = System.Text.Encoding.ASCII.GetBytes(msg);
                stream.Write(msgBytes, 0, msgBytes.Length);
                stream.Flush();
            }
        }
    }
}

When we have acquired an image from TWAIN scanner, send it to a socket client.

twain_pc_server

Android Document Scanning via Remote Control

Create a new Android project with a Button and an ImageView.

Declare the Internet permission:

<uses-permission android:name="android.permission.INTERNET"/>

Create a Socket client for receiving images from TWAIN scan server:

package com.dynamsoft.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import com.dynamsoft.ui.UIListener;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;

public class SocketClient extends Thread {
	private Socket mSocket;
	private UIListener mUIListener;

	public SocketClient(UIListener client) {
		mUIListener = client;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();

		try {
			mSocket = new Socket("192.168.8.84", 2015);
			BufferedOutputStream outputStream = new BufferedOutputStream(mSocket.getOutputStream());
			BufferedInputStream inputStream = new BufferedInputStream(mSocket.getInputStream());
			ByteArrayOutputStream out = new ByteArrayOutputStream();

			JsonObject jsonObj = new JsonObject();
            jsonObj.addProperty("type", "info");

			byte[] buff = new byte[256];
			int len = 0;
            String msg = null;
            outputStream.write(jsonObj.toString().getBytes());
            outputStream.flush();
            int sum = 0;
            int total = 0;    
            boolean isDataReady = false;

            while ((len = inputStream.read(buff)) != -1) {
            	if (!isDataReady) {
            		msg = new String(buff, 0, len);

                    // JSON analysis
                    JsonParser parser = new JsonParser();
                    boolean isJSON = false;
                    JsonElement element = null;
                    try {
                        element =  parser.parse(msg);

                        if (element != null) {
                        	isJSON = true;
                        }
                    }
                    catch (JsonParseException e) {
                        System.out.println("exception: " + e);
                    }

                    if (isJSON) {
                    	System.out.println(element.toString());
                        JsonObject obj = element.getAsJsonObject();
                        element = obj.get("length");
                        if (element != null) {
                        	total = element.getAsInt();
                        	jsonObj = new JsonObject();
                            jsonObj.addProperty("type", "data");
                            outputStream.write(jsonObj.toString().getBytes());
                            outputStream.flush();
                            isDataReady = true;
                        }
                    }
            	}
                else {
                	out.write(buff, 0, len);  
                	sum += len;
                	if (sum == total) {
                		break;
                	}
                }
            }

            mUIListener.updateImage(out);
            System.out.println("close");
			outputStream.close();
			inputStream.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			try {
				mSocket.close();
				mSocket = null;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		System.out.println("data sent");
	}

	public void close() {
		if (mSocket != null) {
			try {
				mSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

Source Code

https://github.com/dynamsoft-dnt/Wireless-TWAIN-Scan-on-Android

 

 

  • http://www.dynamsoft.com/ Xiao Ling

    Yes, you are right. Internet access is required. Dynamic .NET TWAIN works as a scanner server. It sends scanned images to Android app via socket connection.

  • Ken

    Hi, may I ask the Dynamic. Net Twain SDK (Document Scanning Server) must be installed on the PC where the scanner (printer) is connected to by USB? and this PC acting as the scanning server must be connected to the internet ? if the wireless network card been removed from PC , will it still work without connection? in this case , the Android phone client cannot receive the scanned document, right ?

  • Maxipes Fik

    Wow, this is interesting, I will check it! Have a nice day 😉