Android Tutorial Android FTP tutorial

Status
Not open for further replies.
Old and irrelevant tutorial. Follow this one instead: [B4X] Net library (FTP, SMTP, POP) with Wait For

This tutorial covers the FTP object which is part of the Net library.
The Net library is based on Apache Commons Net.

Android OS doesn't allow us, the developers, to block the main thread for more than 5 seconds. When the main thread is busy for too long and is not able to handle the user events the "Application not responding" dialog appears.
Therefore slow operations like network operations should be done in the background.
The FTP library is built in such a way. All of the methods return immediately. When a task completes an event is raised. In fact you can submit several tasks one after another. The FTP protocol supports a single task at a time so the tasks will be processed serially.

Using the FTP library is pretty simple.
The first step is to initialize the FTP object. If this is an Activity module then you should do it in Activity_Create when FirstTime is true.
For Service modules it should be initialized in Service_Create.
B4X:
Sub Process_Globals
    Dim FTP As FTP
End Sub
Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        FTP.Initialize("FTP", "ftp.example.com", 21, "user", "password")
    End If
FTP.Initialize doesn't connect to the server. Connection will be established implicitly together with the next task.

Download

Downloading a file is done by calling DownloadFile with the remote file path and the local file path.
If you want to show the download progress then you should handle DownloadProgress event.
When download completes the DownloadCompleted event is raised. The ServerPath is passed as the first parameter to all events. You can use it to distinguish between different tasks. Make sure to check the Success parameter. If Success is False then you can find the exception message by calling LastException.

B4X:
    FTP.DownloadFile("/somefolder/files/1.zip", False, File.DirRootExternal, "1.zip")
   
Sub FTP_DownloadProgress (ServerPath As String, TotalDownloaded As Long, Total As Long)
    Dim s As String
    s = "Downloaded " & Round(TotalDownloaded / 1000) & "KB"
    If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
    Log(s)
End Sub

Sub FTP_DownloadCompleted (ServerPath As String, Success As Boolean)
    Log(ServerPath & ", Success=" & Success)
    If Success = False Then Log(LastException.Message)
End Sub
Upload

Uploading is similar to downloading.
B4X:
    FTP.UploadFile(File.DirRootExternal, "1.txt", True, "/somefolder/files/1.txt")

Sub FTP_UploadProgress (ServerPath As String, TotalUploaded As Long, Total As Long)
    Dim s As String
    s = "Uploaded " & Round(TotalUploaded / 1000) & "KB"
    If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
    Log(s)
End Sub

Sub FTP_UploadCompleted (ServerPath As String, Success As Boolean)
    Log(ServerPath & ", Success=" & Success)
    If Success = False Then Log(LastException.Message)
End Sub
List files and folders

FTP.List sends a request for the list of files and folders in a specific path.
The ListCompleted event is raised when the data is available.
You can use code similar to the following code to get more information on the entries:
B4X:
FTP.List("/")
...
Sub FTP_ListCompleted (ServerPath As String, Success As Boolean, Folders() As FTPEntry, Files() As FTPEntry)
    Log(ServerPath)
    If Success = False Then
        Log(LastException)
    Else
        For i = 0 To Folders.Length - 1
            Log(Folders(i).Name)
        Next
        For i = 0 To Files.Length - 1
            Log(Files(i).Name & ", " & Files(i).Size & ", " & DateTime.Date(Files(i).Timestamp))
        Next
    End If
End Sub
Delete
Delete is done by calling FTP.Delete with the full path. Again an event will be raised when the task completes (DeleteCompleted).

Closing the connection
You can close the connection by calling FTP.Close. Close will wait for the other tasks to complete and then will close the connection. This happens in the background.
FTP.CloseNow will immediately close the connection, failing the remaining tasks.

Some notes:
- At any given time there should be less than 15 waiting tasks. Otherwise you will get a RejectedExecutionException (this happens when the internal threads pool is exhausted).
- The order of the completed tasks may be different than the order of submission.
- The AsciiFile parameters sets the file transfer mode. If AsciiFile is true then every occurrence of an end of line character will be translated based on the server native end of line character. If your FTP server is Unix or Linux then the end of line character is the same as Android.
In most cases you can set AsciiFile to false.

The library is available for download here: http://www.b4x.com/forum/additional...92-new-net-library-android-ftp-smtp-pop3.html
 
Last edited:

Rusty

Well-Known Member
Licensed User
Longtime User
Erel,
With the ABFTP lib, you could detect the connection was or was not made with


Dim ABFT As ABFTP
abft.ABFTPConnect(txtftp, txtport,txtlogin, txtpassword)
WiFiAvailable = abft.ABFTPConnected
abft.ABFTPDisconnect

the ABFTPConnect returns true if the connection is made and false otherwise. With the FTP library, is there a similar capability? If so, how?
Thanks,
 

Rusty

Well-Known Member
Licensed User
Longtime User
Yes, I understand that part. The question is, how can I tell that there is no wireless connection available or that the wireless unit is not on or...? In other words, is there a way to tell that the connection failed?
My example is that my APP is being used in L.A. The place it was being used has a secured WiFi and the passphrase is not available, therefore the connection will fail. My ListFiles request is never satisfied causing delays. I would like to be able to detect the failure at or before the connection is attempted (and failed).
thanks Erel
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
If the connection fails then the Completed event will be raised and Success parameter will be False. You can get the error message by calling LastException.

You can issue a List command at the beginning just to test the connection.
This library manages all operations in the background to avoid blocking your program. This includes the connection. I preferred to keep the API simpler and implicitly connect as needed.
 

Rusty

Well-Known Member
Licensed User
Longtime User
Perfect! That's what I needed to know. I'll implement today.
Thanks
 

ppico

Member
Licensed User
Longtime User
I'm using this code:

'Activity module
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Dim FTP As FTP

End Sub

Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.

Dim ToggleButton1 As ToggleButton
Dim ToggleButton2 As ToggleButton
Dim ToggleButton3 As ToggleButton
Dim ToggleButton4 As ToggleButton
Dim Button1 As Button
Dim Button2 As Button
Dim Button3 As Button
Dim Button4 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout ("Prueba03a")

If FirstTime Then
FTP.Initialize("FTP", "10.0.0.52", 21, "android1", "pucara")
End If

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub FTP_UploadProgress (ServerPath As String, TotalUploaded As Long, Total As Long)
Dim s As String
s = "Uploaded " & Round(TotalUploaded / 1000) & "KB"
If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
Log(s)
End Sub

Sub FTP_UploadCompleted (ServerPath As String, Success As Boolean)
Log(ServerPath & ", Success=" & Success)
If Success = False Then Log(LastException.Message)
End Sub


Sub ToggleButton4_CheckedChange(Checked As Boolean)

End Sub
Sub ToggleButton3_CheckedChange(Checked As Boolean)

End Sub
Sub ToggleButton2_CheckedChange(Checked As Boolean)

End Sub
Sub ToggleButton1_CheckedChange(Checked As Boolean)

End Sub
Sub Button1_Click
' Button1.SetBackgroundImage ("img-pepe.bmp")
End Sub
Sub ImageView1_Click

End Sub
Sub Button1_Down

End Sub
Sub Button1_Up

End Sub
Sub Button1_LongClick
End Sub
Sub Button4_Click
Dim TextReader As TextReader
TextReader.Initialize(File.OpenInput(File.DirDefaultExternal, "datos.txt"))
Dim line As String
line = TextReader.ReadLine
Do While line <> Null
Log(line) 'write the line to LogCat
line = TextReader.ReadLine
Loop
TextReader.Close
End Sub
Sub Button3_Click
Dim Writer As TextWriter

Writer.Initialize(File.OpenOutput(File.DirDefaultExternal, "datos.txt", False))
Writer.WriteLine("Linea 1")
Writer.WriteLine("Linea 2")
Writer.Close
Msgbox("Grabó el archivo", "Graba archivo")

End Sub
Sub Button2_Click
FTP.UploadFile(File.DirDefaultExternal, "datos.txt", False, "1.txt")

Msgbox("Subió el archivo", "Ftp")
End Sub

el servidor ftp es "cerberus FTP server"
the error is when loading the file
the server receives the command, but after a few seconds stops
I am using the emulator



1.txt, Success=false

java.lang.RuntimeException: Error uploading file.
425 Unable to open the data connection

** Activity (main) Pause, UserClosed = true **
 
Last edited:

ppico

Member
Licensed User
Longtime User
2011-08-17 17:10:48]:COMMAND [ 1] - TYPE I
[2011-08-17 17:10:48]: REPLY [ 1] - 200 Type Binary

[2011-08-17 17:10:48]:COMMAND [ 1] - PORT 10,0,2,2,10,145
[2011-08-17 17:10:48]: REPLY [ 1] - 200 Port command received

[2011-08-17 17:10:48]:COMMAND [ 1] - STOR 1.txt
[2011-08-17 17:11:09]: ERROR [ 1] - Unable to connect : Se produjo un error durante el intento de conexión ya que la parte conectada no respondió adecuadamente tras un periodo de tiempo, o bien se produjo un error en la conexión establecida ya que el host conectado no ha podido responder.

[2011-08-17 17:11:09]:SUGGEST [ 1] - For help see Cerberus Cerberus FTP Server FAQ - Initial Setup
[2011-08-17 17:11:09]: REPLY [ 1] - 425 Unable to open the data connection

[2011-08-17 17:12:49]:CONNECT [ 1] - Connection timed out - Shutting down connection...
[2011-08-17 17:12:50]:CONNECT [ 1] - Connection terminated
 

bosscarnage

New Member
Licensed User
Longtime User
a newbie question :

I put both files ftp.jar and ftp.xml in my B4A libraries folder

1.jpg

but I still can't create a FTP object

2.jpg

Is there anything else to do in my project to get this library recognized ?

Thx
 

Fabrice La

Active Member
Licensed User
Longtime User
Error FTP Library

Hi,

In my project, the fact to check the FTP library (1.01) give me an compile error (Whithout to add anything in the program):

Compiling code. 0.18
Generating R file. 0.00
Compiling generated Java code. 0.97
Convert byte code - optimized dex. Error
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lorg/apache/commons/net/DatagramSocketClient;
at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
at com.android.dx.dex.file.DexFile.add(DexFile.java:143)
at com.android.dx.command.dexer.Main.processClass(Main.java:372)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:346)
at com.android.dx.command.dexer.Main.access$400(Main.java:59)
at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:294)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:130)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:108)
at com.android.dx.command.dexer.Main.processOne(Main.java:313)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:233)
at com.android.dx.command.dexer.Main.run(Main.java:185)
at com.android.dx.command.dexer.Main.main(Main.java:166)
at com.android.dx.command.Main.main(Main.java:90)
1 error; aborting
Standard dexer.
 

Fabrice La

Active Member
Licensed User
Longtime User
The library chesked are :
AHLocale 1.10
Camera 1.00
Core 1.57
Dioalogs 2.7
Licensing 1.00
Net 1.11
Phone 1.55
Reflection 1.8
SQL 1.02
StringUtils 1.02

If I add FTP 1.01 = Errors Compiling
 

Fabrice La

Active Member
Licensed User
Longtime User
Hi

Other problem :

if the system try to connect to ftp server I have a tempo of 20s. After this 20s
the program use FTP.closeNow
If I restart the connection the "success" is already "false" in
Sub FTP_DownloadCompleted (ServerPath As String, Success As Boolean)

I cant start to download.

I have to kill my appli and restart it to be able to try to download again.

It seems that the Sub FTP_DownloadCompleted (ServerPath As String, Success As Boolean) "Success" is stay at "false" .....

If you understand me ;)
 
Status
Not open for further replies.
Top