簡體   English   中英

使用SSH將文件從android應用發送到raspberry pi

[英]Sending a file from android application to raspberry pi using SSH

我正在嘗試通過WIFI將文件從Android應用程序發送到RaspberryPi。

我可以連接到RPI並通過SSH發送命令。

這是我用來發送ssh命令的功能:

public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
            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("scp " + file + " " + username + "@" + hostname + ":/home/pi/Desktop");
        channelssh.connect();
        try{Thread.sleep(5000);}catch(Exception ee){}
        channelssh.disconnect();
        return baos.toString();
    }

這是將要發送的SSH命令

scp /storage/emulated/0/Download/201906071017.txt pi@192.168.4.1:/home/pi/Desktop

我嘗試在Windows終端上運行SSH命令,它成功上傳了文件

編輯:

我在.disconnect() .connect().disconnect()之間添加了此代碼,以等待直到收到命令的響應以斷開與RPi的連接

        channelssh.setErrStream(System.err);

        InputStream in=channelssh.getInputStream();

        channelssh.connect();

        byte[] tmp=new byte[1024];
        while(true){
            while(in.available()>0){
                int i=in.read(tmp, 0, 1024);
                if(i<0)break;
                System.out.print(new String(tmp, 0, i));
            }
            if(channelssh.isClosed()){
                if(in.available()>0) continue;
                System.out.println("exit-status: "+channelssh.getExitStatus());
                break;
            }
            try{Thread.sleep(1000);}catch(Exception ee){}
        }

        channelssh.disconnect();

現在,我在日志中被拒絕權限,用戶名和密碼正確。

W/System.err: Permission denied, please try again.
W/System.err: Permission denied, please try again.
W/System.err: Permission denied (publickey,password).
W/System.err: lost connection
I/System.out: exit-status: 1

我做的!! 我最終使用sftp服務上傳了我使用ChannelSshChannelExec的文件。 我應該使用ChannelSftp

這是工作代碼

package com.example.a.sitetool;

import android.util.Log;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class RpiUpdate {


    public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
            throws Exception {

        Log.d("MainActivity", "Entered executeRemoteCommand");

        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
        Channel channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp channelsftp = (ChannelSftp) channel;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        channelsftp.cd("/home/pi/Desktop");
        channelsftp.put(new FileInputStream(file), file.getName());
        channelsftp.setOutputStream(baos);

        // Execute command
        channelsftp.put(file.getName(),"/home/pi/Desktop");

        InputStream in=channelsftp.getInputStream();

        byte[] tmp=new byte[1024];
        while(true){
            while(in.available()>0){
                int i=in.read(tmp, 0, 1024);
                if(i<0)break;
                System.out.print(new String(tmp, 0, i));
            }
            if(channelsftp.isClosed()){
                if(in.available()>0) continue;
                System.out.println("exit-status: "+channelsftp.getExitStatus());
                break;
            }
            try{Thread.sleep(1000);}catch(Exception ee){}
        }

        channel.disconnect();

        return baos.toString();
    }
}

編輯:我優化了代碼,並刪除了ByteArrayOutputStream ,因為Channelsftp不需要它。 此更改導致返回void而不是String我還添加了更改輸出文件權限的功能。

package com.example.a.sitetool;

import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;

public class RpiUpdate {
    private static boolean success;


    public static void update() {
        //TODO add online version checking and download
        if (success)
            uploadFile();

    }

    private static void uploadFile() {
        Log.d("RPIUpdate", "Entered upload File");
        success=false;
        new AsyncTask<Integer, Void, Void>() {
            @Override
            protected Void doInBackground(Integer... params) {
                try {
                    executeRemoteCommand("pi", "rbs", "192.168.4.1", 22);
                    Log.d("MainActivity", "File Uploaded");
                    success = true;
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("MainActivity", "Failed to upload file");
                    success = false;
                }
                return null;
            }
        }.execute(1);
    }


public static void executeRemoteCommand(final String username, final String password, final String hostname, final int port)
            throws Exception {
        Log.d("RPiUpdate", "Entered executeRemoteCommand");

        //Creating the path on android to bbserver.py
        File root;
        root = new File(Environment.getExternalStorageDirectory() + File.separator + "Download");
        if (!root.exists()) {
            root.mkdirs();
        }
        File file = new File(root, "bbserver.py");

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

        //SFTP setup
        Channel channel = session.openChannel("sftp");
        channel.connect();

        ChannelSftp channelsftp = (ChannelSftp) channel;
        //Renaming the old bbserver.py
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd:HH:mm", Locale.ENGLISH);
        Date now = new Date();
        channelsftp.cd("/home/pi/Desktop");
        // 384 in octal is 600. This makes the file non executable. only readable and writable

        channelsftp.chmod(384, "/home/pi/Desktop/bbserver.py");

        channelsftp.rename("/home/pi/Desktop/bbserver.py", "/home/pi/Desktop/bbserver" + formatter.format(now) + ".py");

        //sending the new bbserver.py file
        channelsftp.put(new FileInputStream(file), file.getName());
        Log.d("RPiUpdate", "Sent file");

        //511 in octal is 777. This gives the file all available permissions(read, write, execute). thus making the file an executable

        channelsftp.chmod(511, "/home/pi/Desktop/" + file.getName());
        Log.d("RPiUpdate", "Changed permissions");

        channel.disconnect();

    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM