2013-01-14 41 views
13

Tôi đang cố gắng để làm một cái gì đó từ ví dụ này đơn giản:Simple SSH kết nối với JSch

SSH, execute remote commands with Android

Tôi chỉ muốn xem liệu tôi có thể kết nối từ điện thoại Android của tôi đến một máy chủ Linux sử dụng SSH nhưng nó doesn 't làm việc ...

Dưới đây là mã chính của tôi:

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()); 
    } 
} 
} 

tôi đã làm gì sai? Tôi không có thông báo lỗi và tôi không thấy bất kỳ kết nối SSH nào trên Linux của mình. Tôi đã thêm các thư viện jsch và jzlib. Tôi không có vấn đề gì để kết nối với một phiên putty.

EDIT1: Trên thực tế, tôi đã tìm thấy lỗi giải thích tại sao nó không hoạt động ngay cả khi tôi không biết cách giải quyết vấn đề. Lỗi này là:

android.os.NetworkOnMainThreadException

nên nó dường như có nghĩa là ứng dụng không thể thực hiện một hoạt động mạng về chủ đề chính của nó ...

Trả lời

16

Bạn có để thực thi mã trong một chủ đề khác để bạn không treo thread UI là những gì mà ngoại lệ có nghĩa là. Nếu chuỗi giao diện người dùng đang thực hiện cuộc gọi mạng, nó không thể vẽ lại giao diện người dùng để người dùng của bạn thấy giao diện người dùng bị đóng băng không phản hồi trong khi ứng dụng đang chờ cuộc gọi mạng kết thúc. Android muốn tránh những trải nghiệm người dùng xấu như thế này để nó ngăn bạn làm những việc như thế này bằng cách ném ngoại lệ này.

Phương thức onCreate() của bạn nên gọi một luồng khác (tôi khuyên bạn nên sử dụng AsyncTask trên luồng thô) để thực hiện kết nối SSH. Sau đó, khi nó được thực hiện nó có thể đăng các kết quả trở lại chủ đề giao diện người dùng và cập nhật giao diện người dùng ứng dụng của bạn một cách an toàn từ chuỗi giao diện người dùng. giải pháp

http://developer.android.com/reference/android/os/AsyncTask.html

+0

Cảm ơn ! Tôi sẽ thử giải pháp của bạn. – Pozinux

12

chubbsondubs là hoàn hảo. Tôi chỉ muốn chia sẻ mã mà tôi làm cho vấn đề này quá cho những người muốn có một giải pháp nhanh chóng:

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(); 
} 
0

Một giải pháp Kotlin:

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() 
} 

Trong build.gradle add:

dependencies { 
    ... 
    compile group: 'com.jcraft', name: 'jsch', version: '0.1.54' 
} 
Các vấn đề liên quan