B4J Tutorial PDF creation (with the help of Android)

Erel posted this nice tutorial to create pdf's on Android: https://www.b4x.com/android/forum/threads/printing-and-pdf-creation.76712/#content

For B4J there are some examples but these are based on (expensive) libs or other have other dependencies. So I was thinking of a combination:

- create pdf's on an Android device
- send these to a B4J app and store it (pc, database, send them via mail, etc.)

Take a look at:

Network + AsyncStreams + B4XSerializator
https://www.b4x.com/android/forum/threads/b4x-network-asyncstreams-b4xserializator.72149/

to exchange the data via Network. You don't need the serializator :) as we just handle some bytes here.

B4A Service

add this service to your app ("Network"). As it just sends data to the B4J app I've stripped all subs handling incoming connections

B4X:
Sub Process_Globals
    Public connected As Boolean
    Private client As Socket
    Public server As ServerSocket
    Private astream As AsyncStreams
    Private const PORT As Int = 51042
    Private working As Boolean = True
    Private ServerIPAddress As String="192.168.178.23" 'the ip of the machine where B4J is running on
End Sub

Sub Service_Create
    server.Initialize(PORT, "server")
    ListenForConnections
End Sub

Private Sub ListenForConnections
    Do While working
        server.Listen
        Wait For Server_NewConnection (Successful As Boolean, NewSocket As Socket)
        If Successful Then
            CloseExistingConnection
            client = NewSocket
            astream.InitializePrefix(client.InputStream, False, client.OutputStream, "astream")
            UpdateState(True)
        End If
    Loop
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Public Sub ConnectToServer
    Log("Trying to connect to: " & ServerIPAddress)
    CloseExistingConnection
    Dim client As Socket
    client.Initialize("client")
    client.Connect(ServerIPAddress, PORT, 10000)
    Wait For Client_Connected (Successful As Boolean)
    If Successful Then
        astream.InitializePrefix(client.InputStream, False, client.OutputStream, "astream")
        UpdateState (True)
    Else
        Log("Failed to connect: " & LastException)
    End If
End Sub

Public Sub Disconnect
    CloseExistingConnection
End Sub

Sub CloseExistingConnection
    If astream.IsInitialized Then astream.Close
    If client.IsInitialized Then client.Close
    UpdateState (False)
End Sub

Sub UpdateState (NewState As Boolean)
    connected = NewState
    CallSubDelayed2(Main, "NetworkState",connected)
End Sub

Sub AStream_Error
    UpdateState(False)
End Sub

Sub AStream_Terminated
    UpdateState(False)
End Sub

Sub AStream_NewData (Buffer() As Byte)
    CallSubDelayed2(Main, "NewData", Buffer)
End Sub

Public Sub SendData (data() As Byte)
    If connected Then astream.Write(data)
End Sub


'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub Service_Destroy

End Sub

Main (B4A)

In resume we call the service to connect to the B4J "server"

B4X:
Sub Activity_Resume
    CallSubDelayed(Network,"ConnectToServer")
End Sub

The service calls this sub if the connection to the server is established (or not = False). If it is, start to create your pdf's.

B4X:
Sub NetworkState(connected As Boolean)
    If connected=False Then Return
    CreatePDFs
End Sub

If you've created a pdf, call this to send the data to the B4J app (I use a loop to create 100 pdf's and send each)

B4X:
Dim FileBuffer() As Byte
        Dim out As OutputStream
        out.InitializeToBytesArray(1000)
        pdf.WriteToStream(out)
        FileBuffer=out.ToBytesArray
        out.close
        pdf.Close
      
        CallSub2(Network,"SendData",FileBuffer)

B4J (the layout is the same as in Erel's example. I removed all views except the labels)

B4X:
#Region Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 600
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
      
    Private connected As Boolean
    Private client As Socket
    Public server As ServerSocket
    Private astream As AsyncStreams
    Private const PORT As Int = 51042
    Private working As Boolean = True
    Private lblStatus As Label
    Private lblMyIp As Label
    Public FileNumber As Int
    Private ScrollPane1 As ScrollPane
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("1") 'Load the layout file.
    MainForm.Show
    server.Initialize(PORT, "server")
    ListenForConnections
    UpdateState(False)
End Sub

Private Sub ListenForConnections
    Do While working
        server.Listen
        Wait For Server_NewConnection (Successful As Boolean, NewSocket As Socket)
        If Successful Then
            CloseExistingConnection
            client = NewSocket
            astream.InitializePrefix(client.InputStream, False, client.OutputStream, "astream")
            UpdateState(True)
        End If
    Loop
End Sub


Sub CloseExistingConnection
    If astream.IsInitialized Then astream.Close
    If client.IsInitialized Then client.Close
    UpdateState (False)
End Sub

Sub AStream_Error
    UpdateState(False)
End Sub

Sub AStream_Terminated
    UpdateState(False)
End Sub
Sub UpdateState (NewState As Boolean)
    connected = NewState
  
    If connected Then
        lblStatus.Text = "Connected"
    Else
        lblStatus.Text = "Disconnected"
    End If
    lblMyIp.Text = "My ip: " & server.GetMyIP
End Sub


Sub AStream_NewData (Buffer() As Byte)
  
    Dim Dir, Filename As String
    Dir=File.DirApp
    FileNumber=FileNumber+1
    Filename="PDF_"&FileNumber&"_" &DateTime.Now&".pdf"
    Log("Receiving data. Storing file:" & Filename)
    Dim out As OutputStream = File.OpenOutput(Dir, Filename, False)
    out.WriteBytes(Buffer, 0, Buffer.Length)
    out.Close
  
End Sub

The last sub receives the data and stores it to a file. You could upload these files to a server or do other things.

Benchmark: In debug mode it will take 5 secs to create, transmit and store 100 pdf's with 3 pages. So you can create about 1000 pdf's a minute which is quite good.
 
Top