installer / désinstaller les Apk par programme (PackageManager vs Intentions)
Mon application s'installe d'autres applications, et il a besoin de garder une trace de ce que les applications qu'il a installé. Bien sûr, cela pourrait être réalisé en gardant simplement une liste des applications installées. Mais cela ne devrait pas être nécessaire! Il devrait être de la responsabilité de l'PackageManager pour maintenir la installedBy(a, b) de la relation. En fait, selon l'API, il est:
public abstract String getInstallerPackageName(String packageName) -
Récupérer le nom du package de l'application qui a installé un paquet. Ce qui identifie le marché provient le paquet.
L'approche actuelle
Installer APK en utilisant l'Intention de
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);
Désinstaller APK en utilisant l'Intention:
Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);
Ce n'est évidemment pas la façon dont par exemple l'Android Market s'installe /désinstalle les paquets. Ils utilisent une version enrichie de la PackageManager. Cette montre en téléchargeant le code source Android à partir de l'Android dépôt Git. Ci-dessous sont les deux cachés méthodes qui correspond à l'Intention de l'approche. Malheureusement, ils ne sont pas disponibles à des développeurs externes. Mais peut-être qu'ils le seront dans le futur?
La meilleure approche
Installer APK en utilisant les 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);
Désinstallation APK en utilisant les 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);
Différences
-
Lors de l'utilisation de modes locaux gestionnaire de paquets n'est pas informé de l'application de l'installation provient. Plus précisément, getInstallerPackageName(...) renvoie la valeur null.
-
Cachés méthode installationprogiciel(...) prend le package d'installation nom en tant que paramètre, et est le plus susceptible capable de régler cette valeur.
Question
il Est possible de spécifier le package de l'installateur nom de l'aide intentions?
(Peut-être le nom du package du programme d'installation peut être ajouté comme un supplément à l'installation de l'intention?)
Astuce: Si vous souhaitez télécharger le code source Android, vous pouvez suivre les étapes décrites ici: Téléchargement de l'Arbre Source. Pour extraire l' *.java fichiers et les mettre dans des dossiers en fonction de la hiérarchie des paquets, vous pouvez vérifier cet soigné script: Afficher le Code Source Android dans Eclipse.
- Certains des URIs sont manquants dans le texte. Je les ajouterai dès que j'ai le droit de (nouveaux utilisateurs a quelques restrictions pour éviter le spam).
- comment désactiver la fonctionnalité de désinstallation ?
- "comment désactiver la fonctionnalité de désinstallation ?" - Travailler sur certains difficiles à désinstaller les logiciels malveillants, en sommes-nous?
Vous devez vous connecter pour publier un commentaire.
Ce n'est actuellement pas disponible pour les applications tierces. Notez que, même en utilisant la réflexion ou autres astuces pour l'accès installationprogiciel() ne va pas aider, car seules les applications du système de pouvoir l'utiliser. (C'est parce que c'est le faible niveau de mécanisme d'installation, une fois que les autorisations ont été approuvés par l'utilisateur, de sorte qu'il n'est pas sûr pour les applications d'avoir accès à.)
Également la installationprogiciel() les arguments de la fonction ont souvent changé entre la plate-forme de communiqués, de sorte que tout ce que vous faites en essayant d'accès elle échoue sur divers autres versions de la plate-forme.
EDIT:
Il est également intéressant de souligner que cette installerPackage n'a été ajouté à assez récemment à la plate-forme (2.2?) et à l'origine, non utilisés pour le suivi de la personne ayant installé l'application -- il est utilisé par la plate-forme afin de déterminer qui à lancer lorsque les rapports de bogues avec l'application, de la mise en œuvre Android Commentaires. (C'était aussi l'un des moments la méthode de l'API arguments changé.) Pour au moins un long moment après qu'il a été introduit, le Marché n'a toujours pas l'utiliser pour suivre les apps qu'il a été installé (et il se peut très bien encore de ne pas l'utiliser), mais au lieu de simplement utilisé cette fonction pour définir le Android Commentaires de l'app (qui était distincte de Marché) que le "propriétaire" de prendre soin de commentaires.
Android P+ a besoin de cette autorisation dans AndroidManifest.xml
Alors:
de désinstaller. Il semble plus facile...
onDestroy()
méthode?API de niveau 14 introduit deux nouvelles actions: ACTION_INSTALL_PACKAGE et ACTION_UNINSTALL_PACKAGE. Ces actions vous permettent de passer EXTRA_RETURN_RESULT booléen supplémentaire pour obtenir un (onu)installation de l'avis du résultat.
Exemple de code pour appeler la boîte de dialogue désinstaller:
Et de recevoir la notification dans votre Activité#onActivityResult méthode:
ACTION_INSTALL_PACKAGE
nécessitera la signature de niveauREQUEST_INSTALL_PACKAGES
la permission. De même, à partir de l'API 28 (Android P), l'appel deACTION_UNINSTALL_PACKAGE
nécessitera la non-dangereuxREQUEST_DELETE_PACKAGES
la permission. Au moins selon les docs.Si vous avez le Propriétaire de l'Appareil (ou le profil de propriétaire, je n'ai pas essayé) l'autorisation vous pouvez silencieusement installer/désinstaller des paquets en utilisant le propriétaire de l'appareil de l'API.
pour la désinstallation:
et d'installer le paquet:
.apk
fichier, mais le rappel de l'intention n'est jamais de feu et l'application n'est jamais mis à jour. Pas d'erreurs ou d'exceptions apparaissent dansadb logcat
. (J'ai changé tous lesSystem.out
s àLog.e
s).La seule façon d'accéder à ces méthodes est par la réflexion. Vous pouvez obtenir une poignée sur la
PackageManager
objet en appelantgetApplicationContext().getPackageManager()
et en utilisant la réflexion d'accès à ces méthodes. La caisse cette tutoriel.Selon Froyo code source, l'Intention.EXTRA_INSTALLER_PACKAGE_NAME clé supplémentaire est interrogé pour le package du programme d'installation nom de l'PackageInstallerActivity.
Sur un dispositif enracinée, vous pouvez utiliser:
Util.sudo()
est défini ici.Si vous êtes de passage nom du package paramètre à l'un de vos fonctions définies par l'utilisateur, puis utiliser le code ci-dessous :
Si vous êtes à l'aide de Kotlin, l'API 14+, et souhaite juste montrer boîte de dialogue désinstaller pour votre application:
Vous pouvez modifier
packageName
à tout autre nom du package si vous voulez demander à l'utilisateur de désinstaller une application sur l'appareilPréalable:
Votre APK doit être signé par le système comme l'a relevé plus haut. Un moyen d'y parvenir est la construction de l'AFST image de vous-même et en ajoutant le code source dans le build.
Code:
Une fois installé comme une application système, vous pouvez utiliser le gestionnaire de paquets méthodes pour installer et désinstaller une APK comme suit:
Installer:
Désinstaller:
D'avoir un rappel une fois votre APK est installé/désinstallé, vous pouvez utiliser ceci: