WebView详细使用四(和H5 JS交互)

一、WebView和H5交互接口(IEvent )定义
  • H5和Android原生交互三要素:行为(方法)、参数、返回值。
  • 定义一个通用的接口,包括上面三要素。
/**
 * Web交互事件处理的接口定义
 */

public interface IEvent {
    /**
     *  H5调用原生方法
     * @param params 传递的是Json数据
     * @return 也是Json数据
     */
    String execute(String params);
}

注意:execute方法名称是和H5约定的。

  1. params:H5调用时传递过来的数据,用Json形式,比如H5要调用原生的分享,数据如下:
{
    "action": "share",// 行为:分享
    // 分享要使用到的数据
    "data": {
        "shareTitle": "",
        "shareDes": "",
        "shareImageUrl": "",
        "shareActionUrl": "",
        "shareType": "",
        ....// 其它参数
    }
}
  1. 返回String类型也是用Json,比如H5要获取原生的UserToken数据如下:
// params:H5调用时传递过来的数据
{
    "action": "getUserToken",// 行为:获取用户的UserToken
    // 无数据传递给Android
    "data": {
        
    }
}
// Android返回给H5的数据
{
    "action": "getUserToken",// 行为:获取用户的UserToken
    // Android给H5的数据
    "data": {
        "userToken":"xxxxxx"
    }
}
二、WebView和H5交互方法参数和返回值的定义
  1. 数据和返回值无论是数据格式还是形式,其实都是一样。
  2. Android解析H5传递过来的参数时候,可以根据Action的值去解析Data的值。
  3. Data的值是不确定的,不确定的可以用泛型定义。
/**
 * 1. H5传递过来的参数
 */

public class ParamsData<T> {
    public String action;
    public T data;
}

/**
 * 2. 返回给H5的参数
 */
public class ReturnParamsData<T> {
    public String action;
    public T data;

    public ReturnParamsData(String action) {
        this.action = action;
    }
}
三、WebView和H5交互接口(IEvent )实现
/**
 * Web JS交互的事件处理
 */
public class JSEvent implements IEvent {
    private Activity activity;

    public JSEvent(Activity activity) {
        this.activity = activity;
    }

    @Override
    @JavascriptInterface
    public String execute(String params) {
        // TODO 待解析params数据
        return null;
    }
}

注意:execute方法上要加上@JavascriptInterface

四、数据解析和返回给H5的数据创建(用到JSONObject和Gson)
/**
 * Web JS交互的事件处理
 */
public class JSEvent implements IEvent {
    // 实际开发用得上
    private Activity mActivity;
    private Gson gson = new Gson();

    public JSEvent(Activity activity) {
        this.mActivity = activity;
    }

    @Override
    @JavascriptInterface
    public String execute(String params) {
        // 1. 先判断数据是不是空
        if (!TextUtils.isEmpty(params)) {
            try {
                JSONObject object = new JSONObject(params);
                // 2. 拿到行为
                String action = object.getString("action");
                // 3. 创建返回的数据
                ReturnParamsData rData = new ReturnParamsData(action);
                // 4. 根据行为去做真正的数据解析
                switch (action) {
                    case "share": // 分享行为
                        // 分享数据解析
                        ShareData shareData = parseJson(ShareData.class, params);
                        // TODO 调原生要做的事情
                        break;
                }
                // 5. 组装H5要的数据
                rData.data=getReturnData(action);
                // 返回给H5的数据,自己组装好
                return gson.toJson(rData);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 根据动作,组装数据给H5
     */
    private ReturnData getReturnData(String action) {
        ReturnData rData = new ReturnData();
        switch (action){
            case "getUserToken":
                rData.userToken="用户的UserToken";
                break;
            case "getUserId":
                rData.userId="用户的UserId";
                break;
        }
        return rData;
    }

    /**
     * 解析H5传递过来的数据
     *
     * @param clazz T的实际类型
     * @param json  H5传递过来的参数
     * @param <T>   实际类型
     * @return 实际类型
     */
    private <T> T parseJson(Class<?> clazz, String json) {
        Type type = new ParamsTypeImpl(ParamsData.class, new Type[]{clazz});
        ParamsData<T> data = gson.fromJson(json, type);
        return data.data;
    }
}
// -----------------------------------下面是用到的类,实际开发根据项目定义---------------------------------------
/**
 * 分享的数据的实体Bean
 */
public class ShareData {
    public String shareTitle;
    public String shareDes;
    public String shareImageUrl;
    public String shareActionUrl;
    public String shareType;
}   
/**
 * H5要的数据,根据实际项目,可以继续扩展
 */
public class ReturnData {
    public String userToken; // 用户的Token
    public String userId;// 用户ID
    public String userType;// 用户类型
}
/**
 * 解析JavaBean的实际类型
 */
public class ParamsTypeImpl implements ParameterizedType {
    private final Class raw;
    private final Type[] args;

    public ParamsTypeImpl(Class raw, Type[] args) {
        this.raw = raw;
        this.args = args != null ? args : new Type[0];
    }

    @Override
    public Type[] getActualTypeArguments() {
        return args;
    }

    @Override
    public Type getRawType() {
        return raw;
    }

    @Override
    public Type getOwnerType() {
        return null;
    }
}
四、项目里面使用
 /**
 * JS注入的名称,和H5约定的
 */
private static final String JS_NAME = "appXXX";
@SuppressLint("JavascriptInterface")
private void initWebView() {
    // ...... 前面省去一些代码
    WebSettings webSetting = webView.getSettings();
    // ===设置JS可用
    webSetting.setJavaScriptEnabled(true);
    // JS打开窗口
    webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
    // ===设置JS可用
    // 注入JS交互
    mWebView.addJavascriptInterface(new JSEvent(this), JS_NAME);
}

至此WebView的使用写完。

    原文作者:刘付文
    原文地址: https://www.jianshu.com/p/35354b2abf5b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞