Soru WebView kaynak isteklerine özel başlık ekleyin - android


WebView'den gelen HER talebe özel başlık eklemem gerekiyor. biliyorum loadURL parametresi var extraHeadersAncak bunlar sadece ilk talebe uygulanır. Tüm sonraki istekler başlık içermiyor. İçindeki tüm geçersiz kılmaları inceledim WebViewClientama hiçbir şey kaynak isteklerine başlık eklemez. onLoadResource(WebView view, String url). Herhangi bir yardım harika olurdu.

Teşekkürler, ışın


67
2017-09-30 13:06


Menşei


@MediumOne: Bu, eksik olduğu düşünülen bir özellik olduğu kadar bir hata değildir. HTTP belirtiminde, sonraki HTTP isteklerinin önceki HTTP isteklerinden rastgele başlıkları yansıtması gerektiğini söyleyen hiçbir şeyin farkında değilim. - CommonsWare
@CommonsWare: "Sonraki" kelimesi burada yanıltıcıdır. Yazdığımda "facebook.com"; facebook.com ana sayfasını yüklemek için herhangi bir tarayıcıda, CSS, js ve img dosyalarını yüklemek için birkaç destekleyici "kaynak isteği" vardır. Bunu, F12 özelliğini (Ağ sekmesi) kullanarak Chrome'da kontrol edebilirsiniz. Bu istekler için web görünümü başlık eklemiyor. Kullanarak FireFox isteklerine özel başlık eklemeye çalıştım. addons.mozilla.org/en-us/firefox/addon/modify-headers Eklenti. Bu eklenti, bu tür tüm üstbilgi "kaynak isteklerine" başlık ekleyebildi. Bence WebView aynı şeyi yapmalı. - MediumOne
@MediumOne: "WebView'in aynı şeyi yapması gerektiğini düşünüyorum" - eksik olduğunu düşündüğünüz bir özellik. Firefox'u yapmak için bir eklentiye başvurmak zorunda kaldığınızı unutmayın. Önerilen özellikinizin kötü bir fikir olduğunu söylemiyorum. Bunu bir hata olarak nitelendirmenin sebebinin, Android'e eklenen bu özelliğin nedenini almanıza yardımcı olamayacağını söylüyorum. - CommonsWare
@CommonsWare: Özel bir HTTP proxy'si ile çalışacak şekilde yapılandırılabilen bir tarayıcı oluşturmak için WebView kullanıyorum. Bu vekil, isteklerin özel bir üstbilgiye sahip olması gereken özel kimlik doğrulama kullanır. Artık web görünümü, özel üstbilgileri ayarlamak için bir API sağlıyor, ancak dahili olarak, başlığını oluşturduğu tüm kaynak isteklerine ayarlamıyor. Bu isteklerin yanı sıra üstbilgileri ayarlamak için herhangi bir ek API yoktur. Bu nedenle, WebView isteklerine özel üstbilgileri eklemeye dayanan herhangi bir özellik başarısız olur. - MediumOne
@CommonsWare - Bu konuşmayı 4 yıl sonra tekrar ziyaret ediyorum. Şimdi katılıyorum - bu bir hata olmamalı. HTTP belirtiminde, sonraki isteklerin aynı üstbilgileri göndermesi gerektiğini belirten hiçbir şey yoktur. :) - MediumOne


Cevaplar:


Deneyin

loadUrl(String url, Map<String, String> extraHeaders)

Kaynak yükleme isteklerine üstbilgi eklemek için, özel WebViewClient oluşturun ve geçersiz kılın:

API 24+:
WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
or
WebResourceResponse shouldInterceptRequest(WebView view, String url)

61
2017-11-21 08:50



Üzgünüm, ama bu işe yaramıyor. Sadece başlıkları da ilk istekleri uygular. Kaynak isteklerine başlıklar eklenmez. Diğer fikirler? Teşekkürler. - Ray
Evet, WebClient.shouldOverrideUrlLoading'i şu şekilde geçersiz kılın: public boolean shouldOverrideUrlLoading (WebView görünümü, Dize URL'si) {view.loadUrl (url, extraHeaders); gerçek geri dönüş; } - peceps
@peceps - kaynak yükleme sırasında geri arama 'shouldOverrideUrlLoading' çağrılmıyor. Örneğin, denediğimizde view.loadUrl("http://www.facebook.com", extraHeaders)gibi çoklu kaynak istekleri var 'http://static.fb.com/images/logo.png' web sitesinden gönderilen vb. Bu istekler için fazladan başlık eklenmez. Ve bu tür kaynak istekleri sırasında shouldOverrideUrlLoading çağrılmıyor. Geri arama 'OnLoadResource' çağrıldı, ancak bu noktada üstbilgileri ayarlamanın bir yolu yok. - MediumOne
@MediumOne, kaynak yükleme için geçersiz kılma WebViewClient.shouldInterceptRequest(android.webkit.WebView view, java.lang.String url) Çıkış yapmak API daha fazlası için. - yorkw
@yorkw: Bu yöntem tüm kaynak istek URL'lerini yakalar. Ancak, bu isteklere başlık eklemenin bir yolu yoktur. Amacım, tüm isteklere özel HTTP üstbilgileri eklemektir. Bu kullanılarak elde edilebilir shouldInterceptRequest yöntem, nasıl açıklayabilir misiniz? - MediumOne


Her isteği kullanarak engellemeniz gerekecek WebViewClient.shouldInterceptRequest

Her bir engellemeyle, URL’yi almanız, bu isteği kendiniz yapmanız ve içerik akışını geri göndermeniz gerekir:

WebViewClient wvc = new WebViewClient() {
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

        try {
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("MY-CUSTOM-HEADER", "header value");
            httpGet.setHeader(HttpHeaders.USER_AGENT, "custom user-agent");
            HttpResponse httpReponse = client.execute(httpGet);

            Header contentType = httpReponse.getEntity().getContentType();
            Header encoding = httpReponse.getEntity().getContentEncoding();
            InputStream responseInputStream = httpReponse.getEntity().getContent();

            String contentTypeValue = null;
            String encodingValue = null;
            if (contentType != null) {
                contentTypeValue = contentType.getValue();
            }
            if (encoding != null) {
                encodingValue = encoding.getValue();
            }
            return new WebResourceResponse(contentTypeValue, encodingValue, responseInputStream);
        } catch (ClientProtocolException e) {
            //return null to tell WebView we failed to fetch it WebView should try again.
            return null;
        } catch (IOException e) {
             //return null to tell WebView we failed to fetch it WebView should try again.
            return null;
        }
    }
}

Webview wv = new WebView(this);
wv.setWebViewClient(wvc);

Minimum API hedefiniz seviye 21 ise, yeni kullanabilirsin shouldInterceptRequest Bu, yalnızca URL yerine size ek bilgi (başlık gibi) verir.


28
2018-04-23 00:13



Sadece birisinin aynı durumla karşılaşması durumunda, bu hile kullanıyorum. (Bu zaten iyi bir şey.) İşte size bir not. Charset gibi isteğe bağlı parametreler içerebilen http içerik türü üstbilgisi, MIME türüyle tam olarak uyumlu olmadığından, WebResourceResponse yapıcısının ilk parametresi gereksinimini karşılar, böylece MIME türü bölümünü içerik türünden herhangi bir ortama göre çıkarmamız gerekir. Çoğu durum için çalışmasını sağlamak için RegExp gibi düşünebilir. - James Chen
Bu etkinlik kullanımdan kaldırıldı. public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request) bunun yerine daha fazlasını bul İşte - Hirdesh Vishwdewa
@HirdeshVishwdewa - son cümleye bakın. - Martin Konecny
Üst sınıfın shouldInterceptRequest yönteminin sonuçlarını web görünümünüz ve değiştirilmiş isteğinizi parametre olarak döndürerek kendi yükünüzü atlayabilirsiniz. Bu özellikle URL'ye göre tetiklediğiniz, yeniden yüklemede değişmediği ve sonsuz bir döngü içinde çalışacağı senaryolarda kullanışlıdır. Yine de yeni istek örneği için çok teşekkürler. Bir şeyleri ele almanın Java yolları bana karşı son derece mantıklı. - Erik Reppen
HttpClient, compileSdk 23 ve üstü ile kullanılamaz. - Tamás Kozmér


Daha önce de belirtildiği gibi, bunu yapabilirsiniz:

 WebView  host = (WebView)this.findViewById(R.id.webView);
 String url = "<yoururladdress>";

 Map <String, String> extraHeaders = new HashMap<String, String>();
 extraHeaders.put("Authorization","Bearer"); 
 host.loadUrl(url,extraHeaders);

Bunu test ettim ve bir MVC Kontrolörüyle, başlığı kontrol etmek için Başlık Yetkilendirmesini genişlettim ve başlık orada.


14
2017-09-11 19:55



Bu çalışmıyor ... ?? - Hirdesh Vishwdewa
Yazıldığı ve Kit-Kat ile birlikte çalıştığına göre bunu tekrar ele almak zorunda kalacağım. Lolly Pop ile denemedim. - leeroya
Jöle fasulyesi ya da Marshmallow'da benim için çalışmıyor ... başlıklarda hiçbir şey değişmiyor - Erik Verboom
Bu OP'nin sorduğu şeyi yapmaz. Webview tarafından yapılan tüm isteklere başlık eklemek istiyor. Bu, yalnızca ilk istek için özel başlık ekler - NinjaCoder
OP'nin sorduğu bu değil - Akshay


Belki cevabım geç kaldı, ancak API'yi kapsar altında ve yukarıdaki 21 seviye.

Başlıkları eklemek için her talebi engellemek ve yeni bir tane oluştur gerekli başlıklarla.

Bu yüzden geçersiz kılmaya ihtiyacımız var. shouldInterceptRequest her iki durumda da denilen yöntem: 1. API için seviye 21'e kadar; 2. API seviyesi 21+ için

    webView.setWebViewClient(new WebViewClient() {

        // Handle API until level 21
        @SuppressWarnings("deprecation")
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

            return getNewResponse(url);
        }

        // Handle API 21+
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {

            String url = request.getUrl().toString();

            return getNewResponse(url);
        }

        private WebResourceResponse getNewResponse(String url) {

            try {
                OkHttpClient httpClient = new OkHttpClient();

                Request request = new Request.Builder()
                        .url(url.trim())
                        .addHeader("Authorization", "YOU_AUTH_KEY") // Example header
                        .addHeader("api-key", "YOUR_API_KEY") // Example header
                        .build();

                Response response = httpClient.newCall(request).execute();

                return new WebResourceResponse(
                        null,
                        response.header("content-encoding", "utf-8"),
                        response.body().byteStream()
                );

            } catch (Exception e) {
                return null;
            }

        }
   });

Yanıt tipi işlenmeli ise değişebilir

        return new WebResourceResponse(
                null, // <- Change here
                response.header("content-encoding", "utf-8"),
                response.body().byteStream()
        );

için

        return new WebResourceResponse(
                getMimeType(url), // <- Change here
                response.header("content-encoding", "utf-8"),
                response.body().byteStream()
        );

ve yöntem ekle

        private String getMimeType(String url) {
            String type = null;
            String extension = MimeTypeMap.getFileExtensionFromUrl(url);

            if (extension != null) {

                switch (extension) {
                    case "js":
                        return "text/javascript";
                    case "woff":
                        return "application/font-woff";
                    case "woff2":
                        return "application/font-woff2";
                    case "ttf":
                        return "application/x-font-ttf";
                    case "eot":
                        return "application/vnd.ms-fontobject";
                    case "svg":
                        return "image/svg+xml";
                }

                type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            }

            return type;
        }

14
2018-04-10 09:34





Bu benim için çalışıyor:

  1. Öncelikle, sizin İstek eklemek istediğiniz başlıklar:

    private Map<String, String> getCustomHeaders()
    {
        Map<String, String> headers = new HashMap<>();
        headers.put("YOURHEADER", "VALUE");
        return headers;
    }
    
  2. İkincisi, WebViewClient'i oluşturmanız gerekir:

    private WebViewClient getWebViewClient()
    {
    
        return new WebViewClient()
        {
    
        @Override
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
        {
            view.loadUrl(request.getUrl().toString(), getCustomHeaders());
            return true;
        }
    
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url)
        {
            view.loadUrl(url, getCustomHeaders());
            return true;
        }
    };
    }
    
  3. WebViewClient'i WebView'unuza ekleyin:

    webView.setWebViewClient(getWebViewClient());
    

Bu yardımcı olur umarım.


5
2018-01-25 02:32



İyi görünüyor, ama bunu yapıyor eklemek bir başlık veya bu mu değiştirmek üstbilgiler - Ivo Renkema
Ajax aramaları ve kaynak talebi için çalışıyor mu? - Xavier Lin


Tüm üstbilgilerinizi, loadUrl'yi atlayıp Java'nın HttpURLConnection'ı kullanarak kendi loadPage'inizi yazarak kontrol edebilmelisiniz. Ardından yanıtı görüntülemek için webview'in loadData'sını kullanın.

Google’ın sağladığı başlıklara erişim yoktur. WebView kaynağında derin bir JNI çağrısındalar.


4
2018-02-12 12:32



Cevabınızda ne söylediğine dair bir referans var mı? Cevaplarınızla uygulama referansları verirseniz başkaları için yararlı olacaktır. - Hirdesh Vishwdewa


Bu benim için çalıştı. WebViewClient'i aşağıdaki gibi oluşturun ve webclient'i web görünümünüze ayarlayın. Webview.loadDataWithBaseURL kullanmak zorunda kaldım, benim URL'lerim (içeriğimde) baseurl ama sadece nispi url'ler yoktu. Url'yi, yalnızca loadDataWithBaseURL kullanılarak bir baseurl kümesi olduğunda doğru şekilde alırsınız.

public WebViewClient getWebViewClientWithCustomHeader(){
    return new WebViewClient() {
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            try {
                OkHttpClient httpClient = new OkHttpClient();
                com.squareup.okhttp.Request request = new com.squareup.okhttp.Request.Builder()
                        .url(url.trim())
                        .addHeader("<your-custom-header-name>", "<your-custom-header-value>")
                        .build();
                com.squareup.okhttp.Response response = httpClient.newCall(request).execute();

                return new WebResourceResponse(
                        response.header("content-type", response.body().contentType().type()), // You can set something other as default content-type
                        response.header("content-encoding", "utf-8"),  // Again, you can set another encoding as default
                        response.body().byteStream()
                );
            } catch (ClientProtocolException e) {
                //return null to tell WebView we failed to fetch it WebView should try again.
                return null;
            } catch (IOException e) {
                //return null to tell WebView we failed to fetch it WebView should try again.
                return null;
            }
        }
    };

}

1
2018-04-17 20:30



post yöntemi için çalışmıyor: s - Badre
Benim için işe yarar: RequestPody reqbody = RequestBody.create (null, ""); - Karoly


Aynı problemle karşılaştım ve çözdüm.

Önceden söylendiği gibi, özel WebViewClient'inizi oluşturmanız ve shouldInterceptRequest yöntemini geçersiz kılmanız gerekir.

WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)

Bu yöntem bir "boş" WebResourceResponse döndürürken bir webView.loadUrl vermelidir.

Böyle bir şey:

@Override
public boolean shouldInterceptRequest(WebView view, WebResourceRequest request) {

    // Check for "recursive request" (are yor header set?)
    if (request.getRequestHeaders().containsKey("Your Header"))
        return null;

    // Add here your headers (could be good to import original request header here!!!)
    Map<String, String> customHeaders = new HashMap<String, String>();
    customHeaders.put("Your Header","Your Header Value");
    view.loadUrl(url, customHeaders);

    return new WebResourceResponse("", "", null);
}

1
2018-02-16 17:58



Üzgünüm, kodu çözdüm! - John


Bunu kullanabilirsiniz:

@Override

 public boolean shouldOverrideUrlLoading(WebView view, String url) {

                // Here put your code
                Map<String, String> map = new HashMap<String, String>();
                map.put("Content-Type","application/json");
                view.loadUrl(url, map);
                return false;

            }

-2
2017-12-18 12:30



Bu sadece URL'yi yeniden yüklemeyi sürdürüyor, değil mi? - Onheiron


Bunu kullan:

webView.getSettings().setUserAgentString("User-Agent");

-9
2017-11-29 22:34



Bu soruya cevap vermiyor - younes0