Есть ли способ просмотра заголовков ответов HTTP в Activity, как только веб-страница была загружена в WebView? Похоже, это должно быть возможно, но я не могу найти никаких методов, которые отображают заголовки.
Доступ к заголовкам ответов HTTP в WebView?
Ответ 1
Ни WebView
, ни WebViewClient
не предоставляют методы для этого, хотя вы можете попытаться реализовать это вручную. Вы можете сделать что-то вроде этого:
private WebView webview;
public void onCreate(Bundle icicle){
// bla bla bla
// here you initialize your webview
webview = new WebView(this);
webview.setWebViewClient(new YourWebClient());
}
// this will be the webclient that will manage the webview
private class YourWebClient extends WebViewClient{
// you want to catch when an URL is going to be loaded
public boolean shouldOverrideUrlLoading (WebView view, String urlConection){
// here you will use the url to access the headers.
// in this case, the Content-Length one
URL url;
URLConnection conexion;
try {
url = new URL(urlConection);
conexion = url.openConnection();
conexion.setConnectTimeout(3000);
conexion.connect();
// get the size of the file which is in the header of the request
int size = conexion.getContentLength();
}
// and here, if you want, you can load the page normally
String htmlContent = "";
HttpGet httpGet = new HttpGet(urlConection);
// this receives the response
HttpResponse response;
try {
response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
// la conexion fue establecida, obtener el contenido
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = entity.getContent();
htmlContent = convertToString(inputStream);
}
}
} catch (Exception e) {}
webview.loadData(htmlContent, "text/html", "utf-8");
return true;
}
public String convertToString(InputStream inputStream){
StringBuffer string = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try {
while ((line = reader.readLine()) != null) {
string.append(linea + "\n");
}
} catch (IOException e) {}
return string.toString();
}
}
Я не могу проверить это прямо сейчас, но это в основном то, что вы могли бы сделать (это очень сумасшествие, хотя:).
Ответ 2
вдохновлен Cristian answer Мне нужно перехватить вызовы AJAX, которые просматривает webview, где мне нужно перехватить заголовки ответов, чтобы получить некоторую информацию (количество элементов корзины в приложении для электронной коммерции), которые мне нужно было использовать в приложении. Поскольку приложение использует okhttp, я закончил это и работал:
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Log.i(TAG,"shouldInterceptRequest path:"+request.getUrl().getPath());
WebResourceResponse returnResponse = null;
if (request.getUrl().getPath().startsWith("/cart")) { // only interested in /cart requests
returnResponse = super.shouldInterceptRequest(view, request);
Log.i(TAG,"cart AJAX call - doing okRequest");
Request okRequest = new Request.Builder()
.url(request.getUrl().toString())
.post(null)
.build();
try {
Response okResponse = app.getOkHttpClient().newCall(okRequest).execute();
if (okResponse!=null) {
int statusCode = okResponse.code();
String encoding = "UTF-8";
String mimeType = "application/json";
String reasonPhrase = "OK";
Map<String,String> responseHeaders = new HashMap<String,String>();
if (okResponse.headers()!=null) {
if (okResponse.headers().size()>0) {
for (int i = 0; i < okResponse.headers().size(); i++) {
String key = okResponse.headers().name(i);
String value = okResponse.headers().value(i);
responseHeaders.put(key, value);
if (key.toLowerCase().contains("x-cart-itemcount")) {
Log.i(TAG,"setting cart item count");
app.setCartItemsCount(Integer.parseInt(value));
}
}
}
}
InputStream data = new ByteArrayInputStream(okResponse.body().string().getBytes(StandardCharsets.UTF_8));
Log.i(TAG, "okResponse code:" + okResponse.code());
returnResponse = new WebResourceResponse(mimeType,encoding,statusCode,reasonPhrase,responseHeaders,data);
} else {
Log.w(TAG,"okResponse fail");
}
} catch (IOException e) {
e.printStackTrace();
}
}
return returnResponse;
}
Я надеюсь, что это может быть полезно другим, и если у кого-то есть предложения по улучшению, я был бы благодарен. К сожалению, он совместим только с LOLLIPOP и выше, поскольку с этой версии вы можете получать/возвращать заголовки, используя WebResourceRequest, что было необходимо для моего случая.
Ответ 3
Вы должны иметь возможность контролировать все свои заголовки, пропуская loadUrl и записывая свой собственный loadPage с помощью Java HttpURLConnection. Затем просмотрите заголовки, сделайте свою работу и используйте файл loadview для просмотра отзыва.
Ответ 4
Существует альтернативное решение, если вы нацелены хотя бы на Kit-Kat, хотя это не будет отображать заголовки в Activity, а скорее в Chrome. Вы можете просто следовать этому короткому руководству по удаленной отладке веб-просмотров.
Во-первых, 2 ключевых момента: включить отладку WebView в вашем приложении
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
А затем откройте chrome://inspect
на вкладке Chrome на компьютере. Как только вы подключите свой телефон через USB к компьютеру, вы увидите свое приложение WebView в списке отлаживаемых устройств.
Ответ 5
Поскольку принятый ответ будет работать только с HttpGet, вот трюк, который я сейчас использую (на данный момент он работает)
В обработчике onPageFinished, если есть ошибка, заголовок страницы будет похож на "ERROR_NUM - ERROR_DESCRIPTION", например "500 - Internal Server Error", так что все, что я делаю, это получить заголовок из webview в функции, и затем проверьте заголовок.
view.getTitle()