Android学习笔记三十八之WebView网页视图

前面我们介绍过了HTTP协议和Socket,这一篇我们来介绍一下Android的一个网络控件:WebView-网页视图。我们知道,现在移动端有两种开发方向:原生开发和H5移动端开发。

  所谓的H5移动端开发就是通过HTML5+CSS+js来构建一个网页版的移动应用,这中间的媒介就是我们今天介绍的WebView,现在H5开发很热门,优势是:可以用百分比布局;更新的时候不需要我们像原生开发一样需要重新下载一个APP重新安装,只需要修改一下网页就可以了;H5开发支持多平台,开发成本比较低,开发一款应用就可以在iOSandroid平台上运行;但是相应的H5开发也有很多的缺点:比原生应用响应慢;耗电比较大;数据积累问题;还有闪屏问题等。原生的JS是非常难学的,所以现在有很多的第三方框架:Bootstrap、AUI、Amaze UI、Frozen UI、Ionic等。下面我们开始学习一下这个WebView控件吧!

1、WebView 简介

  在Android系统中,内置了一款高性能的浏览器,其内核就是WebKit,WebView网页视图,就是在这个基础上封装的一个控件,我们可以直接用这个控件去显示Web页面,直接用HTML文件做为布局文件,可以和JavaScript交互调用。简单的说:WebView就是一个嵌套在界面上的浏览器控件。

2、WebView的属性和方法

下面我们了解一下WebView的常用属性和方法

WebSettings:WebView相关配置的设置,可以通过WebView.getSettings得到设置,相关方法如下:

  • getSettings():返回一个WebSettings对象,用来控制WebView的属性设置

  • loadUrl(String url):加载指定的Url

  • loadData(String data,String mimeType,String encoding):加载指定的Data到WebView中.data:是要加载的数据类型,但在数据里面不能出现英文字符:’#’, ‘%’, ‘\’ , ‘?’ 这四个字符.其中mimeType为数据类型如:textml,image/jpeg. encoding为字符的编码方式

  • loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl):作用跟上一个方法一样,但是比上一个更加强大,推荐使用,其中baseUrl是HTML代码片段中相关资源的相对根路径;historyUrl是历史Url。其余三个参数同上

  • setWebViewClient(WebViewClient client):为WebView指定一个WebViewClient对象.WebViewClient可以辅助WebView处理各种通知,请求等事件。

  • setWebChromeClient(WebChromeClient client):为WebView指定一个WebChromeClient对象,WebChromeClient专门用来辅助WebView处理js的对话框,网站title,网站图标,加载进度条等

WebViewClient:辅助WebView处理各种通知与请求事件,常用如下的方法:

  • onPageStared(WebView view,String url):通知主程序网页开始加载

  • onPageFinished(WebView view,String url,Bitmap favicon):通知主程序,网页加载完毕

  • doUpdateVisitedHistory(WebView view,String url,boolean isReload):更新历史记录

  • onLoadResource(WebView view,String url):通知主程序WebView即将加载指定url的资源

  • onScaleChanged(WebView view,float oldScale,float newScale):WebView的缩放发生改变时调用

  • shouldOverrideKeyEvent(WebView view,KeyEvent event):控制webView是否处理按键事件,如果返回true,则WebView不处理,返回false则处理

  • shouldOverrideUrlLoading(WebView view,String url):控制对新加载的Url的处理,返回true,WebView不做处理,返回false,WebView会对其进行处理

  • onReceivedError(WebView view,int errorCode,String description,String failingUrl):遇到不可恢复的错误信息时调用

WebChromeClient:辅助WebView处理javascript的对话框、网站图标、网站title、加载进度等,常用方法如下:

  • onJsAlert(WebView view,String url,String message,JsResult result):处理Js中的Alert对话框

  • onJsConfirm(WebView view,String url,String message,JsResult result):处理Js中的Confirm对话框

  • onJsPrompt(WebView view,String url,String message,String defaultValue,JsPromptResult result):处理Js中的Prompt对话框

  • onProgressChanged(WebView view,int newProgress):当加载进度条发生改变时调用

  • onReceivedIcon(WebView view, Bitmap icon):获得网页的icon

  • onReceivedTitle(WebView view, String title):获得网页的标题

这里只是一部分的方法,还有其它的可以自行查看官方文档:WebSettings WebViewClient WebChromeClient

3、WebView基本使用

上面我们介绍了WebView的基本概念和一些常用方法和属性,下面我们来具体使用一下WebView这个控件:

WebView可以在XML文件中指定,也可以在Java代码中生成,下面我们就是用在Java代码中生成的方法:

package com.example.webview;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

/**
 * Created by Devin on 2016/8/4.
 */
public class FirstWebViewActivity extends AppCompatActivity {

private WebView mWebView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_first);
    mWebView = new WebView(this);
    //设置在当前界面打开网页,如果不设置的话会使用手机浏览器打开网页
    mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            view.loadUrl("https://www.baidu.com/");
            return true;
        }
    });
    mWebView.loadUrl("https://www.baidu.com/");
    //获取到WebSettings
    WebSettings webSettings = mWebView.getSettings();
    //设置允许加载JS
    webSettings.setJavaScriptEnabled(true);
    setContentView(mWebView);
}
}

布局文件非常简单,就是一个布局文件而已,就不再贴代码了。运行效果图:

这样就可以实现一个简单的WebView使用例子,下面我们来学习其它的使用

4、WebView与JS的交互

  上面我们学习了WebView的基本概念、常用方法、和基本使用等,我们都知道,现在HTML中有很多的JS脚本,当我们Android需要和这些JS脚本做交互的时候,需要怎么实现呢?下面我们一起来学习WebView与JS的交互。

4.1、HTML通过JS调用Java代码

我们通过一个例子来体会一下JS调用Java代码:

HTML代码:

<html xmlns="http://www.w3.org/1999/html">
<head>
    <title>HTML通过JS调用Java代码</title>
</head>

<body>
    <input type="button" value="HTML通过JS显示Toast"  onclick="jS2Java.showToast('HTML通过JS显示Toast');" /></br>
    <br>
    <input type="button" value="HTML通过JS显示列表对话框"  onclick="jS2Java.showListDialog();" /></br>
    <br>
    <input type="button" value="HTML通过JS显示单选对话框"  onclick="jS2Java.showSingleChoice();" /></br>
    <br>
    <input type="button" value="HTML通过JS显示多选对话框"  onclick="jS2Java.showChoices();" /></br>
</body>

</html>

暴露的对象:

package com.example.webview;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

/**
 * Created by Devin on 2016/8/4.
 * 提供方法给JS调用
 *
 * @JavascriptInterface 版本兼容问题,需要在调用的方法上添加这个注解和导入这个import android.webkit.JavascriptInterface包
 */
public class JS2Java {

private Context mContext;

public JS2Java(Context mContext) {
    this.mContext = mContext;
}

/**
 * 显示吐司
 *
 * @param content
 */
@JavascriptInterface
public void showToast(String content) {
    Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show();
}

/**
 * 显示普通列表对话框
 */
@JavascriptInterface
public void showListDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    builder.setTitle("普通的列表对话框");
    builder.setItems(new String[]{"打篮球", "踢足球", "跑步", "游泳", "打羽毛球", "打乒乓球"}, null);
    builder.setPositiveButton("选好了", null);
    builder.create();
    builder.show();
}

/**
 * 显示单选对话框
 */
@JavascriptInterface
public void showSingleChoice() {
    final String[] mChoices = {"五花肉炒西兰花", "泡菜豆腐汤", "鸡腿菇炒豆腐", "老火靓汤", "广州文昌鸡", "烧鹅", "白灼虾"};
    final String[] select = {""};
    AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    builder.setTitle("选择你喜欢的菜");
    builder.setSingleChoiceItems(mChoices, 0, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            select[0] = mChoices[i];
        }
    });
    builder.setPositiveButton("选好了", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            ToastUtils.showToast(mContext, "选择了:" + select[0]);
        }
    });
    builder.create();
    builder.show();
}

/**
 * 显示多选对话框
 */
@JavascriptInterface
public void showChoices() {
    final String[] menu = {"丝瓜面筋", "糖醋鲤鱼", "糖醋排骨", "剁椒鱼头", "清蒸咸鱼", "鱼香肉丝", "清炒上海青", "麻婆豆腐"};
    final boolean[] isCheck = {false, false, false, false, false, false, false, false};
    AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    builder.setTitle("请选择你的想要的菜");
    builder.setMultiChoiceItems(menu, isCheck, new DialogInterface.OnMultiChoiceClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i, boolean b) {
            isCheck[i] = b;
        }
    });
    builder.setPositiveButton("选好了", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            String select = "";
            for (int j = 0; j < isCheck.length; j++) {
                if (isCheck[j]) {
                    select += menu[j];
                }
            }
            ToastUtils.showToast(mContext, "你选择的菜有:" + select);
        }
    });
    builder.create();
    builder.show();
}


}

最后是Activity代码:

public class JS2JavaActivity extends AppCompatActivity {

private WebView mWebView;

@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_js2java);
    mWebView = (WebView) findViewById(R.id.js2java);
    mWebView.loadUrl("file:///android_asset/js2java.html");
    //获取到webSettings
    WebSettings webSettings = mWebView.getSettings();
    //设置允许加载JS
    webSettings.setJavaScriptEnabled(true);
    webSettings.setDefaultTextEncodingName("UTF-8");
    //调用addJavascriptInterface方法,将JS2Java对象暴露给JS
    mWebView.addJavascriptInterface(new JS2Java(JS2JavaActivity.this), "jS2Java");
}
}

实现的效果图如下:

4.2、Android调用HTML中的JS代码

  我们实现一个例子:点击Android的中按钮,弹出一个多选列表,选择之后将选择的项传递给HTML页面,并将选择项通过innerHTML写到HTML页面上:

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_margin="10dp"
          android:orientation="vertical">

<Button
    android:id="@+id/btn_show_js_alert"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="调用HTML页面中的JS代码"/>


<WebView
    android:id="@+id/webview1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="10dp"/>

</LinearLayout>

HTML页面代码:

<html>
<head>
    <title>Java调用JS中的方法</title>
    <script language="JavaScript">
        function showText(content){
             document.getElementById("demo").innerHTML="你选择的菜有:"+content;
        }
    </script>
</head>
<body>
    <p id="demo"> </p>
</body>

</html>

Activity代码:

package com.example.webview;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;

/**
 * Created by Devin on 2016/8/4.
 */
public class Java2JSActivity extends AppCompatActivity {

private WebView mWebView;
private Button btn_show_js_alert;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_java2js);
    mWebView = (WebView) findViewById(R.id.webview1);

    WebSettings webSettings = mWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    mWebView.loadUrl("file:///android_asset/java2js.html");

    btn_show_js_alert = (Button) findViewById(R.id.btn_show_js_alert);
    btn_show_js_alert.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            final String[] menu = {"丝瓜面筋", "糖醋鲤鱼", "糖醋排骨", "剁椒鱼头", "清蒸咸鱼", "鱼香肉丝", "清炒上海青", "麻婆豆腐"};
            final boolean[] isCheck = {false, false, false, false, false, false, false, false};
            AlertDialog.Builder builder = new AlertDialog.Builder(Java2JSActivity.this);
            builder.setTitle("请选择你的想要的菜");
            builder.setMultiChoiceItems(menu, isCheck, new DialogInterface.OnMultiChoiceClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i, boolean b) {
                    isCheck[i] = b;
                }
            });
            builder.setPositiveButton("选好了", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    String select = "";
                    for (int j = 0; j < isCheck.length; j++) {
                        if (isCheck[j]) {
                            select += menu[j];
                        }
                    }
                    ToastUtils.showToast(Java2JSActivity.this, "你选择的菜有:" + select);
                    mWebView.loadUrl("javascript:showText('" + select + "')");
                }
            });
            builder.create();
            builder.show();
        }
    });

}
}

实现的效果图:

这样实现了Android调用JS的代码,并实现参数传递。

5、WebView文件下载

  我们知道WebView是浏览器的一个组件,我们可以通过浏览器下载很多东西,那么也可以通过WebView来实现文件的下载,下面我们通过例子实现文件的下载:

第一种下载方式:通过系统自身下载方式下载

package com.example.webview;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.webkit.DownloadListener;
import android.webkit.WebView;

/**
 * Created by Devin on 2016/8/5.
 */
public class FirstDownloadActivity extends AppCompatActivity {
private WebView mWebView;
private String url = "http://sqdd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk";

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_downfirst);
    mWebView = (WebView) findViewById(R.id.wv_first);
    mWebView.loadUrl(url);
    //为WebView设置setDownloadListener,然后重写DownloadListener的 onDownloadStart,
    // 然后在里面写个Intent,然后startActivity对应的Activity即可!
    //这种方式会在通知栏显示进度,如果手机安装有多个浏览器,会弹出让用户自己选择下载的浏览器
    mWebView.setDownloadListener(new DownloadListener() {
        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition,String mimeType, long contentLength) {
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        }
    });
}
}

实现效果图:

第二种:实现自定义下载操作类:

package com.example.webview;

import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Devin on 2016/8/5.
 */
public class DownLoadThread extends Thread {
private static final String TAG = "DownLoadThread";
private String downLoadUrl;
private Context context;
private FileOutputStream out = null;
private File downLoadFile = null;
private File sdCardFile = null;
private InputStream in = null;

public DownLoadThread(Context context, String downLoadUrl) {
    super();
    this.context = context;
    this.downLoadUrl = downLoadUrl;

}

@Override
public void run() {
    Log.i(TAG, "开始下载APK文件");
    try {
        URL httpUrl = new URL(downLoadUrl);
        HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        in = conn.getInputStream();
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Toast.makeText(context, "SD卡不可用!", Toast.LENGTH_SHORT).show();
            return;
        }
        downLoadFile = Environment.getExternalStorageDirectory();
        sdCardFile = new File(downLoadFile, "download.apk");
        out = new FileOutputStream(sdCardFile);
        byte[] b = new byte[1024];
        int len;
        Log.i(TAG, "正在下载APK");
        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
        }
        if (out != null) {
            out.close();
        }
        if (in != null) {
            in.close();
        }
        Log.i(TAG, "下载APK文件完成");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}


package com.example.webview;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.webkit.DownloadListener;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;

/**
 * Created by Devin on 2016/8/5.
 */
public class SecondDownloadActivity extends AppCompatActivity {
private String url = "http://sqdd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk";
private WebView mWebView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_downsecond);
    mWebView = (WebView) findViewById(R.id.wv_second);
    mWebView.loadUrl(url);
    mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            view.loadUrl(url);
            return true;
        }
    });
    mWebView.setDownloadListener(new DownloadListener() {
        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
            new DownLoadThread(SecondDownloadActivity.this, url).start();
        }
    });
}
}

实现效果图:

 

如此可是现实WebView下载文件

6、WebView缓存机制

  现在很多门户信息类网站的APP都是用WebView实现数据展示,这就涉及到了WebView的缓存问题。WebView中存在着两种缓存,分别是:网页数据缓存(存储打开过的页面及资源)、H5缓存(即AppCache)。

网页数据缓存

当我们用WebView加载HTML的时候,会在data/应用package下生成database与cache两个文件夹:

/data/data/package_name/cache/
/data/data/package_name/database/webview.db
/data/data/package_name/database/webviewCache.db

其中我们请求的Url记录是保存在webviewCache.db里,而url的内容是保存在webviewCache文件夹下。有五中缓存模式:

  • LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据

  • LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。

  • LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式

  • LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.

  • LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

使用这五种缓存模式的策略是:判断是否有网络,有的话,使用LOAD_DEFAULT,无网络时,使用LOAD_CACHE_ELSE_NETWORK。

清除缓存需要调用clearCache(boolean),CacheManager.clear高版本中需要调用隐藏API。

H5缓存
  • 1、缓存构成,根据setAppCachePath(String appCachePath)提供的路径,在H5使用缓存过程中生成的缓存文件。

  • 2、缓存模式,无模式选择,通过setAppCacheEnabled(boolean flag)设置是否打开。默认关闭,即,H5的缓存无法使用。

  • 3、清除缓存,找到调用setAppCachePath(String appCachePath)设置缓存的路径,把它下面的文件全部删除就OK了。

  • 4、控制大小,通过setAppCacheMaxSize(long appCacheMaxSize)设置缓存最大容量,默认为Max Integer。同时,可能通过覆盖WebChromeClient.onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)来设置缓存超过先前设置的最大容量时的策略。

7、WebView常见问题汇总

1.为WebView自定义错误显示界面,覆写WebViewClient中的onReceivedError()方法:

2.WebView cookies清理:

CookieSyncManager.createInstance(this);   
CookieSyncManager.getInstance().startSync();   
CookieManager.getInstance().removeSessionCookie();

3.清理cache 和历史记录:

webView.clearCache(true);   
webView.clearHistory();  

4.判断WebView是否已经滚动到页面底端:

getScrollY()方法返回的是当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离.   
getHeight()或者getBottom()方法都返回当前WebView 这个容器的高度   
getContentHeight 返回的是整个html 的高度,但并不等同于当前整个页面的高度,因为WebView 有缩放功能, 所以当前整个页面的高度实际上应该是原始html 的高度再乘上缩放比例. 因此,更正后的结果,准确的判断方法应该是:   
if(WebView.getContentHeight*WebView.getScale() == (webview.getHeight()+WebView.getScrollY())){ //已经处于底端 } 

5.WebView保留缩放功能但隐藏缩放控件:

    mWebView.getSettings().setSupportZoom(true);  
    mWebView.getSettings().setBuiltInZoomControls(true);  
    if (DeviceUtils.hasHoneycomb())  
          mWebView.getSettings().setDisplayZoomControls(false);  

6.在WebView加入 flash支持:

String temp = "<html><body bgcolor=\"" + "black"  
+ "\"> <br/><embed src=\"" + url + "\" width=\"" + "100%"  
+ "\" height=\"" + "90%" + "\" scale=\"" + "noscale"  
+ "\" type=\"" + "application/x-shockwave-flash"  
+ "\"> </embed></body></html>";  
String mimeType = "text/html";  
String encoding = "utf-8";  
web.loadDataWithBaseURL("null", temp, mimeType, encoding, ""); 

7.屏蔽掉长按事件 因为webview长按时将会调用系统的复制控件:

mWebView.setOnLongClickListener(new OnLongClickListener() {  

      @Override  
      public boolean onLongClick(View v) {  
          return true;  
      }  
  });  

8.在页面中先显示图片:

    @Override  
    public void onLoadResource(WebView view, String url) {  
      mEventListener.onWebViewEvent(CustomWebView.this, OnWebViewEventListener.EVENT_ON_LOAD_RESOURCE, url);  
if (url.indexOf(".jpg") > 0) {  
 hideProgress(); //请求图片时即显示页面  
 mEventListener.onWebViewEvent(CustomWebView.this, OnWebViewEventListener.EVENT_ON_HIDE_PROGRESS, view.getUrl());  
 }  
super.onLoadResource(view, url);  
}  

9.处理WebView中的非超链接请求(如Ajax请求):

@SuppressLint("NewApi")  
@Override  
public WebResourceResponse shouldInterceptRequest(WebView view,String url) {  
// 非超链接(如Ajax)请求无法直接添加请求头,现拼接到url末尾,这里拼接一个imei作为示例  

String ajaxUrl = url;  
// 如标识:req=ajax  
if (url.contains("req=ajax")) {  
   ajaxUrl += "&imei=" + imei;  
}  

return super.shouldInterceptRequest(view, ajaxUrl);  

} 

10.WebView页面中播放了音频,退出Activity后音频仍然在播放:

webView.destroy(); 

WebView网页控件就介绍到这里了,最后附上国内镜像API

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值