Mi aplicación instala otras aplicaciones y necesita realizar un seguimiento de las aplicaciones que ha instalado. Por supuesto, esto podría lograrse simplemente manteniendo una lista de las aplicaciones instaladas. ¡Pero esto no debería ser necesario! Debería ser responsabilidad del PackageManager mantener la relación instalada ByB (a, b). De hecho, según la API es:
public abstract String getInstallerPackageName (String packageName): recupera el nombre del paquete de la aplicación que instaló un paquete. Esto identifica de qué mercado proviene el paquete.
El enfoque actual
Instalar APK usando Intención
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);
Desinstalar APK usando Intención:
Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);
Obviamente, esta no es la forma, por ejemplo, Android Market instala / desinstala paquetes. Usan una versión más rica del PackageManager. Esto se puede ver descargando el código fuente de Android desde el repositorio de Android Git. A continuación se muestran los dos métodos ocultos que corresponden al enfoque de intención. Lamentablemente, no están disponibles para desarrolladores externos. Pero tal vez lo serán en el futuro?
El mejor enfoque
Instalar APK usando el PackageManager
/**
* @hide
*
* Install a package. Since this may take a little while, the result will
* be posted back to the given observer. An installation will fail if the calling context
* lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
* package named in the package file's manifest is already installed, or if there's no space
* available on the device.
*
* @param packageURI The location of the package file to install. This can be a 'file:' or a
* 'content:' URI.
* @param observer An observer callback to get notified when the package installation is
* complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
* called when that happens. observer may be null to indicate that no callback is desired.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
* {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that is performing the
* installation. This identifies which market the package came from.
*/
public abstract void installPackage(
Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName);
Desinstalar APK usando el PackageManager
/**
* Attempts to delete a package. Since this may take a little while, the result will
* be posted back to the given observer. A deletion will fail if the calling context
* lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
* named package cannot be found, or if the named package is a "system package".
* (TODO: include pointer to documentation on "system packages")
*
* @param packageName The name of the package to delete
* @param observer An observer callback to get notified when the package deletion is
* complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
* called when that happens. observer may be null to indicate that no callback is desired.
* @param flags - possible values: {@link #DONT_DELETE_DATA}
*
* @hide
*/
public abstract void deletePackage(
String packageName, IPackageDeleteObserver observer, int flags);
Las diferencias
Al usar intentos, el administrador de paquetes local no tiene conocimiento de qué aplicación se originó la instalación. Específicamente, getInstallerPackageName (...) devuelve nulo.
El método oculto installPackage (...) toma el nombre del paquete del instalador como parámetro y es muy probable que sea capaz de establecer este valor.
Pregunta
¿Es posible especificar el nombre del instalador del paquete usando intentos? (¿Tal vez el nombre del paquete de instalación se puede agregar como un extra a la intención de instalación?)
Consejo: Si desea descargar el código fuente de Android, puede seguir los pasos descritos aquí: Descargar el árbol de fuentes. Para extraer los archivos * .java y colocarlos en carpetas de acuerdo con la jerarquía del paquete, puede consultar este script ordenado: Ver el código fuente de Android en Eclipse .
Respuestas:
Actualmente no está disponible para aplicaciones de terceros. Tenga en cuenta que incluso usar la reflexión u otros trucos para acceder a installPackage () no ayudará, porque solo las aplicaciones del sistema pueden usarlo. (Esto se debe a que es el mecanismo de instalación de bajo nivel, después de que los permisos hayan sido aprobados por el usuario, por lo que no es seguro que las aplicaciones normales tengan acceso).
Además, los argumentos de la función installPackage () a menudo han cambiado entre las versiones de la plataforma, por lo que cualquier cosa que intente acceder a ella fallará en varias otras versiones de la plataforma.
EDITAR:
También vale la pena señalar que este paquete de instalador solo se agregó recientemente a la plataforma (2.2?) Y originalmente no se usó realmente para rastrear quién instaló la aplicación; la plataforma lo usa para determinar a quién lanzar cuando se informan errores con la aplicación, para implementar Android Feedback. (Esta fue también una de las veces que los argumentos del método API cambiaron). Durante al menos mucho tiempo después de que se introdujo, Market todavía no lo usó para rastrear las aplicaciones que ha instalado (y es muy posible que todavía no lo use ), pero solo usé esto para configurar la aplicación Android Feedback (que era independiente de Market) como el "propietario" para encargarse de los comentarios.
fuente
Android P + requiere este permiso en AndroidManifest.xml
Luego:
para desinstalar Parece más fácil ...
fuente
onDestroy()
método?El nivel 14 de la API introdujo dos nuevas acciones: ACTION_INSTALL_PACKAGE y ACTION_UNINSTALL_PACKAGE . Esas acciones le permiten pasar EXTRA_RETURN_RESULT boolean extra para obtener una notificación de resultado (no) de instalación.
Código de ejemplo para invocar el cuadro de diálogo de desinstalación:
Y reciba la notificación en su método Activity # onActivityResult :
fuente
ACTION_INSTALL_PACKAGE
requerirán elREQUEST_INSTALL_PACKAGES
permiso de nivel de firma . Del mismo modo, comenzando con API 28 (Android P), las llamadasACTION_UNINSTALL_PACKAGE
requerirán unREQUEST_DELETE_PACKAGES
permiso no peligroso . Al menos según los documentos.Si tiene permiso de propietario del dispositivo (o propietario del perfil, no lo he probado), puede instalar / desinstalar silenciosamente paquetes utilizando la API del propietario del dispositivo.
para desinstalar:
e instalar el paquete:
fuente
La única forma de acceder a esos métodos es a través de la reflexión. Puede obtener un identificador de un
PackageManager
objeto llamandogetApplicationContext().getPackageManager()
y utilizando el acceso de reflexión a estos métodos. Mira este tutorial.fuente
Según el código fuente de Froyo, se consulta la clave adicional Intent.EXTRA_INSTALLER_PACKAGE_NAME para obtener el nombre del paquete del instalador en PackageInstallerActivity.
fuente
En un dispositivo rooteado, puede usar:
Util.sudo()
se define aquí.fuente
Si está pasando el nombre del paquete como parámetro a cualquiera de las funciones definidas por el usuario, utilice el siguiente código:
fuente
Si está utilizando Kotlin, API 14+, y solo desea mostrar el diálogo de desinstalación para su aplicación:
Puede cambiar
packageName
a cualquier otro nombre de paquete si desea solicitar al usuario que desinstale otra aplicación en el dispositivofuente
Requisito previo:
Su APK debe estar firmado por el sistema como se señaló anteriormente correctamente. Una forma de lograrlo es construir la imagen AOSP usted mismo y agregar el código fuente a la compilación.
Código:
Una vez instalado como una aplicación del sistema, puede usar los métodos del administrador de paquetes para instalar y desinstalar un APK de la siguiente manera:
Instalar en pc:
Desinstalar:
Para recibir una devolución de llamada una vez que su APK esté instalado / desinstalado, puede usar esto:
fuente