B4A Library Android SFTP based on JSch tutorial

JSch is an open source Java implementation of SSH2. It supports many features.

Currently the Basic4android JSch library supports the SFTP protocol which is SSH File Transfer Protocol or Secured File Transfer Protocol.

SFTP is similar to FTP with the difference that the communication is done over a secured channel.

A good tutorial about SSH authentication is available here: SSH Host Key Protection | Symantec Connect Community

When the client first connects to the SSH server he needs to approve the host key (unless it is in the list of approved keys).

SS-2013-03-05_12.08.04.png


The SFtp object raises a PromptYesNo event for this question:
B4X:
Sub sftp1_PromptYesNo (Message As String)
   Dim res As Int = Msgbox2(Message, "", "Yes", "", "No", Null)
   'The next line might be a bit confusing. It is a condition.
   'The value will be True if res equals to DialogResponse.POSITIVE.
   sftp1.SetPromptResult(res = DialogResponse.POSITIVE)
End Sub
The network thread will wait until you call SetPromptResult or after 60 seconds. In the later case the result will be False.

If you want to automatically accept the host key (which should only be done in a secured local network) then you can write:
B4X:
Sub sftp1_PromptYesNo (Message As String)
   sftp1.SetPromptResult(True)
End Sub

Sftp should be declared as a process global variable and initialized in Activity_Create (or Service_Create):
B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      sftp1.Initialize("sftp1", "username", "password", "example.com", 22)
      sftp1.SetKnownHostsStore(File.DirInternal, "hosts.txt")
   End If
   Activity.LoadLayout("1")
End Sub

Calling SetKnownHostsStore sets a file that will save the known keys. Without it the user will need to approve the key each time.

In Activity_Resume we need to call SFtp.Activity_Resume:
B4X:
Sub Activity_Resume
   sftp1.Activity_Resume
End Sub
The purpose of this call is to redisplay the visible prompt if it was visible when the activity was paused. This is relevant for example when the user changes the orientation while the dialog is visible.

SFtp can also show a message to the user in some cases. This is done with the ShowMessage event:
B4X:
Sub sftp1_ShowMessage (Message As String)
   Msgbox(Message, "")
End Sub

The other methods work in the same way as the FTP object: Android FTP tutorial

The library is attached. The open source project is embedded in the jar file.

Updates:
1.31 - New Rmdir method - deletes empty folders.
1.30 - Based on the latest version of Jsch (0.1.54).
 

Attachments

  • JSch.zip
    274.1 KB · Views: 210
Last edited:

Yuretz2

Member
Licensed User
Longtime User
Please try this update (v1.20). It includes a new Mkdir method.
It work's! And fires "CommandCompleted" event, with "Command" and "Success" fields, but "Reply" field is empty. It's not critical for me right now, but my be useful for other user's.
Thank You very much! B4A support is brilliant.
 

Yuretz2

Member
Licensed User
Longtime User
Hi, Erel. As I know, this library uses
version 0.1.49 of JSch. It works great, but sometimes I can see in my server logs error messages like "bad packet". Is it possible to update this library to the latest
version 0.1.53 of JSch? Thank you.
 
Last edited:

Yuretz2

Member
Licensed User
Longtime User
I'm using this lib in a service module. I'm initializing sftp and call yes_no in service_create. sftp.close is in service_destroy . is that correct?
 

Yuretz2

Member
Licensed User
Longtime User
I've updated the library. It is based on version 0.1.54.
With new library got this error while compile:
B4A version: 6.31
Parsing code. (0.06s)
Compiling code. (0.06s)
Compiling layouts code. (0.02s)
Organizing libraries. (0.00s)
Generating R file. (0.06s)
Compiling generated Java code. (1.97s)
Convert byte code - optimized dex. Error
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lcom/jcraft/jsch/Buffer;
at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:122)
at com.android.dx.dex.file.DexFile.add(DexFile.java:161)
at com.android.dx.command.dexer.Main.processClass(Main.java:615)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:570)
at com.android.dx.command.dexer.Main.access$2(Main.java:546)
at com.android.dx.command.dexer.Main$2.processFileBytes(Main.java:514)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:537)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:449)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:236)
at com.android.dx.command.dexer.Main.run(Main.java:206)
at com.android.dx.command.dexer.Main.main(Main.java:179)
at com.android.dx.command.Main.main(Main.java:103)
1 error; aborting
 

MarcRB

Active Member
Licensed User
Longtime User
In a big project I still get this error:

An error has occurd in sub:
java.lang.Exception: Sub sftpupdw_listcompleted signature does not match expected signature. Continue? Yes / no



In a small test connected to the same server, I didn't get this error.
But the sFTP part of the code is like identical in both projects and identical to the given example on the first page of this topic. Strange!

Could it be a difference between the stored host file and the real host information? (from early test)
I use sFTPupdw.SetKnownHostsStore(File.DirInternal, "hosts.txt").

I changed already the filename and I deleted the existing file. But still get this error on listcompleted.

Do you have any suggestions?
 
Top