Instalar / desinstalar do comando shell no Android

Eu quero implementar um silencioso installer-from-apk-file e unistaller-package no Android. O tópico foi amplamente discutido no SO e em outros lugares, mas não posso aplicar nenhum por algum motivo que esteja faltando. O escopo é obviamente difícil de alcançar porque, se for bem-sucedido, seria uma séria falha de segurança no Android. MAS, preciso implementá-lo para um projeto especial, não para o mercado consumidor. Existem duas abordagens:

para gerar uma ROM personalizada a partir de um código-fonte (AOSP ou Cyanogen mod, por exemplo), ajustando o instalador do PackageManager (na verdade apenas para remover as caixas de diálogo de aceitação do usuário).para fazer isso programaticamente, criando um processo como superusuário e executando um 'adb shell pm install'. Eu instalei anteriormente 'su' em / system / xbin e testei durante o tempo de execução que RootTools.rootIsAvailable ().

No primeiro caso, eu mergulhei no código-fonte do Froyo, mas entrei num beco sem saída com um método marcado pelo @hide. Para o segundo eu tentei pela primeira vez os comandos do terminal

adb shell pm install /mnt/sdcard/HelloAndroid.apk

e

adb shell pm uninstall com.example.helloandroid

Ambos funcionam bem. Então, usei o seguinte código, o desenvolvimento sendo testado em um emulador enraizado (2.2 - Froyo):

@Override
    public void onClick(View v) {
        switch (v.getId())
           {
              case R.id.btnInstall:
                  try {  
                      install = Runtime.getRuntime().exec("su\n");   
                      DataOutputStream os = new DataOutputStream(install.getOutputStream());
                      os.writeBytes("pm install /mnt/sdcard/HelloAndroid.apk\n"); 
                      os.writeBytes("exit\n"); 
                      os.flush();
                      install.waitFor();

                              if (install.exitValue() == 0) {  
                                  Toast.makeText(MainActivity.this, "Success!", Toast.LENGTH_LONG).show();
                              }  
                              else {  
                                  Toast.makeText(MainActivity.this, "Failure. Exit code: "+String.valueOf(install.exitValue()), Toast.LENGTH_LONG).show();
                              }
                  }
                  catch (InterruptedException e) {  
                      logError(e);
                  }
                  catch (IOException e) {  
                  logError(e);
                  } 
                  break;

              case R.id.btnUninstall:
                  try {
                      install = Runtime.getRuntime().exec("su\n"); 
                      install=Runtime.getRuntime().exec("pm uninstall "+txtPackageName.getText().toString()+"\n");

                } catch (Exception e) {
                    logError(e);
                }
                  break;
           }

    }

Para evitar erros de digitação e outros ajustes, codifiquei o parâmetro do arquivo apk do comando para a instalação; no caso 'R.id.btnInstall' o comando não é executado e a saída está em "Failure" com o valor de saída 1, significando que "a classe não pode ser encontrada"; Não sei o que isso significa ... Eu agradeço a sua ajuda!

EDITADO: Eu tenho a solução limpa, vou postar a resposta de A-Z, assim que eu tiver o tempo e o código na forma correta !!

questionAnswers(6)

yourAnswerToTheQuestion