Android WebView打开Facebook视频链接出现net::ERR_UNKNOWN_URL_SCHEME错误
Android WebView打开Facebook视频链接报错net::ERR_UNKNOWN_URL_SCHEME
问题详情
- 目标链接:
https://www.facebook.com/watch/?v=269637072007881 - 错误表现:在App的WebView中打开该链接时,会自动重定向到
fb://fullscreen_video/269637072007881?loop=false&wtsid=wt_0p0MNje32ZvW5oQjV,随后抛出错误:
Webpage not available
The webpage at fb://fullscreen_video/269637072007881?loop=false&wtsid=wt_0p0MNje32ZvW5oQjV could not be loaded because:
net::ERR_UNKNOWN_URL_SCHEME
- 对比结果:在第三方浏览器中打开该链接可正常播放视频
现有WebView代码
WebSettings webSettings = page.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setAllowUniversalAccessFromFileURLs(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); page.setWebViewClient(new WebViewClient() {//it seems not setting webclient, launches //default browser instead of opening the page in webview @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if(blockedWebsites.contains(Utils.getBaseDomain(request.getUrl().toString()))){ Log.d("vdd", "URL : " + request.getUrl().toString()); new AlertDialog.Builder(getContext()) .setMessage("Youtube is not supported according to google policy.") .setNegativeButton("Ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .create() .show(); return true; } return super.shouldOverrideUrlLoading(view, request); } @Override public void onPageStarted(final WebView webview, final String url, Bitmap favicon) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { EditText urlBox = getVDActivity().findViewById(R.id.et_search_bar); urlBox.setText(url); urlBox.setSelection(urlBox.getText().length()); BrowserWindow.this.url = url; } }); view.findViewById(R.id.loadingProgress).setVisibility(View.GONE); loadingPageProgress.setVisibility(View.VISIBLE); super.onPageStarted(webview, url, favicon); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); loadingPageProgress.setVisibility(View.GONE); } @Override public void onLoadResource(final WebView view, final String url) { Log.d("fb :", "URL: " + url); final String page = view.getUrl(); final String title = view.getTitle(); new VideoContentSearch(getActivity(), url, page, title) { @Override public void onStartInspectingURL() { Utils.disableSSLCertificateChecking(); } @Override public void onFinishedInspectingURL(boolean finishedAll) { HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSF); } @Override public void onVideoFound(String size, String type, String link, String name, String page, boolean chunked, String website, boolean audio) { videoList.addItem(size, type, link, name, page, chunked, website, audio); updateFoundVideosBar(); } }.start(); } @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if (getActivity() != null) { Log.d("VDDebug", "Url: " + url); if (getActivity().getSharedPreferences("settings", 0).getBoolean(getString(R .string.adBlockON), true) && (url.contains("ad") || url.contains("banner") || url.contains("pop")) && getVDActivity().getBrowserManager().checkUrlIfAds(url)) { Log.d("VDDebug", "Ads detected: " + url); return new WebResourceResponse(null, null, null); } } return super.shouldInterceptRequest(view, url); } @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && getVDActivity() != null) { if (MyApplication.getInstance().getSharedPreferences("settings", 0).getBoolean(getString (R.string.adBlockON), true) && (request.getUrl().toString().contains("ad") || request.getUrl().toString().contains("banner") || request.getUrl().toString().contains("pop")) && getVDActivity().getBrowserManager().checkUrlIfAds(request.getUrl() .toString())) { Log.i("VDInfo", "Ads detected: " + request.getUrl().toString()); return new WebResourceResponse(null, null, null); } else return null; } else { return shouldInterceptRequest(view, request.getUrl().toString()); } } }); page.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { loadingPageProgress.setProgress(newProgress); } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); videoList.deleteAllItems(); updateFoundVideosBar(); // VisitedPage vp = new VisitedPage(); // vp.title = title; // vp.link = view.getUrl(); // new HistorySQLite(getActivity()).addPageToHistory(vp); } }); page.loadUrl(url); loadedFirsTime = true;
解决方案
错误原因是WebView默认仅支持http/https协议,遇到fb://这类自定义协议时无法识别处理。需要在shouldOverrideUrlLoading方法中添加自定义协议的处理逻辑:
修改后的shouldOverrideUrlLoading方法
@Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); // 处理被屏蔽网站逻辑 if(blockedWebsites.contains(Utils.getBaseDomain(url))){ Log.d("vdd", "URL : " + url); new AlertDialog.Builder(getContext()) .setMessage("Youtube is not supported according to google policy.") .setNegativeButton("Ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .create() .show(); return true; } // 处理非http/https协议的URL if (!url.startsWith("http://") && !url.startsWith("https://")) { // 尝试调用系统应用打开自定义协议链接 try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } catch (ActivityNotFoundException e) { // 如果没有对应应用,转换为网页版链接(以fb://为例) if (url.startsWith("fb://")) { String webUrl = url.replace("fb://", "https://www.facebook.com/"); view.loadUrl(webUrl); return true; } // 其他协议可根据需求扩展处理 e.printStackTrace(); } } return super.shouldOverrideUrlLoading(view, request); }
逻辑说明
- 保留原有被屏蔽网站的处理逻辑;
- 判断当前URL是否为http/https协议,若不是则进入自定义处理分支;
- 优先尝试调用系统应用打开自定义协议链接(比如用户手机上安装了Facebook应用,会直接跳转到应用内播放视频);
- 如果没有对应应用,将
fb://协议转换为https://www.facebook.com/开头的网页链接,让WebView加载网页版内容。
内容的提问来源于stack exchange,提问作者TheClimbGamer
相关产品推荐
相关产品推荐

