在完成主体聊天机器人功能后,拓展了新闻资讯及小游戏模块。精力有限,新闻列表用原生,具体内容则用h5嵌入第三方站点,而游戏则分为两部分,有几个原生小游戏(2048、防御小鸟、打飞机、贪吃蛇),更多的是爬了4399的h5小游戏。

xmb.itlao5.com

既然用到了第三方H5新闻及小游戏,肯定需要用到webview,这里仅做了一些基本处理;另外用到的是第三方的网页,需要去掉一些广告或第三方标志等,这就需要一套广告过滤的机制。

WebView

WebView做了一些基本设置,标题修改、返回及退出、页面加载控制、加载进度等...

WebSettings

这一块不多说,每个参数什么意思网上都很详细

    @SuppressLint("SetJavaScriptEnabled")    @SuppressWarnings("deprecation")    public void initWebView() {        mWebView.setInitialScale(80);        mWebView.setScrollbarFadingEnabled(true);        mWebView.setWebViewClient(new ReWebViewClient());        mWebView.setWebChromeClient(new ReWebChomeClient(this, mProgressDialog));        mWebView.getSettings().setDefaultTextEncodingName("UTF-8");        WebSettings settings = mWebView.getSettings();        // settings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);        settings.setBuiltInZoomControls(false);        settings.setSupportZoom(false);        int screenDensity = getResources().getDisplayMetrics().densityDpi;        WebSettings.ZoomDensity zoomDensity = WebSettings.ZoomDensity.MEDIUM;        switch (screenDensity) {        case DisplayMetrics.DENSITY_LOW:            zoomDensity = WebSettings.ZoomDensity.CLOSE;            break;        case DisplayMetrics.DENSITY_MEDIUM:            zoomDensity = WebSettings.ZoomDensity.MEDIUM;            break;        case DisplayMetrics.DENSITY_HIGH:            zoomDensity = WebSettings.ZoomDensity.FAR;            break;        }        settings.setDefaultZoom(zoomDensity);        settings.setRenderPriority(RenderPriority.HIGH);        settings.setUseWideViewPort(true);        settings.setLoadWithOverviewMode(true);        settings.setJavaScriptEnabled(true);        settings.setAllowFileAccess(true);// 设置允许访问文件数据        settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);        settings.setJavaScriptCanOpenWindowsAutomatically(true);        settings.setLoadsImagesAutomatically(true);        settings.setDomStorageEnabled(true);        settings.setDatabaseEnabled(true);        fixDirPath();        settings.setBlockNetworkImage(false);//解决图片不显示        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);        }    }

文件选择

定义了一个文件选择回调接口

    public interface OpenFileChooserCallBack {        void openFileChooserCallBack(ValueCallback uploadMsg,                                     String acceptType);        void openFileChooserImplForAndroid5(ValueCallback uploadMsg);    }

在ReWebChomeClient中

    private OpenFileChooserCallBack mOpenFileChooserCallBack;    private ProgressDialogEx mProgressDialog;    public ReWebChomeClient(OpenFileChooserCallBack openFileChooserCallBack, ProgressDialogEx progressDialog) {        mOpenFileChooserCallBack = openFileChooserCallBack;        mProgressDialog = progressDialog;    }    // For Android 3.0+    public void openFileChooser(ValueCallback uploadMsg, String acceptType) {        mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType);    }    // For Android < 3.0    public void openFileChooser(ValueCallback uploadMsg) {        openFileChooser(uploadMsg, "");    }    // For Android > 4.1.1    public void openFileChooser(ValueCallback uploadMsg,                                String acceptType, String capture) {        openFileChooser(uploadMsg, acceptType);    }     // For Android > 5.0     public boolean onShowFileChooser (WebView webView, ValueCallback         uploadMsg, WebChromeClient.FileChooserParams fileChooserParams) {         mOpenFileChooserCallBack.openFileChooserImplForAndroid5(uploadMsg);         return true;     }

加载进度

加载进度显示,这里采用动画TranslateAnimation

public class AnimaUtils {    public static void startImageViewAnima(ImageView loading) {        TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 120);         animation.setDuration(500);        animation.setRepeatMode(Animation.REVERSE);        animation.setRepeatCount(Integer.MAX_VALUE);        loading.startAnimation(animation);    }        public static void removeImageViewAnima(ImageView loading) {        loading.setAnimation(null);    }}

进入网页时

    AnimaUtils.startImageViewAnima(loadingIv);

在ReWebViewClient中

    @Override    public void onProgressChanged(WebView view, int newProgress) {        if(newProgress >= 100) {            AnimaUtils.removeImageViewAnima();        }        super.onProgressChanged(view, newProgress);    }        @Override    public void onReceivedTitle(WebView view, String title) {        AnimaUtils.removeImageViewAnima();        super.onReceivedTitle(view, title);    }

onBackPressed

写得有点繁琐,大体逻辑是:点击返回时,显示顶部退出按钮(为了解决反复301重定向导致退不出);然后通过canGoBack判断是返回goBack还是退出finish,如果是goBack,则将标题修改为上一页的标题。

    @Override    public void onBackPressed() {        if(closeView != null) {             closeView.setVisibility(View.VISIBLE);        } else {            finishAct();            return;        }        if (mWebView.canGoBack()) {            mWebView.goBack();            try {                setTitleTv(mWebView.copyBackForwardList().getCurrentItem().getTitle());            } catch (Exception e) {                new Handler().postDelayed(new Runnable() {                    @Override                    public void run() {                        try {                            setTitleTv(mWebView.getTitle());                        } catch (Exception e2) {                            e2.printStackTrace();                        }                    }                }, 500);            }            return;        }        finishAct();    }

广告过滤

广告过滤是比较繁琐的一块,做过几个版本,但是都不是很彻底,在机型兼容性和版本兼容性上不太好。大体还是围绕两个方向来展开,shouldInterceptRequest拦截和页面加载完毕后的js移除

这两种方法都是在ReWebViewClient中进行操作:

shouldInterceptRequest拦截

通过shouldInterceptRequest方法拦截指定页面及资源,这里5.0前后用到的不同

    @SuppressLint("DefaultLocale")    @Override    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {        try {            if (ADFilterUtil.hasAd(view.getContext(), url) || ADFilterUtil.isAd(view.getContext(), url.toLowerCase())) {                return new WebResourceResponse(null,null,null);            }        } catch (Exception e) {            e.printStackTrace();        }        return super.shouldInterceptRequest(view, url);    }    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)    @Override    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {        try {            String url = request.getUrl().getHost().toLowerCase() +  request.getUrl().getPath().toLowerCase();            if (ADFilterUtil.hasAd(view.getContext(), url) || ADFilterUtil.isAd(view.getContext(), url)) {                return new WebResourceResponse(null,null,null);            }        } catch (Exception e) {            e.printStackTrace();        }        return super.shouldInterceptRequest(view, request);    }

上面用到的isAd和hasAd中对拦截列表中的url或者关键字进行拦截

    public static boolean hasAd(Context context, String url) {        Resources res = context.getResources();        String[] adUrls = res.getStringArray(R.array.adBlockUrl);        for (String adUrl : adUrls) {            if (url.contains(adUrl)) {                return true;            }        }        return false;    }    public static boolean isAd(Context context, String url) {        Resources res = context.getResources();        String[] adUrls = res.getStringArray(R.array.adUrl);        for (String adUrl : adUrls) {            if (url.equals(adUrl)) {                return true;            }        }        return false;    }

onPageFinished中通过js移除

这里因为app中都是用到的同一个站点的内容,所以分析其网页,移除指定的模块

    // Override    public void onPageFinished(WebView view, String url) {        super.onPageFinished(view, url);        view.loadUrl(ADFilterUtil.getClearAdDivJs(E7App.mApp));    }    public static String getClearAdDivJs(Context context) {        String js = "javascript:";        Resources res = context.getResources();        String[] adDivs = res.getStringArray(R.array.adBlockDiv);        for (int i = 0; i < adDivs.length; i++) {            js += "var adDiv" + i + "= document.getElementById('news_check').getElementById('" + adDivs[i] + "');" +                    "if(adDiv" + i + " != null)" +                    "adDiv" + i + ".parentNode.removeChild(adDiv" + i + ");";        }        String[] adDivsC = res.getStringArray(R.array.adBlockDivClass);        for (int i = 0; i < adDivsC.length; i++) {            js += "var adDivsC" + i + "= document.getElementsByClassName('" + adDivsC[i] + "');" +                    "if(adDivsC" + i + " != null)" +                    "adDivsC" + i + ".parentNode.removeChild(adDivsC" + i + ");";        }        String[] adSections = res.getStringArray(R.array.adBlockSectionClass);        for (int i = 0; i < adSections.length; i++) {            js += "var adSection" + i + "= document.getElementById('news_check').getElementById('J_hot_news').getElementsByClassName('" + adSections[i] + "');" +                    "if(adSection" + i + " != null)" +                    "adSection" + i + ".parentNode.removeChild(adSection" + i + ");";        }        return js;    }

简书:ThinkinLiu 博客: IT老五

以上就是【小萌伴】App中关于新闻/H5游戏模块及广告过滤的主体内容,具体的可以参考项目中com.e7yoo.e7.app.news中的内容。

相关内容:
1.【小萌伴Android】思量再三,终于鼓起勇气开源~
2.【小萌伴Android】机器人陪聊模块分享
3.【小萌伴Android】新闻/H5游戏模块及广告过滤

更多相关文章

  1. android小游戏制作基础,View实现游戏布局和方法
  2. Android上如何让应用截获系统按键
  3. Android小游戏-数独(附源码)
  4. Android事件分发机制以及滑动冲突处理
  5. Android实现短信验证码自动拦截读取功能
  6. 关于Handler的拦截
  7. Android仿京东App购物车 二级列表+全选反选+Ok封装+拦截器+结算+
  8. Android中Touch事件分发过程全解析
  9. @功能 中用到 android EditText插入字符串到光标所在位置

随机推荐

  1. How to add custom title bar to android
  2. Android悬浮框
  3. Android 8.0新特性调研
  4. android ImageView的scaleType属性
  5. Android Studio UI布局
  6. [转帖] android平台刷机包的制作研究 1~2
  7. android View onMeasure
  8. Android Studio使用org.apache.http报错
  9. Android清空画布
  10. Android支持Smart Lock 人脸解锁