作者微信 bishe2022

代码功能演示视频在页面下方,请先观看;如需定制开发,联系页面右侧客服
android native+h5——混合开发初步,通过js交互数据

Custom Tab


先来说说大概:
native app中布局很简单,就一个webview,这里就不贴出来了。

前端包含一个index.html 和一个index.js;里面是测试数据

先来说说实现哪些功能:
1,native app显示html
2,模拟服务器端的html和js
3,通过协商的方法完成 native app调用前段js中的数据
4,通过协商的方法完成native app 回馈给js信息(也就是app和前端 js的双向调用)

先看看成功调用js后的效果图:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

1,index.html代码

<!DOCTYPE html><html><head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Hello Native+H5!</title>
    <script type="text/javascript" charset="UTF-8" src="../js/index.js"></script>
    <script type="text/javascript" charset="UTF-8">

            function showMessage() {
                control.showToast("欢迎使用native+h5");
            }        </script></head><body>
    <input type="button" value="欢迎1" onclick="showToast('Hell_Native+H5')" />
    <input type="button" value="欢迎2" onclick="showMessage()" />
    <input type="button" value="警告" onclick="onAlert()" />
    <input type="button" value="确定" onclick="onConfirm()" />
    <input type="button" value="提示" onclick="onPrompt()" /></body></html>

2,index.js代码

function loadingImg() {
    alert("欢迎使用native+h5");
}//android中的toast显示信息框function showToast(toast) {
     android.showToast(toast);
}//警告  function onAlert() {
    alert("This is a alert sample from html");
}//确定  function onConfirm() {
    //得到true/false
    var b = confirm("are you sure to login?");
     control.showToast("your choice is " + b);
}//提示  function onPrompt() {
    //得到输入内容  
    var b = prompt("please input your password", "aaa");
     control.showToast("your input is " + b);
}//用于app向js反向输出日志function info(msg) {
    console.info(msg);
}

3,MainActivity.javaM代码

package com.example.hellonativeh5;public class MainActivity extends Activity { 
    private WebView native_web;    @Override
    protected void onCreate(Bundle savedInstanceState) {        
    super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        native_web = (WebView) findViewById(R.id.native_web);
        initWeb();
    }    /**
     * 初始化webview 允许js后要小心XSS攻击了
     * 
     * @JavascriptInterface这个注解 在4.2以上修复了,但是需要注意兼容性
     */
    @SuppressLint("SetJavaScriptEnabled")    private void initWeb() 
    {
        WebSettings webSettings = native_web.getSettings();        
        //
        webSettings.setJavaScriptEnabled(true);        
        // 第一个参数里面包含了需要从js调用的方法或者反向回馈给js的方法
        // 第二个参数调用的是和js里规定的方法一样,调用function:android中的方法showToast,前缀javascript可有可无
        // js代码:
        // function showToast(toast) {
        // android.showToast(toast);
        // }
        // 在js中,android.showToast(toast);是不能被执行的,
        可能在html中执行会报错。因为它是js和原生app协商后定义的方法,不是js原有方法
        native_web.addJavascriptInterface(new JsInterface(), "android");        
        // 设置拦截js中的三种弹框
        native_web.setWebChromeClient(new MyWebChromeClien());        
        // 监听点击的每一个url,做自己的特殊处理用
        native_web.setWebViewClient(new MyWebViewClient());        
        // 加载项目asset文件夹下的本地html
        native_web.loadUrl("file:///android_asset/h5/html/index.html");
        // 加载本地的html布局文件
        // 加载 asset 文件的内容,第二种加载本地html的方法
        String tpl = getFromAssets("h5/html/index.html");        
        // native_web.loadDataWithBaseURL(null, tpl, "text/html", "utf-8",null);
    }    
    /*
     * 获取html文件的内容
     */
    public String getFromAssets(String fileName) 
    {        
    try 
    {
            InputStreamReader inputReader = new InputStreamReader(getResources().getAssets().open(fileName));
            BufferedReader bufReader = new BufferedReader(inputReader);
            String line = "";
            String Result = "";            while ((line = bufReader.readLine()) != null)
                Result += line;            return Result;
        } catch (Exception e) {
            e.printStackTrace();
        }        return "";
    }    /**
     * 监听 所有点击的链接,如果拦截到我们需要的,就跳转到相对应的页面。
     */
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.d("webview", "url===>" + url);            
            try 
            {                
            // 如果url满足某种特定的格式,则进行特殊处理
                if (url.contains("http://")) {
                    view.loadUrl(url);
                } else {
                    view.loadUrl(url);
                }                return true;
            } catch (Exception e) {                return true;
            }
        }
    }    /**
     * 拦截js的提示框
     */
    private class MyWebChromeClien extends WebChromeClient {
        // 提示框
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,                
        final JsPromptResult result) {            
        new AlertDialog.Builder(MainActivity.this).setMessage(message)
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() 
                    {                        
                    @Override
                        public void onClick(DialogInterface dialog, int which) 
                        {                            
                        // 当弹出框点击的时候,手动用代码给js返回确认的信息
                            result.confirm("true");
                        }
                    }).setNegativeButton("取消", new DialogInterface.OnClickListener() 
                    {                        
                    @Override
                        public void onClick(DialogInterface dialog, int which) 
                        {
                            result.cancel();
                        }
                    }).show();            
                    // 返回false会弹出原声dialog,这里不让原声的弹出
            return true;
        }        // 警告框
        @SuppressLint("NewApi")        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {            
        // api 17以后才有onDismiss 接口,这里稍作处理
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {                
            new AlertDialog.Builder(MainActivity.this).setMessage(message)
                        .setOnDismissListener(new OnDismissListener() {                            
                        @Override
                            public void onDismiss(DialogInterface arg0) {                                
                            // TODO Auto-generated method stub
                                result.cancel();
                            }
                        }).show();
            } else {
                AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).setMessage(message)
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {                            @Override
                            public void onClick(DialogInterface dialog, int which) {                                // 当弹出框点击的时候,手动用代码给js返回确认的信息
                                result.cancel();
                            }
                        }).show();
                alertDialog.setCanceledOnTouchOutside(false);
                alertDialog.setCancelable(false);
            }            return true;
        }        // 确认框
        @Override
        public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) 
        {            
        new AlertDialog.Builder(MainActivity.this).setMessage(message)
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() 
                    {                        
                    @Override
                        public void onClick(DialogInterface dialog, int which) 
                        {                            
                        // 当弹出框点击的时候,手动用代码给js返回确认的信息
                            result.confirm();
                        }
                    }).setNegativeButton("取消", new DialogInterface.OnClickListener() 
                    {                        
                    @Override
                        public void onClick(DialogInterface dialog, int which) 
                        {
                            result.cancel();
                        }
                    }).show();            return true;
        }
    }    /**
     * 对应js中的调用方法
     */
    public class JsInterface {
        //这个方法就是js中带有android.前缀的方法名
        @JavascriptInterface    
        public void showToast(String toast) {
            Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();            
            // 当显示出toast的时候,就向js反向输出一条log
            log("show toast success");
        }        //这里是将app产生的信息回馈给js
        public void log(final String msg) {
            native_web.post(new Runnable() {                @Override
                public void run() {                    // 调用js中指向info的方法
                    // 这个方法会将信息在浏览器的控制台的info中显示出来
                    native_web.loadUrl("info(" + "'" + msg + "'" + ")");
                }
            });
        }
    }
}

这里需要注意的是:js中的特定方法是前段和app端协商定义下的方法名和参数名,是不受js控制的

也就是说,如果在前端调用了这些“特殊”的方法,前端会报错。

如果你向深入的了解native+h5 那么一定要熟悉js/html和css;
因为如果没有其他人给你做前端页面的话,你自己可能就要亲自去写这些了。
就算有人给你完好的html和js,你也得会看,会调用。

实战中的js和html可没有这么简单。

上述功能是点击html页面中的js代码,实现js对android的回调。还有一种,直接使用android代码调用js,与之前的相反,实现android调用js代码。
这个就很简单了:

web_view.loadUrl("hideDown()");//直接loadUrl。hideDown()是html中的js代码方法名




转载自:http://blog.csdn.net/yehui928186846/article/details/53381366

Home