web-dev-qa-db-fra.com

Victimes en kit: Interdit de charger la ressource locale: file: ///Android_asset/webkit/Android-weberror.png

J'ai une application qui utilise WebViews. J'ai modifié mon targetAPI de 18 à 19 ans et je teste actuellement le nouveau 4.4. Pour une raison quelconque, j'obtiens cette erreur: Not allowed to load local resource: file:///Android_asset/webkit/Android-weberror.png sur 4.4 mais pas sur 4.3, quelqu'un a-t-il la moindre idée pourquoi?

Comme je ne sais pas vraiment par où commencer, je ne peux pas donner le code complet. Cela a peut-être quelque chose à voir avec la méthode shouldInterceptRequest(Webview, String) dans WebViewClient mais je ne suis pas vraiment sûr. Si j'en sais plus, je mettrai à jour la question.

21
dumazy

"Interdiction de charger une ressource locale" est une erreur de sécurité d'origine. KitKat WebView a des restrictions de sécurité plus strictes et il semble que celles-ci soient déjà mises en place. FWIW J'ai juste essayé de charger un URL: /// Android_asset et cela a fonctionné.

Avez-vous appelé des API WebSettings associées aux fichiers (comme setAllowFileAccess (false)) par hasard? Essayez-vous de charger la ressource à partir d'une URL https:?

8
marcin.kosiba

Un peu d'un piratage intrusif, mais j'ai résolu ce problème en introduisant un "jeton unique" et en implémentant la variable WebViewClient avec une substitution shouldInterceptRequest.

Commencez par changer l'URL de file:///Android/asset en un chemin relatif avec un jeton d'identification unique:

<script src="**injection**www/scripts.js"></script>

Ensuite, remplacez shouldInterceptRequest comme suit:

// Injection token as specified in HTML source
private static final String INJECTION_TOKEN = "**injection**";

webView.setWebViewClient(new WebViewClient() {

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        WebResourceResponse response = super.shouldInterceptRequest(view, url);
        if(url != null && url.contains(INJECTION_TOKEN)) {
            String assetPath = url.substring(url.indexOf(INJECTION_TOKEN) + INJECTION_TOKEN.length(), url.length());
            try {
                response = new WebResourceResponse(
                        "application/javascript",
                        "UTF8",
                        getContext().getAssets().open(assetPath)
                );
            } catch (IOException e) {
                e.printStackTrace(); // Failed to load asset file
            }
        }
        return response;
    }
});

Cela risquerait de dégrader les performances de WebView légèrement car nous appelons la contains() sur chaque ressource que l’on tente de charger, mais c’est la seule solution que j’ai trouvée à ce problème.

20
CodingIntrigue

J'ai trouvé que j'avais ce problème sur KitKat lorsque j'ai utilisé webview.loadData(). Si au lieu de cela, j'ai utilisé webview.loadDataWithBaseURL() (j'ai utilisé "fichier: /// Android_asset /" comme baseURL), le problème a disparu.

Les méthodes setAllowFileAccess(), setAllowFileAccessFromFileURLs() et setAllowUniversalAccessFromFileURLs() n'ont eu aucun effet visible.

17
mikejonesguy

ICI IS LA SOLUTION: Ce problème se produit lorsque vous essayez de charger un fichier à partir de projets de bibliothèque. Si votre application dépend d'une bibliothèque hébergeant les fichiers WebView et HTML, vous devez inclure les actifs de ce projet de bibliothèque dans le projet d'application principal lors de la compilation. Par exemple, IntelliJ a une option pour le faire. Dans les paramètres du compilateur "Inclure les actifs des dépendances dans APK", assurez-vous que vos fichiers d'actif doivent avoir des noms différents de ceux de l'application principale. Vous ne voulez pas que le fichier index.html du projet de bibliothèque soit remplacé par l'application principale.

5
Nizzy

La solution ci-dessous fonctionne pour moi.

webview.loadDataWithBaseURL( baseUrl, htmlStr, "text/html", "UTF-8", "");

baseUrl est votre domaine externe, pas le fichier: /// Android_asset/(i.e. http://a.domain.com ).

1
CodeRen

Il peut être nécessaire d'ajouter une permission 

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

à un manifeste.

Cette autorisation est appliquée à partir du niveau 19 de l'API.

1
nor_miya

Non disponible pour le moment, cela fonctionne maintenant (bien que ce ne soit pas recommandé):

webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

Voici ce que dit la doc sur setMixedContentMode:

Configure le comportement de la vue Web lorsqu'une origine sécurisée tente de charger une ressource à partir d'une origine non sécurisée. Par défaut, les applications qui ciblent KitKat ou une valeur inférieure à MIXED_CONTENT_ALWAYS_ALLOW. Les applications ciblant Lollipop sont définies par défaut sur MIXED_CONTENT_NEVER_ALLOW. Le mode de fonctionnement préféré et le plus sûr pour WebView est MIXED_CONTENT_NEVER_ALLOW et l'utilisation de MIXED_CONTENT_ALWAYS_ALLOW est fortement déconseillée.

Cependant, cela pourrait ne pas répondre à la question initiale; il semble que la restriction n'ait commencé qu'avec Lollipop.

1
wamfous

J'ai trouvé une solution de contournement de Nice dans ce lien: http://trentmilton.com/Android-webview.html

Un résumé de la solution est quelque chose comme: 

WebView webView = new WebView(this); // this is the context
webView.getSettings().setDomStorageEnabled(true);

J'espère que cela pourra aider

0
akdeveloper