博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android 与JS之间的交互
阅读量:5841 次
发布时间:2019-06-18

本文共 8719 字,大约阅读时间需要 29 分钟。

在页面布局很复杂并且是动态的时候,android本身的控件就变得不是那么地灵活了,只有借助于网页的强大布局能力才能实现,但是在操作html页面的同时也需要与android其它的组件存在交互,比如说

在load一个url时, 用户点击页面内的某个按钮后, 页面调用android内的组件函数或由android组件去调用JS代码去更新页面,这都是交互问题,听起来很复杂,其实不用担心,webview这个类已经帮我们实现了,只需要直接用就好了。

 webview用法1

1.在要Activity中实例化WebView组件:WebView webView = new WebView(this);

2.调用WebView的loadUrl()方法,设置WevView要显示的网页:

  互联网用:webView.loadUrl("http://www.google.com"); 
  本地文件用:webView.loadUrl("file:///android_asset/XX.html"); 本地文件存放在:assets 文件中

3.调用Activity的setContentView)方法来显示网页视图

4.用WebView点链接看了很多页以后为了让WebView支持回退功能,需要覆盖覆盖Activity类的onKeyDown()方法,如果不做任何处理,点击系统回退剪键,整个浏览器会调用finish()而结束自身,而不是回退到上一页面

5.需要在AndroidManifest.xml文件中添加权限,否则会出现Web page not available错误。

  <uses-permission android:name="android.permission.INTERNET" />

webview用法2

1、在布局文件中声明WebView

2、在Activity中实例化WebView

3、调用WebView的loadUrl( )方法,设置WevView要显示的网页

4、为了让WebView能够响应超链接功能,调用setWebViewClient( )方法,设置  WebView视图

5、用WebView点链接看了很多页以后为了让WebView支持回退功能,需要覆盖覆盖Activity类的onKeyDown()方法,如果不做任何处理,点击系统回退剪键,整个浏览器会调用finish()而结束自身,而不是回退到上一页面

6、需要在AndroidManifest.xml文件中添加权限,否则出现Web page not available错误。

<uses-permission android:name="android.permission.INTERNET"/>

 

设置webview对象显示的网页的函数为loadUrl();

  互联网页面直接用: 

myWebView.loadUrl(“http://www.google.com“);

  本地文件用(本地文件存放在:assets文件中):

myWebView.loadUrl(“file:///android_asset/XX.html“);

  还可以直接载入html的字符串,如:

String htmlString = "

Title

This is HTML text

Formatted in italics
Anothor Line

";// 载入这个html页面myWebView.loadData(htmlString, "text/html", "utf-8");

 与JS交互调用必须进行下面的设置

  可以通过获得,然后用使能JavaScript:

WebView myWebView = (WebView) findViewById(R.id.webview);WebSettings webSettings = myWebView.getSettings();webSettings.setJavaScriptEnabled(true);  

 javascript与android交互

android端代码:

webView.getSettings().setJavaScriptEnabled(true);webView.addJavascriptInterface(new JSHook(), "hello"); //在JSHook类里实现javascript想调用的方法,并将其实例化传入webview, "hello"这个字串告诉javascript调用哪个实例的方法
public class JSHook{        public void javaMethod(String p){            Log.d(tag , "JSHook.JavaMethod() called! + "+p);        }                public void showAndroid(){            String info = "来自手机内的内容!!!";            webView.loadUrl("javascript:show('"+info+"')");        }                public String getInfo(){            return "获取手机内的信息!!";        }    }

html端代码:

调用Android组件测试测试

代码实现效果图

 

补充一下:如果在调用js中的方法时,需要访问值,只是采用 webView.loadUrl("javascript:show('"+info+"')");没法得到,可通过两种方式取得:

1) 在js中的show方法,继续调用android 原生方法将返回值通过参数的形式传过来

2)在API19后,android新增接口可直接得到返回值

 

//第一个参数为js中的方法名,该段代码每执行一次则调用js方法一次progressWebView.getWebview().evaluateJavascript("window.hasUserEditData()", new ValueCallback
() { @Override public void onReceiveValue(String value) {//这里为返回值 boolean hasChanged = Boolean.parseBoolean(value); //todo } });

 

 

实例代码

package com.example.jscallandroid;import android.support.v7.app.ActionBarActivity;import android.annotation.SuppressLint;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.KeyEvent;import android.view.Menu;import android.view.MenuItem;import android.view.Window;import android.view.WindowManager;import android.webkit.JavascriptInterface;import android.webkit.JsResult;import android.webkit.WebChromeClient;import android.webkit.WebView;import android.webkit.WebViewClient;public class MainActivity extends ActionBarActivity {    //private static final String URL = "http://shouji.baidu.com/";    private static final String URL = "file:///android_asset/helloworld.html";    private WebView webView;    public String tag = "MainActivity";    private Context mContext;        @SuppressLint("JavascriptInterface")     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                //this.requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_main);        // 进行全屏        mContext = this;        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                WindowManager.LayoutParams.FLAG_FULLSCREEN);        webView = (WebView) this.findViewById(R.id.wv);        webView.loadUrl(URL);        webView.getSettings().setJavaScriptEnabled(true);        webView.addJavascriptInterface(new JSHook(), "hello");        webView.setWebViewClient(new WebViewClient() {            @Override            public boolean shouldOverrideUrlLoading(WebView view, String url) {                Log.d(tag, " url:"+url);              view.loadUrl(url);// 当打开新链接时,使用当前的 WebView,不会使用系统其他浏览器                return true;            }         });    }      public class JSHook{        @JavascriptInterface        public void javaMethod(String p){            Log.d(tag , "JSHook.JavaMethod() called! + "+p);        }        @JavascriptInterface        public void showAndroid(){            final String info = "来自手机内的内容!!!";            MainActivity.this.runOnUiThread(new Runnable(){                @Override                public void run() {                    webView.loadUrl("javascript:show('"+info+"')");                }            });        }        public String getInfo(){            return "获取手机内的信息!!";        }    }    @Override     //设置回退      //覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法      public boolean onKeyDown(int keyCode, KeyEvent event) {          if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {              webView.goBack(); //goBack()表示返回WebView的上一页面             this.finish();            return true;          }          return false;  }}

可能的异常:

public class JSHook{        public void javaMethod(String p){            Log.d(tag , "JSHook.JavaMethod() called! + "+p);        }                public void showAndroid(){            String info = "来自手机内的内容!!!";            webView.loadUrl("javascript:show('"+info+"')");        }                public String getInfo(){            return "获取手机内的信息!!";        }    }

上面这段代码在android4.4版本及之前是没有问题的, 4.4之后就会出现以下两个异常错误。

07-10 10:25:21.417: I/chromium(27333): [INFO:CONSOLE(19)] "Uncaught TypeError: Object [object Object] has no method 'showAndroid'", source: file:///android_asset/helloworld.html (19)
 

解决方法:在js调用方法上面加注解@JavascriptInterface

07-10 10:42:58.437: I/chromium(27621): [INFO:CONSOLE(19)] "Uncaught Error: Error calling method on NPObject.", source: file:///android_asset/helloworld.html (19)

解决方法:在对界面进行修改时必须在UI线程进行,即便它是Html的界面,因此在出现这个错误的时候可以用handler或runOnUiThread()方法去执行更新UI操作。

注:实例代码是排除了在高版本中出现异常的最终代码。

异常原因:

webview允许JavaScript 控制宿主应用程序,这是个很强大的特性,但同时,在4.2的版本前存在重大安全隐患,因为JavaScript 可以使用反射访问注入webview的java对象的public fields,在一个包含不信任内容的WebView中使用这个方法,会允许攻击者去篡改宿主应用程序,使用宿主应用程序的权限执行java代码。因此4.2以后,任何为JS暴露的接口,都需要加

@JavascriptInterface

注解,这样,这个Java对象的fields 将不允许被JS访问。

API

public void addJavascriptInterface ( object,  name)

Added in 

Injects the supplied Java object into this WebView. The object is injected into the JavaScript context of the main frame, using the supplied name. This allows the Java object's methods to be accessed from JavaScript. For applications targeted to API level  and above, only public methods that are annotated with  can be accessed from JavaScript. For applications targeted to API level  or below, all public methods (including the inherited ones) can be accessed, see the important security note below for implications.

Note that injected objects will not appear in JavaScript until the page is next (re)loaded. For example:

 class JsObject { @JavascriptInterface public String toString() { return "injectedObject"; } } webView.addJavascriptInterface(new JsObject(), "injectedObject"); webView.loadData("", "text/html", null); webView.loadUrl("javascript:alert(injectedObject.toString())");

IMPORTANT:

  • This method can be used to allow JavaScript to control the host application. This is a powerful feature, but also presents a security risk for applications targeted to API level  or below, because JavaScript could use reflection to access an injected object's public fields. Use of this method in a WebView containing untrusted content could allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. Use extreme care when using this method in a WebView which could contain untrusted content.
  • JavaScript interacts with Java object on a private, background thread of this WebView. Care is therefore required to maintain thread safety.
  • The Java object's fields are not accessible.
Parameters
object the Java object to inject into this WebView's JavaScript context. Null values are ignored.
name the name used to expose the object in JavaScript
 

转载于:https://www.cnblogs.com/lovemo1314/p/4634895.html

你可能感兴趣的文章
mysql定时备份自动上传
查看>>
17岁时少年决定把海洋洗干净,现在21岁的他做到了
查看>>
《写给大忙人看的java se 8》笔记
查看>>
倒计时:计算时间差
查看>>
Linux/windows P2V VMWare ESXi
查看>>
Windows XP倒计时到底意味着什么?
查看>>
运维工程师在干什么学些什么?【致菜鸟】
查看>>
Linux中iptables详解
查看>>
java中回调函数以及关于包装类的Demo
查看>>
maven异常:missing artifact jdk.tools:jar:1.6
查看>>
终端安全求生指南(五)-——日志管理
查看>>
Nginx 使用 openssl 的自签名证书
查看>>
创业维艰、守成不易
查看>>
PHP环境安装套件:快速安装LAMP环境
查看>>
CSS3
查看>>
ul下的li浮动,如何是ul有li的高度
查看>>
C++ primer plus
查看>>
python mysqlDB
查看>>
UVALive 3942 Remember the Word Tire+DP
查看>>
从微软的DBML文件中我们能学到什么(它告诉了我们什么是微软的重中之重)~目录...
查看>>