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

如何解决Android WebView中reCAPTCHA重复验证10-20次的问题

解决Android WebView中Google reCAPTCHA重复验证的问题

我来帮你搞定这个头疼的reCAPTCHA重复验证问题~ 之所以WebView每次打开都要反复验证10-20次,而Chrome只需要一次,核心原因是WebView的默认配置没有让reCAPTCHA识别并持久化你的验证状态,比如Cookie、本地存储、浏览器标识这些关键信息没配置到位。结合你的代码,我给你整理了具体的解决方案:

关键问题分析与修复步骤

1. 正确配置Cookie(尤其是第三方Cookie)

reCAPTCHA的验证状态依赖Cookie持久化,而你当前的Cookie配置有两个明显问题:

  • Android 5.0(API 21)及以上版本,需要单独开启第三方Cookie支持,否则reCAPTCHA的跨域Cookie无法被保存
  • CookieSyncManager在API 21之后已经废弃,改用CookieManager.flush()来确保Cookie持久化到本地

修改后的Cookie配置代码:

CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // 启用第三方Cookie支持,这是reCAPTCHA保存状态的关键
    cookieManager.setAcceptThirdPartyCookies(web, true);
} else {
    cookieManager.setAcceptCookie(true);
}
// 强制将Cookie持久化到本地
cookieManager.flush();

2. 调整User-Agent,贴近Chrome移动端

你当前用的是非常旧的Chrome User-Agent(Chrome 18),reCAPTCHA可能会把WebView识别为陌生/过时的浏览器,从而强制重复验证。建议用系统自带的Chrome User-Agent,或者更接近当前版本的:

// 方式1:获取系统Chrome的原生User-Agent
String chromeUserAgent = web.getSettings().getUserAgentString();
web.getSettings().setUserAgentString(chromeUserAgent);

// 方式2:直接设置一个较新的移动端Chrome UA
web.getSettings().setUserAgentString("Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36");

3. 启用缓存与本地存储,让验证状态持久化

你当前设置了LOAD_NO_CACHE,这会导致WebView每次都重新加载页面,完全无法保留reCAPTCHA的验证状态。同时要确保DOM Storage、数据库存储的配置正确:

WebSettings webSettings = web.getSettings();
// 改用默认缓存策略,允许缓存验证状态
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
// 启用DOM Storage(reCAPTCHA会用它存储验证会话)
webSettings.setDomStorageEnabled(true);
// 启用数据库存储
webSettings.setDatabaseEnabled(true);
// 设置数据库存储路径,确保App有权限写入
String databasePath = getApplicationContext().getFilesDir().getPath() + "/databases";
webSettings.setDatabasePath(databasePath);
// 启用App缓存
webSettings.setAppCacheEnabled(true);
webSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath());

4. 修正代码中的语法错误与废弃API

你的代码里有几处语法问题(比如WebChromeClient的括号未闭合),还有废弃的CookieSyncManager调用,我已经在修正后的完整代码里统一处理了。

完整修正后的代码示例

static boolean ASWP_CAMUPLOAD = SmartWebView.ASWP_CAMUPLOAD;
static boolean ASWP_ONLYCAM = SmartWebView.ASWP_ONLYCAM;
static boolean ASWP_MULFILE = SmartWebView.ASWP_MULFILE;
private static String ASWV_F_TYPE = SmartWebView.ASWV_F_TYPE;
private String asw_cam_message;
private ValueCallback<Uri> asw_file_message;
private ValueCallback<Uri[]> asw_file_path;
private final static int asw_file_req = 1;
private final static int file_perm = 2;
private static final String TAG = MainActivity.class.getSimpleName();
// 改用贴近当前Chrome的User-Agent
public static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36";

@SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_vtop);
    AndroidNetworking.initialize(getApplicationContext());
    WebView web = findViewById(R.id.web);
    ProgressBar progressBar = findViewById(R.id.progressBar);
    ActionBar ab = getSupportActionBar();
    assert ab != null;
    ab.setElevation(0);
    checkConnection();

    if (Build.VERSION.SDK_INT < 18) {
        web.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        web.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    } else {
        web.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    WebSettings webSettings = web.getSettings();
    // 设置User-Agent
    webSettings.setUserAgentString(USER_AGENT);
    // 调整缓存策略,允许保留验证状态
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
    // 启用DOM Storage和数据库存储
    webSettings.setDomStorageEnabled(true);
    webSettings.setDatabaseEnabled(true);
    String databasePath = getApplicationContext().getFilesDir().getPath() + "/databases";
    webSettings.setDatabasePath(databasePath);
    // 启用App缓存
    webSettings.setAppCacheEnabled(true);
    webSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
    
    webSettings.setJavaScriptEnabled(true);
    webSettings.setUseWideViewPort(true);
    webSettings.setSupportZoom(true);
    webSettings.setSaveFormData(true);
    webSettings.setAllowContentAccess(true);
    webSettings.setLoadWithOverviewMode(true);
    webSettings.setSupportMultipleWindows(true);

    // 正确配置Cookie
    CookieManager cookieManager = CookieManager.getInstance();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        cookieManager.setAcceptThirdPartyCookies(web, true);
    } else {
        cookieManager.setAcceptCookie(true);
    }
    cookieManager.flush();

    web.setWebChromeClient(new WebChromeClient() {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            return super.onJsAlert(view, url, message, result);
        }
    });

    web.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            progressBar.setVisibility(View.VISIBLE);
            super.onPageStarted(view, url, favicon);
            web.setVisibility(View.INVISIBLE);
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            web.loadUrl("about:blank");
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            progressBar.setVisibility(View.VISIBLE);
            view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            web.setVisibility(View.VISIBLE);
            progressBar.setVisibility(View.GONE);
            // 用flush替代废弃的CookieSyncManager
            CookieManager.getInstance().flush();
        }
    });

    progressBar.setMax(100);
    web.setDownloadListener(new DownloadListener() {
        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
            // 这里可以添加自定义下载逻辑
        }
    });

    registerForContextMenu(web);

    if (savedInstanceState == null) {
        web.post(new Runnable() {
            @Override
            public void run() {
                web.loadUrl("https://vtop.vitap.ac.in/vtop/login?logout/");
            }
        });
    }
}

// 检查网络连接状态
protected boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    assert cm != null;
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

public void checkConnection() {
    if (!isOnline()) {
        web.setVisibility(View.INVISIBLE);
        final AlertDialog.Builder builder = new AlertDialog.Builder(VTOP.this);
        builder.setTitle("Connection");
        builder.setMessage("Make sure you are connected to Internet or College Wi-Fi");
        builder.setCancelable(false);
        builder.setNegativeButton("Back", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
                finish();
            }
        });
        builder.setPositiveButton("Reload", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                web.reload();
                checkConnection();
            }
        });
        AlertDialog alertDialog = builder.create();
        alertDialog.show();
    } else {
        Toasty.info(VTOP.this, "Just a second", Toasty.LENGTH_SHORT).show();
        web.setVisibility(View.VISIBLE);
        web.loadUrl("https://vtop.vitap.ac.in/vtop/login?logout/");
    }
}

额外注意事项

  • 确保你的App已经在AndroidManifest.xml中申请了INTERNET权限
  • 如果测试后还是有问题,可以尝试清除WebView的缓存和Cookie,然后重新验证一次,看是否能持久化状态
  • 有些网站的reCAPTCHA会基于设备指纹验证,上面的配置已经尽可能缩小WebView和Chrome的差异,一般能解决重复验证的问题

内容的提问来源于stack exchange,提问作者sai gopal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:10:31