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

xmb.itlao5.com
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(<span class="hljs-keyword">true</span>);
settings.setDatabaseEnabled(<span class="hljs-keyword">true</span>);
fixDirPath();
settings.setBlockNetworkImage(<span class="hljs-keyword">false</span>);<span class="hljs-comment">//解决图片不显示</span>
<span class="hljs-keyword">if</span>(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
}
文件选择
定义了一个文件选择回调接口 public interface OpenFileChooserCallBack {
void openFileChooserCallBack(ValueCallback<Uri> uploadMsg,
String acceptType);
void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg);
}
在ReWebChomeClient中
private OpenFileChooserCallBack mOpenFileChooserCallBack;
private ProgressDialogEx mProgressDialog;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ReWebChomeClient</span><span class="hljs-params">(OpenFileChooserCallBack openFileChooserCallBack, ProgressDialogEx progressDialog)</span> </span>{
mOpenFileChooserCallBack = openFileChooserCallBack;
mProgressDialog = progressDialog;
}
<span class="hljs-comment">// For Android 3.0+</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">openFileChooser</span><span class="hljs-params">(ValueCallback<Uri> uploadMsg, String acceptType)</span> </span>{
mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType);
}
<span class="hljs-comment">// For Android < 3.0</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">openFileChooser</span><span class="hljs-params">(ValueCallback<Uri> uploadMsg)</span> </span>{
openFileChooser(uploadMsg, <span class="hljs-string">""</span>);
}
<span class="hljs-comment">// For Android > 4.1.1</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">openFileChooser</span><span class="hljs-params">(ValueCallback<Uri> uploadMsg,
String acceptType, String capture)</span> </span>{
openFileChooser(uploadMsg, acceptType);
}
<span class="hljs-comment">// For Android > 5.0</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">onShowFileChooser</span> <span class="hljs-params">(WebView webView, ValueCallback<Uri[]>
uploadMsg, WebChromeClient.FileChooserParams fileChooserParams)</span> </span>{
mOpenFileChooserCallBack.openFileChooserImplForAndroid5(uploadMsg);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
}
加载进度
加载进度显示,这里采用动画TranslateAnimationpublic class AnimaUtils {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startImageViewAnima</span><span class="hljs-params">(ImageView loading)</span> </span>{
TranslateAnimation animation = <span class="hljs-keyword">new</span> TranslateAnimation(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">120</span>);
animation.setDuration(<span class="hljs-number">500</span>);
animation.setRepeatMode(Animation.REVERSE);
animation.setRepeatCount(Integer.MAX_VALUE);
loading.startAnimation(animation);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">removeImageViewAnima</span><span class="hljs-params">(ImageView loading)</span> </span>{
loading.setAnimation(<span class="hljs-keyword">null</span>);
}
}
进入网页时
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);
}
<span class="hljs-meta">@RequiresApi</span>(api = Build.VERSION_CODES.LOLLIPOP)
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> WebResourceResponse <span class="hljs-title">shouldInterceptRequest</span><span class="hljs-params">(WebView view, WebResourceRequest request)</span> </span>{
<span class="hljs-keyword">try</span> {
String url = request.getUrl().getHost().toLowerCase() + request.getUrl().getPath().toLowerCase();
<span class="hljs-keyword">if</span> (ADFilterUtil.hasAd(view.getContext(), url) || ADFilterUtil.isAd(view.getContext(), url)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> WebResourceResponse(<span class="hljs-keyword">null</span>,<span class="hljs-keyword">null</span>,<span class="hljs-keyword">null</span>);
}
} <span class="hljs-keyword">catch</span> (Exception e) {
e.printStackTrace();
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.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));
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">getClearAdDivJs</span><span class="hljs-params">(Context context)</span> </span>{
String js = <span class="hljs-string">"javascript:"</span>;
Resources res = context.getResources();
String[] adDivs = res.getStringArray(R.<span class="hljs-built_in">array</span>.adBlockDiv);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < adDivs.length; i++) {
js += <span class="hljs-string">"var adDiv"</span> + i + <span class="hljs-string">"= document.getElementById('news_check').getElementById('"</span> + adDivs[i] + <span class="hljs-string">"');"</span> +
<span class="hljs-string">"if(adDiv"</span> + i + <span class="hljs-string">" != null)"</span> +
<span class="hljs-string">"adDiv"</span> + i + <span class="hljs-string">".parentNode.removeChild(adDiv"</span> + i + <span class="hljs-string">");"</span>;
}
String[] adDivsC = res.getStringArray(R.<span class="hljs-built_in">array</span>.adBlockDivClass);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < adDivsC.length; i++) {
js += <span class="hljs-string">"var adDivsC"</span> + i + <span class="hljs-string">"= document.getElementsByClassName('"</span> + adDivsC[i] + <span class="hljs-string">"');"</span> +
<span class="hljs-string">"if(adDivsC"</span> + i + <span class="hljs-string">" != null)"</span> +
<span class="hljs-string">"adDivsC"</span> + i + <span class="hljs-string">".parentNode.removeChild(adDivsC"</span> + i + <span class="hljs-string">");"</span>;
}
String[] adSections = res.getStringArray(R.<span class="hljs-built_in">array</span>.adBlockSectionClass);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < adSections.length; i++) {
js += <span class="hljs-string">"var adSection"</span> + i + <span class="hljs-string">"= document.getElementById('news_check').getElementById('J_hot_news').getElementsByClassName('"</span> + adSections[i] + <span class="hljs-string">"');"</span> +
<span class="hljs-string">"if(adSection"</span> + i + <span class="hljs-string">" != null)"</span> +
<span class="hljs-string">"adSection"</span> + i + <span class="hljs-string">".parentNode.removeChild(adSection"</span> + i + <span class="hljs-string">");"</span>;
}
<span class="hljs-keyword">return</span> js;
}
简书:ThinkinLiu 博客: IT老五
以上就是【小萌伴】App中关于新闻/H5游戏模块及广告过滤的主体内容,具体的可以参考项目中com.e7yoo.e7.app.news中的内容。相关内容: 1. 思量再三,终于鼓起勇气开源~ 2.【小萌伴】机器人陪聊模块分享 3.【小萌伴】新闻/H5游戏模块及广告过滤
评论