20

この簡単な例から何かを作ろうとしています:

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

アプリがメインスレッドでネットワーク操作を実行できないことを意味しているようです...

4

3 に答える 3

23

UIスレッドがハングしないように、別のスレッドでそのコードを実行する必要があります。これは、その例外の意味です。UI スレッドがネットワーク呼び出しを実行している場合、UI を再描画できないため、アプリがネットワーク呼び出しの終了を待機している間、応答しないフリーズした UI がユーザーに表示されます。Android は、このような悪いユーザー エクスペリエンスを回避したいため、この例外をスローすることで、このようなことを行うことを防ぎます。

SSH 接続を実行するには、 onCreate() メソッドで別のスレッドを呼び出す必要があります (生のスレッドで AsyncTask を使用することをお勧めします)。それが完了すると、結果を UI スレッドに戻して、UI スレッドからアプリケーションの UI を安全に更新できます。

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

于 2013-01-14T19:03:59.320 に答える
8

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

加えbuild.gradleて:

dependencies {
    ...
    compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
}
于 2018-02-08T02:47:26.600 に答える