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