My goal is to write an app which runs on a handset and lets the user choose from a list of APK's, then installs the one selected to an Android Things device on the same network.
We can actually forget Android Things because the same code would work between two handsets, it's just that there it would be pointless because the target can just receive the APK in many other ways such as an attachment, BT etc. AT devices only have ADB for this, apart from the recently announced Android Things Console which is overkill for regular local development. I'm therefore looking to replicate the sequence a PC would go through to install it, i.e. "adb connect, adb install ..." etc but from the handset itself. We can assume all devices involved are rooted.
It seems to me this means my app has to issue these commands as a process, but I'm having a hard time getting it fully working. When I issue "adb help" I get back the help message, and when I issue "adb reboot" the device reboots, so I think I'm on the right lines. It's when I try anything apart from those I get nothing back - the example of "adb shell ping -c 1 192.168.62.40" fails, but is OK from ADB on the PC. Also, it's very curious "adb version" fails which again is OK from the terminal.
At first I thought the handsets might only have an "adb lite" installed which has just enough to get them to work as an adb target, but using a shell from a PC showed that's not the case.
Here's the code I'm trying:
Process process = Runtime.getRuntime().exec("su adb help");
//Process process = Runtime.getRuntime().exec("su adb reboot");
//Process process = Runtime.getRuntime().exec("su adb version");
//Process process = Runtime.getRuntime().exec("su adb shell ping -c 1 192.168.62.40");
process.waitFor();
Log.d("PROCESS", "Status: "+process.exitValue());
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder everything = new StringBuilder();
String line;
while( (line = bufferedReader.readLine()) != null) {
everything.append(line);
}
Log.d("PROCESS", "Process output: "+everything.toString());
Toast.makeText(MainActivity.this, everything.toString(), Toast.LENGTH_SHORT).show();
If multiple devices are running, you must specify the target device when you issue the adb command. To specify the target, use the devices command to get the serial number of the target. Once you have the serial number, use the -s option with the adb commands to specify the serial number.
The problem is that the adb
client (which you use to communicate to the ADB server which communicates to and from a device on a development machine) is not packaged on an Android device. The adbd
daemon, however, (used to communicate between the adb
client and the device) can and will be found on an Android system.
There are a few options to help use the adb
client on an Android device:
adb
client for an Android device from the adb
sources on GitHub.adb
"client". Since the adb
client and adbd
daemon communicate via USB or TCP, you could try emulating the communication protocols to open read/write streams on the device. More on the client-daemon communication protocols here. This library that I am working on might help you: eviltak/adb-nmap
The quick and dirty option is to build the adb
client from sources and push to the device. That is, if you can get it to build on an Android device.
The second option is probably the most time consuming, but can be the most "clean" choice. You will, however, have to emulate the adb
authentication system, properly handle streams and so on, which can be cumbersome. The source will help you.
In either case, the GitHub adb
source directory should have everything you need for the long road ahead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With