脚本宝典收集整理的这篇文章主要介绍了Android中WebView页面交互,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
代码
在android内打开一个网页的时候,有时我们会要求与网页有一些交互。而这些交互是在基于javaScript的基础上。那么我们来学习一下android如何与网页进行JS交互。完整代码如下:
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.JavascriptInterface;
import android.webkit.URLUtil;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**
* 软件内通用打开网页的容器页面
*
* @author ZRP
*/
public class CommonWebActivity extends FragmentActivity {
private ProgressBar progress_bar;
protected CustomFrameLayout customFrameLayout;
protected TextView titleText, errorTxt;
protected View refresh;// 刷新按钮
protected WebView webView;
protected String url = "";// 网址url
protected String param = "";// 交互参数,如json字符串
protected WebChromeClient chromeClient = new WebChromeClient() {
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100) {
progress_bar.setVisibility(View.GONE);
// 判断有无网络
if (!NetUtils.isAvailable(CommonWebActivity.this)) {
customFrameLayout.show(R.id.common_net_error);
refresh.setVisibility(View.VISIBLE);
refresh.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
webView.loadUrl(url);
}
});
} else {
// 判断网络请求网址是否有效
if (!URLUtil.isValidUrl(url)) {
customFrameLayout.show(R.id.common_net_error);
errorTxt.setText("无效网址");
} else {
customFrameLayout.show(R.id.common_web);
}
}
} else {
progress_bar.setVisibility(View.VISIBLE);
progress_bar.setProgress(newProgress);
}
}
// 获取到url打开页面的标题
public void onReceivedTitle(WebView view, String title) {
titleText.setText(title);
}
// js交互提示
public boolean onJsAlert(WebView view, String url, String message, android.webkit.JsResult result) {
return super.onJsAlert(view, url, message, result);
}
};
@Override
protected void onCreate(Bundle savedInstancestate) {
super.onCreate(savedInstanceState);
url = getIntent().getStringExtra("url");
param = getIntent().getStringExtra("param");
setContentView(R.layout.common_web_activity);
initView();
}
@SuppressLint("SetJavaScriptEnabled")
private void initView() {
findViewById(R.id.back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
titleText = (TextView) findViewById(R.id.title);
progress_bar = (ProgressBar) findViewById(R.id.progress_bar);
customFrameLayout = (CustomFrameLayout) findViewById(R.id.web_fram);
customFrameLayout.setList(new int[]{R.id.common_web, R.id.common_net_error});
refresh = findViewById(R.id.error_btn);
errorTxt = (TextView) findViewById(R.id.error_txt);
webView = (WebView) findViewById(R.id.common_web);
webView.getSettings().setDefaultTextEncodingName("utf-8");
webView.getSettings().setJavaScriptEnabled(true);
synCookies();//格式化写入cookie,需写在setJavaScriptEnabled之后
webView.setWebChromeClient(chromeClient);
webView.setWebViewClient(new WebViewClient() {// 让webView内的链接在当前页打开,不调用系统浏览器
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
webView.addJavascriptInterface(new JavaScriptInterface(), "zrp");
webView.loadUrl(url);
new Handler().postDelayed(new Runnable() {//异步传本地数据给网页
@Override
public void run() {
onNotifyListener(param);
}
}, 1000);
}
/**
* CookieManager会将这个Cookie存入该应用程序/data/data/databases/目录下的webviewCookiesChromium.db数据库的cookies表中
* 需要在当前用户退出登录的时候进行清除
*/
private void synCookies() {
String[] split = App.cookie.split(";");
for (int i = 0; i < split.length; i++) {
CookieSyncManager.createInstance(CommonWebActivity.this);
CookieManager.getInstance().setCookie(url, split[i]);
CookieSyncManager.getInstance().sync();
}
}
/**
* 回调网页中的脚本接口。
*
* @param notify 传给网页的通知内容。
*/
public void onNotifyListener(String notify) {
if (webView != null) {
webView.loadUrl("javascript:test('" + notify + "')");
}
}
/**
* android js交互实现:
* - window.zrp.command("");//在网页的方法中添加该代码获取android内容
* - webView.loadUrl("javascript:test('param')");//android给网页传值,须异步执行
*/
public class JavaScriptInterface {
@JavascriptInterface
public void command(String jsonString) {
if (TextUtils.iSEMpty(jsonString)) {
return;
}
//根据网页交互回传的json串进行操作
Toast.makeText(CommonWebActivity.this, jsonString, Toast.LENGTH_LONG).show();
}
}
}
切记:需要设置联网权限与网络状态获取权限!
@H_2_360@<uses-permission android:name="android.permission.internet" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
其中CustomFrameLayout为界面切换控件,分别在无网络,网址错误等情况下进行提示:
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
/**
* 用于状态切换的布局,只显示1个状态
*/
public class CustomFrameLayout extends FrameLayout {
private int[] list;
public CustomFrameLayout(Context context) {
super(context);
initView();
}
public CustomFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CustomFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
/**
* 设置子面板id数组
*
* @param list
*/
public void setList(int[] list) {
this.list = list;
show(0);
}
/**
* 显示某个面板
*
* @param id
*/
public void show(int id) {
if (list == null) {
for (int i = 0; i < getChildCount(); ++i) {
View view = getChildAt(i);
if (id == view.getId()) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
return;
}
for (int aList : list) {
View item = findViewById(aList);
if (item == null) {
continue;
}
if (aList == id) {
item.setVisibility(View.VISIBLE);
} else {
item.setVisibility(View.GONE);
}
}
}
/**
* 隐藏所有面板
*/
public void GoneAll() {
if (list == null) {
for (int i = 0; i < getChildCount(); ++i) {
View view = getChildAt(i);
view.setVisibility(View.GONE);
}
return;
}
for (int aList : list) {
View item = findViewById(aList);
if (item == null) {
continue;
}
item.setVisibility(View.GONE);
}
}
/**
* 切换。
*
* @param index 布局在fram中的index
*/
public void showOfIndex(int index) {
for (int i = 0; i < getChildCount(); ++i) {
View view = getChildAt(i);
if (index == i) {
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
}
public void initView() {
}
}
界面布局为:
<?XMl version="1.0" encoding="utf-8"?>
<RelativeLayout >"http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingLeft="10dp">
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:src="@drawable/ic_back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
android:textSize="15sp" />
</LinearLayout>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="加载中"
android:textSize="15sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/title"
android:background="#666666" />
<ProgressBar
android:id="@+id/progress_bar"
style="@style/update_progress"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_marginTop="51dp"
android:max="100" />
<com.zrp.webviewdemo.web.CustomFrameLayout
android:id="@+id/web_fram"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="51dp">
<WebView
android:id="@+id/common_web"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="@layout/common_net_error" />
</com.zrp.webviewdemo.web.CustomFrameLayout>
</RelativeLayout>
混淆打包
JavaScript是通过调用android中指定的方法名来进行值传递的,所以android部分的代码不能进行混淆,需要添加keep语句:-keep class com.zrp.webviewdemo.web.CommonWebActivity$JavaScriptInterface {*;}
测试分析
好了,这时候我们来添加一些数据进行测试:
用上面的方法为web页面中的param赋值,在asset文件夹中放入要进行测试的htML文件,url赋值为:url = "file:///android_asset/html.html";
如上html.html文件源码为: