Android发送Token后WebView未跳转至首页问题求助
看起来你的问题核心是WebView的初始请求没有带上Authorization Token,导致服务器判定未登录,跳转到登录页。结合你的代码,我整理了几个关键问题点和对应的修复方案:
1. 先加载URL再设置WebViewClient,导致第一个请求未被拦截
你的initWebView方法里,先调用了webView.loadUrl(url),之后才设置webView.setWebViewClient(new WebClient())。这会导致WebView发起的第一个请求(也就是加载目标URL的请求)不会被你的WebClient拦截,自然也就没有带上Authorization头,服务器直接返回登录页。
修复方案:
把setWebViewClient放在loadUrl之前,确保所有请求都能被拦截:
private void initWebView(String url) { // 先设置WebViewClient,再加载URL webView.setWebViewClient(new WebClient()); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setLoadsImagesAutomatically(true); webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH); webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); webView.getSettings().setAppCacheEnabled(true); webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webView.getSettings().setSupportMultipleWindows(true); webView.getSettings().setUseWideViewPort(true); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); // 最后加载URL webView.loadUrl(url); }
2. 旧版shouldInterceptRequest方法可能不被高版本系统调用
你使用的是shouldInterceptRequest(WebView view, String url),这个方法在API 21之后被标记为过时,高版本Android系统会优先调用新的重载方法shouldInterceptRequest(WebView view, WebResourceRequest request)。如果你的App运行在API 21+的设备上,旧方法可能不会触发,导致请求没加Token。
修复方案:
同时实现两个重载方法,提取公共拦截逻辑,确保覆盖所有版本:
public class WebClient extends WebViewClient { // 旧版API(API < 21) @Nullable @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return interceptRequest(url, view); } // 新版API(API >= 21) @Nullable @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { return interceptRequest(request.getUrl().toString(), view); } // 公共拦截逻辑 private WebResourceResponse interceptRequest(String url, WebView view) { try { String token = preferences.getString(LoginActivity.KEY_TOKEN, ""); if (token.isEmpty()) { Log.w("WebClient", "Token is empty, skipping header addition"); return null; } Log.d("Arg", "Token used: " + token); // 复用OkHttpClient,避免重复创建实例 OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .build(); Request request = new Request.Builder() .url(url) .addHeader("Authorization", "Bearer " + token) // 复制WebView的User-Agent,避免请求被服务器拦截 .addHeader("User-Agent", view.getSettings().getUserAgentString()) .build(); Response response = okHttpClient.newCall(request).execute(); // 正确解析响应的Content-Type和编码 MediaType mediaType = response.body().contentType(); String mimeType = mediaType != null ? mediaType.toString() : "text/html"; String encoding = response.header("Content-Encoding", "utf-8"); return new WebResourceResponse( mimeType, encoding, response.body().byteStream() ); } catch (IOException e) { Log.e("WebClient", "Error intercepting request", e); return null; // 让WebView自行处理请求 } } // 原有onPageStarted、onPageFinished方法保持不变 }
3. 确认Token已同步写入SharedPreferences
你使用的editor.apply()是异步写入操作,存在跳转Activity时Token还未完全保存的小概率情况。可以改用同步写入的commit()方法确保Token立即生效:
可选修复:
private void setKeyToken(String token) { preferences = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString(KEY_TOKEN, token); editor.commit(); // 同步写入,确保Token立即生效 }
4. 检查网站是否依赖Cookie维持会话
有些网站除了Authorization头,还需要会话Cookie来保持登录状态。如果你的网站是这种情况,需要在登录成功后将服务器返回的Cookie同步到WebView的CookieManager中:
可选补充(若需Cookie支持):
// 在LoginActivity的fetchToken方法中,同步服务器返回的Cookie RxUtil.asyncConsumer(service.getToken(userRequest), new Consumer<TokenResponse>() { @Override public void accept(TokenResponse response) throws Exception { if (response.getSuccess() != null) { String token = response.getSuccess().getToken(); setKeyToken(token); // 同步服务器返回的Cookie到WebView CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); List<String> cookies = response.headers().values("Set-Cookie"); for (String cookie : cookies) { // 替换为你的网站域名 cookieManager.setCookie("your_website_domain.com", cookie); } Intent intent = new Intent(LoginActivity.this,MainActivity.class); startActivity(intent); } else { Toast.makeText(LoginActivity.this, "Something went wrong please try again", Toast.LENGTH_LONG).show(); } } });
验证步骤
- 运行App登录后,查看WebFragment的Log,确认
Token used输出的是正确的登录Token。 - 用Chrome DevTools调试WebView,检查每个请求的Request Headers是否包含
Authorization: Bearer xxx。
按照这些步骤修复后,WebView应该能正确携带Token,跳转到网站首页而非登录页。
内容的提问来源于stack exchange,提问作者Mohammed Qadah

