Instalar aplicaciones en silencio, con el permiso INSTALL_PACKAGES concedido

Estoy tratando de instalar silenciosamente apk en el sistema. Mi aplicación se encuentra en / system / app y se ha concedido permiso correctamente "android.permission.INSTALL_PACKAGES"

Sin embargo, no puedo encontrar en ningún lugar cómo utilizar este permiso. Traté de copiar archivos a / data / app y no tuvo éxito. También he intentado usar este código

Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType( Uri.parse("file:///sdcard/app.apk"), "application/vnd.android.package-archive"); startActivity(intent); 

Pero este código abre diálogo de instalación estándar. ¿Cómo puedo instalar la aplicación en silencio sin root con android.permission.INSTALL_PACKAGES concedido?

PS Estoy escribiendo una aplicación que instalará muchos apks de la carpeta en el sistema en el primer inicio (reemplace el asistente de configuración). Lo necesito para hacer el firmware más ligero.

Si piensa que estoy escribiendo un virus: Todos los programas están instalados en / data / app. Permiso Los paquetes_instalación sólo se pueden conceder a los programas de nivel de sistema ubicados en / system / app o firmados con la clave del sistema. Así que el virus no puede llegar allí.

Como se ha dicho http://www.mail-archive.com/[email protected]/msg06281.html las aplicaciones PUEDEN ser instaladas en silencio si tienen permiso de install_packages. Además, no necesita el permiso Install_packages para instalar los paquetes de forma silenciosa. Más http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html

Su primera apuesta es mirar en PackageInstaller nativo de Android. Yo recomendaría modificar la aplicación de la forma que desee, o simplemente extraer la funcionalidad necesaria.


Específicamente, si observa PackageInstallerActivity y su método onClickListener :

  public void onClick(View v) { if(v == mOk) { // Start subactivity to actually install the application Intent newIntent = new Intent(); ... newIntent.setClass(this, InstallAppProgress.class); ... startActivity(newIntent); finish(); } else if(v == mCancel) { // Cancel and finish finish(); } } 

Entonces notará que el instalador real se encuentra en la clase InstallAppProgress . Inspeccionando esa clase encontrarás que initView es la función de instalador central, y lo último que hace es llamar a la función installPackage PackageManager :

 public void initView() { ... pm.installPackage(mPackageURI, observer, installFlags, installerPackageName); } 

El siguiente paso es inspeccionar PackageManager , que es clase abstracta. Encontrarás installPackage(...) allí. La mala noticia es que está marcada con @hide. Esto significa que no está disponible directamente (no podrá compilar con la llamada a este método).

  /** * @hide * .... */ public abstract void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName); 

Pero podrá acceder a estos métodos a través de la reflexión.

Si está interesado en cómo se implementa la función installPackage PackageManager , eche un vistazo a PackageManagerService .

Resumen

Tendrá que obtener el objeto del gestor de paquetes a través de getPackageManager() Context . A continuación, llamará a la función installPackage mediante la reflexión.

He comprobado cómo ADB instala aplicaciones.
– Copia el APK a / data / local / tmp
– ejecuta 'shell: pm install /data/local/tmp/app.apk'

He intentado replicar este comportamiento haciendo: (en pc, usando el usb-cable)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
Esto funciona. La aplicación está instalada.

Hice una aplicación (llamada AppInstall) que debería instalar la otra aplicación.
(Instalado normalmente, dispositivo no enraizado)
Lo hace:
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
Pero esto da el error:
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
Parece que el error es lanzado por pm, no por AppInstall.
Debido a que la excepción de seguridad no se captura por AppInstall y la aplicación no se bloquea.

He intentado lo mismo en un dispositivo con raíz (la misma aplicación y AppInstall) y funcionó como un encanto.
(También se instala normalmente, no en / system o nada)
AppInstall ni siquiera pidió permiso de root.
Pero eso es porque el shell siempre es # lugar de $ en ese dispositivo.

Por cierto, necesita root para instalar una aplicación en / system, correcto?
He intentado remontar adb en el dispositivo no arraigado y tiene:
remount failed: Operation not permitted.
Por eso no pude probar la cosa / system en el dispositivo no enraizado.

Conclusión: debe utilizar un dispositivo enraizado
Espero que esto ayude 🙂

Debe definir

 <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

En su manifiesto, entonces si si está en la partición del sistema (/ system / app) o tiene su aplicación firmada por el fabricante, va a tener el permiso de INSTALL_PACKAGES.

Mi sugerencia es crear un pequeño proyecto androide con nivel de compatibilidad 1.5 utilizado para llamar a installPackages a través de la reflexión y para exportar un jar con métodos para instalar paquetes y llamar a los métodos reales. Luego, al importar el frasco en su proyecto, estará listo para instalar paquetes.

No tenía ni idea de cómo hacer esto, porque nadie respondió a esa hora, y no encontré documentación sobre este permiso. Así que encontré mi propia solución. Es worser que el suyo, pero esto es una solución de todos modos.

He instalado busybox, que establece 777 permiso para / data / app (no me importa la seguridad). A continuación, acaba de ejecutar "busybox install" de la aplicación. Esto funciona, pero tiene una gran fuga de seguridad. Si establece permisos 777, no se necesita root.

Aquí hay un post muy agradable sobre este tema. Me ayudó mucho.

Simplemente puede usar el comando adb install para instalar / actualizar APK en silencio. El código de ejemplo está por debajo

 public static void InstallAPK(String filename){ File file = new File(filename); if(file.exists()){ try { String command; filename = StringUtil.insertEscape(filename); command = "adb install -r " + filename; Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } } } 

He probado en arraigada Android 4.2.2 y este método funciona para mí:

 private void installApk(String filename) { File file = new File(filename); if(file.exists()){ try { final String command = "pm install -r " + file.getAbsolutePath(); Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } } } 

Puede usar la API oculta android.content.pm.IPackageInstallObserver por reflexión:

 public class PackageManagement { public static final int INSTALL_REPLACE_EXISTING = 0x00000002; public static final int INSTALL_SUCCEEDED = 1; private static Method installPackageMethod; private static Method deletePackageMethod; static { try { installPackageMethod = PackageManager.class.getMethod("installPackage", Uri.class, IPackageInstallObserver.class, Integer.TYPE, String.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public static void installPackage(PackageManager pm, Uri mPackageUri, IPackageInstallObserver observer, int installFlags, String installerPackageName) { try { installPackageMethod.invoke(pm, mPackageUri, observer, installFlags, installerPackageName); } catch (Exception e) { e.printStackTrace(); } } } 

Importe android.content.pm.IPackageInstallObserver en su proyecto. Su aplicación debe ser el sistema. Debe activar el permiso android.permission.INSTALL_PACKAGES en el archivo de manifiesto.

He estado implementando la instalación sin el consentimiento del usuario recientemente – era una aplicación de kiosco para el nivel de la API 21 + donde tenía control total sobre el medio ambiente.

Los requisitos básicos son:

  • Nivel de API 21+
  • Root para instalar el actualizador como una aplicación privilegiada del sistema.

El siguiente método lee e instala APK de InputStream:

 public static boolean installPackage(Context context, InputStream in, String packageName) throws IOException { PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); params.setAppPackageName(packageName); // set params int sessionId = packageInstaller.createSession(params); PackageInstaller.Session session = packageInstaller.openSession(sessionId); OutputStream out = session.openWrite("COSU", 0, -1); byte[] buffer = new byte[65536]; int c; while ((c = in.read(buffer)) != -1) { out.write(buffer, 0, c); } session.fsync(out); in.close(); out.close(); Intent intent = new Intent(context, MainActivity.class); intent.putExtra("info", "somedata"); // for extra data if needed.. Random generator = new Random(); PendingIntent i = PendingIntent.getActivity(context, generator.nextInt(), intent,PendingIntent.FLAG_UPDATE_CURRENT); session.commit(i.getIntentSender()); return true; } 

El código siguiente llama a la instalación

  try { InputStream is = getResources().openRawResource(R.raw.someapk_source); installPackage(MainActivity.this, is, "com.example.apk"); } catch (IOException e) { Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); } 

Para que todo funcione necesitas desesperadamente permiso de INSTALL_PACKAGES , o el código anterior fallará silenciosamente

 <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 

Para obtener este permiso debe instalar su APK como aplicación del sistema que REQUIERE root (sin embargo, después de haber instalado su aplicación de actualización que parecen trabajar sin raíz)

Para instalar como aplicación del sistema, creé un APK firmado y lo empujé con

 adb push updater.apk /sdcard/updater.apk 

Y luego se trasladó a system/priv-app – que requiere volver a montar FS (es por eso que la raíz es necesario)

 adb shell su mount -o rw,remount /system mv /sdcard/updater.apk /system/priv-app chmod 644 /system/priv-app/updater.apk 

Por alguna razón no funcionó con la versión de depuración simple, pero logcat muestra información útil si su aplicación en priv-app no es recogido por alguna razón.

Hice una aplicación de prueba para instalaciones silenciosas, utilizando el método PackageManager.installPackage.

Consigo el método del installPackage con la reflexión, e hice la interfaz de android.content.pm.IPackageInstallObserver en mi carpeta del src (porque está ocultada en el paquete de android.content.pm).

Cuando ejecuto installPackage, tengo SecurityException con indicación de cadena, que mi aplicación no tiene android.permission.INSTALL_PACKAGES, pero se definió en AndroidManifest.xml.

Por lo tanto, creo, no es posible utilizar este método.

PD. He probado en Android SDK 2.3 y 4.0. Tal vez funcionará con las versiones anteriores.

Intente esto LD_LIBRARY_PATH=/vendor/lib:/system/lib antes de pm install. Funciona bien.

! / Bin / bash

 f=/home/cox/myapp.apk #or $1 if input from terminal. #backup env var backup=$LD_LIBRARY_PATH LD_LIBRARY_PATH=/vendor/lib:/system/lib myTemp=/sdcard/temp.apk adb push $f $myTemp adb shell pm install -r $myTemp #restore env var LD_LIBRARY_PATH=$backup 

Esto funciona para mí. Funciono esto en ubuntu 12.04, en terminal de la cáscara.

  • Instalar APK de forma programática en android
  • Android: No se pudo instalar .apk en el dispositivo "device": timeout
  • Cómo configurar Android sdk desde la línea de comandos en servidor sin cabeza?
  • Error en la instalación del SDK de Android
  • Instalar a través de OTA, la aplicación empieza desde splash cuando se minimiza y vuelve a entrar
  • Actividad que solo se inicia una vez después de una nueva instalación?
  • Conceder permisos de sistema a una aplicación en el emulador de Android
  • Actualización de la aplicación Android con cordova-webintent y detención de la fuerza
  • Problema al instalar el controlador USB de Android en Galaxy SII
  • ¿Cómo instalar aps en Windroy?
  • ¿Hay alguna forma de ignorar INSTALL_FAILED_VERSION_DOWNGRADE en la instalación de la aplicación con Android Debug Bridge?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.