WebView 리소스 요청에 사용자 지정 헤더 추가-Android
WebView에서 오는 모든 요청에 사용자 지정 헤더를 추가해야합니다. 에 loadURL
대한 매개 변수가 있다는 것을 알고 extraHeaders
있지만 초기 요청에만 적용됩니다. 모든 후속 요청에는 헤더가 포함되지 않습니다. 에서 모든 재정의를 살펴 보았지만 WebViewClient
리소스 요청에 헤더를 추가 할 수있는 것은 없습니다 onLoadResource(WebView view, String url)
. 어떤 도움이라도 좋을 것입니다.
고마워, 레이
시험
loadUrl(String url, Map<String, String> extraHeaders)
리소스로드 요청에 헤더를 추가하려면 사용자 지정 WebViewClient를 만들고 다음을 재정의합니다.
API 24+:
WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
or
WebResourceResponse shouldInterceptRequest(WebView view, String url)
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 인 경우 URL 대신 추가 요청 정보 (예 : 헤더)를 제공 하는 새로운 shouldInterceptRequest 를 사용할 수 있습니다 .
어쩌면 내 대답은 아주 늦게, 그러나 그것은 API를 커버 아래 및 위의 21 수준.
헤더를 추가하려면 모든 요청을 가로 채서 필요한 헤더로 새 요청 을 만들어야 합니다.
따라서 두 경우 모두에서 호출되는 shouldInterceptRequest 메서드 를 재정의해야합니다 . 1. 수준 21까지의 API; 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);
나는 헤더를 검사하기 위해 Authorize Attribute를 확장 한 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에 추가합니다.
webView.setWebViewClient(getWebViewClient());
도움이 되었기를 바랍니다.
loadUrl을 건너 뛰고 Java의 HttpURLConnection을 사용하여 자체 loadPage를 작성하여 모든 헤더를 제어 할 수 있어야합니다. 그런 다음 webview의 loadData를 사용하여 응답을 표시합니다.
Google이 제공하는 헤더에 대한 액세스 권한이 없습니다. WebView 소스의 깊은 곳에서 JNI 호출에 있습니다.
이것은 나를 위해 일했습니다. 아래와 같이 WebViewClient를 만들고 webclient를 webview로 설정하십시오. 내 URL (내 콘텐츠)에 baseurl이 없지만 상대 URL 만 있으므로 webview.loadDataWithBaseURL을 사용해야했습니다. loadDataWithBaseURL을 사용하여 설정된 baseurl이있는 경우에만 URL을 올바르게 가져옵니다.
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;
}
}
};
}
나는 같은 문제를 건너서 해결했다.
앞서 말했듯이 사용자 지정 WebViewClient를 만들고 shouldInterceptRequest 메서드를 재정의해야합니다.
WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
이 메서드는 "빈"WebResourceResponse를 반환하는 동안 webView.loadUrl을 실행해야합니다.
이 같은:
@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);
}
다음은 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
}
}
Note that this does not work for POST requests because WebResourceRequest doesn't provide POST data. There is a Request Data - WebViewClient library which uses a JavaScript injection workaround for intercepting POST data.
You can use this:
@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;
}
Use this:
webView.getSettings().setUserAgentString("User-Agent");
참고URL : https://stackoverflow.com/questions/7610790/add-custom-headers-to-webview-resource-requests-android
'Programing' 카테고리의 다른 글
.NET 목록 (0) | 2020.09.22 |
---|---|
두 변수가 파이썬에서 동일한 객체를 참조하는지 비교 (0) | 2020.09.22 |
"catch, when"을 사용하여 예외 잡기 (0) | 2020.09.22 |
특히 malloc의 결과를 캐스팅하는 것이 위험한 것은 무엇입니까? (0) | 2020.09.22 |
MySQL에 PHP 배열을 저장 하시겠습니까? (0) | 2020.09.22 |