Meine App verfügt über eine automatische Aktualisierungsfunktion, mit der eine APK heruntergeladen werden kann. Wenn der Download abgeschlossen ist, wird eine Intent.VIEW_ACTION zum Öffnen der App und zum Installieren der heruntergeladenen APK durch den Benutzer angezeigt
Uri uri = Uri.parse("file://" + destination);
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setDataAndType(uri,
manager.getMimeTypeForDownloadedFile(downloadId));
activity.startActivity(install);
Dies funktioniert hervorragend für alle Geräte <24
Mit Android 24 dürfen wir anscheinend keine Absichten mehr mit file: /// beginnen, und nach einigem googeln wurde empfohlen, A File Provider zu verwenden
neuer Code:
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri apkUri = FileProvider.getUriForFile(AutoUpdate.this,
BuildConfig.APPLICATION_ID + ".provider", file);
install.setDataAndType(apkUri,
manager.getMimeTypeForDownloadedFile(downloadId));
activity.startActivity(install);
Jetzt activity.startActivity (installieren); wirft einen Fehler
Es wurde keine Aktivität für Intent gefunden {act = android.intent.action.VIEW dat = content: //com.xxxx.xx.provider/MyFolder/Download/MyApkFile.apk typ = application / vnd.android.package-archive flg = 0x4000000}
Kann ich den APK-Viewer in Android 7 (24) auf irgendeine Weise öffnen?
Antworten:
Nach vielen Versuchen konnte ich dieses Problem lösen, indem ich verschiedene Absichten für etwas niedrigeres als Nougat erstellte, indem ich mit dem FileProvider eine Installationsabsicht mit Android-Versionen erstellte, bevor Nougat den Fehler verursacht:
ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.INSTALL_PACKAGE dat=content://XXX.apk flg=0x1 }
Bei Verwendung eines normalen Uri unter Android erzeugt Nougat den folgenden Fehler:
FileUriExposedException: file:///XXX.apk exposed beyond app through Intent.getData()
Meine Lösung, die für mich mit Android N auf dem Emulator und einem Telefon mit Android M funktioniert.
File toInstall = new File(appDirectory, appName + ".apk");
Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileprovider", toInstall);
intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
Uri apkUri = Uri.fromFile(toInstall);
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
activity.startActivity(intent);
UPDATE FÜR Android Nougat 7.1:
Sie müssen auch die Berechtigung REQUEST_INSTALL_PACKAGES in Ihrem Manifest hinzufügen. Es ist ab Api Level 23 (Android 6.0 Marshmallow) verfügbar und ab Level 25 (Android 7.1 Nougat) erforderlich.
AKTUALISIEREN:
Denken Sie daran, die Berechtigungen zum Lesen und Schreiben in den externen Speicher anzufordern, wenn sich die zu installierende Datei im externen Speicher befindet. Und auch, um einen korrekten FileProvider für Android Nougat und höher einzurichten.
Überprüfen Sie zunächst, ob Sie über eine Schreibberechtigung verfügen, indem Sie canReadWriteExternal()
unten anrufen . Wenn nicht, rufen Sie requestPermission()
vorher an:
private static final int REQUEST_WRITE_PERMISSION = 786;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Toast.makeText(this, "Permission granted", Toast.LENGTH_LONG).show();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
}
private boolean canReadWriteExternal() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
}
Hier ist ein Beispiel eines Dateianbieters für den Download-Ordner im externen Speicher. AndroidManifest.xml :
<application ... >
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
resources / xml / filepaths.xml :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_download" path="Download"/>
</paths>
Wenn beim Installieren der .apk-Datei eine Fehlermeldung angezeigt wird, die besagt, dass beim Parsen des Pakets ein Problem vorliegt. Möglicherweise haben Sie nicht nach der Lese- / Schreibberechtigung gefragt, oder die Datei, die Sie installieren möchten, ist nicht vorhanden oder beschädigt.
setFlags
zweimal anrief, was im Grunde das erste Flag zurücksetzt. Ich musste addFlag
stattdessen verwenden.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
erforderlich für Android N (Nougot)
Antworten:
Ich hatte dieses Problem beim Aufrufen der Startaktivität. Nachdem ich meine aktuelle Aktivität angehalten hatte, kam sie plötzlich zurück und rief onResume auf. als wäre nichts passiert. Mein Problem war mit dieser Erlaubnis im Manifest:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
Das hat fast niemand erwähnt. Also denk daran. in sdk> = 24 müssen Sie den Provider verwenden, da eine Absicht erforderlich ist, die mit file: /// unter sdk 24 beginnt. Sie sollten uri beginnend mit content: /// angeben. Deshalb benötigen wir den Dateianbieter für sdk 24 und höher. Ich glaube nicht, dass ich dafür Codes schreiben muss, da @just_user die richtige Antwort geschrieben hat.
quelle
Dies könnte das Problem sein, das Sie haben
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
in deinem Beispiel sollte es sein
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
as install ist der Name der Absicht.
quelle
Sie sollten beachten, dass Sie für API <24 Folgendes verwenden müssen:
setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive")
anstatt Daten einzustellen und separat einzugeben:
data = Uri.fromFile(apkFile)
type = "application/vnd.android.package-archive"
Andernfalls erhalten Sie ActivityNotFoundException
quelle
DataAndType
dann gibt es kein Problem.
ACTION_INSTALL_PACKAGE
. Das hat bei mir ab der Juni-Ausgabe der N Developer Preview funktioniert .ACTION_INSTALL_PACKAGE
,FileProvider
die APK zu verwenden, wenn ich sie auf einem Nexus 9 mit Android 7.0 (Build NRD90M) teste. Verglichen mit IhremIntent
, abgesehen von dem Unterschied zwischen Aktionszeichenfolgen, verwende ich nichtFLAG_ACTIVITY_CLEAR_TOP
und ich verwendesetData()
eher alssetDataAndType()
.getUriForFile