Ejecutar comandos de shell en Android usando Runtime.getRuntime

8

Estoy trabajando en una aplicación de administración de dispositivos (ha sido firmada por el fabricante). Lo estoy usando para instalar otras aplicaciones usando el siguiente comando adb shell para android 9: -

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

y lo estoy pasando así:

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

Pero me sale el error "gato desconocido opción S".

El mismo comando funciona perfectamente bien cuando lo ejecuto desde adb shell. No sé qué estoy haciendo mal y podría necesitar algo de ayuda.

EDITAR 1: - Intenté ejecutar el comando como a continuación: -

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

Pero ahora me sale el error: -

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)

Edición 2: - Antes de Android 9, podía hacer lo siguiente para instalar aplicaciones: -

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

Respuestas:

4

Mirando el código fuente de PackageInstallerSession descubrí que se había cambiado a: -

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

Fuente Por lo tanto, incluso si se trata de una aplicación del sistema, el comando de shell para la instalación podría no funcionar. Parece que a partir de los mensajes de confirmación, esto se hizo para permitir que PackageInstaller haga este trabajo.

Sin embargo, parece que esto cambió nuevamente en algún momento, pero probablemente no está incluido en 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");
            }

Fuente

Entonces, si la aplicación es una aplicación del sistema, entonces la mejor manera sería usar PackageInstaller.

sin nombre
fuente
Exactamente, verifique mi intento más delgado de borrar los datos del navegador de Android, a través de adb shell funciona bien, pero cuando lo hace pragmáticamente, incluso su aplicación del sistema o en dispositivos rooteados. estos cmd no están 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");
                }

Si su aplicación está bajo sistema / aplicación, tal vez tenga que ponerla en system / priv-app. Espero que el origen de la excepción te ayude de alguna manera.

Sina
fuente
Vi esto y el uid de llamada y el uid del sistema deberían ser los mismos. Además, el mensaje de error dice: - el modo inverso solo es compatible con shell. Entonces, tal vez algo cambió en Android p.
noname