From a1e55f06d8ee0b94fb8cf092d970cb8ca40bd526 Mon Sep 17 00:00:00 2001 From: Samuel Carlsson Date: Thu, 28 Apr 2016 13:09:49 +0200 Subject: [PATCH] Now possible to install packages easily. --- README.md | 5 +++ src/se/vidstige/jadb/Stream.java | 7 +++++ src/se/vidstige/jadb/managers/Bash.java | 11 +++++++ .../jadb/managers/PackageManager.java | 29 ++++++++++++++++-- ... platformBuildVersionName=_apkpure.com.apk | Bin 0 -> 3425 bytes .../jadb/test/PackageMangerTests.java | 8 +++++ 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/se/vidstige/jadb/managers/Bash.java create mode 100644 test/data/Tiniest Smallest APK ever_v' platformBuildVersionName=_apkpure.com.apk diff --git a/README.md b/README.md index b5a309f..11dd7fc 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,11 @@ It's very easy to send and receive files from your android device, for example a JadbDevice device = ... device.pull(new RemoteFile("/path/to/file.txt"), new File("file.txt")); +Some high level operations such as installing and uninstalling packages are also available. + + JadbDevice device = ... + new PackageManager(device).install(new File("/path/to/my.apk")); + ## Protocol Description ## An overview of the protocol can be found here: [Overview](https://github.com/cgjones/android-system-core/blob/master/adb/OVERVIEW.TXT) diff --git a/src/se/vidstige/jadb/Stream.java b/src/se/vidstige/jadb/Stream.java index db807db..5a1a31b 100644 --- a/src/se/vidstige/jadb/Stream.java +++ b/src/se/vidstige/jadb/Stream.java @@ -1,8 +1,10 @@ package se.vidstige.jadb; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.Charset; public class Stream { public static void copy(InputStream in, OutputStream out) throws IOException { @@ -13,4 +15,9 @@ public class Stream { } } + public static String readAll(InputStream input, Charset charset) throws IOException { + ByteArrayOutputStream tmp = new ByteArrayOutputStream(); + Stream.copy(input, tmp); + return new String(tmp.toByteArray(), charset); + } } diff --git a/src/se/vidstige/jadb/managers/Bash.java b/src/se/vidstige/jadb/managers/Bash.java new file mode 100644 index 0000000..3f2ef04 --- /dev/null +++ b/src/se/vidstige/jadb/managers/Bash.java @@ -0,0 +1,11 @@ +package se.vidstige.jadb.managers; + +public class Bash { + public static String quote(String s) { + // TODO: Should also check other whitespace + if (!s.contains(" ")) { + return s; + } + return "'" + s.replace("'", "'\\''") + "'"; + } +} diff --git a/src/se/vidstige/jadb/managers/PackageManager.java b/src/se/vidstige/jadb/managers/PackageManager.java index 905a9bb..a1aefc5 100644 --- a/src/se/vidstige/jadb/managers/PackageManager.java +++ b/src/se/vidstige/jadb/managers/PackageManager.java @@ -2,10 +2,10 @@ package se.vidstige.jadb.managers; import se.vidstige.jadb.JadbDevice; import se.vidstige.jadb.JadbException; +import se.vidstige.jadb.RemoteFile; +import se.vidstige.jadb.Stream; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @@ -37,4 +37,27 @@ public class PackageManager { } return result; } + + private String getErrorMessage(String operation, String target, String errorMessage) { + return "Could not " + operation + " " + target + ": " + errorMessage; + } + + private void verifyOperation(String operation, String target, String result) throws JadbException { + if (!result.contains("Success")) throw new JadbException(getErrorMessage(operation, target, result)); + } + + public void install(File apkFile) throws IOException, JadbException { + RemoteFile remote = new RemoteFile("/sdcard/tmp/" + apkFile.getName()); + device.push(apkFile, remote); + InputStream s = device.executeShell("pm", "install", Bash.quote(remote.getPath())); + String result = Stream.readAll(s, Charset.forName("UTF-8")); + // TODO: Remove remote file + verifyOperation("install", apkFile.getName(), result); + } + + public void uninstall(Package name) throws IOException, JadbException { + InputStream s = device.executeShell("pm", "uninstall", name.toString()); + String result = Stream.readAll(s, Charset.forName("UTF-8")); + verifyOperation("uninstall", name.toString(), result); + } } diff --git a/test/data/Tiniest Smallest APK ever_v' platformBuildVersionName=_apkpure.com.apk b/test/data/Tiniest Smallest APK ever_v' platformBuildVersionName=_apkpure.com.apk new file mode 100644 index 0000000000000000000000000000000000000000..966cb995d797a7ec6e1774cd2f4f3ae3e04c1401 GIT binary patch literal 3425 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 literal 0 HcmV?d00001 diff --git a/test/se/vidstige/jadb/test/PackageMangerTests.java b/test/se/vidstige/jadb/test/PackageMangerTests.java index d47e417..6c0a10d 100644 --- a/test/se/vidstige/jadb/test/PackageMangerTests.java +++ b/test/se/vidstige/jadb/test/PackageMangerTests.java @@ -7,6 +7,7 @@ import se.vidstige.jadb.JadbConnection; import se.vidstige.jadb.managers.Package; import se.vidstige.jadb.managers.PackageManager; +import java.io.File; import java.io.IOException; import java.util.List; @@ -37,4 +38,11 @@ public class PackageMangerTests { System.out.println(p); } } + + @Test + public void testInstallUninstallCycle() throws Exception { + File f = new File("test/data/Tiniest Smallest APK ever_v' platformBuildVersionName=_apkpure.com.apk"); + pm.install(f); + pm.uninstall(new Package("b.a")); + } }