Installieren Sie die Anwendung programmgesteuert unter Android
211
Ich bin daran interessiert zu wissen, ob es möglich ist, eine dynamisch heruntergeladene apk programmgesteuert von einer benutzerdefinierten Android-Anwendung zu installieren.
Ich weiß nicht, was "dynamischer Loader, abhängig von der aktuellen Benutzerumgebung" bedeutet. Die Antwort von @Lie Ryan zeigt, wie Sie eine APK installieren können, die mit den von Ihnen gewählten Mitteln heruntergeladen wurde.
CommonsWare
Antworten:
240
Sie können ganz einfach einen Play Store-Link oder eine Installationsaufforderung starten:
Sie können .apks jedoch nicht ohne die ausdrückliche Erlaubnis des Benutzers installieren . Nicht, wenn das Gerät und Ihr Programm nicht gerootet sind.
Gute Antwort, aber kein Hardcode /sdcard, da dies auf Android 2.2+ und anderen Geräten falsch ist. Verwenden Sie Environment.getExternalStorageDirectory()stattdessen.
CommonsWare
3
Das Verzeichnis / asset / ist nur auf Ihrem Entwicklungscomputer vorhanden. Wenn die Anwendung zu einer APK kompiliert wird, ist das Verzeichnis / asset / nicht mehr vorhanden, da alle Assets in der APK komprimiert sind. Wenn Sie aus Ihrem Verzeichnis / asset / installieren möchten, müssen Sie dies zuerst in einen anderen Ordner extrahieren.
Lie Ryan
2
@LieRyan. Schön, Ihre Antwort zu sehen. Ich habe das gerootete Gerät mit benutzerdefiniertem ROM. Ich möchte Themen dynamisch installieren, ohne den Benutzer zu bitten, die Installationsschaltfläche zu drücken. Kann ich das machen.
Sharanabasu Angadi
1
Dies scheint nicht mehr zu funktionieren, wenn targetSdk 25 ist. Es gibt eine Ausnahme: "android.os.FileUriExposedException: ... apk über Intent.getData () ... hinaus außerhalb der App verfügbar gemacht." Woher?
Android-Entwickler
4
@ android Entwickler: Ich kann dies derzeit nicht testen, aber auf targetSdkVersion> = 24 gilt Folgendes: stackoverflow.com/questions/38200282/… Sie müssen also FileProvider verwenden.
Ich hatte das gleiche Problem und nach mehreren Versuchen hat es für mich so geklappt. Ich weiß nicht warum, aber das separate Einstellen von Daten und Typ hat meine Absicht durcheinander gebracht.
Ich kann diese Antwort nicht genug bewerten. Aus irgendeinem Grund führt das separate Festlegen der Absichtsdaten und des MIME-Typs zu ActivityNotFoundException in API-Ebene 17.
Brent M. Spell
Ich habe das auch gerade hochgestimmt. Diese Form war die einzige, die ich zur Arbeit bringen konnte. Noch Jahre später ... was ist das für ein verdammter Käfer? Stunden verschwendet. Ich benutze übrigens Eclipse (Helios).
Tam
10
@ BrentM.Spell und andere: Wenn Sie in die Dokumentation schauen, werden Sie feststellen, dass jedes Mal, wenn Sie nur Daten ODER-Typ festlegen, der andere automatisch ungültig wird, z. B.: setData()Würde dazu führen, dass der Typparameter entfernt wird. Sie MÜSSEN verwenden, setDataAndType()wenn Sie Werte für beide angeben möchten. Hier: developer.android.com/reference/android/content/…
Bogdan Alexandru
41
Die Lösungen für diese Frage gelten alle für targetSdkVersions von 23 und darunter. Für Android N, dh API-Level 24 und höher, funktionieren sie jedoch nicht und stürzen mit der folgenden Ausnahme ab:
android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()
Dies liegt daran, dass sich ab Android 24 die UriAdressierung der heruntergeladenen Datei geändert hat. Zum Beispiel wurde eine Installationsdatei appName.apkauf dem primären externe Dateisystem des App mit Paketnamen gespeichert com.example.testwären als
Das pathNameist , dass oben in dem beispielhaften Inhalt uri Beispiel gezeigt und pathValueist der tatsächliche Pfad auf dem System. Es wäre eine gute Idee, ein "." (ohne Anführungszeichen) für pathValue oben, wenn Sie kein zusätzliches Unterverzeichnis hinzufügen möchten.
Schreiben Sie den folgenden Code, um die apk mit dem Namen appName.apkauf dem primären externen Dateisystem zu installieren :
Ich folgte dieser Methode. Es heißt jedoch, dass die Datei beschädigt ist, wenn ich auf die Schaltfläche "Installieren" drücke. Ich kann dieselbe Datei installieren, indem ich sie über Bluetooth übertrage. warum so?
HI Wenn Sie den Fehler "Datei beschädigt" erhalten, welche Art von Transport haben Sie Ihrer App gegeben, um die APK zu bringen. Wenn Sie vom Server herunterladen, überprüfen Sie, ob die Streams in der Kopierdatei vom Server gelöscht werden sollen. Da die Installation der APK, die über Bluetooth übertragen wurde, funktioniert, denke ich, ist dies das Problem.
Sridhar S
2
java.lang.NullPointerException: Versuch virtuelle Methode 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData (android.content.pm.PackageManager, java.lang.String)' auf einem Null - Objekt Bezug aufzurufen
Makvin
Ihre Bibliothek könnte endlich eine einfache Readme-
Datei
2
Vielen Dank, nach einer Woche des Kampfes mit dieser Antwort habe ich mein Problem gelöst! @SridharS, weiß ich es vor langer Zeit gewesen ist , wie ich sehe, aber wenn Sie Interesse an der Linie 5, sollten Sie hinzufügen , .authorityStrnach dem context.getPackageName()dann sollte es funktionieren.
sehrob
30
Nun, ich habe tiefer gegraben und Quellen für die PackageInstaller-Anwendung von Android Source gefunden.
android.permission.INSTALL_PACKAGES ist nur für vom System signierte Apps verfügbar. Das würde also nicht viel helfen
Hubert Liberacki
21
Ich möchte nur die Tatsache teilen, dass meine APK-Datei in meinem App-Verzeichnis "Daten" gespeichert wurde und dass ich die Berechtigungen für die APK-Datei so ändern musste, dass sie weltweit lesbar ist, damit sie auf diese Weise installiert werden kann, andernfalls auf dem System warf "Parse error: Es gibt ein Problem beim Parsen des Pakets"; Verwenden Sie also eine Lösung von @Horaceman, die Folgendes ergibt:
Ich erhalte den gleichen Parserfehler! Ich weiß nicht, wie ich es lösen soll? Ich habe file.setReadable (true, false) festgelegt, aber es funktioniert nicht für mich
Drittens: Definieren Sie path.xml im Ordner res / xml wie unten! Ich verwende diesen Pfad für den internen Speicher, wenn Sie ihn in etwas anderes ändern möchten. Es gibt einige Möglichkeiten! Sie können zu diesem Link gehen:
FileProvider
Ermöglicht einer Anwendung, die Installation von Paketen anzufordern. Apps, die auf APIs mit mehr als 25 abzielen, müssen über diese Berechtigung verfügen, um Intent.ACTION_INSTALL_PACKAGE verwenden zu können.
Bitte stellen Sie sicher, dass die Anbieterbehörden gleich sind!
Danke, der vierte Schritt war das, was in allen fehlte.
Amin Keshavarzian
1
In der Tat ist der 4. Punkt absolut notwendig. Alle anderen Antworten haben es komplett verpasst.
Whiteagle
Ist android.permission.REQUEST_INSTALL_PACKAGES nicht nur für System-Apps oder Apps verfügbar, die mit dem System-Keystore oder was auch immer signiert sind?
pavi2410
@Pavitra Ermöglicht einer Anwendung, die Installation von Paketen anzufordern. Apps, die auf APIs mit mehr als 25 abzielen, müssen über diese Berechtigung verfügen, um Intent.ACTION_INSTALL_PACKAGE verwenden zu können. Schutzstufe: Unterschrift
Hadi Note
Dieser Code verwendet nicht Intent.ACTION_INSTALL_PACKAGE. Warum also diese Erlaubnis?
Alexander Dyagilev
5
Eine weitere Lösung, bei der die empfangende App nicht fest codiert werden muss und die daher sicherer ist:
Ja es ist möglich. Dafür benötigen Sie jedoch das Telefon, um nicht überprüfte Quellen zu installieren. Zum Beispiel macht slideMe das. Ich denke, das Beste, was Sie tun können, ist zu überprüfen, ob die Anwendung vorhanden ist, und eine Absicht für den Android Market zu senden. Sie sollten etwas das URL-Schema für Android Market verwenden.
market://details?id=package.name
Ich weiß nicht genau, wie ich die Aktivität starten soll, aber wenn Sie eine Aktivität mit dieser Art von URL starten. Es sollte den Android-Markt öffnen und Ihnen die Wahl geben, die Apps zu installieren.
Wie ich sehe, ist diese Lösung der Wahrheit am nächsten :). Aber es ist nicht passend für meinen Fall. Ich brauche einen dynamischen Lader, der von der aktuellen Benutzerumgebung abhängt und auf den Markt kommt - keine gute Lösung. Aber trotzdem danke.
Alkersan
4
Es ist erwähnenswert, dass Sie den DownloadManagerDownload an einem externen Ort speichern müssen, z setDestinationInExternalFilesDir(c, null, "<your name here>).apk";. Die Absicht mit einem Paketarchivtyp scheint das content:Schema, das beim Herunterladen an einen internen Speicherort verwendet wird, nicht zu mögen, gefällt aber file:. (Der Versuch, den internen Pfad in ein Dateiobjekt zu verpacken und dann den Pfad file:abzurufen, funktioniert ebenfalls nicht, obwohl dies zu einer URL führt, da die App die apk nicht analysiert. Sieht so aus, als müsste sie extern sein.)
String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));String title = filePath.substring( filePath.lastIndexOf('/')+1, filePath.length());Intent intent =newIntent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newFile(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);
UpdateNode bietet eine API für Android, mit der APK-Pakete in einer anderen App installiert werden können.
Sie können Ihr Update einfach online definieren und die API in Ihre App integrieren - fertig.
Derzeit befindet sich die API im Beta-Status, Sie können jedoch bereits einige Tests selbst durchführen.
Darüber hinaus bietet UpdateNode auch die Anzeige von Nachrichten über das System an - sehr nützlich, wenn Sie Ihren Benutzern etwas Wichtiges mitteilen möchten.
Ich bin Teil des Client-Entwicklerteams und verwende mindestens die Nachrichtenfunktionalität für meine eigene Android-App.
Antworten:
Sie können ganz einfach einen Play Store-Link oder eine Installationsaufforderung starten:
oder
Sie können .apks jedoch nicht ohne die ausdrückliche Erlaubnis des Benutzers installieren . Nicht, wenn das Gerät und Ihr Programm nicht gerootet sind.
quelle
/sdcard
, da dies auf Android 2.2+ und anderen Geräten falsch ist. Verwenden SieEnvironment.getExternalStorageDirectory()
stattdessen.Ich hatte das gleiche Problem und nach mehreren Versuchen hat es für mich so geklappt. Ich weiß nicht warum, aber das separate Einstellen von Daten und Typ hat meine Absicht durcheinander gebracht.
quelle
setData()
Würde dazu führen, dass der Typparameter entfernt wird. Sie MÜSSEN verwenden,setDataAndType()
wenn Sie Werte für beide angeben möchten. Hier: developer.android.com/reference/android/content/…Die Lösungen für diese Frage gelten alle für
targetSdkVersion
s von 23 und darunter. Für Android N, dh API-Level 24 und höher, funktionieren sie jedoch nicht und stürzen mit der folgenden Ausnahme ab:Dies liegt daran, dass sich ab Android 24 die
Uri
Adressierung der heruntergeladenen Datei geändert hat. Zum Beispiel wurde eine InstallationsdateiappName.apk
auf dem primären externe Dateisystem des App mit Paketnamen gespeichertcom.example.test
wären alsfile:///storage/emulated/0/Android/data/com.example.test/files/appName.apk
für
API 23
und unter, während so etwas wiefür
API 24
und darüber.Weitere Details dazu finden Sie hier und ich werde es nicht durchgehen.
Zur Beantwortung der Frage nach
targetSdkVersion
dem24
und oben, muss man folgendermaßen vor: Fügen Sie folgende zu dem AndroidManifest.xml:2. Fügen Sie dem Ordner in src, main, die folgende
paths.xml
Datei hinzu :xml
res
Das
pathName
ist , dass oben in dem beispielhaften Inhalt uri Beispiel gezeigt undpathValue
ist der tatsächliche Pfad auf dem System. Es wäre eine gute Idee, ein "." (ohne Anführungszeichen) für pathValue oben, wenn Sie kein zusätzliches Unterverzeichnis hinzufügen möchten.Schreiben Sie den folgenden Code, um die apk mit dem Namen
appName.apk
auf dem primären externen Dateisystem zu installieren :Es ist auch keine Berechtigung erforderlich, wenn Sie in das private Verzeichnis Ihrer eigenen App im externen Dateisystem schreiben.
Ich habe hier eine AutoUpdate-Bibliothek geschrieben , in der ich die oben genannten verwendet habe.
quelle
.authorityStr
nach demcontext.getPackageName()
dann sollte es funktionieren.Nun, ich habe tiefer gegraben und Quellen für die PackageInstaller-Anwendung von Android Source gefunden.
https://github.com/android/platform_packages_apps_packageinstaller
Aus dem Manifest habe ich herausgefunden, dass es eine Erlaubnis erfordert:
Der eigentliche Installationsvorgang erfolgt nach Bestätigung
quelle
Ich möchte nur die Tatsache teilen, dass meine APK-Datei in meinem App-Verzeichnis "Daten" gespeichert wurde und dass ich die Berechtigungen für die APK-Datei so ändern musste, dass sie weltweit lesbar ist, damit sie auf diese Weise installiert werden kann, andernfalls auf dem System warf "Parse error: Es gibt ein Problem beim Parsen des Pakets"; Verwenden Sie also eine Lösung von @Horaceman, die Folgendes ergibt:
quelle
Dies kann anderen sehr helfen!
Zuerst:
Zweitens: Für Android 7 und höher sollten Sie einen Anbieter im Manifest wie unten definieren!
Drittens: Definieren Sie path.xml im Ordner res / xml wie unten! Ich verwende diesen Pfad für den internen Speicher, wenn Sie ihn in etwas anderes ändern möchten. Es gibt einige Möglichkeiten! Sie können zu diesem Link gehen: FileProvider
Viertens: Sie sollten diese Berechtigung im Manifest hinzufügen:
quelle
Eine weitere Lösung, bei der die empfangende App nicht fest codiert werden muss und die daher sicherer ist:
quelle
Ja es ist möglich. Dafür benötigen Sie jedoch das Telefon, um nicht überprüfte Quellen zu installieren. Zum Beispiel macht slideMe das. Ich denke, das Beste, was Sie tun können, ist zu überprüfen, ob die Anwendung vorhanden ist, und eine Absicht für den Android Market zu senden. Sie sollten etwas das URL-Schema für Android Market verwenden.
Ich weiß nicht genau, wie ich die Aktivität starten soll, aber wenn Sie eine Aktivität mit dieser Art von URL starten. Es sollte den Android-Markt öffnen und Ihnen die Wahl geben, die Apps zu installieren.
quelle
Es ist erwähnenswert, dass Sie den
DownloadManager
Download an einem externen Ort speichern müssen, zsetDestinationInExternalFilesDir(c, null, "<your name here>).apk";
. Die Absicht mit einem Paketarchivtyp scheint dascontent:
Schema, das beim Herunterladen an einen internen Speicherort verwendet wird, nicht zu mögen, gefällt aberfile:
. (Der Versuch, den internen Pfad in ein Dateiobjekt zu verpacken und dann den Pfadfile:
abzurufen, funktioniert ebenfalls nicht, obwohl dies zu einer URL führt, da die App die apk nicht analysiert. Sieht so aus, als müsste sie extern sein.)Beispiel:
quelle
Vergessen Sie nicht, Berechtigungen anzufordern:
Fügen Sie in AndroidManifest.xml den Anbieter und die Berechtigung hinzu:
Erstellen Sie den XML-Dateianbieter res / xml / provider_paths.xml
Verwenden Sie den folgenden Beispielcode:
quelle
Nur eine Erweiterung, wenn jemand eine Bibliothek , dann müssen diese helfen könnte. Danke an Raghav
quelle
Versuche dies
quelle
Fügen Sie zunächst die folgende Zeile zu AndroidManifest.xml hinzu:
Verwenden Sie dann den folgenden Code, um apk zu installieren:
quelle
UpdateNode bietet eine API für Android, mit der APK-Pakete in einer anderen App installiert werden können.
Sie können Ihr Update einfach online definieren und die API in Ihre App integrieren - fertig.
Derzeit befindet sich die API im Beta-Status, Sie können jedoch bereits einige Tests selbst durchführen.
Darüber hinaus bietet UpdateNode auch die Anzeige von Nachrichten über das System an - sehr nützlich, wenn Sie Ihren Benutzern etwas Wichtiges mitteilen möchten.
Ich bin Teil des Client-Entwicklerteams und verwende mindestens die Nachrichtenfunktionalität für meine eigene Android-App.
Hier finden Sie eine Beschreibung zur Integration der API
quelle
Versuchen Sie dies - Schreiben Sie auf Manifest:
Schreiben Sie den Code:
quelle