3.【小萌伴Android】新聞/H5游戲模塊及廣告過濾

在完成主體聊天機器人功能后瞧毙,拓展了新聞資訊及小游戲模塊隙笆。精力有限锌蓄,新聞列表用原生,具體內(nèi)容則用h5嵌入第三方站點撑柔,而游戲則分為兩部分瘸爽,有幾個原生小游戲(2048、防御小鳥铅忿、打飛機剪决、貪吃蛇),更多的是爬了4399的h5小游戲檀训。

xmb.itlao5.com

既然用到了第三方H5新聞及小游戲柑潦,肯定需要用到webview,這里僅做了一些基本處理峻凫;另外用到的是第三方的網(wǎng)頁渗鬼,需要去掉一些廣告或第三方標志等,這就需要一套廣告過濾的機制荧琼。

WebView

WebView做了一些基本設(shè)置譬胎,標題修改、返回及退出命锄、頁面加載控制堰乔、加載進度等...

WebSettings

這一塊不多說,每個參數(shù)什么意思網(wǎng)上都很詳細

    @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);// 設(shè)置允許訪問文件數(shù)據(jù)
        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);
        }
    }

文件選擇

定義了一個文件選擇回調(diào)接口

    public interface OpenFileChooserCallBack {
        void openFileChooserCallBack(ValueCallback<Uri> uploadMsg,
                                     String acceptType);
        void openFileChooserImplForAndroid5(ValueCallback<Uri[]> 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<Uri> uploadMsg, String acceptType) {
        mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType);
    }

    // For Android < 3.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
        openFileChooser(uploadMsg, "");
    }

    // For Android > 4.1.1
    public void openFileChooser(ValueCallback<Uri> uploadMsg,
                                String acceptType, String capture) {
        openFileChooser(uploadMsg, acceptType);
    }

     // For Android > 5.0
     public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]>
         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);
    }
}

進入網(wǎng)頁時

    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

寫得有點繁瑣镐侯,大體邏輯是:點擊返回時,顯示頂部退出按鈕(為了解決反復(fù)301重定向?qū)е峦瞬怀觯┦幻埃蝗缓笸ㄟ^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或者關(guān)鍵字進行攔截

    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中都是用到的同一個站點的內(nèi)容季稳,所以分析其網(wǎng)頁擅这,移除指定的模塊

    // 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;
    }

個人博客: IT老五
微信公眾號:【IT老五(it-lao5)】,一起源創(chuàng)景鼠,一起學(xué)習(xí)仲翎!

以上就是【小萌伴】App中關(guān)于新聞/H5游戲模塊及廣告過濾的主體內(nèi)容痹扇,具體的可以參考項目中com.e7yoo.e7.app.news中的內(nèi)容。

相關(guān)內(nèi)容:
【小萌伴Android】相關(guān)文章目錄
1.【小萌伴Android】思量再三溯香,終于鼓起勇氣開源~
2.【小萌伴Android】機器人陪聊模塊分享
3.【小萌伴Android】新聞/H5游戲模塊及廣告過濾
4.【小萌伴Android】段子趣圖模塊及其實現(xiàn)段子趣圖數(shù)據(jù)爬取
5.【小萌伴Android】原生小游戲及其實現(xiàn)(一)2048

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲫构,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子玫坛,更是在濱河造成了極大的恐慌结笨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件湿镀,死亡現(xiàn)場離奇詭異炕吸,居然都是意外死亡,警方通過查閱死者的電腦和手機勉痴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門赫模,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蒸矛,你說我怎么就攤上這事瀑罗。” “怎么了莉钙?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵廓脆,是天一觀的道長。 經(jīng)常有香客問我磁玉,道長停忿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任蚊伞,我火速辦了婚禮席赂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘时迫。我一直安慰自己颅停,他們只是感情好,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布掠拳。 她就那樣靜靜地躺著癞揉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪溺欧。 梳的紋絲不亂的頭發(fā)上喊熟,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天,我揣著相機與錄音姐刁,去河邊找鬼芥牌。 笑死,一個胖子當著我的面吹牛聂使,可吹牛的內(nèi)容都是我干的壁拉。 我是一名探鬼主播谬俄,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弃理!你這毒婦竟也來了溃论?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤案铺,失蹤者是張志新(化名)和其女友劉穎蔬芥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體控汉,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡笔诵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了姑子。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乎婿。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖街佑,靈堂內(nèi)的尸體忽然破棺而出谢翎,到底是詐尸還是另有隱情,我是刑警寧澤沐旨,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布森逮,位于F島的核電站,受9級特大地震影響磁携,放射性物質(zhì)發(fā)生泄漏褒侧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一谊迄、第九天 我趴在偏房一處隱蔽的房頂上張望闷供。 院中可真熱鬧,春花似錦统诺、人聲如沸歪脏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婿失。三九已至,卻和暖如春啄寡,著一層夾襖步出監(jiān)牢的瞬間豪硅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工这难, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人葡秒。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓姻乓,卻偏偏與公主長得像嵌溢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹋岩,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容