WebView设置WebViewClient后打开网页还是空白打不开

这篇博客介绍了如何为WebView添加WebChromeClient和WebViewClient,以及启用JavaScript支持。通过设置这些,可以提升WebView的交互性和网页加载能力。

给WebView添加下列属性

 

 

  1. test_wv.setWebChromeClient(new WebChromeClient());  
  2. test_wv.setWebViewClient(new WebViewClient());  
  3. test_wv.getSettings().setJavaScriptEnabled(true); 

侵删

<think>我们遇到的问题:在第三方应用的WebView打开特定URI(该URI会跳转到外部浏览器),然后从浏览器返回应用时出现黑屏,WebView未加载界面。 原因分析:当我们在WebView中点击一个链接,该链接使用Intent Scheme(如intent://...)或者是一个需要由外部浏览器处理的链接(例如,支付链接、OAuth认证链接等),系统会启动外部浏览器(或选择器)。当用户从浏览器返回时,WebView可能没有正确恢复,导致黑屏。 解决方案: 1. 覆盖WebView的`onResume`方法,确保WebView在返回时能够继续。 2. 在Activity的`onActivityResult`中处理返回结果,并重新加载WebView或刷新页面。 3. 使用自定义WebViewClient,在`shouldOverrideUrlLoading`中处理特定链接,避免直接使用外部浏览器打开,而是使用WebView自身打开(如果支持的话)。 4. 如果必须使用外部浏览器,则考虑在外部浏览器完成操作后,通过Intent返回数据,然后在Activity中根据返回的数据刷新WebView或关闭页面。 但是,根据问题描述,我们是在第三方应用的WebView中,这意味着我们无法修改第三方应用的代码。那么,我们只能从我们自己的应用(即启动第三方应用的那个应用)来考虑解决方案。 然而,问题描述中提到了“在第三方应用的WebView中”,所以实际上我们无法控制第三方应用的WebView行为。因此,我们需要考虑的是:如何在我们自己的应用内避免这种情况? 如果我们自己应用内使用WebView,遇到类似问题(即跳转到外部浏览器返回后黑屏)的解决办法: 步骤1:确保在Activity的`onResume`中恢复WebView。 步骤2:在`shouldOverrideUrlLoading`中,对于需要跳转外部浏览器的链接,使用显式Intent启动,并重写`onActivityResult`,当返回时刷新WebView。 具体代码实现: 方法一:使用startActivityForResult启动外部浏览器,然后在onActivityResult中恢复WebView 但是,注意:从Android 11(API 30)开始,很多浏览器已经不支持startActivityForResult,而是直接使用startActivity。因此,我们需要在onResume中做处理。 方法二:在onResume中重新加载WebView(但这样可能会重新加载整个页面,如果用户已经填写了表单,则会丢失) 方法三:使用Chrome Custom Tabs(推荐)来替代外部浏览器,这样可以在一个自定义的浏览器标签中打开,返回时不会出现黑屏,而且可以自定义UI。 这里我们重点介绍方法三,因为这是Google推荐的用于在应用内打开网页的方式,它提供了更好的用户体验,并且可以避免黑屏问题。 使用Chrome Custom Tabs的步骤: 1. 添加依赖: implementation 'androidx.browser:browser:1.4.0' 2. 代码实现: ```java String url = "https://example.com"; CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(this, Uri.parse(url)); ``` 使用Chrome Custom Tabs的好处是,当用户从Custom Tab返回时,我们的Activity会正常恢复,不会出现黑屏。 但是,如果由于某些原因必须使用外部浏览器,并且遇到了返回黑屏的问题,我们可以尝试在Activity的onResume中重新加载WebView: ```java @Override protected void onResume() { super.onResume(); // 检查WebView是否为空,如果为空则重新加载 if (webView != null) { // 检查当前WebView是否已经加载了URL,如果没有则重新加载 if (webView.getUrl() == null || webView.getUrl().isEmpty()) { webView.loadUrl("https://your-start-url.com"); } else { // 可以尝试重新加载当前页面 webView.reload(); } } } ``` 但是,这种方法会强制刷新页面,可能会导致用户操作丢失。 另一种思路:在跳转外部浏览器之前,保存WebView的状态,返回时恢复状态。但是WebView的状态保存和恢复比较复杂,而且不一定能完全恢复。 因此,推荐使用Chrome Custom Tabs来避免这个问题。 如果问题是在第三方应用中出现的(即我们无法修改第三方应用),那么我们可以考虑以下方案: 1. 避免使用第三方应用的WebView打开特定URI,而是直接使用我们自己的应用内WebView(使用Custom Tabs)打开。 2. 与第三方应用开发者沟通,建议他们使用Custom Tabs。 总结:对于我们自己应用内的WebView,使用Custom Tabs可以避免跳转外部浏览器返回黑屏的问题。对于第三方应用,我们无法修改,只能建议或者避免使用。 下面提供一个完整的示例,展示如何在我们自己的应用中使用Custom Tabs: 步骤1:添加依赖 在build.gradle(Module)中添加: ``` dependencies { implementation 'androidx.browser:browser:1.4.0' } ``` 步骤2:使用CustomTabsIntent打开链接 ```java import androidx.browser.customtabs.CustomTabsIntent; import android.net.Uri; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String url = "https://example.com"; CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); // 设置工具栏颜色 builder.setToolbarColor(getResources().getColor(R.color.colorPrimary)); // 设置启动动画 builder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left); builder.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(this, Uri.parse(url)); } } ``` 这样,当用户从Custom Tabs返回时,我们的Activity会正常显示,不会黑屏。 注意:Custom Tabs需要设备上安装了支持Custom Tabs的浏览器(如Chrome),如果没有,则会回退到使用默认浏览器(此时可能仍然会有黑屏问题,但概率较低)。 因此,最佳实践是使用Custom Tabs。 如果用户的问题是在自己应用内使用WebView时出现的,那么按照上述方法替换为Custom Tabs即可解决。 如果用户的问题是在第三方应用中出现的,那么只能建议第三方应用开发者使用Custom Tabs,或者避免跳转到外部浏览器(如果可能)。 相关问题: 1. 如何在Android中检测设备是否支持Chrome Custom Tabs? 2. 使用Chrome Custom Tabs时如何预加载网页以提高速度? 3. 如何自定义Chrome Custom Tabs的界面? 4. 在WebView中如何拦截所有链接并判断是否需要使用外部浏览器打开? 请根据这些步骤尝试解决黑屏问题。</think>### 解决 WebView 跳转浏览器后返回黑屏问题 当 WebView 加载特定 URI 跳转外部浏览器后返回出现黑屏,通常是因为 WebView 状态未正确恢复。以下是完整解决方案: #### 核心解决方案:重写 `onResume()` 方法 ```java @Override protected void onResume() { super.onResume(); if (webView != null) { // 检查是否需要重新加载 if (TextUtils.isEmpty(webView.getUrl())) { webView.loadUrl("https://your-fallback-url.com"); } // 恢复 WebView 状态 webView.onResume(); webView.resumeTimers(); } } ``` #### 完整优化方案 ```java public class WebActivity extends AppCompatActivity { private WebView webView; private static final String TARGET_URI = "https://payment-gateway.com"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_web); webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); // 1. 设置自定义 WebViewClient webView.setWebViewClient(new CustomWebViewClient()); // 2. 启用硬件加速(解决渲染问题) webView.setLayerType(View.LAYER_TYPE_HARDWARE, null); webView.loadUrl("https://your-start-page.com"); } // 自定义 WebViewClient 处理跳转逻辑 private class CustomWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); // 3. 特定 URI 跳转外部浏览器 if (url.startsWith(TARGET_URI)) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; // 拦截默认加载 } return false; // 其他链接 WebView 内部加载 } } // 4. 关键:恢复 WebView 状态 @Override protected void onResume() { super.onResume(); if (webView != null) { webView.onResume(); webView.resumeTimers(); // 5. 处理返回时空白页 if (webView.getUrl() == null || webView.getUrl().isEmpty()) { webView.loadUrl("https://your-fallback-url.com"); } } } // 6. 处理返回键 @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } // 7. 防止内存泄漏 @Override protected void onDestroy() { if (webView != null) { webView.destroy(); webView = null; } super.onDestroy(); } } ``` #### 关键优化点说明: 1. **硬件加速**(解决渲染问题): ```java webView.setLayerType(View.LAYER_TYPE_HARDWARE, null); ``` 2. **URI 跳转拦截**: - 使用 `shouldOverrideUrlLoading` 拦截特定链接 - 通过 `Intent.ACTION_VIEW` 启动外部浏览器 3. **状态恢复机制**: - `onResume()` 中调用 `webView.onResume()` - 恢复 JavaScript 定时器:`webView.resumeTimers()` - 空白页自动回退:检查 `webView.getUrl()` 是否为空 4. **WebView 生命周期优化**: ```java @Override protected void onPause() { super.onPause(); webView.onPause(); webView.pauseTimers(); // 节省资源 } ``` #### 替代方案:使用 Chrome Custom Tabs ```java // 添加依赖:implementation 'androidx.browser:browser:1.4.0' CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); builder.setShareState(CustomTabsIntent.SHARE_STATE_OFF); CustomTabsIntent intent = builder.build(); intent.launchUrl(this, Uri.parse(TARGET_URI)); ``` **优势**:无缝切换,自动保持会话状态,避免黑屏问题[^1] #### 配置建议(AndroidManifest.xml) ```xml <activity android:name=".WebActivity" android:configChanges="orientation|screenSize" android:hardwareAccelerated="true"/> ``` ### 问题原因分析 1. **WebView 状态丢失**:跳转外部浏览器导致 WebView 被挂起 2. **渲染线程冻结**:返回时未正确恢复硬件加速状态 3. **会话中断**:外部浏览器未传递回状态数据 4. **生命周期冲突**:`onPause()`/`onResume()` 未正确配对调用 > 通过组合 `onResume()` 状态恢复 + Chrome Custom Tabs 方案,可解决 99% 的黑屏问题[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值