Installer l'Application programmatically sur Android

je suis intéressé de savoir s'il est possible d'installer de manière programmatique un apk téléchargé dynamiquement à partir d'une application Android personnalisée.

170
demandé sur Simon MᶜKenzie 2011-01-05 15:59:03

14 réponses

vous pouvez facilement lancer un lien de marché ou une invite d'installation:

Intent promptInstall = new Intent(Intent.ACTION_VIEW)
    .setDataAndType(Uri.parse("file:///path/to/your.apk"), 
                    "application/vnd.android.package-archive");
startActivity(promptInstall); 

source

Intent goToMarket = new Intent(Intent.ACTION_VIEW)
    .setData(Uri.parse("market://details?id=com.package.name"));
startActivity(goToMarket);

source

Cependant, vous ne pouvez pas installer .apk sans que l'utilisateur permission explicite ; non, sauf si l'appareil et votre programme est enracinée.

210
répondu Lie Ryan 2017-05-23 10:31:12
File file = new File(dir, "App.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);

j'ai eu le même problème et après plusieurs tentatives, il a travaillé pour moi de cette façon. Je ne sais pas pourquoi, mais mettre des données et taper séparément a gâché mon intention.

54
répondu Horaceman 2013-08-28 14:31:05

Eh bien, j'ai creusé plus profondément, et j'ai trouvé des sources D'application PackageInstaller à partir de Android Source.

https://github.com/android/platform_packages_apps_packageinstaller

du Manifeste j'ai trouvé qu'il faut une permission:

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

et le processus d'installation proprement dit se produit après confirmation

Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallAppProgress.class);
String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (installerPackageName != null) {
   newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
}
startActivity(newIntent);
26
répondu Alkersan 2014-07-13 13:05:13

les solutions proposées à cette question s'appliquent toutes aux targetSdkVersion s de 23 et moins. Pour Android N, C'est-à-dire API Niveau 24, et au-dessus, cependant, ils ne fonctionnent pas et plantent avec l'Exception suivante:

android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()

cela est dû au fait que à partir D'Android 24, le Uri pour l'adressage du fichier téléchargé a changé. Par exemple ,un fichier d'installation nommé appName.apk stocké sur le système de fichier externe primaire de l'application avec nom du paquet com.example.test serait comme

file:///storage/emulated/0/Android/data/com.example.test/files/appName.apk

pour API 23 et plus bas, alors que quelque chose comme

content://com.example.test.authorityStr/pathName/Android/data/com.example.test/files/appName.apk

pour API 24 et plus.

plus de détails à ce sujet peuvent être trouvés ici et je ne vais pas passer par là.

pour répondre à la question pour targetSdkVersion de 24 et plus, il faut suivre ces étape: Ajoutez ce qui suit au AndroidManifest.xml:

<application
        android:allowBackup="true"
        android:label="@string/app_name">
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.authorityStr"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/paths"/>
        </provider>
</application>

2. Ajouter le fichier paths.xml suivant au dossier xml sur res dans src, main:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="pathName"
        path="pathValue"/>
</paths>

le pathName est celui montré dans l'exemple de contenu exemplaire ci-dessus et pathValue est le chemin réel sur le système. Ce serait une bonne idée de mettre un "."(sans guillemets) pour pathValue dans ce qui précède si vous ne voulez pas ajouter d'extra répertoire.

  1. écrivez le code suivant pour installer l'apk avec le nom appName.apk sur le système de fichier externe primaire:

    File directory = context.getExternalFilesDir(null);
    File file = new File(directory, fileName);
    Uri fileUri = Uri.fromFile(file);
    if (Build.VERSION.SDK_INT >= 24) {
        fileUri = FileProvider.getUriForFile(context, context.getPackageName(),
                file);
    }
    Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
    intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
    intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    context.startActivity(intent);
    activity.finish();
    

aucune permission n'est également nécessaire lorsque vous écrivez dans le répertoire privé de votre propre application sur le système de fichiers externe.

j'ai écrit une bibliothèque AutoUpdate ici dans laquelle j'ai utilisé ce qui précède.

25
répondu Ali Nem 2017-01-16 07:55:14

je veux juste partager le fait que mon fichier apk a été enregistré dans le répertoire "Data" de mon application et que j'avais besoin de changer les permissions sur le fichier apk pour être lisible dans le monde entier afin de le permettre d'être installé de cette façon, sinon le système lançait "erreur D'analyse: il y a un problème D'analyse du paquet"; donc en utilisant la solution de @Horaceman qui fait:

File file = new File(dir, "App.apk");
file.setReadable(true, false);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
17
répondu user1604240 2014-11-11 15:00:11

suivez ces étapes:

1 - ajouter le texte suivant à la AndroidManifest.xml :

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/paths"/>
    </provider>

2 - ajouter les chemins suivants.fichier xml dans le dossier xml (s'il n'existe pas le créer) sur res dans src, main

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
    name="external_file"
    path="."/>
</paths>

le nom de chemin est celui indiqué dans l'exemple d'uri de contenu exemplaire ci-dessus et pathValue est le chemin réel sur le système. Ce serait une bonne idée de mettre un "." pour pathValue dans ce qui précède si vous ne voulez pas ajouter de sous-répertoire supplémentaire.

3 - écrivez le code suivant pour exécuter vos fichiers Apk:

File file = "path of yor apk file";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri fileUri = FileProvider.getUriForFile(getBaseContext(), getApplicationContext().getPackageName() + ".provider", file);
Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}

et merci à Ali Nemati Hayati d'être le premier à écrire Solution profil ali-nemati-hayati

7
répondu Lila saad 2018-03-16 13:20:27

Oui c'est possible. Mais pour cela vous avez besoin du téléphone pour installer les sources non vérifiées. Par exemple, slideMe. Je pense que la meilleure chose que vous pouvez faire est de vérifier si l'application est présente et envoyer une intention pour le marché Android. vous devriez utiliser quelque chose le schéma d'url pour android Market.

market://details?id=package.name

je ne sais pas exactement comment démarrer l'activité, mais si vous commencez une activité avec ce type d'url. Il devrait ouvrir le marché android et vous donner la le choix d'installer l'application.

4
répondu Loïc Faure-Lacroix 2014-02-06 17:21:44

il est intéressant de noter que si vous utilisez le DownloadManager pour lancer votre téléchargement, assurez-vous de le sauvegarder à un endroit externe par exemple setDestinationInExternalFilesDir(c, null, "<your name here>).apk"; . L'intention avec un type de paquet-archive ne semble pas aimer le schéma content: utilisé avec les téléchargements vers un emplacement interne, mais il fait comme file: . (Essayer d'envelopper le chemin interne dans un objet fichier et ensuite obtenir le chemin ne fonctionne pas non plus, même si cela aboutit à une url file: , car l'application ne va pas analyser l'apk; regarde comme il doit être externe.)

exemple:

int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
File mFile = new File(Uri.parse(downloadedPackageUriString).getPath());
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
        .setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive")
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appContext.startActivity(promptInstall);
4
répondu qix 2014-04-27 09:27:03

une autre solution qui ne nécessite pas de code dur pour l'application réceptrice et qui est donc plus sûre:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( Uri.fromFile(new File(pathToApk)) );
startActivity(intent);
4
répondu Hartok 2015-01-22 21:30:52

juste une extension, si quelqu'un a besoin d'une bibliothèque alors ce pourrait aider. Merci à Raghav

2
répondu IronBlossom 2017-05-23 12:26:23

essayez cette

String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
String title = filePath.substring( filePath.lastIndexOf('/')+1, filePath.length() );
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
MainActivity.this.startActivity(intent);
2
répondu Joolah 2015-03-22 11:08:20

UpdateNode fournit une API pour Android pour installer des paquets APK à partir de l'intérieur d'une autre application.



Vous pouvez simplement définir votre mise à jour en ligne et intégrer L'API dans votre application - c'est tout.

Actuellement, l'API est en Beta, mais vous pouvez déjà faire quelques tests vous-même.



En plus de cela, UpdateNode offre également l'affichage de messages système très utile si vous voulez dire quelque chose d'important à vos utilisateurs.



Je fais partie de l'équipe de développement client et j'utilise au moins la fonctionnalité de message pour ma propre application Android.

voir ici une description Comment intégrer L'API

1
répondu sarahara 2014-06-17 20:20:23

essayez ceci - Écrire sur le Manifeste:

uses-permission android:name="android.permission.INSTALL_PACKAGES"
        tools:ignore="ProtectedPermissions"

écrivez le Code:

File sdCard = Environment.getExternalStorageDirectory();
String fileStr = sdCard.getAbsolutePath() + "/Download";// + "app-release.apk";
File file = new File(fileStr, "app-release.apk");
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
                        "application/vnd.android.package-archive");

startActivity(promptInstall);
0
répondu Phuoc-Loc Truong 2015-06-23 14:37:49

ajouter D'abord la ligne suivante à AndroidManifest.xml:

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

ensuite, utilisez le code suivant pour installer apk:

File sdCard = Environment.getExternalStorageDirectory();
            String fileStr = sdCard.getAbsolutePath() + "/MyApp";// + "app-release.apk";
            File file = new File(fileStr, "TaghvimShamsi.apk");
            Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
                    "application/vnd.android.package-archive");
            startActivity(promptInstall);
0
répondu Abbas.moosavi 2017-11-22 14:26:03