web-dev-qa-db-fra.com

Installer par programme un apk sous Android 7/api 24

J'essaie d'obtenir que mon application installe automatiquement un apk. Cela fonctionne très bien pour api <24. Mais pour 24 ans, c'est un échec. Android a mis en place une sécurité supplémentaire:

Pour les applications ciblant Android 7.0, l'infrastructure Android applique la stratégie de l'API StrictMode qui interdit l'exposition des fichiers: // URI en dehors de votre application. Si une intention contenant un URI de fichier quitte votre application, celle-ci échoue avec une exception FileUriExposedException.

Alors j'ai essayé ceci:

    Uri myuri;
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){
        myuri = Uri.parse("file://"+outapk);
    } else {
        File o = new File(outapk);
        myuri = FileProvider.getUriForFile(con, con.getApplicationContext().getPackageName() + ".provider", o);
    }
    Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(myuri,"application/vnd.Android.package-archive");
    con.startActivity(promptInstall);

mais obtenez une exception fatale:

com.Android.packageinstaller "Caused by: Java.lang.SecurityException: Permission Denial: opening provider Android.support.v4.content.FileProvider from ProcessRecord{b42ee8a 6826:com.Android.packageinstaller/u0a15} (pid=6826, uid=10015) that is not exported from uid 10066". 

J'ai export = true dans mon manifeste.

Le problème semble être que packageinstaller ne peut pas utiliser un contenu: // uri.

Existe-t-il un moyen de permettre à une application d'installer progressivement un apk avec api24?

9
elsie

Existe-t-il un moyen de permettre à une application d'installer progressivement un apk avec api24?

Ajoutez addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) à votre configuration promptInstall pour accorder un accès en lecture au contenu.

J'ai export = true dans mon manifeste.

Pas sur votre FileProvider car cela ferait planter votre application.

Le problème semble être que packageinstaller ne peut pas utiliser un contenu: // uri.

Non, le problème est que vous n'avez pas autorisé le programme d'installation du paquet à lire à partir de cette Uri. Si le programme d'installation du paquet n'avait pas été en mesure d'utiliser un schéma content, vous auriez obtenu un ActivityNotFoundException.

Notez cependant que c'est uniquement avec Android 7.0 que le programme d'installation du paquet commence à prendre en charge content. Les versions antérieures d'Android doivent utiliser file.

11
CommonsWare

Pour Oreo, ajoutez une autorisation dans AndroidManifast (sinon, cela échoue en silence)

<uses-permission Android:name="Android.permission.REQUEST_INSTALL_PACKAGES"/>

maintenant ajouter à votre manifeste

  <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/provider_paths"/>
</provider>

dans le répertoire xml ajouter ...

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

utilisez ensuite ces codes où vous voulez.

File directory = Environment.getExternalStoragePublicDirectory("myapp_folder"); 

 File file = new File(directory, "myapp.apk"); // assume refers to "sdcard/myapp_folder/myapp.apk"


    Uri fileUri = Uri.fromFile(file); //for Build.VERSION.SDK_INT <= 24

    if (Build.VERSION.SDK_INT >= 24) {

        fileUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".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_NEW_TASK);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //dont forget add this line
    context.startActivity(intent);
}
1
smartmob

Pour Oreo, Ajouter une autorisation dans AndroidManifast

<uses-permission Android:name="Android.permission.REQUEST_INSTALL_PACKAGES"/>
1
Dwivedi Ji

Ajouter un fichier dans res/xml -> provider_paths.xml

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

Ajoutez ce code dans AndroidManifest.xml

     <provider
        Android:name="Android.support.v4.content.FileProvider"
        Android:authorities="com.example.provider" <-- change this with your package name
        Android:exported="false"
        Android:grantUriPermissions="true">
        <meta-data
            Android:name="Android.support.FILE_PROVIDER_PATHS"
            Android:resource="@xml/provider_paths"/>
    </provider>

lancez ce code pour installer votre application ou ouvrir

    public void installApk(String file) {
        Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider",new File(file));
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(uri, "application/vnd.Android.package-archive");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        context.startActivity(intent);
    }
0
Ahmad Aghazadeh