微信红包记怎样微信能看到对方qq号码微信号

原文地址:http:///131085.html重写WebView的WebViewClientpublic class MyWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}}然后再WebView里面设置即可:
webView.setWebViewClient(new MyWebViewClient(){//解决部分机型打开Url会提示使用外部浏览器
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
});date:日01:09:57
最新教程周点击榜
微信扫一扫安卓webview和js+html交互利用的addJavascriptInterface和webview.loadUrl(&javascript:**&);
时间: 09:55:38
&&&& 阅读:129
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&近期做一个项目需要把一个 服务支持的界面用webview来显示..呀 html白雪了js更是一样啥也不会,相信很多初学屌丝员跟我一样,,
html开发工具都不知道怎么写..哈哈哈.....现在把做完的结果分享一下先上图了
这是从项目中特意分离出来的demo这里之上一些关键代码
源码下载地址&
步骤 首先在assets目录下建一个html文件
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=utf-8& /&
&script type=&text/javascript&&
function createTable(phon){
var table = document.getElementById(&table&);
var arrya=phon.split(&;&);
var rowindex=0;
for(var i=0;i&arrya.i++){
child= arrya[i].split(&,&);
var row = table.insertRow(rowindex);//创建一行
rowindex+=1;
var cell1 = row.insertCell();//创建一个单元
cell1.innerHTML=child[0];
var cell2 = row.insertCell();//创建一个单元
cell2.innerHTML=&(&+i+&)&;
for(var n=1;n&child.n++){
var row = table.insertRow(rowindex);//创建一行
rowindex+=1;
var cell1 = row.insertCell();//创建一个单元
cell1.innerHTML= &&a href='javascript:Android.callPhone(\&&+child[n]+&\&)'&& +child[n];
}else if(i==1){
cell1.innerHTML= &&img src=\&file:///android_asset/qqicon.png\& height=\&14\& width=\&16\& & &+ &&a href='javascript:Android.callQQ(\&&+child[n]+&\&)'&& +child[n];
}else if(i==2){
cell1.innerHTML= &&img src=\&file:///android_asset/wxicon.png\& height=\&12\& width=\&16\& & &+ &&a href='javascript:Android.callWeixin(\&&+child[n]+&\&)'&& +child[n];
var cell2 = row.insertCell();
&font color=&#0099FF& size=&5&& 服务支持&/font& &/p&
&table id=&table& &
&/p&&/p&&/p&&/p&&/p&
&font color=&#233fF1& size=&2&&
以上连接可以点击进入QQ或者微信程序,界面的电话号码QQ号码都是从服务器获取,获取的数据直接保存在应用的私有目录下,然后从该目录取出数据通过java类调用js填充到html上,html根据绑定的java对象调用java类的方法实现拨打电话,, 转载请标明出处
&/p& 尊重作者 @author yung7086
&/p& 日 11:25:46&/font&
玩这个都玩了好久应为直接是eclipse开发 写一个function写了N遍老师少了逗号大括号还不报错。。。。郁闷的求推荐html+js的开发工具
算了还是整片的贴出来吧..html需要调用拨打电话这些功能就需要调用java类了这里我就需要定义一个java类实现html需要调用的方法
package com.example.
import ponentN
import android.content.C
import android.content.I
import android.content.pm.ApplicationI
import android.content.pm.PackageM
import android.content.pm.PackageManager.NameNotFoundE
import android.net.U
import android.webkit.JavascriptI
* JS的调用的方法
* @author yung
日 09:26:14
此类中的打开的QQ 和微信是直接通过包名和类名调用虽然QQ微信包名不容易变 但是主界面好事可能会变
如果发现打不开QQ微信应用可以查看是否是QQ微信升级更改了类名
public class AndroidJavaScript {
String[] qqpackage = new String[] { &com.tencent.mobileqq&,
&com.tencent.mobileqq.activity.SplashActivity& };
String[] wxpackage = new String[] { &com.tencent.mm&,
&com.tencent.mm.ui.LauncherUI& };
public AndroidJavaScript(Context c) {
@JavascriptInterface
public void callPhone(final String telphone) {
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(&tel:&
+ telphone));
c.startActivity(intent);
@JavascriptInterface
public void callQQ(String qq) {
// 实现调用电话号码
if (!checkBrowser(qqpackage[0])) {
Intent intent = new Intent();
ComponentName cmp = new ComponentName(qqpackage[0], qqpackage[1]);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(cmp);
c.startActivity(intent);
@JavascriptInterface
public void callWeixin(String weixin) {
if (!checkBrowser(wxpackage[0])) {
Intent intent = new Intent();
ComponentName cmp = new ComponentName(wxpackage[0], wxpackage[1]);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(cmp);
c.startActivity(intent);
// 获取在webview上获取js生成的html的源码
@JavascriptInterface
public void getSource(String htmlstr) {
// Log.e(&html&, htmlstr);
// String path = c.getFilesDir().getAbsolutePath() + &/serve.html&; //
// data/data目录
//检测包名的应用是否已经安装在手机
public boolean checkBrowser(String packageName) {
if (packageName == null || &&.equals(packageName))
ApplicationInfo info = c.getPackageManager().getApplicationInfo(
packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
} catch (NameNotFoundException e) {
}现在有了方法有了html就差怎么调用了这样记得设置webview必要是参数
myWebView.addJavascriptInterface(new AndroidJavaScript(this), &Android&);
你是否发现html的js方法里面有酱紫的语句
&a href=‘javascript:Android.callWeixin(\&&+child[n]+&\&)‘&&
确实这里面的”Android和“myWebView.addJavascriptInterface(new AndroidJavaScript(this), &Android&);必须相同哦..
这里注意双引号哈
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
isExistsHTML();
// myWebView.loadUrl(&file:///android_asset/ss.html&);
String path = getFilesDir().getAbsolutePath() + HTMLNAME; // data/data目录
myWebView.loadUrl(&file:///& + path);
myWebView.addJavascriptInterface(new AndroidJavaScript(this), &Android&);
// myWebView.loadUrl(&javascript:getStr('& + 122222 + &')&);
myWebView.setWebViewClient(webviewcilnt);
好把这里就解决了html里面调用java类实现的方法,,
下面说说 我这些QQ号和电话是从服务器获取的怎么添加到html上去。。这就是js的任务了
你看到我的html是没有什么布局,数据都是js生成出来的界面,。
怎么从java传到js里面呢 &?在java里面写myWebView.loadUrl(&javascript:createTable(‘& + phon + &‘)&);啦.
createTable(”“);就是js的function名字.记住这个myWebView.loadUrl(&javascript:createTable(‘& + phon + &‘)&)
在onCreate加应该是不行的需要酱紫
myWebView.setWebViewClient(webviewcilnt);
WebViewClient webviewcilnt = new WebViewClient() {
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
String phon = loadHTMLData();
myWebView.loadUrl(&javascript:createTable('& + phon + &')&);
// 获取webview加载的html页面
view.loadUrl(&javascript:window.Android.getSource('&html&'+&
+ &document.getElementsByTagName('html')[0].innerHTML+'&/html&');&);
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
等待webview初始化html完成之后在调用js呵呵就这样啦转载请标明出处&
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &尊重作者 yung7086
标签:&&&&&&&&&
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!你正在使用的浏览器版本过低,将不能正常浏览和使用知乎。Android布局和图片使用规范
Android布局和图片使用规范
发布时间: 22:50:09
编辑:www.fx114.net
本篇文章主要介绍了"Android布局和图片使用规范",主要涉及到Android布局和图片使用规范方面的内容,对于Android布局和图片使用规范感兴趣的同学可以参考一下。
先熟悉几个Android屏幕的计量单位屏幕尺寸:指的是手机实际的物理尺寸也就是屏幕的对角线的长度,比如常用的4.0英寸,4.7英寸,5.0英寸,5.5英寸。单位 英寸inch ,屏幕的对角线的长度,1英寸=2.54厘米。屏幕分辨率:屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素*横向像素,如、 、800*480。屏幕像素密度&dpi:屏幕像素密度是指每英寸上的像素点数 dpi:“dot per inch”的缩写。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。假设设备内每英寸有160个像素,那么该设备的屏幕像素密度=160dpi屏幕尺寸、屏幕分辨率、屏幕像素密度之间的关系:&加入一个手机的屏幕分辨率是X*Y &屏幕尺寸是M ,&那么这个手机的屏幕像素密度 =这里用更加直观的形式表示一下 假设 屏幕分辨率为 ,屏幕尺寸为5英寸,则屏幕像素密度为:2203/5=440dpi下面在解释几个概念:px(像素):px是pixel的缩写,pixel即像素,它不是自然界的长度单位。px就是一张图片中最小的点,一张位图就是由这些点构成的。1024px就是1024像素。dp&(密度无关像素):density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果。Android开发时用dp而不是px单位设置图片大小,是Android特有的单位 场景:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。dp与px的转换:因为ui设计师给你的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么我们需要进行转换:在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1pxsp(独立比例像素):scale-independent pixel,叫sp或sip 单位:spAndroid开发时用此单位设置文字大小,可根据字体大小首选项进行缩放 。Android 屏幕适配最蛋疼的就是 Android手机的分辨率都不太统一,不像苹果手机 只有四五种,但是我们也没必要适配所有的分辨率上面这张图是目前主流分辨率排行。考虑到手机分辨率的不同,为了能让我们的程序在不同分辨率的手机上显示出一样的效果,我们需要对我们的图片资源 和布局资源进行适配处理。所谓的屏幕适配 主要也就是对于&layout和drawble 的适配。官方的标准:xlarge&screens are at least 960dp x 720dplarge&screens are at least 640dp x 480dpnormal&screens are at least 470dp x 320dpsmall&screens are at least 426dp x 320dplayout 根据根据手机分辨率来区分,当手机分辨率为高分辨率时,就去加载相应的 目录下的资源。drawable 图片资源 根据在相应位置创建相应的文件夹:res/layout/my_layout.xml
// layout for normal screen size (&default&)
res/layout-small/my_layout.xml
// layout for small screen size
res/layout-large/my_layout.xml
// layout for large screen size
res/layout-xlarge/my_layout.xml
// layout for extra large screen size
res/layout-xlarge-land/my_layout.xml
// layout for extra large in landscape orientation
res/drawable-mdpi/my_icon.png
// bitmap for medium density
res/drawable-hdpi/my_icon.png
// bitmap for high density
res/drawable-xhdpi/my_icon.png
// bitmap for extra high density
这里我们分别拿
两种分辨率去演示一下:在Layout 与 &layout-xlarge 下面分别有 两个activity_main.xml 布局, 当用
分辨率去加载 时,界面显示的是当用
分辨率去加载 时,界面显示的是:由此可以得出结论可以看出, 当加载大分辨率时,如果 xlarge 下面有相应的布局,则会去加载 相应的布局,如果我没删除xlarge 下面的布局,则会加载layout 下面的布局,当然也可以通过layout- 这样的目录去做区分 不同的分辨率 加载不同的布局。相应的 对于 res-drawable 目录 也区分&根据 屏幕像素密度 &由小到大:ldpi & & & & & & & & & & & & & & & &120dpimdpi & & & & & & & & & & & & & & &160dpihdpi & & & & & & & & & & & & & & & &240dpixhdpi & & & & & & & & & & & & & & &320dpixxhdpi & & & & & & & & & & & & & &480dpi则 像素密度越大(并不一定是分辨率越大,比如 分辨率 如果屏幕尺寸是10 英寸,则会去加载hdpi),就会去加载响应目录下的图片资源。实际开发中,UI可能会以&<span style="color: rgb(51, 51, 51); font-family: font-size: 13.3333 line-height: 22.×750设计UI图, 接近于我们的,因此我们可以用画图 将设计图更改一下分辨率 改成的, 如果是 分辨率 ,假设手机屏幕尺寸为5英寸,则手机屏幕dpi= 293dpi,接近于320dpi 因此 将切图放在xhdpi 下。以前由于手机分辨率较低,一般低于 800*480, 比如240*320 等等,我们通常将切图放在 hdpi 中,现在手机分辨率上来了,我们应该优先放在xhdpi 中。&根据不同的 dpi , drawable &目录下的匹配规则是 &先去找 对应的 dpi 下, 比如 :
dpi 为293,如果需要一张资源图片, 先去找xhdpi, 如果没有,则去hdpi 下面去找。 重复上述方式直到找到最先最接近的资源图片。这张图片可以描述出 &drawable根据dpi&以及 &layout 根据 屏幕尺寸 &不同的对应关系:上面介绍的 大多是 &Android 设备 加载的原理,在实际开发中我们还是要遵循以下方式去遵循UI适配:1 .使用”wrap_content”、”match_parent”和”weight“来控制视图组件的宽度和高度。2. 使用代码设置宽高,通过代码计算 手机分辨率 去动态设置 view 的 layoutparams 也是比较常用的方式。& &比如 弹窗,在高分辨率手机上 获取手机分辨率,然后设置layoutparams &和 低分辨率手机上 设置layoutparams 可以使用 宽/ num 这样的比例。3.尽量使用线性布局(LinearLayout)和相对布局(RelativeLayout) 。4. 在需要确定size 的地方使用sp 表示文字 &dp 表示 view 。5. 优先选择 xhdpi目录,目前市面上最普遍的高端机的分辨率还多集中在720X1080范围内(xhdpi),所以目前来看xhpdi规格的图片资源成为了首选节省设计资源,设计师们一般都会用最新的iPhone6和iPhone5s(5s和5的尺寸以及分辨率都一样)来做原型设计,iPhone主流的屏幕dpi约等于320, 刚好属于xhdpi,所以选择xhdpi作为唯一一套dpi图片资源,可以让设计师不用专门为Android端切图,直接把iPhone的那一套切好的图片资源放入drawable-xhdpi文件夹里就好,这样大大减少的设计师的工作量。6 .图片资源使用优先级 &drawable & .9.png &.png &优先使用drawable 绘制背景, 能不用png,就不用png,可以减少图片资源占用的空间。相关:应用启动图标的适配对于使用Android studio 构建的项目, 会有mipmaps 和 drawable 两个目录,那么这两个目录怎么选择呢?mipmap系统会在缩放上提供一定的性能优化。可以把 他当做drawable 使用,但是注意 .9.png 不可以放在 mipmaps 目录里,只能放在drawable。对于启动图标 优先选择 mipmaps中。谢谢认真观读本文的每一位小伙伴,衷心欢迎小伙伴给我指出文中的错误,也欢迎小伙伴与我交流学习。欢迎爱学习的小伙伴加群一起进步: 。
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:Android WebView使用方法详解 附js交互调用方法
Android WebView使用方法详解 附js交互调用方法
目前很多Android app都内置了可以显示web页面的界面,会发现这个界面一般都是由一个叫做WebView的组件渲染出来的,学习该组件可以为你的app开发提升扩展性。
先说下WebView的一些优点:
--可以直接显示和渲染web页面,直接显示网页
--webview可以直接用html文件(网络上或本地assets中)作布局
--和JavaScript交互调用&
一、基本使用
首先layout中即为一个基本的简单控件:
android:id="@+id/webView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp" /&
同时,因为要房访问网络,所以manifest中必须要加uses-permission:
&uses-permission android:name="android.permission.INTERNET"/&
在activity中即可获得webview的引用,同时load一个网址:
webview = (WebView) findViewById(R.id.webView1);
webview.loadUrl("/");
//webview.reload();// reload page
这个时候发现一个问题,启动应用后,自动的打开了系统内置的浏览器,解决这个问题需要为webview设置 WebViewClient,并重写方法:
webview.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
若自己定义了一个页面加载进度的progressbar,需要展示给用户的时候,可以通过如下方式获取webview内页面的加载进度:
webview.setWebChromeClient(new WebChromeClient(){
public void onProgressChanged(WebView view, int newProgress) {
//get the newProgress and refresh progress bar
每个页面,都有一个标题,比如这个页面的title即“百度一下,你就知道”,那么如何知道当前webview正在加载的页面的title呢:
webview.setWebChromeClient(new WebChromeClient(){
public void onReceivedTitle(WebView view, String title) {
titleview.setText(title);//a textview
二、通过webview控件下载文件
通常webview渲染的界面中含有可以下载文件的链接,点击该链接后,应该开始执行下载的操作并保存文件到本地中。webview来下载页面中的文件通常有两种方式:
1. 自己通过一个线程写java io的代码来下载和保存文件(可控性好)
2. 调用系统download的模块(代码简单)
首先要写一个下载并保存文件的线程类
public class HttpThread extends Thread {
private String mU
public HttpThread(String mUrl) {
this.mUrl = mU
public void run() {
url = new URL(mUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
InputStream in = conn.getInputStream();
File downloadF
FileOutputStream out =
if(Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)){
downloadFile = Environment.getExternalStorageDirectory();
sdFile = new File(downloadFile, "test.file");
out = new FileOutputStream(sdFile);
//buffer 4k
byte[] buffer = new byte[1024 * 4];
int len = 0;
while((len = in.read(buffer)) != -1){
if(out != null)
out.write(buffer, 0, len);
//close resource
if(out != null)
out.close();
if(in != null){
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
随后要实现一个DownloadListener接口,这个接口实现方法OnDownloadStart(),当用户点击一个可以下载的链接时,该回调方法被调用同时传进来该链接的URL,随后即可以对该URL塞入HttpThread进行下载操作:
//创建DownloadListener (webkit包)
class MyDownloadListenter implements DownloadListener{
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype, long contentLength) {
System.out.println("url ==== &" + url);
new HttpThread(url).start();
//给webview加入监听
webview.setDownloadListener(new MyDownloadListenter());
直接发送一个action_view的intent即可:
class MyDownloadListenter implements DownloadListener{
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype, long contentLength) {
System.out.println("url ==== &" + url);
//new HttpThread(url).start();
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
三、错误处理
当我们使用浏览器的时候,通常因为加载的页面的服务器的各种原因导致各种出错的情况,最平常的比如404错误,通常情况下浏览器会提示一个错误提示页面。事实上这个错误提示页面是浏览器在加载了本地的一个页面,用来提示用户目前已经出错了。
但是当我们的app里面使用webview控件的时候遇到了诸如404这类的错误的时候,若也显示浏览器里面的那种错误提示页面就显得很丑陋了,那么这个时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面。
1. 首先我们需要些一个html文件,比如error_handle.html,这个文件里面就是当出错的时候需要展示给用户看的一个错误提示页面,尽量做的精美一些。然后将该文件放置到代码根目录的assets文件夹下。
2. 随后我们需要复写WebViewClient的onRecievedError方法,该方法传回了错误码,根据错误类型可以进行不同的错误分类处理
webview.setWebViewClient(new WebViewClient(){
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
switch(errorCode)
case HttpStatus.SC_NOT_FOUND:
view.loadUrl("file:///android_assets/error_handle.html");
其实,当出错的时候,我们可以选择隐藏掉webview,而显示native的错误处理控件,这个时候只需要在onReceivedError里面显示出错误处理的native控件同时隐藏掉webview即可。
四、webview同步cookies
cookies是服务器用来保存每个客户的常用信息的,下次客户进入一个诸如登陆的页面时服务器会检测cookie信息,如果通过则直接进入登陆后的页面。
在webview中,如果之前已经登陆过了,那么下次再进入同样的登陆界面时,若需要再次登陆的话,一定会很恼人,所以这里提供一个webview同步cookies的方法。&
1.首先,我们假设某个网站的登陆界面需要提供两个参数,一个是name,一个是pwd,那么要是对这个页面进行登陆,那么必须给与这两个信息。我们假设服务器已经注册了name为jason,pwd为123456这个账号。
2.下面,写一个Thread用来将name和pwd自动的登入,在服务器返回的response中获得cookie信息,稍后对这个cookie进行保存,这里先给出这个Thread的代码:
public class HttpCookie extends Thread {
private Handler mH
public HttpCookie(Handler mHandler) {
this.mHandler = mH
public void run() {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("");//this place should add the login address
List&NameValuePair& list = new ArrayList&NameValuePair&();
list.add(new BasicNameValuePair("name", "jason"));
list.add(new BasicNameValuePair("pwd", "123456"));
post.setEntity(new UrlEncodedFormEntity(list));
HttpResponse reponse = client.execute(post);
if(reponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
AbstractHttpClient absClient = (AbstractHttpClient)
List&Cookie& cookies = absClient.getCookieStore().getCookies();
for(Cookie cookie:cookies){
if(cookie != null){
//this place would get the cookies
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
由于这是一个子线程,所以需要在主线程中创建并执行。
同时,因为其实子线程,那么里面必须含有一个handler的元素,用来当成功获取cookie后通知主线程进行同步和保存。初始化这个子线程的时候需要将主线程上的handler给传过来,随后在以上代码的TODO中发送消息,让主线程记录cookie,发送的这个消息需要将cookie信息包含进去:
if(cookie != null){
//this place would get the cookies
Message msg = new Message();
if(mHandler != null){
mHandler.sendMessage(msg);
随后在主线程中(webview加载登陆界面前),在handler中将会获取到cookie信息,下面将对该cookie进行保存和同步:
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg)
CookieSyncManager.createInstance(MainActivity.this);
CookieManager cookieMgr = CookieManager.getInstance();
cookieMgr.setAcceptCookie(true);
cookieMgr.setCookie("", msg.obj.toString());// this place should add the login host address(not the login index address)
CookieSyncManager.getInstance().sync();
webview.loadUrl("");// login index address
这个时候发现webview加载的login index页面中可以自动的登陆了并显示登陆后的界面。&
五、 WebView与JavaScript的交互
1. webview调用js
mWebView.loadUrl("javascript:do()");
以上是webview在调用js中的一个叫做do的方法,该js所在的html文件大致如下:
&script language="javascript"&
/* This function is invoked by the webview*/
function do() {
alert("1");
&a onClick="window.demo.clickOnAndroid()"&&div style="width:80
padding:10
text-align:
border:2px solid #111111;" &
&img id="droid" src="xx.png"/&&br&
&/div&&/a&
2. js调用webview
我们假设下列的本地类是要给js调用的:
package com.test.
class DemoJavaScriptInterface {
DemoJavaScriptInterface() {
* This is not called on the UI thread. Post a runnable to invoke
* loadUrl on the UI thread.
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
首先给webview设置:
mWebview.setJavaScriptEnabled(true);
随后将本地的类(被js调用的)映射出去:
mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
“demo”这个名字就是公布出去给JS调用的,那么js久可以直接用下列代码调用本地的DemoJavaScriptInterface类中的方法了:
&body onload="javascript:demo.clickOnAndroid()"&&
六、WebView与JavaScript相互调用混淆问题
若webview中的js调用了本地的方法,正常情况下发布的debug包js调用的时候是没有问题的,但是通常发布商业版本的apk都是要经过混淆的步骤,这个时候会发现之前调用正常的js却无法正常调用本地方法了。
这是因为混淆的时候已经把本地的代码的引用给打乱了,导致js中的代码找不到本地的方法的地址。
解决这个问题很简单,即在proguard.cfg文件中加上一些代码,声明本地中被js调用的代码不被混淆。下面举例说明:
第五节中被js调用的那个类DemoJavaScriptInterface的包名为com.test.webview,那么就要在proguard.cfg文件中加入:
-keep public class com.test.webview.DemoJavaScriptInterface{
&&& public &methods&;
若是内部类,则大致写成如下形式:
-keep public class com.test.webview.DemoJavaScriptInterface$InnerClass{
&&& public &methods&;
若android版本比较新,可能还需要添加上下列代码:
-keepattributes *Annotation*&
-keepattributes *JavascriptInterface*
另一种讲解:
一、基本用法
<span style="color: #、加载在线URL
void loadUrl(String url)&
这个函数主要加载url所对应的网页地址,或者用于调用网页中的指定的JS方法(调用js方法的用法,后面会讲),但有一点必须注意的是:loadUrl()必须在主线程中执行!!!否则就会报错!!!。
注意:加载在线网页地址是会用到联网permission权限的,所以需要在AndroidManifest.xml中写入下面代码申请权限:
&uses-permission android:name="android.permission.INTERNET" /&&
本示例效果为:
从效果图中可以明显看出本示例的布局:
&&#63;xml version="1.0" encoding="utf-8"&#63;&
&LinearLayout xmlns:android="/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="加载URL"/&
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/&
&/LinearLayout&
对应的处理代码如下
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView)findViewById(R.id.webview);
mBtn = (Button)findViewById(R.id.btn);
mBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mWebView.loadUrl("");
代码很简单,就是在点击按钮的时候加载网址,但需要注意的是:网址必须完整即以http://或者ftp://等协议开头,不能省略!不然将加载不出来,这是因为webview是没有自动补全协议功能的,所以如果我们不加,它将识别不出来网址类型,也就加载不出来了。
但如果我们运行上面的代码,效果却是利用浏览器来打开网址,却不是使用webview打开网址:
如果我们想实现像示例一样在webview中打开网址需要怎么做呢?
我们需要设置WebViewClient:
修改后的代码为:
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView)findViewById(R.id.webview);
mBtn = (Button)findViewById(R.id.btn);
mWebView.setWebViewClient(new WebViewClient());
mBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mWebView.loadUrl("");
在上面的基础上,我们添加了下面一段代码:
mWebView.setWebViewClient(new WebViewClient());&
在这里我们利用mWebView.setWebViewClient()函数仅仅设置了一个WebViewClient实例,就可以实现在WebView中打开链接了,至于原因我们下篇会讲到,这里就先忽略了,大家只需要知道要在WebView中打开链接,就必须要设置WebViewC
最终的效果图就与开篇时一样的了,这里就不再帖效果图了,下面我们来看看如何加载本地html网页。
2、加载本地URL
一般而言,我们会将本地html文件放在assets文件夹下,比如:
web.html的内容为:
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
&h1&欢迎光临启舰的blog&/h1&
即大标题显示一段文字
我们同样在上面的示例的基础上加以改造,在点击按钮的时候加载本地web.html文件
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView)findViewById(R.id.webview);
mBtn = (Button)findViewById(R.id.btn);
mBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mWebView.loadUrl("file:///android_asset/web.html");
从这里可以看到与加载在线URL有两点不同:
1)、URL类型不一样
在加载本地URL时,是以“file:///”开头的,而assets目录所对应的路径名为anroid_asset,写成其它的将识别不了,这是assets目录的以file开头的url形式的固定访问形式。
2)、不需要设置WebViewClient
这里很明显没有设置WebViewClient函数,但仍然是在webview中打开的本地文件。具体原因下篇文章讲到WebViewClient时我们会具体解释。
本例效果图如下:
所以对于加载URL的总结就是:
1、如果是在线网址记得添加网络访问权限
2、在线网址中,如果要使用webview打开,记得设置WebViewClient
3、打开本地html文件时,是不需要设置WebViewClient,对应的asstes目录的url为:file:///android_asset/xxxxx
3、WebView基本设置
如果我们需要设置WebView的属性,是通过WebView.getSettings()获取设置WebView的WebSettings对象,然后调用WebSettings中的方法来实现的。
WebSettings的方法及说明如下:(这里先列出来所有的方法及解释,大家可以先忽略,看后面的举例中所使用的几个常用方法即可,用到哪个函数的时候再回来查查就可以了)
* 是否支持缩放,配合方法setBuiltInZoomControls使用,默认true
setSupportZoom(boolean support)
* 是否需要用户手势来播放Media,默认true
setMediaPlaybackRequiresUserGesture(boolean require)
* 是否使用WebView内置的缩放组件,由浮动在窗口上的缩放控制和手势缩放控制组成,默认false
setBuiltInZoomControls(boolean enabled)
* 是否显示窗口悬浮的缩放控制,默认true
setDisplayZoomControls(boolean enabled)
* 是否允许访问WebView内部文件,默认true
setAllowFileAccess(boolean allow)
* 是否允许获取WebView的内容URL ,可以让WebView访问ContentPrivider存储的内容。 默认true
setAllowContentAccess(boolean allow)
* 是否启动概述模式浏览界面,当页面宽度超过WebView显示宽度时,缩小页面适应WebView。默认false
setLoadWithOverviewMode(boolean overview)
* 是否保存表单数据,默认false
setSaveFormData(boolean save)
* 设置页面文字缩放百分比,默认100%
setTextZoom(int textZoom)
* 是否支持ViewPort的meta tag属性,如果页面有ViewPort meta tag 指定的宽度,则使用meta tag指定的值,否则默认使用宽屏的视图窗口
setUseWideViewPort(boolean use)
* 是否支持多窗口,如果设置为true ,WebChromeClient#onCreateWindow方法必须被主程序实现,默认false
setSupportMultipleWindows(boolean support)
* 指定WebView的页面布局显示形式,调用该方法会引起页面重绘。默认LayoutAlgorithm#NARROW_COLUMNS
setLayoutAlgorithm(LayoutAlgorithm l)
* 设置标准的字体族,默认”sans-serif”。font-family 规定元素的字体系列。
* font-family 可以把多个字体名称作为一个“回退”系统来保存。如果浏览器不支持第一个字体,
* 则会尝试下一个。也就是说,font-family 属性的值是用于某个元素的字体族名称或/及类族名称的一个
* 优先表。浏览器会使用它可识别的第一个值。
setStandardFontFamily(String font)
* 设置混合字体族。默认”monospace”
setFixedFontFamily(String font)
* 设置SansSerif字体族。默认”sans-serif”
setSansSerifFontFamily(String font)
* 设置SerifFont字体族,默认”sans-serif”
setSerifFontFamily(String font)
* 设置CursiveFont字体族,默认”cursive”
setCursiveFontFamily(String font)
* 设置FantasyFont字体族,默认”fantasy”
setFantasyFontFamily(String font)
* 设置最小字体,默认8. 取值区间[1-72],超过范围,使用其上限值。
setMinimumFontSize(int size)
* 设置最小逻辑字体,默认8. 取值区间[1-72],超过范围,使用其上限值。
setMinimumLogicalFontSize(int size)
* 设置默认字体大小,默认16,取值区间[1-72],超过范围,使用其上限值。
setDefaultFontSize(int size)
* 设置默认填充字体大小,默认16,取值区间[1-72],超过范围,使用其上限值。
setDefaultFixedFontSize(int size)
* 设置是否加载图片资源,注意:方法控制所有的资源图片显示,包括嵌入的本地图片资源。
* 使用方法setBlockNetworkImage则只限制网络资源图片的显示。值设置为true后,
* webview会自动加载网络图片。默认true
setLoadsImagesAutomatically(boolean flag)
* 是否加载网络图片资源。注意如果getLoadsImagesAutomatically返回false,则该方法没有效果。
* 如果使用setBlockNetworkLoads设置为false,该方法设置为false,也不会显示网络图片。
* 当值从true改为false时。WebView会自动加载网络图片。
setBlockNetworkImage(boolean flag)
* 设置是否加载网络资源。注意如果值从true切换为false后,WebView不会自动加载,
* 除非调用WebView#reload().如果没有android.Manifest.permission#INTERNET权限,
* 值设为false,则会抛出java.lang.SecurityException异常。
* 默认值:有android.Manifest.permission#INTERNET权限时为false,其他为true。
setBlockNetworkLoads(boolean flag)
* 设置是否允许执行JS。
setJavaScriptEnabled(boolean flag)
* 是否允许Js访问任何来源的内容。包括访问file scheme的URLs。考虑到安全性,
* 限制Js访问范围默认禁用。注意:该方法只影响file scheme类型的资源,其他类型资源如图片类型的,
* 不会受到影响。ICE_CREAM_SANDWICH_MR1版本以及以下默认为true,JELLY_BEAN版本
* 以上默认为false
setAllowUniversalAccessFromFileURLs(boolean flag)
* 是否允许Js访问其他file scheme的URLs。包括访问file scheme的资源。考虑到安全性,
* 限制Js访问范围默认禁用。注意:该方法只影响file scheme类型的资源,其他类型资源如图片类型的,
* 不会受到影响。如果getAllowUniversalAccessFromFileURLs为true,则该方法被忽略。
* ICE_CREAM_SANDWICH_MR1版本以及以下默认为true,JELLY_BEAN版本以上默认为false
setAllowFileAccessFromFileURLs(boolean flag)
* 设置存储定位数据库的位置,考虑到位置权限和持久化Cache缓存,Application需要拥有指定路径的
* write权限
setGeolocationDatabasePath(String databasePath)
* 是否允许Cache,默认false。考虑需要存储缓存,应该为缓存指定存储路径setAppCachePath
setAppCacheEnabled(boolean flag)
* 设置Cache API缓存路径。为了保证可以访问Cache,Application需要拥有指定路径的write权限。
* 该方法应该只调用一次,多次调用自动忽略。
setAppCachePath(String appCachePath)
* 是否允许数据库存储。默认false。查看setDatabasePath API 如何正确设置数据库存储。
* 该设置拥有全局特性,同一进程所有WebView实例共用同一配置。注意:保证在同一进程的任一WebView
* 加载页面之前修改该属性,因为在这之后设置WebView可能会忽略该配置
setDatabaseEnabled(boolean flag)
* 是否存储页面DOM结构,默认false。
setDomStorageEnabled(boolean flag)
* 是否允许定位,默认true。注意:为了保证定位可以使用,要保证以下几点:
* Application 需要有android.Manifest.permission#ACCESS_COARSE_LOCATION的权限
* Application 需要实现WebChromeClient#onGeolocationPermissionsShowPrompt的回调,
* 接收Js定位请求访问地理位置的通知
setGeolocationEnabled(boolean flag)
* 是否允许JS自动打开窗口。默认false
setJavaScriptCanOpenWindowsAutomatically(boolean flag)
* 设置页面的编码格式,默认UTF-8
setDefaultTextEncodingName(String encoding)
* 设置WebView代理,默认使用默认值
setUserAgentString(String ua)
* 通知WebView是否需要设置一个节点获取焦点当
* WebView#requestFocus(int,android.graphics.Rect)被调用的时候,默认true
setNeedInitialFocus(boolean flag)
* 基于WebView导航的类型使用缓存:正常页面加载会加载缓存并按需判断内容是否需要重新验证。
* 如果是页面返回,页面内容不会重新加载,直接从缓存中恢复。setCacheMode允许客户端根据指定的模式来
* 使用缓存。
* LOAD_DEFAULT 默认加载方式
* LOAD_CACHE_ELSE_NETWORK 按网络情况使用缓存
* LOAD_NO_CACHE 不使用缓存
* LOAD_CACHE_ONLY 只使用缓存
setCacheMode(int mode)
* 设置加载不安全资源的WebView加载行为。KITKAT版本以及以下默认为MIXED_CONTENT_ALWAYS_ALLOW方
* 式,LOLLIPOP默认MIXED_CONTENT_NEVER_ALLOW。强烈建议:使用MIXED_CONTENT_NEVER_ALLOW
setMixedContentMode(int mode)
下面我们就举个例子来看下用法
示例1:在WebView中启用JavaScript:
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mBtn = (Button) findViewById(R.id.btn);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
示例2:设置缓存
优先使用缓存
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);&
不使用缓存:
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);&
示例3:打开页面时,自适应屏幕:
WebSettings webSettings = mWebView .getSettings();
webSettings.setUseWideViewPort(true);//设置此属性,可任意比例缩放
webSettings.setLoadWithOverviewMode(true);
效果图如下:
示例4:使页面支持缩放:
WebSettings webSettings = mWebView.getSettings();
//开启javascript支持
webSettings.setJavaScriptEnabled(true);
// 设置可以支持缩放
webSettings.setSupportZoom(true);
// 设置出现缩放工具
webSettings.setBuiltInZoomControls(true);
示例5:.如果webView中需要用户手动输入用户名、密码或其他,则webview必须设置支持获取手势焦点
webview.requestFocusFromTouch();&
其它的设置就靠大家自己去尝试啦,这里就不再一一缀述了,大家只需要记着,如果需要设置webview就从WebSettings里面去找就可以啦。
二、JS调用Java代码
在看了如何设置webview以后,我们来看下如何让Webview与网页中的JS代码交互的问题。
更多时候,网页中需要通过JS代码来调用本地的Android代码,比如H5页面需要判断当前用户是否登录等。
利用JS代码调用JAVA代码,主要是用到WebView下面的一个函数:
public void addJavascriptInterface(Object obj, String interfaceName)&
这个函数有两个参数:
--Object obj:interfaceName所绑定的对象
--String interfaceName:所绑定的对象所对应的名称
它有意义就是向WebView注入一个interfaceName的对象,这个对象绑定的是obj对象,通过interfaceName就可以调用obj对象中的方法,这个表述可能大家不太理解,因为interfaceName是一个String,怎么被你说成对象了,理解不了没关系,下面有具体示例
下面同样是上面的示例,我们对它加以更改,效果图如下:
在原来html上面添加了一个按钮,当点击按钮时调用Android的Toast函数弹出一个toast消息。
先看Android代码:
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(this, "android");
mWebView.loadUrl("file:///android_asset/web.html");
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), "通过Natvie传递的Toast:"+message, Toast.LENGTH_LONG).show();
这里最主要是的下面这句:
mWebView.addJavascriptInterface(this, "android");&
这句的意思是把MyActivity对象注入到WebView中,在WebView中的对象别名叫android;另外,我们还在MyActivity中额外写了一个函数toastMessage(String message),用于弹出MSG
下面我们看看html代码:
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
&h1&欢迎光临启舰的blog&/h1&
&input type="button" value="js调native" onclick="ok()"&
&script type="text/javascript"&
function ok() {
android.toastMessage("哈哈,i m webview msg");
在这个html中,我添加了一个button按钮,当点击时调用ok函数:
function ok() {
android.toastMessage("哈哈,i m webview msg");
它的意义就是调用android对象里的toastMessage方法,这个android就是我们利用mWebView.addJavascriptInterface(this, “android”)注入到WebView的android,它所对应的对象就将MyActivity;所以在JS中,我们就可以通过android这个别名来调用MyActivity对象中的任何public方法。
3、addJavascriptInterface自定义作用对象
在上面的示例中mWebView.addJavascriptInterface(this, “android”);我们直接通过this,把当前整个类作为对象传给WebView了,但这会有很大风险,因为我们这个类中可能会有各种函数,而这些函数是只有本地Native代码才会用到,WebView是根本用不到的。所以如果通过全部注入给WebView的话,那么一些存心不良的同学就可以任意调用我们这个类中的方法,给我们APP带来危害。
所以,一般而言,我们很少直接会传this,把整个类注入给WebView,而是单独写一个类专门用于JS交互,比如:
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mBtn = (Button) findViewById(R.id.btn);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSBridge(), "android");
mWebView.loadUrl("file:///android_asset/web.html");
public class JSBridge{
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), "通过Natvie传递的Toast:"+message, Toast.LENGTH_LONG).show();
在这段代码中,在通过addJavascriptInterface注入时:
mWebView.addJavascriptInterface(new JSBridge(), "android");&
指定android对象绑定的是JSBridge对象!所以在WebView中,通过JS只能访问JSBridge中所定义的对象,如果访问其它类的函数,比如MyActivity中的函数,就会报下面的错误(即方法找不到)
大家可以自己尝试下;
然后对应的html代码:
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
&h1&欢迎光临启舰的blog&/h1&
&input type="button" value="js调native" onclick="ok()"&
&script type="text/javascript"&
function ok() {
android.toastMessage("哈哈,i m webview msg");
由于在注入时的对象别名和所调用的函数名都没有变,所以HTML中的JS代码是无需更改的。效果图与上节一样,就不再帖出了。
源码在文章底部给出
4、addJavascriptInterface注入漏洞
上面我们说了在addJavascriptInterface注入时,为了防止WebView调用我们不想被它调用的函数,所以我们需要单独为WebView交互定义一个类,让它只执行这个类里面的函数
但……这真的能挡住黑客的攻击吗?
当然是NO……,不然我就不会写这一段了……
mWebView.addJavascriptInterface(new JSBridge(), "android");&
在注入时,我们已经把对象传给了JS,在JS中当然可以通过反射得到APP中的各种类的实例!现在反编译Android代码可不是什么难事(本文结尾附jadx反编译方法),很容易拿到你有哪些类,有哪些函数,通过这些就可以想执行哪个执行哪个了,有没有细思极恐……
具体的细节我就不讲了,不在本篇范围,给大家找了篇文章,有兴趣的同学可以参考下:《Android WebView的Js对象注入漏洞解决方案》
5、JavascriptInterface注解
为了解决addJavascriptInterface()函数的安全问题,在android:targetSdkVersion数值为17(Android4.2)及以上的APP中,JS只能访问带有 @JavascriptInterface注解的Java函数,所以如果你的android:targetSdkVersion是17+,与JS交互的Native函数中,必须添加JavascriptInterface注解,不然无效,比如:
public class JSBridge {
@JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), "通过Natvie传递的Toast:" + message, Toast.LENGTH_LONG).show();
这也就是很多同学在高target上,addJavascriptInterface()函数无效的主要原因。
注意:虽然在target 17以后,已经修复了这个安全问题,但目前大多数APP都还是target 17以前的,所以大家可以尝试着找一些APP来演示下这个漏洞哦……
三、JAVA调用JS代码
1、JAVA调用JS代码
前面给大家演示了如何通过JS调用Java代码,这里就反过来看看,如何在Native中调用JS的代码
本例的效果图如下:
在点击“加载URL”按钮时,调用webview中的JavaScript求和函数,将结果显示在标题中。
先看html代码:
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
&h1 id="h"&欢迎光临启舰的blog&/h1&
&input type="button" value="js调native" onclick="ok()"&
&script type="text/javascript"&
function sum(i,m)
document.getElementById("h").innerHTML= (i+m);
在这里,我们写了一个求和函数sum(i,m)
结果中就是把h1标签的内容改为求和后的结果值。
再来看看JAVA的调用代码:
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mBtn = (Button) findViewById(R.id.btn);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("file:///android_asset/web.html");
mBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mWebView.loadUrl("javascript:sum(3,8)");
在点击按钮时调用JS函数:
mWebView.loadUrl("javascript:sum(3,8)");&
这里也就是在JAVA中调用JS函数的方法:
String url = "javascript:methodName(params……);"&
webView.loadUrl(url);&
javascript:伪协议让我们可以通过一个链接来调用JavaScript函数
中间methodName是JavaScript中实现的函数
jsonParams是传入的参数列表
使用起来难度不大,就不再多讲了
源码在文章底部给出
2、JAVA中如何得到JS中的返回值(Android4.4以前)
现在我们再考虑一下,如果我们要在JAVA中需要得到JS的结果返回值要怎么办?比如在上面的例子中,我们需要在JAVA中得到在计算后的结果值
Android在4.4之前并没有提供直接调用js函数并获取值的方法,也就是说,我们只能调用JS中的函数,并不能得到该函数的返回值,想得到返回值我们就得想其它办法,所以在此之前,常用的思路是 java调用js方法,js方法执行完毕,再次调用java代码将值返回。
1).Java调用js代码
webView.addJavascriptInterface(this, "android");
mWebView.loadUrl("javascript:sum(3,8)");
注意,这里通过addJavascriptInterface将MyActiviy所对应的对象注入到WebView中了。
2).js函数处理,并将结果通过调用java方法返回
function sum(i,m){
var result = i+m;
document.getElementById("h").innerHTML=
android.onSumResult(result)
3)..Java在回调方法中获取js函数返回值
public void onSumResult(int result) {
Log.i(LOGTAG, "onSumResult result=" + result);
先看下效果图:
下面我们就完整地看一下代码:
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
&h1 id="h"&欢迎光临启舰的blog&/h1&
&input type="button" value="js调native" onclick="ok()"&
&script type="text/javascript"&
function sum(i,m){
var result = i+m;
document.getElementById("h").innerHTML=
android.onSumResult(result);
在function sum(i,m)中,先通过result得到结果,最后通过android.onSumResult(result);将结果传给Native
然后再来看看JAVA代码:
public class MyActivity extends Activity {
private WebView mWebV
private Button mB
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mBtn = (Button) findViewById(R.id.btn);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(this, "android");
mWebView.loadUrl("file:///android_asset/web.html");
mBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mWebView.loadUrl("javascript:sum(3,8)");
public void onSumResult(int result) {
Toast.makeText(this,"received result:"+result,Toast.LENGTH_SHORT).show();
这里主要做了两件事:
第一:通过addJavascriptInterface注入MyActivity对象,以便JS访问其中的函数
mWebView.addJavascriptInterface(this, "android");&
第二:供JS调用,以返回结果的函数onSumResult():
public void onSumResult(int result) {
Toast.makeText(this,"received result:"+result,Toast.LENGTH_SHORT).show();
& 3、JAVA中如何得到JS中的返回值(Android4.4之后)
Android 4.4之后使用evaluateJavascript即可。这里展示一个简单的交互示例
先写一个具有返回值的js方法
function getGreetings() {
java代码时用evaluateJavascript方法调用:
private void testEvaluateJavascript(WebView webView) {
webView.evaluateJavascript("getGreetings()", new ValueCallback() {
public void onReceiveValue(String value) {
Log.i(LOGTAG, "onReceiveValue value=" + value);
从上面的用法中很明显看到,通过evaluateJavascript调用JS中的方法,可以向其中添加结果回调,来接收JS的return值。
上面限定了结果返回结果为String,对于简单的类型会尝试转换成字符串返回,对于复杂的数据类型,建议以字符串形式的json返回。
evaluateJavascript方法必须在UI线程(主线程)调用,因此onReceiveValue也执行在主线程。
好了,这篇文章中有关WebView的知识就先到这,下篇继续讲。下面给大家讲讲有关jadx-gui反编译的知识。
四、jadx-gui反编译
在遇到jadx-gui反编译之前,都是使用apktools进行反编译的,apktools有些是反编译不出来的,而且……难用……
想知道jadx-gui有多强?它都可以反编译淘宝、微信代码,是不是够强了。下面我们就来看看它是如何反编译的;
1)、下载、配置
jadx-gui是开源的,项目地址:《/skylot/jadx》
打开终端,切到某个路径下,输入以下命令:
git clone /skylot/jadx.git
./gradlew dist
其实这里只是做了两个动作:
第一,使用git命令将 项目clone下来(这里需要配置git环境,如果没有,请先搜资料配置git环境,然后再来)
然后,执行jadx目录 下gradlew脚本,这个是shell脚本
windows电脑:
git clone /skylot/jadx.git
gradlew.bat dist
在windows电脑中,步骤与mac是一样的,只是最后一步中,已经不再是./gradlew所对应的shell脚本了,而是windows平台上的bat脚本。
可见作者有多牛X,shell脚本和bat脚本都会写,真是屌的不能直视
整个编译过程是比较慢的,这里需要耐心等待下。因为目前会使用gradle 2.7来编译项目,如果没有在环境变量中环境gradle 2.7的环境变量,会自己下载gradle 2.7
编译成功后会打出BUILD SUCCESS字样,如下图所示:
在编译成功后,在jadx目录下,会生成一个build目录,其中包含jadx目录和一个jadx-xxx-dev.zip的打包文件。在build/jadx目录下,就是源码编译出的jadx工具及所用jar包。jadx-xxx-dev.zip解压后的内容与build/jadx内容一样,只是将其打包了一下而已,方便移值,可见作者有多用心。build目录结构如下图所示:
2)、开始反编译
等完毕后,可以开始了,我就介绍个最简单最常用的用法
(1)、把apk改成zip
(2)、解压zip获取class.dex文件
(3)、将class.dex文件放到jadx目录下
cd build/jadx/
bin/jadx -d out classes.dex # 反编译后放入out文件夹下(如果out不存在它会自动创建)
bin/jadx-gui classes.dex # 会反编译,并且使用gui打开
目录结构图如下:
在使用jadx-gui反编译时,左下角会显示当前反编译的进度:
在反编译完成后,在左侧就可以看到目录结构和对应的代码,目录结构中显示的a,b,c,d这些字母是由于在生成apk时使用proguard混淆造成的,proguard混淆的类名是没办法反编译出对应的原类名的,这也是反编译代码中比较蛋疼的地方,下面给大家演示下结果:(还可以通过点击搜索按钮,搜索其中的代码)
有关jadx-gui工具的更多用法,只有靠大家自己去研究啦,到这里我们的源码就已经反编译出来了。
反编译工具和微信的Classes文件,会在源码中给出大家,源码下载地址:Android WebView使用
原文地址:http://blog.csdn.net/lsyz0021/article/details/
以上就是本文的全部内容,希望对大家的学习有所帮助。
Copyright & 2016 phpStudy

我要回帖

更多关于 红包领取 的文章

 

随机推荐