Мне нужно добавлять пользовательские заголовки к КАЖДОМУ запросу, исходящему от WebView. Я знаю, что loadURL
есть параметр для extraHeaders
, но они применяются только к первоначальному запросу. Все последующие запросы не содержат заголовков. Я просмотрел все переопределения WebViewClient
, но ничего не позволяет добавлять заголовки в запросы ресурсов - onLoadResource(WebView view, String url)
. Любая помощь была бы замечательной.
Спасибо, Рэй
Ответы:
Пытаться
Для добавления заголовков к запросам загрузки ресурсов создайте собственный WebViewClient и переопределите:
API 24+: WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) or WebResourceResponse shouldInterceptRequest(WebView view, String url)
источник
view.loadUrl("http://www.facebook.com", extraHeaders)
,'http://static.fb.com/images/logo.png'
из веб-просмотра отправляется несколько запросов к ресурсам, таких как и т. Д. Для этих запросов дополнительные заголовки не добавляются. И shouldOverrideUrlLoading не вызывается во время таких запросов ресурсов. Вызывается обратный вызов OnLoadResource, но на этом этапе нельзя установить заголовки.WebViewClient.shouldInterceptRequest(android.webkit.WebView view, java.lang.String url)
Check out для получения дополнительной информации.shouldInterceptRequest
метода, не могли бы вы объяснить, как?Вам нужно будет перехватывать каждый запрос с помощью WebViewClient.shouldInterceptRequest
При каждом перехвате вам нужно будет взять URL-адрес, сделать этот запрос самостоятельно и вернуть поток контента:
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);
Если ваша минимальная цель API - уровень 21 , вы можете использовать новый shouldInterceptRequest, который дает вам дополнительную информацию о запросе (например, заголовки) вместо только URL-адреса.
источник
public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request)
вместо этого подробнее здесьВозможно, мой ответ довольно поздний, но он касается API ниже и выше 21 уровня.
Чтобы добавить заголовки, мы должны перехватить каждый запрос и создать новый с необходимыми заголовками.
Поэтому нам нужно переопределить метод shouldInterceptRequest, вызываемый в обоих случаях: 1. для API до уровня 21; 2. для уровня API 21+
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; } } });
Если необходимо обработать тип ответа, вы можете изменить
return new WebResourceResponse( null, // <- Change here response.header("content-encoding", "utf-8"), response.body().byteStream() );
к
return new WebResourceResponse( getMimeType(url), // <- Change here response.header("content-encoding", "utf-8"), response.body().byteStream() );
и добавить метод
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; }
источник
Как упоминалось ранее, вы можете сделать это:
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);
Я тестировал это и так далее с помощью контроллера MVC, который расширил атрибут авторизации, чтобы проверить заголовок, и заголовок там.
источник
Это работает для меня:
Для начала вам нужно создать метод, который будет возвращать ваши заголовки, которые вы хотите добавить в запрос:
private Map<String, String> getCustomHeaders() { Map<String, String> headers = new HashMap<>(); headers.put("YOURHEADER", "VALUE"); return headers; }
Во-вторых, вам нужно создать WebViewClient:
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; } }; }
Добавьте WebViewClient в свой WebView:
Надеюсь это поможет.
источник
loadUrl(String url, Map<String, String> additionalHttpHeaders)
означает добавление заголовков дополненийВы должны иметь возможность контролировать все свои заголовки, пропустив loadUrl и написав свой собственный loadPage с использованием Java HttpURLConnection. Затем используйте loadData веб-просмотра для отображения ответа.
Нет доступа к заголовкам, которые предоставляет Google. Они находятся в вызове JNI глубоко в источнике WebView.
источник
Вот реализация с использованием HttpUrlConnection:
class CustomWebviewClient : WebViewClient() { private val charsetPattern = Pattern.compile(".*?charset=(.*?)(;.*)?$") override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? { try { val connection: HttpURLConnection = URL(request.url.toString()).openConnection() as HttpURLConnection connection.requestMethod = request.method for ((key, value) in request.requestHeaders) { connection.addRequestProperty(key, value) } connection.addRequestProperty("custom header key", "custom header value") var contentType: String? = connection.contentType var charset: String? = null if (contentType != null) { // some content types may include charset => strip; e. g. "application/json; charset=utf-8" val contentTypeTokenizer = StringTokenizer(contentType, ";") val tokenizedContentType = contentTypeTokenizer.nextToken() var capturedCharset: String? = connection.contentEncoding if (capturedCharset == null) { val charsetMatcher = charsetPattern.matcher(contentType) if (charsetMatcher.find() && charsetMatcher.groupCount() > 0) { capturedCharset = charsetMatcher.group(1) } } if (capturedCharset != null && !capturedCharset.isEmpty()) { charset = capturedCharset } contentType = tokenizedContentType } val status = connection.responseCode var inputStream = if (status == HttpURLConnection.HTTP_OK) { connection.inputStream } else { // error stream can sometimes be null even if status is different from HTTP_OK // (e. g. in case of 404) connection.errorStream ?: connection.inputStream } val headers = connection.headerFields val contentEncodings = headers.get("Content-Encoding") if (contentEncodings != null) { for (header in contentEncodings) { if (header.equals("gzip", true)) { inputStream = GZIPInputStream(inputStream) break } } } return WebResourceResponse(contentType, charset, status, connection.responseMessage, convertConnectionResponseToSingleValueMap(connection.headerFields), inputStream) } catch (e: Exception) { e.printStackTrace() } return super.shouldInterceptRequest(view, request) } private fun convertConnectionResponseToSingleValueMap(headerFields: Map<String, List<String>>): Map<String, String> { val headers = HashMap<String, String>() for ((key, value) in headerFields) { when { value.size == 1 -> headers[key] = value[0] value.isEmpty() -> headers[key] = "" else -> { val builder = StringBuilder(value[0]) val separator = "; " for (i in 1 until value.size) { builder.append(separator) builder.append(value[i]) } headers[key] = builder.toString() } } } return headers } }
Обратите внимание, что это не работает для запросов POST, поскольку WebResourceRequest не предоставляет данные POST. Существует библиотека данных запроса - WebViewClient, которая использует обходной путь внедрения JavaScript для перехвата данных POST.
источник
Это сработало для меня. Создайте WebViewClient, как показано ниже, и установите веб-клиент для своего веб-просмотра. Мне пришлось использовать webview.loadDataWithBaseURL, поскольку мои URL-адреса (в моем контенте) не имели базового URL-адреса, а имели только относительные URL-адреса. Вы получите правильный URL-адрес только при наличии базового URL-адреса, установленного с помощью loadDataWithBaseURL.
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; } } }; }
источник
Вы можете использовать это:
@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; }
источник
Я столкнулся с той же проблемой и решил.
Как было сказано ранее, вам необходимо создать собственный WebViewClient и переопределить метод shouldInterceptRequest.
WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
Этот метод должен выдавать webView.loadUrl при возврате «пустого» WebResourceResponse.
Что-то вроде этого:
@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); }
источник
Использовать это:
webView.getSettings().setUserAgentString("User-Agent");
источник