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를 사용하여 각 요청을 대행 수신해야 합니다.should Intercept Request(요청 가로채기 요구)
가로채기할 때마다 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인 경우 새로운 API 타깃을 사용할 수 있습니다.InterceptRequest: URL뿐만 아니라 추가 요청 정보(헤더 등)를 제공합니다.
답변이 늦었을지도 모르지만, API는 21레벨 이상입니다.
헤더를 추가하려면 모든 요청을 대행 수신하고 필요한 헤더를 가진 새 요청을 만들어야 합니다.
그래서 우리는 우선시해야 한다InterceptRequest 메서드는 두 경우 모두 호출됩니다. 1. API는 레벨 21까지, 2. API 레벨 21+는 2.
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 컨트롤러를 사용하여 이 테스트를 계속하고 있으며, 헤더를 검사하기 위해 Authorize Attribute를 확장했습니다.
이것으로 충분합니다.
먼저 메서드를 작성해야 합니다.메서드는 요청에 추가할 헤더를 반환합니다.
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를 작성함으로써 모든 헤더를 제어할 수 있습니다.그런 다음 웹 뷰의 loadData를 사용하여 응답을 표시합니다.
Google이 제공하는 헤더에 액세스할 수 없습니다.이들은 WebView소스의 깊은 곳에서 JNI 콜을 받고 있습니다.
다음은 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
}
}
WebResourceRequest는 POST 데이터를 제공하지 않으므로 POST 요청에는 작동하지 않습니다.POST 데이터를 가로채기 위해 JavaScript 주입 회피책을 사용하는 Request Data - WebViewClient 라이브러리가 있습니다.
이건 나한테 효과가 있었어.다음과 같이 WebViewClient를 생성하여 WebView를 설정합니다.webview.loadDataWithBase를 사용해야 했습니다.(내 콘텐츠에 있는) URL로서의 URL에는 baseurl이 없고 상대 URL만 포함되어 있습니다.loadDataWithBase를 사용하여 baseurl이 설정되어 있는 경우에만 URL이 올바르게 표시됩니다.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;
}
}
};
}
다음을 사용할 수 있습니다.
@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를 생성하여 를 덮어쓸 필요가 있습니다.InterceptRequest 메서드.
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");
언급URL : https://stackoverflow.com/questions/7610790/add-custom-headers-to-webview-resource-requests-android
'source' 카테고리의 다른 글
요소가 존재할 때까지 함수를 대기시킵니다. (0) | 2022.09.14 |
---|---|
팬더에서 기둥 이름 바꾸기 (0) | 2022.09.14 |
MariaDB 날짜별 정렬 및 제한 오프셋 및 결측 결과 (0) | 2022.09.14 |
Mysql에서 int(10)의 최대 크기는 얼마입니까? (0) | 2022.09.14 |
Python에서 문자열을 utf-8로 변환하는 방법 (0) | 2022.09.14 |