Android-JS

作者: MinuitZ | 来源:发表于2017-07-27 14:41 被阅读48次

    恩......其实我是最近才知道, JavaScript和JS是同一个东西.........
    前不久在公司做项目的时候, 产品要求展示一个"关于xxx"的界面, 为了方便起见, 我直接把Web端的界面拿来, 调整了布局之后就放在WebView了.
    其实 , Android的WebView不只是用来放html, 还可以支持Android和Js的互相调用.

    WebView的初始化

    1. 在清单文件中开放网络权限
      <uses-permission android:name="android.permission.INTERNET"/>
    2. 在Activity中使用. 在装载Url时候, 要使用全称, 如http://xxxx.xxx/index.html, 否则是访问不到的
    3. 必须允许JS的使用
      mWebView.getSettings().setJavaScriptEnabled(true);
    4. 设置js的接口
      mWebView.addJavascriptInterface(this, "fridge");
      第一个参数, 用来指定可被js调用的方法的位置, 一般我们都写在接口中;
      第二个参数必须与js中的事件前缀相同.

    Android调用JS

    调用无参的js函数:

    实现Android调用JS脚本是非常简单的,直接Webview调用loadUrl方法,里面是JS的方法名,并可以传入参数,javascript:xxx()方法名需要和JS方法名相同即可.

    android代码
    mWebView.loadUrl("javascript:actionFromNative()");

    js代码:

     // 无参方法
      function actionFromNative() {
         document.getElementById("log_msg").innerHTML += "<br\>Android调用了js函数";
    }
    

    调用有参的js函数

    android:
    mWebView.loadUrl("javascript:actionFromNativeWithParam('come from Native')");

    js代码

     //有参方法
     function actionFromNativeWithParam(arg) {
            document.getElementById("log_msg").innerHTML += ("<br\>Android调用了js函数并传递参数:" + arg);
        }
    

    Js调用Android

    1. 首先准备JS方法, 准备调用
      无参:<button onClick="fridge.actionFromJs()">点击调用Android代码</button>
      有参:<button onClick="fridge.actionFromJsWithParam(' data come from Js')">点击调用Android代码并传递参数</button/>
      注意, 这里的事件中的参数fridge可以任意修改,但是必须要和Android端的一致.

    2. Android端

    • mWebView.addJavascriptInterface(this, "fridge");
      第二个参数要对应Js中的参数, 这样才可以调用起来.
    • 在Android中写入对应的方法
      无参数:
      @JavascriptInterface
      public void actionFromJs() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      Toast.makeText(MainActivity.this, "我可以跳转了~", Toast.LENGTH_LONG).show();
      }
      });
      }
      有参数:
      @JavascriptInterface
      public void actionFromJsWithParam(final String str) {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      Toast.makeText(MainActivity.this, "我可以拿到你给我的方法跳转了~" + str, Toast.LENGTH_LONG).show();
      }
      });
      }

    细心的人应该发现了, 我在Android代码中都使用了runOnUiThread方法来弹出吐司, 如果不用的话, 这里的代码会在一个叫JavaBridge的线程中运行, 亲测Toast是可以弹出的, 但是毕竟不是主线程.

    贴代码

    首先是MainActivity

    public class MainActivity extends AppCompatActivity {
    
    protected WebView mWebView;
    
    private String mUrl;
    
    private Button btn1;
    private Button btn2;
    private Button btn_next;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mUrl = "file:///android_asset/index.html";
        setupWebView();
        loadUrl(mUrl);
        btn1 = (Button) findViewById(R.id.btn1);
        btn2 = (Button) findViewById(R.id.btn2);
        btn_next = (Button) findViewById(R.id.btn_next);
        /**
         *  调用js.
         *  WebView.loadUrl("javascript:js中定义的方法")
         */
        btn1.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                // 无参数调用  android端调用js 方法
                mWebView.loadUrl("javascript:actionFromNative()");
            }
        });
        btn2.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                // 传递参数调用
                mWebView.loadUrl("javascript:actionFromNativeWithParam('come from Native')");
            }
        });
    }
    
    protected void loadUrl(String url) {
        mWebView.loadUrl(url);
    }
    
    protected void setupWebView() {
        mWebView = new WebView(getApplicationContext());
        mWebView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        ViewGroup parent = (ViewGroup) findViewById(R.id.container);
        parent.addView(mWebView);
    
        WebSettings settings = mWebView.getSettings();//拿到webbiew的settings
        settings.setSupportZoom(true);//支持缩放
        settings.setBuiltInZoomControls(true);
        settings.setDisplayZoomControls(false); // 隐藏webview缩放按钮
        settings.setUseWideViewPort(true);//让图片更适合窗口
        settings.setLoadWithOverviewMode(true);//打开页面时, 自适应屏幕
        if (Build.VERSION.SDK_INT >= 21) {
            settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
    
        //使WebView支持js
        settings.setJavaScriptEnabled(true);
        settings.setJavaScriptCanOpenWindowsAutomatically(false);
        settings.setMediaPlaybackRequiresUserGesture(false);
        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
    
        mWebView.addJavascriptInterface(this, "fridge");
      //mWebView.addJavascriptInterface(new MyJavaScriptInterface(this),"fridge");
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return true;
            }
    
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                // 如果接受ssl错误, 接受证书, 继续执行
                Log.d("geek", error.toString());
                handler.proceed();
            }
        });
    }
    
    /**
     * js调用此方法
     */
    @JavascriptInterface
    public void actionFromJs() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "我可以跳转了~", Toast.LENGTH_LONG).show();
    
            }
        });
    }
    
    /**
     * js调用此方法. 并且将参数传递过来
     *
     * @param str js  传递过来的参数
     */
    @JavascriptInterface
    public void actionFromJsWithParam(final String str) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "我可以拿到你给我的方法跳转了~" + str, Toast.LENGTH_LONG).show();
                Log.e("123", "actionFromMe: "+Thread.currentThread().getName());
            }
        });
    
    }
    
    @JavascriptInterface
    public void actionFromMe(final String atr){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Intent intent = NextActivity.newIndexIntent(MainActivity.this, atr);
                startActivity(intent);
            }
        });
    }
    
    @Override
    public void onBackPressed() {
        if (mWebView.canGoBack()) {
            mWebView.goBack();
            return;
        }
        super.onBackPressed();
    }
    
    @Override
    protected void onDestroy() {
        if (mWebView != null) {
            ViewParent parent = mWebView.getParent();
            if (parent != null) {
                ((ViewGroup) parent).removeView(mWebView);
            }
    
            mWebView.clearCache(true);
            mWebView.stopLoading();
            mWebView.getSettings().setJavaScriptEnabled(false);
            mWebView.clearHistory();
            mWebView.clearView();
            mWebView.removeAllViews();
    
            try {
                mWebView.destroy();
            } catch (Throwable ex) {
                ex.printStackTrace();
            }
        }
    
        super.onDestroy();
    }
    }
    

    然后是Js代码:

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
    <script type="text/javascript">
        // 无参方法
        function actionFromNative() {
            document.getElementById("log_msg").innerHTML += "<br\>Android调用了js函数";
        }
    
        //有参方法
        function actionFromNativeWithParam(arg) {
            document.getElementById("log_msg").innerHTML += ("<br\>Android调用了js函数并传递参数:" + arg);
        }
    
        //调用
        function actionFromMe(){
            fridge.actionFromMe('hello world');
        }
    </script>
    <title>测试页面</title>
    </head>
    <body>
    <p>WebView与Javascript交互</p>
    <div>
    <button onClick="fridge.actionFromJs()">点击调用Android代码</button>
    </div>
    <br/>
    <div>
    <button onClick="fridge.actionFromJsWithParam(' data come from Js')">
        点击调用Android代码并传递参数
    </button>
    </div>
    <br>
    <input type="button" onclick="actionFromMe()" value="asdasdadsads"/>
    </div>
    <br/>
    <div id="log_msg">调用打印信息</div>
    </body>
    </html>
    

    填会儿坑

    1. 加载处于资产目录中的html, 使用的路径为
      file:///android_asset/xxxxxxx.html
      坑待续.....

    相关文章

      网友评论

        本文标题:Android-JS

        本文链接:https://www.haomeiwen.com/subject/gbyokxtx.html