一、Android WebView是什么

1.1Aandroid WebView一些基本概念

在android手机中内置了一款高性能webkit内核浏览器,在SDK中封装为一个叫做WebView组件。

WebKit是Mac OS X v10.3及以上版本所包含的软件框架(对v10.2.7及以上版本也可通过软件更新获取)。同时,WebKit也是Mac OS X 的Satari网页浏览器的基础。WebKit是一个开源项目,主要由KDE的KHTML修改而来并且包含了一些来自苹果公司的一些组件。

传统上,WebKit包含一个网页引擎WebCore和一个脚本引擎JavasSriptCore,它们分别对应的是KDDE的KHTML和KJS。不过,随着JavaScript引擎的独立性越来越强,现在WebKit和WebCore已经基本上混用不分(例如Google Chrome和Maxthon3采用V8引擎,却仍然宣传自己是WebKit内核)。

这里我们初步体验一下在android是使用WebView浏览网页,在SDK的Dev Guide中有一个WebView简单的例子。

在开发过程中应该注意几点:

1、  AndroidManifest.xml中必须使用许可“android.permission.INTERNET”,否则会出Web page not  available错误。

2、  如果访问的页面中有JavaScript,则WebView必须设置支持JavaScript。

Webview.getSettings().setJavaScriptEnabled(true);

3、  如果页面中有链接,如果希望点击链接继续前往当前browser中响应,而不是新开android系统的browser中响应链接,必须覆盖WebView的WebViewClient对象。

mWebView.setWebViewClient(new WebViewClient(){

public Boolean shouldOverrideUrlLoading(WebView view,String url){

view.loadUrl(url);

return true;

}

})

4、  如果不做任何处理,浏览网页,点击系统“Back”键,整个Browser会调用finish()而结束自身,如果希望浏览的网页回退而不是退出浏览器,需要在当前Activity中处理病消掉该Back事件。

Public Boolean onKeyDown(int KeyCode,KeyEnvent event){

If((keyCode == KeyEnvent.KEYCODE_BACK) && mWebView.canGoBack()){

mWebView.goBack();

return true;

}

Return super.onKeyDown(keyCode,envent);

}

下一步让我们来了解一下android中WebView是如何支持javascript自定义对象的,在w3c标准中js有window、history、document等标准对象,同样我们可以在开发浏览器时自己定义我们的对象调用手机系统功能来处理,这样使用js就可以为所欲为了。

看一个实例:

package test.webview;

import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.webkit.WebSettings;import android.webkit.WebView;

public class WebViewDemoActivity extends Activity { private WebView mWebView; private Handler mHandler = new Handler(); public void onCreate(Bundle icicle) {  super.onCreate(icicle);  setContentView(R.layout.main);  mWebView = (WebView) findViewById(R.id.webView);  WebSettings webSettings = mWebView.getSettings();  webSettings.setJavaScriptEnabled(true);  mWebView.addJavascriptInterface(new Object() {   public void clickOnAndroid() {    mHandler.post(new Runnable() {     public void run() {      mWebView.loadUrl("javascript:wave()");     }    });   }  }, "demo");  mWebView.loadUrl("file:///android_asset/demo.html"); }}

我们看addJavascriptInterface(Object obj,String interfaceName)这个方法,该方法将一个java对象绑定到一个javascript对象中,javascript对象名就是interfaceName(demo),作用域是Global.这样初始化WebView后,在WebView加载的页面中就可以直接通过javascript:window.demo访问到绑定的java对象了。来看看html中是怎样调用的。

<html><mce:script language="javascript"><!--function wave() {document.getElementById("droid").src="android_waving.png";}// --></mce:script><body><a onClick="window.demo.clickOnAndroid()"><img id="droid" src="ic_launcher.png" mce_src="ic_launcher.png"/><br>Click me!</a></body></html>

这样在javascript中就可以调用java对象clickOnAndroid()方法了,同样我们可以在此对象中定义很多方法(比如发短信、调用联系人列表等手机系统功能),这里wave()方法是java中调用javascript的例子。
这里还有几个知识点:
1)为了让WebView从apk文件中加载assets,Android SDK提供了一个schema,前缀为“file:///android_asset/”。WebView遇到这样的schema,就去当前包中的assets目录中找内容。如上面的“file:///android_asset/demo.html”。
2)addJavascriptInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用Handler的目的。
1.2Android WebView组件的使用详解
网络内容
1、LoadUrl直接显示网页内容(单独显示网络图片)
2、LoadData显示中文网页内容(含空格的处理)
APK包内文件
1、LoadUrl显示APK中html和图片文件。
2、LoadData(loadDataWithBaseURL)显示APK这图片和文字混合的html内容res/layout/main.xml
xml代码如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <WebView         android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:id="@+id/WebView"        /></LinearLayout>

Java代码:

package test.webview;

import java.net.URLEncoder;import android.app.Activity;import android.os.Bundle;import android.webkit.WebView;public class WebViewDemoActivity extends Activity { WebView WebView; final String mimeType = "text/html"; final String encoding = "utf-8"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.main);  WebView = (WebView) findViewById(R.id.webView);  WebView.getSettings().setJavaScriptEnabled(true);  //  //webHtml();  //  //webImage();  //  //localHtmlZh();  //  //localHtmlBlankSpace();  //  //localHtml();  //  // localImage();  //  localHtmlImage(); } /**  * 直接网页显示  */ private void webHtml() {  try {   WebView.loadUrl("http://www.google.com");  } catch (Exception ex) {   ex.printStackTrace();  } } /**  * 直接网络图片显示  */ private void webImage() {  try {   WebView   .loadUrl("http://www.gstatic.com/codesite/ph/images/code_small.png");  } catch (Exception ex) {   ex.printStackTrace();  } } /**  * 中文显示  */ private void localHtmlZh() {  try {   String data = "测试含有中文的Html 数据";   // utf-8 编码处理(在SDK1.5 模拟器和真实设备上都将出现乱码,SDK1.6 上能正常显示)   //WebView.loadData(data, mimeType, encoding);   // 对数据进行编码处理(SDK1.5 版本)   WebView.loadData(URLEncoder.encode(data, encoding), mimeType,     encoding);  } catch (Exception ex) {   ex.printStackTrace();  } } /**  * 中文显示(空格的处理)  */ private void localHtmlBlankSpace() {  try {   String data = " 测试含有空格的Html 数据";   // 不对空格做处理   WebView.loadData(URLEncoder.encode(data, encoding), mimeType,     encoding);   //WebView.loadData(data, mimeType, encoding);   // 对空格做处理(在SDK1.5 版本中)   WebView.loadData(URLEncoder.encode(data, encoding).replaceAll(     "\\+", " "), mimeType, encoding);  } catch (Exception ex) {   ex.printStackTrace();  } } /**  * 显示本地图片文件  */ private void localImage() {  try {   // 本地文件处理(如果文件名中有空格需要用+来替代)   WebView.loadUrl("file:///android_asset/icon.png");  } catch (Exception ex) {   ex.printStackTrace();  } } /**  * 显示本地网页文件  */ private void localHtml() {  try {   // 本地文件处理(如果文件名中有空格需要用+来替代)   WebView.loadUrl("file:///android_asset/test.html");  } catch (Exception ex) {   ex.printStackTrace();  } } /**  * 显示本地图片和文字混合的Html 内容  */ private void localHtmlImage() {  try {   String data = "测试本地图片和文字混合显示,这是APK 里的图片";   // SDK1.5 本地文件处理(不能显示图片)   // WebView.loadData(URLEncoder.encode(data, encoding), mimeType,   // encoding);   // SDK1.6 及以后版本   // WebView.loadData(data, mimeType, encoding);   // 本地文件处理(能显示图片)   WebView.loadDataWithBaseURL("about:blank", data, mimeType,     encoding, "");  } catch (Exception ex) {   ex.printStackTrace();  } }}

二、Android WebView入门
本章主要通过简单的例子演示如何使用WebView.
2.1Android编写简单的WebView
在android界面中如果使用WebView,往往可以复用服务器端的内容。先写个简单的WebVie实现。
非常简单,直接在adt 默认项目上加的.加了个WebView,访问我的博客首页.

首先,要记着在AndroidManifest.xml 中加入访问internet 的权限,否则页面无法访问.
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
然后,布局文件加入:
<WebView android:id="@+id/WebView" android:layout_width="fill_parent" android:layout_height="0dip"
android:layout_weight="1" />
最后,在代码中设置WebView 的属性:
this.WebView=(WebView) this.findViewById(R.id.WebView);
this.WebView.getSettings().setSupportZoom(false);
this.WebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
this.WebView.loadUrl("http://marshal.easymorse.com/");

2.2 WebView初探
Android SDK 的Dev Guide 中有一个WebView 的简单例子,寥寥几行代码就可以做一个自己的浏览器.
在实验时,有如下几个注意事项:
1)AndroidManifest.xml 中必须使用许可"android.permission.INTERNET",否则会出Web page not available 错误:
2)如果访问的页面中有Javascript,则WebView 必须设置支持Javascript:
WebView.getSettings().setJavaScriptEnabled(true);
否则显示空白页面.
3)如果页面中链接,如果希望点击链接继续在当前browser 中响应,而不是新开Android 的系统browser 中响
应该链接,必须覆盖WebView 的WebViewClient 对象:
mWebView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
上述方法告诉系统由我这个WebViewClient 处理这个Intent,我来加载URL.点击一个链接的Intent 是向上冒
泡的,shouldOverrideUrlLoading 方法return true 表示我加载后这个Intent 就消费了,不再向上冒泡了.
4)如果不做任何处理,在显示你的Brower UI 时,点击系统“Back”键,整个Browser 会作为一个整体“Back"到其他
Activity 中,而不是希望的在Browser 的历史页面中Back.如果希望实现在历史页面中Back,需要在当前Activity 中
处理并消费掉该Back 事件:
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
三、Android WebView深入
本章将讲解深入一些的WebView技术,比如和js交互,和本地文件,缓存,WebView控件定制等。
3.1Android利用WebView实现在js中调用android代码
在java或android中,接口占有很大比重,做程序员当然要对接口了解了。android和js看似牛马不相及,但是由于WebView的连接在js中就能够调用android写的代码实现android的功能!android和js就像java和c/c++靠jni连接似的,二者也是靠接口连接。
1、首先简述WebView、WebViewClient、WebChromeClient之间的区别:
在WebView的设计中,不是什么事都要WebView类干的,有些杂事是分给其他人的,这样WebView专心干好自己的解析、渲染工作就行了。WebViewClient就是帮助WebView处理各种通知、请求事件等,WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title.
2、功能实现:利用android中的webview加载一个html网页,在html网页中定义一个按钮,点击按钮弹出toast。
3、实现步骤:
1)定义一个接口类,将上下文对象传进去,在接口类中定义要在js中实现的方法。
2)在assets资源包下定义一个html文件,在文件中定义一个button。button的点击事件定义为一个js函数。
3)在xml中定义一个WebView组件,在活动类中获取WebView并对WebView参数进行设置,此处特别注意要设置WebView支持js且将定义的js接口类添加到WebView中去,此后在js就可以利用该接口类中定义的函数了。即:

myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new JavaScriptinterface(this),"android");
4)利用WebView加载本地html文件的方法是:myWebView.loadData(htmlText,"text/html","utf-8");此处的htmlText是以字符串的方式读取assets包下的html中的内容。
4、实现利用返回键回到上一页:
设置webview的按键监听,监听到期返回键并判断网页是否能够返回,利用webview的goBack()返回到上一页。

3.2 Android WebView缓存
在 项目中经常会使用到WebView控件,当加载html页面时,会在data/data/应用package目录下生存database与cache两个文件夹如下如所示:

请求的url 记录是保存在WebViewCache.db,而url 的内容是保存在WebViewCache 文件夹下.

为了便于理解,接下来模拟一个案例,定义一个html 文件,在里面显示一张图片,用WebView 加载出来,然后再
试着从缓存里把这张图片读取出来并显示.
第一步:新建一个Android 工程命名为WebViewCache.目录结构如下:

第二步:在assets 目录下新建一个html 文件,命名为index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>WebViewCacheDemo</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<img
src="http://img04.taobaocdn.com/imgextra/i4/608825099/T2nGXBXXpaXXXXXXXX_!!608825099.jpg_310x310.jpg"/>
</body>
</html>
第三步:修改main.xml 布局文件,一个WebView 控件一个Button(点击加载缓存图片用),代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<WebView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/WebView"/>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="从缓存读取图片"
android:id="@+id/button"/></LinearLayout>
第四步:修改主核心程序WebViewCacheDemo.java,这里我只加载了index.html 文件,按钮事件暂时没写,代码
如下:

package com.ljq.activity;
import java.io.File;
import java.io.FileInputStream;
import android.app.Activity;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
public class WebViewActivity extends Activity {
private WebView WebView;
private static final String url="file:///android_asset/index.html";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView=(WebView)findViewById(R.id.WebView);
WebView.loadUrl(url);
}
}
第五步:在AndroidMainifest.xml 文件中加访问网络的权限:
<uses-permission android:name="android.permission.INTERNET" />
运行效果如下:

此时我们在WebViewCache.db 里的cache.table 里多了一条记录如下图所示:

在cache/WebViewCache/目录下多了一个10d8d5cd 文件,刚好和cache.table 里的filepath,我们可以断定这个
文件就是我们从网上拽下来的图片:
为了验证猜想,我给Button 增加事件响应,就是弹出Dialog,里面加载缓存的图片,完整代码如下:
package com.ljq.activity;import java.io.File;
import java.io.FileInputStream;
import android.app.Activity;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;import android.os.Bundle;
import android.view.View;

import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
public class WebViewActivity extends Activity {
private WebView WebView;
private static final String url="file:///android_asset/index.html";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView=(WebView)findViewById(R.id.WebView);
WebView.loadUrl(url);
//点击按钮时弹出对话框
Button button=(Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ImageView imageView=new ImageView(WebViewActivity.this);
imageView.setImageBitmap(getPictureFromCache());
Builder builder=new android.app.AlertDialog.Builder(WebViewActivity.this);
//设置对话框的图标
builder.setTitle("从缓存查看图片");
builder.setView(imageView);
//退出按钮
builder.setPositiveButton("退出", new OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
//关闭alert 对话框架
dialog.cancel();
}
});
builder.create().show();
}
});
}
/**
* 从缓存获取图片
*
* @return
*/
private Bitmap getPictureFromCache(){
Bitmap bitmap=null;
try {
//这里写死,在实际开发项目中要灵活使用
File file=new File(getCacheDir()+"/WebViewCache/10d8d5cd");
FileInputStream inStream=new FileInputStream(file);
bitmap=BitmapFactory.decodeStream(inStream);
} catch (Exception e) {
e.printStackTrace();
}

return bitmap;
}
}
第六步:再次运行工程,点击button 按钮,效果如下图所示:

3.3 Android WebView删除缓存

删除保存于手机上的缓存:
// clear the cache before time numDays
private int clearCacheFolder(File dir, long numDays) {
int deletedFiles = 0;
if (dir!= null && dir.isDirectory()) {
try {
for (File child:dir.listFiles()) {
if (child.isDirectory()) {
deletedFiles += clearCacheFolder(child, numDays);
}
if (child.lastModified() < numDays) {
if (child.delete()) {

deletedFiles++;
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
return deletedFiles;
}
打开关闭使用缓存
//优先使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//不使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
在退出应用的时候加上如下代码
File file = CacheManager.getCacheFileBaseDir();
if (file != null && file.exists() && file.isDirectory()) {
for (File item : file.listFiles()) {
item.delete();
}
file.delete();
}
context.deleteDatabase("WebView.db");
context.deleteDatabase("WebViewCache.db");
3.4 Android listview中加入WebView

想在listview 的item 中加入一个WebView 页面,只要一个item 和WebView 就可以,不知道怎么在item 中加
入WebView,需要的就是类似上图的效果,在listview 中加入WebView,实现下拉刷新WebView 的效果.知道的朋友
说下,谢谢.
解决办法如下.
List list = new ArrayList();
list.add("http://www.……");
ItemAdapter ia = new ItemAdapter(getApplicationContext(), list);
setListAdapter(ia);
………………
public class ItemAdapter extends BaseAdapter{
private Handler handler;
private List list;
private Context context;
private ViewHolder vh = new ViewHolder();
public ItemAdapter(Context con,List list) {
// TODO Auto-generated constructor stub
this.list = list;
this.context = con;
}
private class ViewHolder {
WebView web;
}
……………………………………
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = LayoutInflater.from(context).inflate(
R.layout.webpage, null);//写一个webpage 的布局xml,WebView id 为WebView
vh.web = (WebView) view.findViewById(R.id.WebView);
setWebpageView(list.get(position).toString(),vh.web);
return view;
}
public void setWebpageView(final String url,WebView WebView){
loadurl(WebView, url);
handler = new Handler(){
public void handleMessage(Message msg){//定义一个Handler,用于处理线程与UI 间通讯
if (!Thread.currentThread().isInterrupted()){
switch (msg.what){
case 0:
pd.show();//显示进度对话框
break;
case 1:
pd.hide();
break;
}
}
super.handleMessage(msg);

}
};
}
public void loadurl(final WebView view,final String url){
new Thread(){
public void run(){
handler.sendEmptyMessage(0);
view.loadUrl(url);//载入网页
}
}.start();
}
}

3.5 Android中WebView跟JAVASCRIPT中的交互
在android 的应用程序中,可以直接调用WebView 中的javascript 代码,而WebView 中的javascript 代码,也可
以去调用ANDROID 应用程序(也就是JAVA 部分的代码).下面举例说明之:
1、JAVASCRIPT 脚本调用android 程序
要在WebView 中,调用addJavascriptInterface(OBJ,interfacename)
其中,obj 为和javascript 通信的应用程序,interfacename 为提供给JAVASCRIPT 调用的名称,设置如下:
WebView WebView = new WebView(this);
WebView.getSettings().setJavaScriptEnabled(true);
WebView.loadUrl(getIntent().getCharSequenceExtra("url").toString());
//设定JavaScript 脚本代码的界面名称是”android”
WebView.addJavascriptInterface(this, "android");
其中WebView 调用的HTML 页中,JS 如下:
<script type="text/javascript">
function ok() {
android.js(document.forms[0].elements[0].value, document.forms[0].elements[1].value);
}
而这个android.js 在哪呢?那是在应用程序中的
//JavaScript 脚本代码可以调用的函数js()处理
public void js(String action, String uri) {
...../
}
这个JS 中就是处理JAVASCRIPT 发送过来的请求了.
2、下面的例子,当WebView 网页中输入后,点提交按钮,会跟ANDROID 的应用程序进行交互
WebView WebView = new WebView(this);
WebView.getSettings().setJavaScriptEnabled(true);
WebView.setWebChromeClient(new MyWebChromeClient());
WebView.loadUrl(getIntent().getCharSequenceExtra("url").toString());
//onJsAlert()函数接收到来自HTML 网页的alert()警告信息
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
if (message.length() != 0) {
AlertDialog.Builder builder = new AlertDialog.Builder(JExample02.this);
builder.setTitle("From JavaScript").setMessage(message).show();
result.cancel();
return true;
}
return false;
}
而HTML 页中的JS 事件为:
<input type="button" value="alert" οnclick="alert(document.forms[0].elements[0].value)">
特别提示下, 在自定义的MyWebChromeClient()) 中, 除了可以重写onJSAlert 外, 还可以重写
onJsPrompt,onJsConfirm 等,可以参考.
http://618119.com/archives/2010/12/20/199.html
3、下面这个例子,先显示第一张图片,点一点后,再显示第2 张图片
HTML JS 中:
<script language="javascript">
function changeImage02() {
document.getElementById("image").src="navy02.jpg";
}
function changeImage01() {
document.getElementById("image").src="navy01.jpg";
}
</script>
</head>
<body>
<a onClick="window.demo.onClick()">
<img id="image" src="navy01.jpg"/></a>
</body>
当点<a onClick="window.demo.onClick()">后,调用ANDROID 应用程序中的处理部分,看程序:
WebView.addJavascriptInterface(new JSInterface(),"demo");
public final class JSInterface {
//JavaScript 脚本代码可以调用的函数onClick()处理
public void onClick() {
handler.post(new Runnable() {
public void run() {
if (flag == 0) {
flag = 1;
WebView.loadUrl("javascript:changeImage02()");
} else {
flag = 0;
WebView.loadUrl("javascript:changeImage01()");
}
}
});
}
}
可以看到,ANDROID 中,通过WebView.loadUrl 去调用HTML 页面中的JS
3.6 Android的WebView与ProgressDialog结合
WebView 组件支持直接加载网页,可以将其视为一个浏览器,要实现该功能,具体步骤如下:
WebView.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<WebView android:id="@+id/WebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
WebViewActivity.java
public class WebViewActivity extends Activity{
private WebView WebView;
private AlertDialog alertDialog;
private ProgressDialog progressBar;
jQuery datatables 使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.WebView);
//加载WebView
initWebView();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK && WebView.canGoBack()){
WebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
class MyWebViewClient extends WebViewClient{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
if(progressBar.isShowing()){
progressBar.dismiss();
}
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
Toast.makeText(WebViewActivity.this, "网页加载出错!", Toast.LENGTH_LONG);
alertDialog.setTitle("ERROR");
alertDialog.setMessage(description);
alertDialog.setButton("OK", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alertDialog.show();
}
}
protected void initWebView(){
//设计进度条
progressBar = ProgressDialog.show(WebViewActivity.this, null, "正在进入网页,请稍后…");
//获得WebView 组件
WebView = (WebView) this.findViewById(R.id.WebView);
WebView.getSettings().setJavaScriptEnabled(true);
WebView.loadUrl("http://www.baidu.com");
alertDialog = new AlertDialog.Builder(this).create();
//设置视图客户端
WebView.setWebViewClient(new MyWebViewClient());
}
}
最后,需要在**Manifest.xml 中添加访问互联网的权限,否则不能显示:
<uses-permission android:name="android.permission.INTERNET"/>
3.7 WebView处理404错误
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebView_404 extends Activity {
private final String HOMEPAGE = "http://10.0.0.95/index.html";//请求的网站的主页
private WebView web;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what==404) {//主页不存在
//载入本地assets 文件夹下面的错误提示页面404.html
web.loadUrl("file:///android_asset/404.html");
} else {
web.loadUrl(HOMEPAGE);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.WebView_404);
web = (WebView) findViewById(R.id.WebView01);
web.getSettings().setJavaScriptEnabled(true);
web.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("http://") && getRespStatus(url)==404) {
view.stopLoading();
//载入本地assets 文件夹下面的错误提示页面404.html
view.loadUrl("file:///android_asset/404.html");
} else {
view.loadUrl(url);
}
return true;
}
});
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
//此处判断主页是否存在,因为主页是通过loadUrl 加载的,
//此时不会执行shouldOverrideUrlLoading 进行页面是否存在的判断
//进入主页后,点主页里面的链接,链接到其他页面就一定会执行shouldOverrideUrlLoading 方法了
if(getRespStatus(HOMEPAGE)==404) {
msg.what = 404;
}
handler.sendMessage(msg);
}
}).start();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK && web.canGoBack()) {
web.goBack();
return false;
}
return super.onKeyDown(keyCode, event);
}
private int getRespStatus(String url) {
int status = -1;
try {
HttpHead head = new HttpHead(url);
HttpClient client = new DefaultHttpClient();
HttpResponse resp = client.execute(head);
status = resp.getStatusLine().getStatusCode();
} catch (IOException e) {}
return status;
}
}

四、Android WebView CookBook
这里收集一些很实用的小技巧~
4.1 Android WebView 中点击打开默认的浏览器
论坛帖子:http://www.eoeandroid.com/thread-174926-1-1.html
---------------------------------------------------------------------------------------------------
我遇到一个简单的问题,我在WebView 中加载了一个外部的url ,现在需要的是在页面加载后,
用户点击里面的连接能像默认的浏览器一样在我的WebView 中打开连接,但问题是现在它会打开android 的默
认浏览器去加载页面???我已经启用了javascript ,但是没用,是否我忘记了什么?
一楼:
如果你不想要开android 默认的浏览器,那么我就得自己去截取在你WebView 中的点击事件.
你可以通过WebView 的WebViewClient 来监控事件.你现在需要的是shouldOverrideUrlLoading()这个方法,它
会允许在一个特定的url 被选中的时候来执行你自己的一个动作.
在sdk 的samples 中有一个示例.代码如下:
private class HelloWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
二楼:
在某些情况下,你或许也要生写onLoadResource.比如说重定向时,因为它不会触发你的加载方法.我这种情况
下,我尝试如下:
@Override
public void onLoadResource(WebView view, String url)
{
if (url.equals("http://redirectexample.com"))
{
//do your own thing here
}
else
{
super.onLoadResource(view, url);
}
}
4.2 追加一个图片到Android WebView
我正在尝试用javascript 来向WebView 中追加一个图片.我自己写的html,并且包含了自己方法.
代码如下:
<script type="text/javascript">
function image(src) {
var img = document.createElement("IMG");
img.src = src;
document.getElementById('image').appendChild(img);
}
</script>
但是我发现我不能通过myview.loadurl(javascript:image('line1.png'));来实现.所以我想试试别的方法.比如说
能不能通过loadurl()方法来实现,但是会报错.不过我也听说可以使用addJavascriptInterface 来实现,但是好像比较
复杂,但是也不确定行不行.不知道你们有没有好的解决办法?
解决办法:
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.WebView;
public class StackOverFlowActivity extends Activity {
private Handler mHandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView view=(WebView)findViewById(R.id.WebView1);
view.getSettings().setJavaScriptEnabled(true);
view.loadUrl("file:///android_asset/index.html");
view.addJavascriptInterface(new MyJavaScriptInterface(), "Android");
}
final class MyJavaScriptInterface
{
public void ProcessJavaScript(final String scriptname, final String args)
{
mHandler.post(new Runnable()
{
public void run()
{
String url="file:///android_asset/img.jpg";
WebView.loadUrl("javascript:image(\""+url+"\")");
}
});
}
}
}
index.html:
<script type="text/javascript">
function getimage()
{
Android.ProcessJavaScript("image",null);
}
function image(src) {
var img = document.createElement("IMG");
img.src = src;
document.getElementById('image').appendChild(img);
}
</script>
and add the following,
<body οnlοad="getimage()" >
4.3 WebView中关于字符串编码问题
我从web service 中获取到的响应如下:
<html><head>
<style type="text/css">
body{
color: #FFFFFF;
background-color: #000000;
}
</style>
</head>
<body><center><div>
Ricardo Viana Vargas ?
09-14 Ricardo Viana Vargas é especialista em gerenciamento de projetos, portfólio e riscos. Foi, nos últimos 15
anos, responsável por mais de 80 projetos de grande porte em diversos países, nas áreas de petróleo, energia,
infraestrutura, telecomunica??es, informática e finan?as, com um portfólio de investimentos gerenciado superior a 18
bilh?es de dólares. Foi o primeiro voluntário latino-americano a ser eleito para exercer a fun??o de presidente do
conselho diretor (Chairman) do Project Management Institute (PMI), maior organiza??o do mundo voltada para a
administra??o de projetos, com cerca de 500 mil membros e profissionais certificados em 175 países. Ricardo Vargas
escreveu dez livros sobre gerenciamento de projetos, publicados em português e inglês, com mais de 240 mil
exemplares vendidos mundialmente. Recebeu em 2005 o prêmio PMI Distinguished Award pela sua contribui??o..
(PRMIA).
</div> </center>
</body>
</html>
怎么才能让WebView 显示出正确的字符串呢?我在WebView 中的代码如下:
System.out.println("strContent is :: " + strContent);
WebView wv = (WebView) findViewById(R.id.WebView_portugage);
wv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
wv.loadData(strContent, "text/html", "UTF-8");
1 楼:
(1)用WebView.loadDataWithBaseURL,它的行为与WebView.loadData 不同(应该说是更好)
(2)试试把UTF-8 替换成其它的编码,如US-ASCII.最好是确认你显示的字符中用的什么编码.
用户回馈:
1,用第一种办法,是可以行.
2. 我用了wv.loadData(object1.getString("post_content").toString(), "text/html", "US-ASCII");, 还是一样的问
题.(此方法无效)
2 楼:
我是在WebView.loadData 中设置MIME-type 为"text/html; charset=utf-8"来解决的.
这种方法并不是对所有的设备都是有效的, 猜测可能与浏览器的内核版本(webkit) 有关. 但是
loadDataWithBaseURL 在所有的设备(已测试)都是有效的.
4.4 Android的WebView研究
最近做的项目大量用到了WebView ,用网页来布局. Android 的WebView 是基于webkit 内核,不过他的运
行效果和firefox 上一模一样,所以写的时候都是先用firefox 测试,测试OK 了再放到程序里面看效果,基本上
不会有什么问题.其实android 的WebView 跟iphone 的WebView 差不多, iphone 上的WebView 比android
上的强大多了.
谈一下研究WebView 的一些成果:
1、加载资源的速度不慢,但是资源多了,就很慢.图片、css 、js 、html 这些资源每个大概需要10-200ms ,
一般都是30ms 就ok 了.如果一个页面上的资源很多,就很浪费时间.
2、Js 和css 的执行速度.开始的时候,我的页面都是用js 生成DOM ,添加样式等也用js 添加.后来发现,
加载一个页面居然要5-6 秒.然后我就怀疑是不是js 的执行效率不高,然后就把能用css 的地方都用css ,能直
接写到html 上的就不用js 动态生成.结果,速度并没有多大的提升,最多提升了1 秒.看来, Js 的执行速度虽然
比不上css ,但是还不至于慢到那种程度.那会是什么原因使得页面加载速度这么慢?经过仔细的排查,最终发现,
是因为我用了jQuery 框架.
WebView 加载页面的顺序是这样的:先加载html ,然后从里面解析出css 、js 文件和页面上写死的图片
资源进行加载,如果webkit 的缓存里面有,就不加载.加载完这些资源之后,就进行css 的渲染和js 的执行. Css
的渲染一般不需要很长时间,几十毫秒就ok .关键是js 的执行,如果用了jQuery ,则执行起来需要5-6 秒.而在
这段时间,如果不在WebView 里设置背景,网页部分是白色的,很难看.这是一个很糟糕的用户体验.所以如果用
网页布局程序,最好别用很大的js 框架.
3、网页和Java 之间的互调.这个功能是iphone 里面就有的,网上也有很多资料,可以告诉我们怎么做,这些
都是很简单、很基本的.我研究了一段时间,总结一下:
①Java 调用js 里面的函数,速度并不令人满意,大概一次一两百毫秒吧,如果要做交互性很强的事情,这种速
度会让人疯掉的.而反过来就不一样了, js 去调java 的方法,速度很快,基本上40-50 毫秒一次.所以尽量用js
调用java 方法,而不是java 去调用js 函数.
②Java 调用js 的函数,没有返回值,而Js 调用java 方法,可以有返回值.返回值可以是字符串,也可以是对
象.如果是字符串,有个很讨厌的问题,第3 点我会讲的.如果是对象,这个对象会被转换为js 的对象,直接可以访
问里面的方法.但是我不推荐java 返回给js 的是对象,除非是必须.因为js 收到java 返回的对象,会产生一些
交换对象,而如果这些对象的数量增加到了500 或600 以上,程序就会出问题.所以尽量返回基本数据类型或者
字符串.
③Js 调用java 的方法,返回值如果是字符串,你会发现这个字符串是native 的,不能对它进行一些修改操
作,比如想对它substr ,取不到.怎么解决呢?转成locale 的.使用toLocaleString() 函数就可以了.不过这个函数
的速度并不快,转化的字符串如果很多,将会很耗费时间.
4、网页上拖动元素.网页上有一个div ,想要拖动它到另外一个地方,怎么做?如果用PC 上的网页做法,监听
onmousedown 、onmousemove 和onmouseup 就可以了.但是在手机上,事件模型就不一样了.在网页上点击,
拖动,然后释放,手离开屏幕的时候, WebView 才会触发onmousedown 、onmousemove 、onmouseup 事件.
所以,要想拖动,不能这么做.这个问题困扰我很长时间,后来发现iphone 上的做法,才解决了. Iphone 上的
WebView 有专为触摸屏设计的事件ontouchstart 、ontouchmove 、ontouchend ,这几个事件的响应是实时的,
就能解决拖动的问题了.
5、一些小问题. WebView 里面的网页,如果有input ,需要输入,但是点上去却没反应,输入法不出来.这种情况
是因为WebView 没有获取焦点.需要在java 里面给WebView 设置一下requestFocus() 就行了.
6、Android 上的WebView 和iphone 的WebView 区别.目前为止,我发现的区别有这么几个:
①Android 上, WebView 不支持多点触控,没有ongesture 系列事件,而iphone 上有.
②Android 上的WebView 不支持透明, iphone 上可以
4.5 Android WebView 总结
1、添加权限:AndroidManifest.xml 中必须使用许可"android.permission.INTERNET",否则会出Web page not
available 错误.
2、在要Activity 中生成一个WebView 组件:WebView WebView = new WebView(this);
3、设置WebView 基本信息:
如果访问的页面中有Javascript,则WebView 必须设置支持Javascript.
WebView.getSettings().setJavaScriptEnabled(true);
触摸焦点起作用
r equestFocus();
取消滚动条
this.setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY);
4、设置WevView 要显示的网页:
互联网用:WebView.loadUrl("http://www.google.com");
本地文件用:WebView.loadUrl("file:///android_asset/XX.html"); 本地文件存放在:assets 文件中
5、如果希望点击链接由自己处理,而不是新开Android 的系统browser 中响应该链接.
给WebView 添加一个事件监听对象(WebViewClient)
并重写其中的一些方法
shouldOverrideUrlLoading:对网页中超链接按钮的响应.
当按下某个连接时WebViewClient 会调用这个方法,并传递参数:按下的url
onLoadResource
onPageStart
onPageFinish
onReceiveError
onReceivedHttpAuthRequest
6、如果用WebView 点链接看了很多页以后,如果不做任何处理,点击系统“Back”键,整个浏览器会调用finish()
而结束自身,如果希望浏览的网页回退而不是退出浏览器,需要在当前Activity 中处理并消费掉该Back 事件.
覆盖Activity 类的onKeyDown(int keyCoder,KeyEvent event)方法.
public boolean onKeyDown(int keyCoder,KeyEvent event){
if(WebView.canGoBack() && keyCoder == KeyEvent.KEYCODE_BACK){
WebView.goBack(); //goBack()表示返回WebView 的上一页面
return true;
}
return false;
}
4.6 Android获取服务器中的session问题
1、Android 中的WebView 如何获取服务器页面的jsessionid 的值
2、Android 的WebView 又是如何把得到的jsessionid 的值在set 到服务器中,一致达到他们在同一个jsessionid
的回话中.
解决如下:
CookieManager cm = CookieManager.getInstance();
cm.removeAllCookie();
cm.getCookie(url);
cm.setCookie(url, cookie);
另外还有个CookieSyncManager,没搞清干嘛使的,但是我按以下顺序调用,设置Cookie 没问题
CookieSyncManager csm = CookieSyncManager.createInstance(this);
CookieManager cm = CookieManager.getInstance();
cm.removeAllCookie();
csm.sync();
cm.setCookie(url, cookie);
4.7 WebView 设置实现两个手指缩放网页
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
代码是这样,但是首先是你的硬件支持多点触控
4.8 WebView cookies清理
在使用新浪微博账户登录应用时,WebView 会自动登录上次的微博帐号!(因为WebView 记录了微博帐号和
密码的cookies)
所以,需要清除SessionCookie:
CookieSyncManager.createInstance(this);
CookieSyncManager.getInstance().startSync();
CookieManager.getInstance().removeSessionCookie();
另外,清理cache 和历史记录的方法:
WebView.clearCache(true);
WebView.clearHistory();
4.9 Android WebView使用cmwap无法联网解决办法
1、某些Rom 在wifi 环境下取代理依然会取到cmwap 设置的代理值,所以取代理时判断一下手机网络环境,
如果是gprs 上网,则不取代理.
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager
.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
int type = activeNetworkInfo.getType();
// TODO 防止wifi 下读取移动的代理
if (type == ConnectivityManager.TYPE_MOBILE) {
//取代理
}else{
//不取代理
2. 某些rom 的webkit 在cmwap 下,webkit 连接不上或是时断时连,需要在onResume()添加
WebView.enablePlatformNotifications();,onStop 添加WebView.disablePlatformNotifications();.但是此时如果你需要
刚进入这个activity 就load 页面,第一次进入时load 的第一个页面是load 不出来的,会停留很久并且不出错误页
面,不调用WebViewClient.onReceivedError.个人试过setHttpAuthUsernamePassword 也不好使.
个人解决方案:
mWebPage.post(new Runnable(){
@Override
public void run() {
mWebPage.loadUrl(url);
}
});
此时第一此load 页面会很快调用WebViewClient.onReceivedError,你再在WebViewClient.onReceivedError 里
面设置标志,重新载入第一个页面即可.
4.10 Android判断WebView是否已经滚动到页面底端
getScrollY()方法返回的是当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离.
getHeight()或者getBottom()方法都返回当前WebView 这个容器的高度
getContentHeight 返回的是整个html 的高度,但并不等同于当前整个页面的高度,因为WebView 有缩放功能,
所以当前整个页面的高度实际上应该是原始html 的高度再乘上缩放比例.
因此,更正后的结果,准确的判断方法应该是:
if(WebView.getContentHeight*WebView.getScale() -(webvi ew.getHeight()+WebView.getScrollY())){
//已经处于底端
}
4.11 Android中WebView实现Javascript调用Java类方法
为了方便网页和Android 应用的交互,Android 系统提供了WebView 中JavaScript 网页脚本调用Java 类方法
的机制.只要调用addJavascriptInterface 方法即可映射一个Java 对象到JavaScript 对象上.
1、映射Java 对象到JavaScript 对象上
mWebView = (WebView) findViewById(R.id.wv_content);
mWebView.setVerticalScrollbarOverlay(true);
final WebSettings settings = mWebView.getSettings();
settings.setSupportZoom(true);
//WebView 启用Javascript 脚本执行
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
//映射Java 对象到一个名为”js2java“的Javascript 对象上
//JavaScript 中可以通过"window.js2java"来调用Java 对象的方法
mWebView.addJavascriptInterface(new JSInvokeClass(), "HTMLOUT");
2、JavaScript 调用Java 对象示例
这里才是最关键的地方所在了,下面是通过javascript 来调用java 中的方法,也就是JSInvokeClass 中的back 方
法window.HTMLOUT.back();
但是上面的方法放在哪里呢?如何去执行喃?请看:
mWebView.loadUrl("javascript:window.HTMLOUT.back();");
当然如果想传参数怎么办?不要急,首先在JSInvokeClass.back 方法处,申明一个代参数的方法就行了:
/**网页Javascript 调用接口**/
class JSInvokeClass {
public void back() {
activity.finish();
}
public void showHtml(String html)
{
Log.e("Html:"+html);
}
}
然后通过javascript 调用就行了.
mWebView.loadUrl("javascript:window.HTMLOUT.showHtml(document.documentElement.innerHTML);");
更多技巧,请访问这里:
http://search.eoeandroid.com/f/search?q=WebView&sId=7379687&ts=1335235840&mySign=4f90227f&menu=1&rfh
=1&qs=txt.form.a

【eoe Android特刊】第二十四期Android WebView相关推荐

  1. 智能化软件开发微访谈·第二十四期 大模型时代的智能化软件生态(讨论汇编)...

    CodeWisdom "智能化软件开发沙龙是由CodeWisdom团队组织的围绕智能化软件开发.数据驱动的软件开发质量与效能分析.云原生与智能化运维等相关话题开展的线上沙龙,通过微信群访谈交 ...

  2. 数据库管理-第二十四期 数据库设计-硬件篇(20220610)

    数据库管理 2022-06-10 第二十四期 数据库设计-硬件篇 1 CPU 2 内存 3 存储 4 网络 5 总结 下期预告: 第二十四期 数据库设计-硬件篇 上次与这次的更新间隔比之前短多了,主要 ...

  3. 机器人按照给定的指令c语言,【高训工控】专业课堂第二十四期——工业机器人调试基础:程序的构造与组成...

    原标题:[高训工控]专业课堂第二十四期--工业机器人调试基础:程序的构造与组成 大家好,欢迎来到[高训工控]专业课堂第二十四期,本期为大家带来--工业机器人调试基础:程序的构造与组成 在之前的文章中有 ...

  4. iOS摸鱼周报 第二十四期

    本期概要 话题:跟一位同学聊一下最近的面试感受. Tips:设计 OC 版本的 defer 功能,使用现有证书创建 Fastlane match 格式加密文件. 面试模块:离屏渲染相关知识点. 优秀博 ...

  5. 笑话集原创笑话精品展第二十四期

    1.有一个多次在大巴车上实施的罪犯在法庭上受审. 法官:这位被告,公诉机关指控你在客车上用暴力.控吓等不正当手段强行夺取他人钱财,你可知道你的行为已构成什么犯罪行为? 罪犯:知道. 法官:什么罪? 罪 ...

  6. Android第二十四期 - 游戏公告跑马灯效果

    代码已经整理好,效果如下: 地址:http://down.51cto.com/data/1887395 本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/lian ...

  7. Android第三十四期 - 极光推送

    代码已经整理好,参照官网的文档很快你会可以配置出来,如下效果:

  8. 【第二十四期】golang 一年经验开发 富途

    他们家是按题目来的,从一个小题目慢慢延伸着问,由浅入深,问到你换题为止. 第一题 给了一个网址,解释一下浏览器填入这个网址后发生了什么? TCP为什么要三次握手四次挥手? 502是什么? 如果出现50 ...

  9. 第二十四期:管理 | 成功领导远程IT团队的7个技巧

    管理虚拟工作环境需要各种真实世界的技能和工具.以下是激发创造力和生产力的策略.为了在日益缺乏人才和竞争激烈的IT世界中取得成功,越来越多的企业开始依赖于地理上分散的劳动力. 作者:John Edwar ...

最新文章

  1. 自学笔记——Python内置的处理字符串的函数
  2. SpringCloud服务消费者第一次调用出现超时问题的解决方案
  3. -Wl,-rpath=
  4. wxWidgets:持久对象概述
  5. 教你如何使用Redis:[7]redis常用命令
  6. springboot 多数据源 读写分离 AOP方式
  7. Windows - Windows下安装MSI程序遇到2503和2502错误
  8. MYSQL执行sql时报错:Table 'performance_schema.session_status' doesn't exist解决办法
  9. angular 关闭当前页_angular刷新当前页 angularjs页面不刷新的解决办法 - 电脑常识 - 服务器之家...
  10. 微信小程序下载图片保存到本地
  11. FFmpeg之编译ffplay(十四)
  12. AlphaGo增强式学习算法:实现‘高手指点’特效
  13. 交直流配电网潮流计算matlab,干货丨交直流混合配电网潮流计算(含分布式电源)...
  14. 如何识别图片中的文字?三种方法轻松搞定
  15. 记DeeCamp 2019夏面试
  16. 小米,红米 root Magisk(面具)安装教程
  17. 南方电网两栖机器人_南方电网首个作业级水下机器人落户海南 为海底电缆“护驾”...
  18. 201.微信公众号开发【文本消息】
  19. leetcode:954. 二倍数对数组
  20. 【机器人学】平面2R机器人(六)——MATLAB仿真

热门文章

  1. windows cmd 命令行 切换屏幕
  2. electron-builder 设置用户可以自己选择安装目录
  3. 港版AI chat如何制作?
  4. origin session
  5. 服务代码 *99#、 *98*1# 、 *98*2#的区别
  6. 因果图模型与d-分离
  7. 如何解决 尝试加载 Oracle 客户端库时引发 BadImageFormatException
  8. 经纬度对象的投影转换。
  9. stm32 DA 数模转换
  10. strcmp(),头文件,返回值