【问题标题】:Running shell commands on Android using Runtime.getRuntime使用 Runtime.getRuntime 在 Android 上运行 shell 命令
【发布时间】:2019-11-28 13:04:08
【问题描述】:

我正在开发一个设备管理应用程序(已由制造商签名)。我正在使用它来安装其他应用程序,使用以下适用于 android 9 的 adb shell 命令:-

cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293

我只是这样传递它:-

String command = "cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293"
Runtime.getRuntime().exec(command);

但我收到错误“猫未知选项 S”。

当我从 adb shell 运行相同的命令时,它运行得非常好。 不知道我做错了什么,可以使用一些帮助。

编辑 1:- 我尝试运行如下命令:-

String[] commandInstall = {
                "/system/bin/sh",
                "-c",
                "cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293"
        };
Process process = Runtime.getRuntime().exec(commandInstall);

但现在我得到了错误:-

ava.lang.SecurityException: Reverse mode only supported from shell
    at com.android.server.pm.PackageInstallerSession.doWriteInternal(PackageInstallerSession.java:679)
    at com.android.server.pm.PackageInstallerSession.write(PackageInstallerSession.java:612)
    at android.content.pm.PackageInstaller$Session.write(PackageInstaller.java:852)
    at com.android.server.pm.PackageManagerShellCommand.doWriteSplit(PackageManagerShellCommand.java:2447)
    at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:915)
    at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:158)
    at android.os.ShellCommand.exec(ShellCommand.java:103)
    at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21330)
    at android.os.Binder.shellCommand(Binder.java:634)
    at android.os.Binder.onTransact(Binder.java:532)
    at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2821)
    at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3856)
    at android.os.Binder.execTransact(Binder.java:731)

编辑 2:- 在 android 9 之前,我可以执行以下操作来安装应用程序:-

Runtime.getRuntime().exec("pm install -r app.apk");

【问题讨论】:

    标签: java android shell adb


    【解决方案1】:

    查看PackageInstallerSession的源码发现改成了:-

    switch (Binder.getCallingUid()) {
        case android.os.Process.SHELL_UID:
        case android.os.Process.ROOT_UID:
            break;
        default:
            throw new SecurityException("Reverse mode only supported from shell");
        }
    

    Source 因此,即使是系统应用程序,安装的 shell 命令也可能不起作用。从提交消息看来,这样做是为了让 PackageInstaller 完成这项工作。

    然而,这似乎在某个时候又被更改为,但可能不包含在 android 9 中:-

        switch (Binder.getCallingUid()) {
                    case android.os.Process.SHELL_UID:
                    case android.os.Process.ROOT_UID:
                    case android.os.Process.SYSTEM_UID:
                        break;
                    default:
                        throw new SecurityException(
                                "Reverse mode only supported from shell or system");
                }
    

    Source

    所以如果应用程序是系统应用程序,那么最好的方法是使用 PackageInstaller。

    【讨论】:

    • 确切地说,检查我尝试通过 adb shell 清除 android 浏览器数据的更苗条的尝试,但什么时候可以实用地执行它,即使是它的系统应用程序或 root 设备。这些 cmd 是不允许的,stackoverflow.com/questions/10934304/…
    【解决方案2】:

    来自 PackageInstallerSession.java:

    switch (Binder.getCallingUid()) {
                        case android.os.Process.SHELL_UID:
                        case android.os.Process.ROOT_UID:
                        case android.os.Process.SYSTEM_UID:
                            break;
                        default:
                            throw new SecurityException(
                                    "Reverse mode only supported from shell or system");
                    }
    

    如果您的应用在 system/app 下,您可能必须将其放在 system/priv-app 中。希望异常的起源对您有所帮助。

    【讨论】:

    • 我确实看到了这个,调用 uid 和系统 uid 应该是一样的。此外,错误消息说:- 仅外壳支持反向模式。所以也许 android p 发生了一些变化。
    猜你喜欢
    • 2019-09-01
    • 2014-01-11
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 2012-05-03
    相关资源
    最近更新 更多