2015-07-12 111 views
2

我目前正在開發一個應用程序,該應用程序可以打印遠程服務器目錄中的文件列表,並且可以單擊指定的文件並下載它。使用onClick從遠程服務器下載SFTP

到目前爲止,這是我:

public class MainActivity extends Activity { 


    private String user = "username"; 
    private String pass = "password"; 
    private String host = "hostname"; 
    private int portNum = 22; 

    private static final String SFTPWORKINGDIR = "/path/to/file"; 
    private String fileName; 

    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     final ListView list = (ListView)findViewById(R.id.choose_sound_listView); 

     new AsyncTask<Void, Void, List<String>>() { 
      @Override 
      protected List<String> doInBackground(Void... params) { 
       try { 
        return executeRemoteCommand(user, pass, host, portNum); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       return null; 
      } 

      @Override 
      public void onPostExecute(List<String> soundNames){ 
       ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_expandable_list_item_1, android.R.id.text1, soundNames); 
       list.setAdapter(adapter); 

       list.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

        @Override 
        public void onItemClick(AdapterView<?> arg0, View arg1, 
              int position, long arg3) { 

         String newFileName = (String) list.getItemAtPosition(position); 

         fileName = newFileName; 

         Downloader(fileName); 

         // Show Alert 
         Toast.makeText(getApplicationContext(), 
           "Downloaded " + fileName , Toast.LENGTH_LONG).show(); 
        } 
       }); 
      } 
     }.execute(); 
    } 

    public List<String> executeRemoteCommand(String username, String password, String hostname, int port) throws Exception { 

     List<String> soundNames = new ArrayList<String>(); 

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

     String command = "ls -la | awk '{ print $9}'"; 

     Channel channel = session.openChannel("exec"); 
     ((ChannelExec) channel).setCommand(command); 

     ((ChannelExec) channel).setErrStream(System.err); 

     InputStream in = channel.getInputStream(); 

     System.out.println("Connect to session..."); 
     channel.connect(); 

     StringBuffer buffer = new StringBuffer(); 

     //This is the recommended way to read the output 
     byte[] tmp = new byte[1024]; 
     while (true) { 
      while (in.available() > 0) { 
       int i = in.read(tmp, 0, 1024); 
       if (i < 0) { 
        break; 
       } 
       buffer.append(new String(tmp, 0, i)); 
      } 
      if (channel.isClosed()) { 
       System.out.println("exit-status: " + channel.getExitStatus()); 
       break; 
      } 
      try { 
       Thread.sleep(1000); 
      } catch (Exception ee) { 
      } 
     } 

     channel.disconnect(); 
     session.disconnect(); 

     Scanner scanner = new Scanner(buffer.toString()); 
     while (scanner.hasNextLine()){ 
      String line = scanner.nextLine(); 
      soundNames.add(line); 

      Log.i("SSH", ": " + line); 
     } 

     return soundNames; 
    } 


    public void Downloader(String fileName) { 

     JSch jsch = new JSch(); 
     Session session = null; 
     Channel channel = null; 
     ChannelSftp sftpChannel = null; 

     try { 

      session = jsch.getSession(user, host, portNum); 
      session.setConfig("StrictHostKeyChecking", "no"); 
      session.setPassword(pass); 
      session.connect(); 

      channel = session.openChannel("sftp"); 
      channel.connect(); 
      sftpChannel = (ChannelSftp) channel; 
      sftpChannel.cd(SFTPWORKINGDIR); //cd to dir that contains file 

      try { 
       byte[] buffer = new byte[1024]; 
       BufferedInputStream bis = new BufferedInputStream(sftpChannel.get(fileName)); 

       File path = Environment.getExternalStoragePublicDirectory(
         Environment.DIRECTORY_DOCUMENTS); 
       File newFile = new File(path, "/" + fileName); 

       Log.d("Dir" , " " + newFile); 

       OutputStream os = new FileOutputStream(newFile); 
       BufferedOutputStream bos = new BufferedOutputStream(os); 
       int readCount; 
       while((readCount = bis.read(buffer)) > 0) { 
        Log.d("Downloading", " " + fileName); 
        bos.write(buffer, 0, readCount); 
       } 
       bis.close(); 
       bos.close(); 

      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      Log.d("SUCCESS ", fileName + " has been downloaded!!!!"); 

      sftpChannel.exit(); 
      session.disconnect(); 

     } catch (JSchException e) { 
      e.printStackTrace(); 
     } catch (SftpException e) { 
      e.printStackTrace(); 
     } 
    } 


    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 
} 

但是,當我點擊在ListView的文件,我得到一絲錯誤:

com.jcraft.jsch。 JSchException:android.os.NetworkOnMainThreadException

編輯:上運行它背景的AsyncTask似乎修復錯誤,但如果我這樣做,除非硬編碼文件的名稱,否則該應用程序將無法下載指定的onClick文件。

任何人都知道我可以解決這個問題嗎?

+1

可能重複的線程中運行,你應該將任何網絡到doInBackground。 NetworkOnMainThreadException](http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception) –

回答

0

您在onPostExecute(List<String> soundNames)執行Downloader(String fileName)。但在主線程上執行。只有doInBackground()在單獨的線程上執行。將執行Downloader(String fileName)移至doInBackground()

編輯:或創建一個單獨的AsyncTask,它在自己的doInBackground()

+0

我能夠解決這個錯誤,在onPostExecute內製作一個新的AsyncTask。謝謝! – adventuredoge

0

您正在主應用程序線程上執行網絡I/O,如異常所示。如果您查看堆棧跟蹤,它會指出您在主應用程序線程上執行網絡I/O的確切位置。

最有可能來自Downloader()方法,因爲您確實正在使用該方法中的網絡I/O,並且該方法從onItemClick()調用,該方法本身在主應用程序線程中調用。請在後臺線程上執行此下載。

0

執行Downloader(String fileName)使其[android.os的的AsyncTask

相關問題