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.
Document Scanning Server with Dynamic .NET TWAIN
Download Dynamic .NET TWAIN SDK.
Download JSON.NET.
Launch Visual Studio to create a Windows Forms Application:
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.
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