Helpex - Trao đổi & giúp đỡ Đăng nhập
74

Tôi cần thêm các tiêu đề tùy chỉnh vào MỌI yêu cầu đến từ WebView. Tôi biết loadURLcó tham số cho extraHeaders, nhưng chúng chỉ được áp dụng cho yêu cầu ban đầu. Tất cả các yêu cầu tiếp theo không chứa các tiêu đề. Tôi đã xem xét tất cả các phần ghi đè WebViewClient, nhưng không có gì cho phép thêm tiêu đề vào các yêu cầu tài nguyên - onLoadResource(WebView view, String url). Bất kỳ trợ giúp sẽ là tuyệt vời.

Cảm ơn, Ray

74 hữu ích 5 bình luận 85k xem chia sẻ
12 trả lời 12
64

Thử

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

Để thêm tiêu đề vào yêu cầu tải tài nguyên, hãy tạo WebViewClient tùy chỉnh và ghi đè:

API 24+:
WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
or
WebResourceResponse shouldInterceptRequest(WebView view, String url)
64 hữu ích 5 bình luận chia sẻ
30

Bạn sẽ cần chặn từng yêu cầu bằng WebViewClient.shouldInterceptRequest

Với mỗi lần chặn, bạn sẽ cần lấy url, tự thực hiện yêu cầu này và trả về luồng nội dung:

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);

Nếu mục tiêu API tối thiểu của bạn là cấp 21 , bạn có thể sử dụng nên nênInterceptRequest mới cung cấp cho bạn thông tin yêu cầu bổ sung (chẳng hạn như tiêu đề) thay vì chỉ URL.

30 hữu ích 5 bình luận chia sẻ
18

Có thể phản hồi của tôi khá muộn, nhưng nó bao gồm API dướitrên 21 cấp.

Để thêm các tiêu đề, chúng ta nên chặn mọi yêu cầutạo một yêu cầu mới với các tiêu đề được yêu cầu.

Vì vậy, chúng ta cần ghi đè phương thức ShouldInterceptRequest được gọi trong cả hai trường hợp: 1. cho API cho đến cấp 21; 2. cho API cấp 21+ trở lên

    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;
            }

        }
   });

Nếu loại phản ứng nên được xử lý, bạn có thể thay đổi

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

đến

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

và thêm phương thức

        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;
        }
18 hữu ích 0 bình luận chia sẻ
17

Như đã đề cập trước đây, bạn có thể làm điều này:

 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);

Tôi đã thử nghiệm điều này và với Bộ điều khiển MVC mà tôi đã mở rộng Thuộc tính ủy quyền để kiểm tra tiêu đề và tiêu đề ở đó.

17 hữu ích 5 bình luận chia sẻ
7

Điều này làm việc cho tôi:

  1. Trước tiên, bạn cần tạo phương thức, sẽ trả về các tiêu đề bạn muốn thêm vào yêu cầu:

    private Map<String, String> getCustomHeaders()
    {
        Map<String, String> headers = new HashMap<>();
        headers.put("YOURHEADER", "VALUE");
        return headers;
    }
  2. Thứ hai bạn cần tạo 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;
        }
    };
    }
  3. Thêm WebViewClient vào WebView của bạn:

    webView.setWebViewClient(getWebViewClient());

Hi vọng điêu nay co ich.

7 hữu ích 2 bình luận chia sẻ
4

Bạn sẽ có thể kiểm soát tất cả các tiêu đề của mình bằng cách bỏ qua loadUrl và viết loadPage của riêng bạn bằng cách sử dụng kết nối httpURLC của Java. Sau đó sử dụng loadData của webview để hiển thị phản hồi.

Không có quyền truy cập vào các tiêu đề mà Google cung cấp. Chúng nằm trong một cuộc gọi JNI, nằm sâu trong nguồn WebView.

4 hữu ích 1 bình luận chia sẻ
1

Điều này làm việc cho tôi. Tạo WebViewClient như thế này bên dưới và đặt webclient vào chế độ xem web của bạn. Tôi đã phải sử dụng webview.loadDataWithBaseURL vì các url của tôi (trong nội dung của tôi) không có cơ sở mà chỉ có các url tương đối. Bạn sẽ nhận được url chính xác chỉ khi có một bộ cơ sở sử dụng 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;
            }
        }
    };

}
1 hữu ích 2 bình luận chia sẻ
0

Tôi đến cùng một vấn đề và giải quyết.

Như đã nói trước khi bạn cần tạo WebViewClient tùy chỉnh của mình và ghi đè phương thức ShouldInterceptRequest.

WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)

Phương pháp đó sẽ phát hành một webView.loadUrl trong khi trả lại một WebResourceResponse "trống".

Một cái gì đó như thế này:

@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);
}
0 hữu ích 3 bình luận chia sẻ
0

Đây là một triển khai bằng cách sử dụng 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
    }
}

Lưu ý rằng điều này không hoạt động đối với các yêu cầu POST vì WebResourceRequest không cung cấp dữ liệu POST. Có một Thư viện dữ liệu yêu cầu - WebViewClient sử dụng cách khắc phục JavaScript để chặn dữ liệu POST.

0 hữu ích 0 bình luận chia sẻ
2

Bạn có thể sử dụng điều này:

@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 hữu ích 1 bình luận chia sẻ
4

Trang: MainActivity.java

nhập android.webkit.WebView;

lớp công khai MainActivity mở rộng AppCompatActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    WebView WebViw = (WebView) findViewById(R.id.webView1);
    WebViw.getSettings().setJavaScriptEnabled(true);
    WebViw.getSettings().setUserAgentString("User-Agent");
    WebViw.loadUrl("http://www.educationlife-online.com/");

}

}

cách này là thành công.

4 hữu ích 0 bình luận chia sẻ
9

Dùng cái này:

webView.getSettings().setUserAgentString("User-Agent");
9 hữu ích 1 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ java android webkit android-webview , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading