J'essaie de faire quelque chose à partir de cet exemple simple:
SSH, exécuter des commandes à distance avec Android
Je veux juste voir si je peux me connecter depuis mon téléphone Android à un serveur Linux en utilisant SSH, mais cela ne fonctionne pas ...
Voici mon code principal:
package com.example.ssh;
import Java.util.Properties;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import Android.os.Bundle;
import Android.app.Activity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try
{
JSch jsch = new JSch();
Session session = jsch.getSession("root","192.168.0.26", 22);
session.setPassword("xxxxx");
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
Qu'ai-je fait de mal ? Je n'ai aucun message d'erreur et je ne vois aucune connexion SSH sur mon Linux. J'ai ajouté les bibliothèques jsch et jzlib. Je n'ai aucun problème pour me connecter avec une session PuTTY.
EDIT1: En fait, j'ai trouvé une erreur qui explique pourquoi cela ne fonctionne pas, même si je ne sais pas comment résoudre le problème. L'erreur est:
Android.os.NetworkOnMainThreadException
cela semble donc vouloir dire que l'application ne peut pas effectuer d'opération de réseau sur son thread principal ...
Vous devez exécuter ce code dans un autre thread afin de ne pas bloquer le thread d'interface utilisateur, c'est ce que cette exception signifie. Si le thread d'interface utilisateur exécute un appel réseau, il ne peut pas repeindre l'interface utilisateur. Vos utilisateurs voient alors une interface utilisateur figée qui ne leur répond pas pendant que l'application attend l'appel du réseau pour se terminer. Android veut éviter de mauvaises expériences utilisateur comme celle-ci afin d'éviter de faire de telles choses en lançant cette exception.
Votre méthode onCreate () doit appeler un autre thread (je suggérerais d'utiliser une AsyncTask sur un thread brut) pour établir la connexion SSH. Ensuite, une fois terminé, il peut publier les résultats dans le thread d'interface utilisateur et mettre à jour en toute sécurité l'interface utilisateur de votre application à partir du thread d'interface utilisateur.
http://developer.Android.com/reference/Android/os/AsyncTask.html
la solution de chubbsondubs est parfaite. Je veux juste partager le code que j'ai créé pour ce problème aussi pour les gens qui veulent une solution rapide:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AsyncTask<Integer, Void, Void>(){
@Override
protected Void doInBackground(Integer... params) {
try {
executeRemoteCommand("root", "myPW","192.168.0.26", 22);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}.execute(1);
}
public static String executeRemoteCommand(String username,String password,String hostname,int port)
throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
ChannelExec channelssh = (ChannelExec)
session.openChannel("exec");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelssh.setOutputStream(baos);
// Execute command
channelssh.setCommand("lsusb > /home/pi/test.txt");
channelssh.connect();
channelssh.disconnect();
return baos.toString();
}
A Kotlin solution:
import Android.os.AsyncTask
import Android.os.Bundle
import Android.support.v7.app.AppCompatActivity
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import Java.io.ByteArrayOutputStream
import Java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
SshTask().execute()
}
class SshTask : AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg p0: Void?): String {
val output = executeRemoteCommand("demo", "password", "test.rebex.net")
print(output)
return output
}
}
}
fun executeRemoteCommand(username: String,
password: String,
hostname: String,
port: Int = 22): String {
val jsch = JSch()
val session = jsch.getSession(username, hostname, port)
session.setPassword(password)
// Avoid asking for key confirmation.
val properties = Properties()
properties.put("StrictHostKeyChecking", "no")
session.setConfig(properties)
session.connect()
// Create SSH Channel.
val sshChannel = session.openChannel("exec") as ChannelExec
val outputStream = ByteArrayOutputStream()
sshChannel.outputStream = outputStream
// Execute command.
sshChannel.setCommand("ls")
sshChannel.connect()
// Sleep needed in order to wait long enough to get result back.
Thread.sleep(1_000)
sshChannel.disconnect()
session.disconnect()
return outputStream.toString()
}
Dans build.gradle
ajouter:
dependencies {
...
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
}