Executando comandos de shell no Android usando Runtime.getRuntime

8

Estou trabalhando em um aplicativo de administração de dispositivos (foi assinado pelo fabricante). Estou usando-o para instalar outros aplicativos usando o comando adb shell abaixo para o Android 9: -

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

e estou passando assim: -

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

Mas eu recebo o erro "opção desconhecida gato S".

O mesmo comando funciona perfeitamente bem quando eu o executo no shell adb. Não sei o que estou fazendo de errado e poderia usar alguma ajuda.

EDIT 1: - Tentei executar o comando como abaixo: -

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

Mas agora eu recebo o erro: -

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)

Editar 2: - Antes do Android 9, eu podia fazer o seguinte para instalar aplicativos: -

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

Respostas:

4

Observando o código-fonte do PackageInstallerSession, descobri que ele foi alterado para: -

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");
    }

Origem Portanto, mesmo que seja um aplicativo do sistema, o comando shell para instalação pode não funcionar. A partir das mensagens de confirmação, isso foi feito para permitir que o PackageInstaller faça esse trabalho.

No entanto, parece que isso foi alterado novamente em algum momento, mas provavelmente não está incluído no 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");
            }

Fonte

Portanto, se o aplicativo for um sistema, a melhor maneira seria usar o PackageInstaller.

noname
fonte
Exatamente, verifique minha tentativa mais fina de limpar os dados do navegador Android, através do shell adb, funciona bem, mas quando o faz pragmaticamente até mesmo no aplicativo do sistema ou em dispositivos raiz. estes cmd não são permitidos, stackoverflow.com/questions/10934304/...
UdayaLakmal
1

de 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");
                }

Se o seu aplicativo estiver no sistema / aplicativo, talvez você precise colocá-lo no sistema / aplicativo privado. Espero que a origem da exceção ajude você de alguma forma.

Sina
fonte
Eu vi isso e o uid de chamada e o uid do sistema devem ser os mesmos. Além disso, a mensagem de erro diz: - modo reverso suportado apenas pelo shell. Então, talvez algo mudou no Android p.
Noname