Android升级OpenWrt固件

有这么一个需求,需要通过Android升级OpenWrt的固件(Firmware)。参考OpenWrt提供的升级方案,可以使用SSHscp命令将固件上传到路由器的/tmp目录下,然后执行命令sysupgrade -v /tmp/firmware_name.bin升级固件。

Android中使用SSH

The SSH protocol uses encryption to secure the connection between a client and a server. All user authentication, commands, output, and file transfers are encrypted to protect against attacks in the network.

站在巨人的肩膀上,不要重复造轮子。Ganymed SSH-2是一个实现了SSH-2协议的Java库,解压ganymed-ssh2-build210.zip,将里面的jar包导入自己的Android项目的libs目录下,并在Module的build.gradle文件中添加如下代码:

1
2
3
4
5
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
... ...
implementation files('libs/ganymed-ssh2-build210.jar')
}

这个时候就可以在项目中愉快地使用SSH了。

升级固件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public static boolean upgradeFirmware(String hostname, String username,String password ,String firmwarePath) {
File firmware = new File(firmwarePath);

try {
/* Create a connection instance */
Connection conn = new Connection(hostname);

/* Now connect */
conn.connect();

/* Authenticate.
* If you get an IOException saying something like
* "Authentication method password not supported by the server at this stage."
* then please check the FAQ.
*/
boolean isAuthenticated = conn.authenticateWithPassword(username, password);

if (!isAuthenticated)
throw new IOException("Authentication failed.");

/* Create a scp client */
SCPClient scpClient = conn.createSCPClient();

/* Upload firmware file to remote's /tmp */
scpClient.put(firmware.getAbsolutePath(), "/tmp");

/* Create a session */
Session session = conn.openSession();

/* Upgrade firmware */
session.execCommand("sysupgrade -v /tmp/" + firmware.getName());

/*
* This basic example does not handle stderr, which is sometimes dangerous
* (please read the FAQ).
*/
InputStream stdout = new StreamGobbler(session.getStdout());

BufferedReader br = new BufferedReader(new InputStreamReader(stdout));

while (true) {
String line = br.readLine();
if (line == null)
break;
System.out.println(line);
}

/* Show exit status, if available (otherwise "null") */
System.out.println("ExitCode: " + session.getExitStatus());

/* Close this session */
session.close();

/* Close the connection */
conn.close();

return true;
} catch (IOException e) {
e.printStackTrace(System.err);

return false;
}
}

代码很简单,这里就不做过多解释了。但是升级固件并不一定会成功,如路由器的空间不足以存放新的固件时。

参考文档

  1. 在Android 中实现scp操作
  2. OpenWrt OS upgrade procedure (LuCI or sysupgrade)