我想从这个简单的例子做的东西:
SSH,执行与Android远程命令
我只是想看看我能不能从我的Android手机使用SSH连接到Linux服务器,但它不工作...
这是我主要的代码:
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());
}
}
}
我做错了什么 ? 我没有任何错误信息,我不看在我的Linux任何SSH连接。 我加入了库jsch和jzlib。 我没有问题得到连接用油灰会议。
EDIT1:事实上,我发现这解释了为什么它,即使我不知道如何解决这个问题不能正常工作的错误。 错误是:
android.os.NetworkOnMainThreadException
所以这似乎也意味着应用程序不能在其主线程进行联网操作...
你必须在另一个线程来执行代码,这样你就不会挂在UI线程是例外的意思。 如果UI线程执行网络调用,以便您的用户看到,而应用程序是在网络上调用完成等待不回应他们冻结的UI不能重新绘制UI。 Android的希望避免这样的坏的用户体验,因此它阻止你通过抛出该异常做这样的事情。
您的onCreate()方法应该调用另一个线程(我建议使用的AsyncTask在原纱)进行SSH连接。 然后,当它完成它可以后的结果返回给用户界面线程和安全地从UI线程更新应用程序的UI。
http://developer.android.com/reference/android/os/AsyncTask.html
chubbsondubs的解决方案是完美的。 我想和大家分享我对这个问题做出过谁想要一个快速的解决方案的人的代码:
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();
}
一个科特林的解决方案:
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()
}
在build.gradle
补充:
dependencies {
...
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
}