标签:
最近项目的需求: Android通过webView调用php的数据 , 这时候是需要整理webview和JavaScript之间相互调用的时候了
一. 理清思路:
(1) . 双方都是客户端 , 一个是Android , 一个是js( js当然是客户端 , 后面说明)
(2) . Android的webview需要支持JavaScript , 即
WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);
(3) 注意设置网络权限 , 因为这里调用的js是在远程服务器端
<uses-permission android:name="android.permission.INTERNET" />
(4) 设置webview实现的相关接口 , 注意顺序:
(1 . 设置JavaScript调用Android接口
webView.addJavascriptInterface(new JsInteration(), "control");
(2 . 设置webView提供网页加载的各个阶段的通知
webView.setWebChromeClient(new WebChromeClient() {});
(3 . 设置提供网页加载过程中提供的数据内容
webView.setWebChromeClient(new MyWebChromeClient());
(4 . 最后 , 设置webView加载网页URL
webView.loadUrl(mConn_url);
二 . 贴上代码 , 然后分解
package com.lxj.sdk.webView.demo;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by xiaojun.lan on 2016/6/21.
*/
public class TestWebViewActivity extends FragmentActivity implements View.OnClickListener {
private static final String TAG = "StartActivity";
private static final int TOTAL_FEE = 1;
private WebSettings setting;
private String mConn_url;
private Integer total_fee;
///////////////////////////////view
private WebView webView;
private TextView webView_title;
private RelativeLayout pay_layout;
private TextView price;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
pay_layout.setVisibility(View.VISIBLE);
if (msg.what == TOTAL_FEE) {
price.setText(total_fee);
}
}
};
private Button gopay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
featureNoTitle();
setContentView(R.layout.start);
//初始化数据
initData();
//初始化视图
initView();
//设置监听
initOnlistener();
}
private void initData() {
mConn_url = "http://www.lovewild.pub";
}
private void initOnlistener() {
gopay.setOnClickListener(this);
}
private void initView() {
webView = (WebView) findViewById(R.id.webView);
webView_title = (TextView) findViewById(R.id.webView_title);
pay_layout = (RelativeLayout) findViewById(R.id.pay_layout);
price = (TextView) findViewById(R.id.price);
gopay = (Button) findViewById(R.id.gopay);
}
@Override
protected void onResume() {
super.onResume();
loadURLInAndroid();
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.gopay) {
// Intent intent = new Intent(TestWebViewActivity.this, NextActivity.class);
// startActivity(intent);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
/**
* 当退出加载webView的Activity时 , 记得将webView销毁
*/
@Override
protected void onDestroy() {
super.onDestroy();
webView.destroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack(); // goBack()表示返回WebView的上一页面
return true;//这里返回true , 表示webview返回到初始页面时 , 不会退出应用
} else {
finish();
}
return super.onKeyDown(keyCode, event);
}
/**
* 设置webView的属性
*/
private void loadURLInAndroid() {
setting = webView.getSettings();
webView.setHorizontalScrollbarOverlay(false);
webView.setHorizontalScrollBarEnabled(false);
webView.requestFocus();
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);//滚动条风格,为0指滚动条不占用空间,直接覆盖在网页上
/**
* 设置js调用Android的接口
*/
webView.addJavascriptInterface(new JsInteration(), "control");
/**
* 提供网页加载各阶段的通知
* */
webView.setWebViewClient(new MyWebViewClient());
/**
* 提供网页加载过程中提供的数据内容
* */
webView.setWebChromeClient(new MyWebChromeClient());
webView.loadUrl(mConn_url);
}
/**
* js调用和传递的数据
* 类JsInteration里面的方法被js调用
* 以下三个接口都是提供给js调用的接口
* -------注意, 一定要加 @JavascriptInterface 在每个方法上面,否则无法执行
*/
public class JsInteration {
@JavascriptInterface
public void payInfoMessage(String payInfoJson) {
//js将返回payInfoJson 信息 , 具体是什么信息 , 需要js传入 , 我这里传入的是json
//获取payInfoJson之后 , 就可以在这里使用了 , 最好用handler
}
@JavascriptInterface
public void checkPaymentApp(String validate){
Log.e(TAG,"======>"+validate);
}
@JavascriptInterface
public void onSumResult(int result) {
result = total_fee;//这里将JavaScript返回的result传递给total_fee
Message mes = new Message();
mes.what = TOTAL_FEE;
handler.sendMessage(mes);//使用handler来处理js返回的结果
}
}
class MyWebViewClient extends WebViewClient {
/**
* 内核加载完当前页面时会通知我们的应用程序
* 在页面加载完毕后调用网页的js,确保js完全加载,Android调用时能调用到
*/
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
setting.setBlockNetworkImage(false);//false下载图片
//try是处理getBooleanQueryParameter返回数据越界时的异常
try{
//这里是判断 , 当url的参数main_page 不为空 , 且等于checkout_confirmation或者checkout_payment
//时 , 将调用JavaScript的响应方法 , 如果URL没有main_page参数 , 将调用JavaScript的onSumResult,
//并且传入 "我传onSumResult给js" 这个值,注意书写格式
if(Uri.parse(url).getBooleanQueryParameter("main_page",false)){
//根据URL参数判断获取预支付订单
if(Uri.parse(url).getQueryParameter("main_page").equals("checkout_confirmation")){
//这里调用js里面的方法去请求预支付订单
String call = "javascript:payInfoMessage()";
webView.loadUrl(call);
}else if(Uri.parse(url).getQueryParameter("main_page").equals("checkout_payment")){
//这里调用js里面的方法去说明是移动应用访问服务器
String call = "javascript:checkPaymentApp(\"" + "android" + "\")";
webView.loadUrl(call);
pay_layout.setVisibility(View.GONE);
}else{
String call = "javascript:onSumResult(\"" + "我传onSumResult给js" + "\")";
webView.loadUrl(call);
pay_layout.setVisibility(View.GONE);
}
}
}catch (Exception e){
Log.e(TAG,"getBooleanQueryParameter error");
}
}
/**
* 内核加载当前主框架开始时调用
* 在网页还没被加载之前设置setting , 确保网页以最快速度加载 , 增加用户体验
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
setting.setDefaultTextEncodingName("UTF-8");//设置字符编码
setting.setJavaScriptEnabled(true);//true加载JavaScript
setting.setCacheMode(WebSettings.LOAD_DEFAULT);//是否覆盖缓存
setting.setDefaultZoom(WebSettings.ZoomDensity.FAR);
setting.setSupportZoom(false);//是否支持缩放 true支持,false不支持
setting.setBuiltInZoomControls(false);//WebView是否应该使用其内置的放大机制,false不使用
setting.setDisplayZoomControls(false);//使用其内置的放大机制时,是否显示放大缩小的图标,false不显示,true显示
setting.setAppCacheEnabled(true);
setting.setDomStorageEnabled(true);
setting.setBlockNetworkImage(true);//true不下载图片
setting.setCacheMode(WebSettings.LOAD_DEFAULT);
setting.setSavePassword(false);
setting.setUseWideViewPort(false);
setting.setLoadWithOverviewMode(false);
}
/**
* 网页是否由webView显示,返回true是由浏览器显示,返回false由webView显示
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//webView.loadUrl(url);//不要加这行,否则将会引起正常网页加载错误
return super.shouldOverrideUrlLoading(view, url);
}
/**
* 如果网页加载失败(超时 , 没有网络等) , 在这里处理
* @param view
* @param errorCode
* @param description
* @param failingUrl
*/
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
handler.proceed(); // 信任所有的证书 默认是handler.cancle(),即不做处理
}
/**
* 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
*/
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
Log.e(TAG,"无论加载图片还是js文件 ,都会调用一次");
}
}
final class MyWebChromeClient extends WebChromeClient {
/**
* 处理js返回的Alter他框
* @param view
* @param url
* @param message
* @param result
* @return
*/
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
//这里弹出的框界面不友好 , 你可以使用AlertDialog.Builder来自定义弹出框 , 下同
result.confirm();
return super.onJsAlert(view, url, message, result);
}
/**
* 处理js返回的Confirm框
* @param view
* @param url
* @param message
* @param result
* @return
*/
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
result.confirm();
return super.onJsConfirm(view, url, message, result);
}
/**
* 处理js返回的Prompt框
* @param view
* @param url
* @param message
* @param defaultValue
* @param result
* @return
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
result.confirm();
return super.onJsPrompt(view, url, message, defaultValue, result);
}
/**
* 处理网页加载过程中进度条
* @param view
* @param newProgress
*/
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
/**
* 获取网页标题
*/
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
webView_title.setText(title);
}
}
/**
* 设置全屏、设置无状态栏、设置竖屏
*/
private void featureNoTitle() {
// 设置无标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 设置全屏 ,不显示状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 设置横屏
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//设置竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
服务器端的JavaScript代码:
<?php
$arr = array(
"age"=>"18",
"name"=>"xiaojun.lan"
);
$jsonData = json_encode($arr,true);
$str = "I am come from js";
$age = 18;
$age = intval($age);//确保$age 是整形数据 , 避免Android出错
//这里我直接在php里面调用JavaScript , php里面调用js , js可以很方便从php中获取数据 ,
//而php从js获取数据就需要ajax , 比较麻烦
echo "<script language=\"JavaScript\" type=\"text/JavaScript\">;
\r\n<!--\r\n
function sayHello() {
alert(\"Hello\")
}
//这是给Android调用的payInfoMessage
function payInfoMessage() {
//这是js调用Android的payInfoMessage
window.control.payInfoMessage(‘".$jsonData."‘)
}
function checkPaymentApp(str){
window.control.checkPaymentApp(‘".$str."‘)
}
//这个str是Android传过来的字符串
function onSumResult(str)
//这个number是js传给Android的整形数据{
window.control.onSumResult(‘".$age."‘)
}
function payInfoMessage() {
window.control.payInfoMessage(‘" . $app_payInfo . "‘)
}
\r\n-->;
\r\n</script>;";
?>
三. 分解
1. Android 在onPageFinished 里面判断url, 当url参数为什么的情况下 , 将会调用不同的js方法 ( 同时可以传递值给js )
2. 当js方法被调用时(这里写在php代码里面) , 就回调用Android相关方法 , 并传递值给Android
3. Android接收到值之后进行处理
android 的webview调用php服务器js , js 调用Android的webview
标签:
原文地址:http://blog.csdn.net/xkjscm/article/details/51858721