我正在尝试通过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命令,它成功上传了文件
编辑:
我在.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
答案 0 :(得分:1)
我做到了!
我最终使用sftp服务上传了文件
我在ChannelSsh
中使用ChannelExec
。我应该使用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();
}