android 与JS之间的交互
在页面布局很复杂并且是动态的时候,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 = "<h1>Title</h1><p>This is HTML text<br /><i>Formatted in italics</i><br />Anothor Line</p>";
// 载入这个html页面
myWebView.loadData(htmlString, "text/html", "utf-8");
与JS交互调用必须进行下面的设置
可以通过getSettings()
获得WebSettings,然后用setJavaScriptEnabled()
使能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端代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>调用Android组件测试</title>
<script type="text/javascript">
function show(info){
document.getElementById("shows").innerHTML = info;
}
</script>
</head> <body>
<b>测试</b>
<br />
<button onClick="window.hello.javaMethod('param')">启动hello world Activity</button>
<br />
<hr color="#99FF00"/>
<button onClick="window.hello.showAndroid()">显示android内容</button>
<br />
<textarea id= "shows" cols="20" rows="10"> 暂无记录 </textarea>
<br /> </body>
</html>
代码实现效果图
补充一下:如果在调用js中的方法时,需要访问值,只是采用 webView.loadUrl("javascript:show('"+info+"')");没法得到,可通过两种方式取得:
1) 在js中的show方法,继续调用android 原生方法将返回值通过参数的形式传过来
2)在API19后,android新增接口可直接得到返回值
//第一个参数为js中的方法名,该段代码每执行一次则调用js方法一次
progressWebView.getWebview().evaluateJavascript("window.hasUserEditData()", new ValueCallback<String>() {
@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 object, String name)
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 JELLY_BEAN_MR1
and above, only public methods that are annotated with JavascriptInterface
can be accessed from JavaScript. For applications targeted to API level JELLY_BEAN
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
JELLY_BEAN
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 |
android 与JS之间的交互的更多相关文章
- OC和JS之间的交互
OC和JS之间的交互 目录 对OC和JS之间交互的理解 JS调用OC OC调用JS 对OC和JS之间交互的理解 JS调用OC JS文件 function sendCommand(cmd,param){ ...
- 深入分析:Android中app之间的交互(二,使用ComponentName)
在前一篇相关主题的博文中我们了解了如何使用Action来启动当前应用之外的Activity处理我们的业务逻辑,在本篇笔记中我在简单介绍一下使用ComponentName来与当前应用之外的应用进行交互. ...
- Android与JS之间跨平台异步调用
为什么突然要搞这个问题呢? 在开发浏览器的时候遇到这个狗血的问题,花了将近1天的时间才想到这个解决方案,Android与JavaScirpt互调. 因为接口是抓取的别人的,所以出现了JS跨域问题, ...
- Android中webview和js之间的交互(转)
http://www.cnblogs.com/leizhenzi/archive/2011/06/29/2093636.html 1.android中利用webview调用网页上的js代码. Andr ...
- 深入分析:Android中app之间的交互(一,使用Action)
在我们开发Android App应用的时候,有些需求需要我们启动其他的App来处理一些逻辑,例如我们需要根据一个地址来调用系统或者相关的地图Map App,这样我们不用在自己的App中编写相应的功能, ...
- Android 中 js 和 原生交互
Android中的WebView 中加载的URL 默认是在手机浏览器中加载的,我们可以覆盖这种默认的动作,让网页在WebView中打开.通过设置WebView的WebViewClent 达到这个效果. ...
- iOS与Html5和JS之间的交互---学习笔记五
首先采用的框架是WebViewJavascriptBridge,采用这套框架可以方便的使iOS与JS交互 一. 流程图(主要介绍思路) 二.iOS端如何使用 首先导入#import "Web ...
- PHP与js之间的交互
<?php//在php中药想使用jquery,首先需要导入jquery类库 echo "<script src='".base_url('static')." ...
- Android 与H5之间的js交互
之前项目做过一些Android和Html5之间js交互方面的东西,今天有时间就总结一下: 一.为什么要进行js交互: 为了方便原生开发和Html之间数据传递,在静态页面的情况下可以改变原生开发的页面: ...
随机推荐
- nginx日志切割总结
Nginx日志切割 方法1(脚本+定时执行): #step1:加脚本 cut_nginx_log.sh,主进程把USR1信号发给worker,worker接到这个信号后,会重新打开日志文件 #!/ ...
- pascal语言中学版整理
P1:主菜单File中的Command shell选项,可以暂时退出Pascal,进入DOS提示符状态,但Pascal仍然驻留在内存中.输入命令exit即可返回Pascal. P3:Edit菜单中Un ...
- NetScaler Best Practice With VMAC In A High Availability Configuration
NetScaler Best Practice With VMAC In A High Availability Configuration https://www.citrix.com/blogs/ ...
- hdu1950 Bridging signals
LIS nlogn的时间复杂度,之前没有写过. 思路是d[i]保存长度为i的单调不下降子序列末尾的最小值. 更新时候,如果a[i]>d[len],(len为目前最长的单调不下降子序列) d[++ ...
- BZOJ3456:城市规划——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3456 求出n个点的简单(无重边无自环)无向连通图数目 模数很熟悉,先敲一个NTT. 然后通过推导式 ...
- BZOJ2668 [cqoi2012]交换棋子 【费用流】
题目链接 BZOJ2668 题解 容易想到由\(S\)向初始的黑点连边,由终态的黑点向\(T\)连边,然后相邻的点间连边 但是这样满足不了交换次数的限制,也无法计算答案 考虑如何满足一个点的交换次数限 ...
- [学习笔记]NTT——快速数论变换
先要学会FFT[学习笔记]FFT——快速傅里叶变换 一.简介 FFT会爆精度.而且浮点数相乘常数比取模还大. 然后NTT横空出世了 虽然单位根是个好东西.但是,我们还有更好的东西 我们先选择一个模数, ...
- 通过psexec实现远程安装软件包
1.在管理机上下载和安装psexec https://docs.microsoft.com/en-us/sysinternals/downloads/psexec 2.在管理机上编写bat脚本,存放在 ...
- 1-shell学习(bash)
1.为什么需要学习shell: (1)通用性,基本上所有的linux机器都会支持 (2)文字传输操作更快 (3)以后的系统管理需要使用 2.知识点: (1)变量相关:
- LightOJ 1135 - Count the Multiples of 3 线段树
http://www.lightoj.com/volume_showproblem.php?problem=1135 题意:给定两个操作,一个对区间所有元素加1,一个询问区间能被3整除的数有多少个. ...