You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

验证步骤

  1. 运行App登录后,查看WebFragment的Log,确认Token used输出的是正确的登录Token。
  2. 用Chrome DevTools调试WebView,检查每个请求的Request Headers是否包含Authorization: Bearer xxx。

按照这些步骤修复后,WebView应该能正确携带Token,跳转到网站首页而非登录页。

内容的提问来源于stack exchange,提问作者Mohammed Qadah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 14:07:46