B4J Tutorial [Server] Build a printer server with PrintHtml

Erel

Administrator
Staff member
Licensed User
PrintHtml is a Windows utility that prints html files. You can see more information about it here: http://www.basic4ppc.com/android/forum/threads/print-with-printhtml-tool.35492/

In this example we use it to print messages from the device. The device sends a POST request with the html message and the PrintServer uses jShell to call PrintHtml and print the message.



The client code is trivial:
B4X:
Sub Process_Globals
   Private link As String = "http://192.168.0.100:51042/print"
End Sub

Sub Activity_Create(FirstTime As Boolean)
   
End Sub

Sub Activity_Click
   Dim j As HttpJob
   j.Initialize("j", Me)
   j.PostString(link, "This is a test message sent from the device...")
End Sub

Sub JobDone(j As HttpJob)
   If j.Success Then
     Log("Success: " & j.GetString)
   Else
     Log("Error: " & j.ErrorMessage)
   End If
   j.Release
End Sub
The server code is more interesting. We want the server to handle requests one after another. There are no advantages for sending multiple printer jobs and it is also not clear whether PrintHtml and the printer driver support concurrent jobs.
This is done by setting the SingleThreaded parameter to True:
B4X:
Sub Process_Globals
   Private srvr As Server
End Sub

Sub AppStart (Args() As String)
   srvr.Initialize("")
   srvr.Port = 51042
   srvr.AddHandler("/print", "Print", True) 'SingleThreaded = True
   srvr.Start
   StartMessageLoop
End Sub
jShell library runs the task in the background and raises the ProcessCompleted event when the task completes. This means that we need to pause the current request until the task completes and then resume it. Otherwise the Handle sub will be completed before the task completes. The response is committed when the execution of Handle completes.

This is done by calling StartMessageLoop in the Handle sub and then StopMessageLoop in js_ProcessCompleted sub:

B4X:
Sub Class_Globals
   Private js As Shell
   Private mresp As ServletResponse
End Sub

Public Sub Initialize

End Sub

Sub Handle(req As ServletRequest, resp As ServletResponse)
   mresp = resp
   'save the request to a file
   Dim out As OutputStream = File.OpenOutput(File.DirApp, "temp.txt", False)
   File.Copy2(req.InputStream, out)
   out.Close
   Dim params As List
   params.Initialize
   'optionally set the printer
   'params.Add("printername=novapdf")
   params.Add("file=temp.txt")
   js.Initialize("js", "printhtml.exe", params)
   js.WorkingDirectory = File.DirApp
   js.Run(-1)
   StartMessageLoop '<--- wait for the event
End Sub

Sub js_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
   Log("Success=" & Success & ", StdOut=" & StdOut & ", StdErr=" & StdErr)
   If Success Then
     mresp.Write("Message was printed successfully.")
   Else
     mresp.SendError(500, StdErr)
   End If
   StopMessageLoop '<-- close the secondary message loop
End Sub
 

FranckB

Member
Licensed User
Hi all,

Witch librairies may i include to run this print server ?
I would like to have a nonUI service running in background what i can call with any browser like "http://localhost:51042/print?12345" to print the "12345.txt" file.
I have this error when running :

B4J version: 4.50
Parsing code. (0.00s)
Compiling code. Error
Error compiling program.
Error description: La référence d'objet n'est pas définie à une instance d'un objet.
Occurred on line: 7
srvr.Port = 51042
Word: port

Thank's by advance.
Franck

UPDATE : Sorry to have disturb you, it works !!! Thanks
 
Last edited:
Top