WebView详细使用三(WebView初始化和Activity
2018-11-19 本文已影响8人
Sky_Blue
一、WebView初始化(接口定义)
WebView初始化主要分为三步:
- 设置WebSettings,打开WebView一些默认关闭的设置。
- 设置WebViewClient,对一些特殊链接统一处理。
- 设置WebChromeClient,对Html标题、页面加载进度、相机相册打开回调等进行一个监听。
对于以上三点,定义出一个接口来初始化设置:
/**
* WebView初始化接口定义
*/
public interface IWebViewInit {
/**
* 1. 初始化和设置WebView
*/
WebView initWebView(WebView webView);
/**
* 2. 初始化WebViewClient
*/
WebViewClient initWebViewClient();
/**
* 3. 初始化WebChromeClient
*/
WebChromeClient initWebChromeClient();
}
二、IWebViewInit接口实现类WebViewInitImpl
/**
* WebView初始化的定义
*/
public class WebViewInitImpl implements IWebViewInit {
private static final String USER_AGENT = "appXXX";
private WebChromeClientImpl mWebChromeClient;
private Activity mActivity;
public WebViewInitImpl(Activity activity) {
mActivity = activity;
}
@Override
public WebView initWebView(WebView webView) {
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
WebSettings webSetting = webView.getSettings();
webSetting.setUserAgentString(USER_AGENT + webSetting.getUserAgentString());
webSetting.setDatabaseEnabled(true);
webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
webSetting.setTextSize(WebSettings.TextSize.NORMAL);
// ===设置JS可用
webSetting.setJavaScriptEnabled(true);
// JS打开窗口
webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
// ===设置JS可用
// 可以访问文件
webSetting.setAllowFileAccess(true);
// ===缩放可用
webSetting.setSupportZoom(true);
webSetting.setDisplayZoomControls(false); //隐藏原生的缩放控件
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS); //设置缩放功能 //能不能缩放 取决于网页设置
webSetting.setLoadWithOverviewMode(true);
webSetting.setBuiltInZoomControls(true);
// ===缩放可用
// 支持多窗口
webSetting.setSupportMultipleWindows(true);
// ===============缓存
webSetting.setCacheMode(WebSettings.LOAD_DEFAULT);// 决定是否从网络上取数据。
webSetting.setAppCacheEnabled(true);
// ===============缓存
webSetting.setUseWideViewPort(true);
webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
// ==定位
webSetting.setDomStorageEnabled(true);
webSetting.setGeolocationEnabled(true);
// ==定位
return webView;
}
@Override
public WebViewClient initWebViewClient() {
return new WebViewClientImpl();
}
@Override
public WebChromeClient initWebChromeClient() {
mWebChromeClient = new WebChromeClientImpl(mActivity);
return mWebChromeClient;
}
/**
* 页面标题、进度回调
*/
public void setOnWebChromeListener(WebChromeClientImpl.OnWebChromeListener onWebChromeListener) {
if (mWebChromeClient != null) {
mWebChromeClient.setOnWebChromeListener(onWebChromeListener);
}
}
/**
* 选择相机相册处理
*/
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mWebChromeClient != null) {
mWebChromeClient.onActivityResult(requestCode, resultCode, data);
}
}
}
三、WebViewClient 实现类WebViewClientImpl
/**
* 对加载Url回调统一处理
* 根据公司业务,自行处理
*/
public class WebViewClientImpl extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
if (webView != null && url != null) {
Context context = webView.getContext();
if (url.endsWith(".apk")) {
Uri apkUri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, apkUri);
context.startActivity(intent);
} else if (url.startsWith("http")) {
webView.loadUrl(url);
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
if (isInstall(context, intent)) {
context.startActivity(intent);
}
}
}
return true;
}
// 判断app是否安装
private boolean isInstall(Context context, Intent intent) {
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
}
四、WebChromeClient封装实现类WebChromeClientImpl
/**
* H5打开相机相册的回调监听
* 进度条的回调监听
*/
public class WebChromeClientImpl extends WebChromeClient {
// WebView打开相机相册的请求码
public static final int FILE_REQUEST_CODE = 0x011;
/**
* 进度条的回调监听
*/
private OnWebChromeListener onWebChromeListener;
/**
* 打开相册 本地文件等等
*/
private ValueCallback<Uri> uploadFile;
private ValueCallback<Uri[]> uploadFiles;
private Activity mActivity;
public WebChromeClientImpl(Activity activity) {
mActivity = activity;
}
/**
* 进度发生改变
*/
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (onWebChromeListener != null) {
onWebChromeListener.onProgressChanged(view, newProgress);
}
}
/**
* 接收到标题
*/
@Override
public void onReceivedTitle(WebView view, String title) {
if (onWebChromeListener != null) {
onWebChromeListener.onReceivedTitle(view, title);
}
}
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
handleFileChooser(uploadMsg, null);
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
handleFileChooser(uploadMsg, null);
}
// For Android > 4.1.1
@Override
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
handleFileChooser(uploadMsg, null);
}
// For Android >= 5.0
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
handleFileChooser(null, filePathCallback);
return true;
}
/**
* 打开相册 本地文件等等
*/
private void handleFileChooser(ValueCallback<Uri> uploadMsg, ValueCallback<Uri[]> filePathCallback) {
if (mActivity == null || mActivity.isFinishing()) {
return;
}
uploadFile = uploadMsg;
uploadFiles = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
mActivity.startActivityForResult(Intent.createChooser(intent, "请选择"), FILE_REQUEST_CODE);
}
/**
* Activity回调处理
*/
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// 处理相机相册选择
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case FILE_REQUEST_CODE:
if (null != uploadFile) {
Uri result = data == null || resultCode != Activity.RESULT_OK ? null : data.getData();
uploadFile.onReceiveValue(result);
uploadFile = null;
}
if (null != uploadFiles) {
Uri result = data == null || resultCode != Activity.RESULT_OK ? null : data.getData();
uploadFiles.onReceiveValue(new Uri[]{result});
uploadFiles = null;
}
break;
}
} else if (resultCode == Activity.RESULT_CANCELED) {
if (null != uploadFile) {
uploadFile.onReceiveValue(null);
uploadFile = null;
}
if (uploadFiles != null) {
uploadFiles.onReceiveValue(null);
uploadFiles = null;
}
}
}
// 页面标题、加载进度回调监听接口
public interface OnWebChromeListener {
void onReceivedTitle(WebView view, String title);
void onProgressChanged(WebView view, int newProgress);
}
public void setOnWebChromeListener(OnWebChromeListener onWebChromeListener) {
this.onWebChromeListener = onWebChromeListener;
}
}
代码有点多,但无非就是做了设置WebSettings、设置WebViewClient、设置WebChromeClient这三件事。
五、WebView在Activity的封装步骤
- Activity数据的传递(标题、URL),根据实际项目可以自己扩展。
- WebView初始化和加载页面的工具类,方便管理页面跳转等一些通用操作。
- Activity的使用封装。
六、Activity数据的传递(标题、URL)
/**
* WebActivity传递参数的Bean
*/
public class WebData implements Serializable {
public String url;
public String title;
}
七、WebView初始化和加载页面的工具类
/**
* WebView初始化和加载页面的工具类
*/
public class WebUtil {
private static boolean isInit;
private WebUtil() {
}
private static class Holder {
private static final WebUtil INSTANCE = new WebUtil();
}
public static WebUtil getInstance() {
return Holder.INSTANCE;
}
/**
* 腾讯X5内核初始化
*/
public void init(Context context) {
if (context == null) {
return;
}
if (isInit) {
return;
}
//--搜集本地tbs内核信息并上报服务器,服务器返回结果决定使用哪个内核。
try {
QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {
@Override
public void onViewInitFinished(boolean arg0) {
}
@Override
public void onCoreInitFinished() {
}
};
//x5内核初始化接口
QbSdk.initX5Environment(context.getApplicationContext(), cb);
} catch (Throwable e) {
e.printStackTrace();
}
isInit = true;
}
private void loadWebPage(WebView webView, String url) {
if (webView != null) {
if (url.startsWith("http")) {
webView.loadUrl(url);
}
} else {
throw new NullPointerException("WebView is null!");
}
}
private void loadLocalPage(WebView webView, String url) {
loadWebPage(webView, "file:///android_asset/" + url);
}
public void loadPage(WebView webView, String url) {
//如果是电话协议
if (url.contains("tel:")) {
callPhone(webView.getContext(), url);
return;
}
if (URLUtil.isNetworkUrl(url) || URLUtil.isAssetUrl(url)) {
loadWebPage(webView, url);
} else {
loadLocalPage(webView, url);
}
}
private void callPhone(Context context, String uri) {
final Intent intent = new Intent(Intent.ACTION_DIAL);
final Uri data = Uri.parse(uri);
intent.setData(data);
context.startActivity(intent);
}
/**
* 打开WebActivity
*/
public void startWebActivity(Activity activity, String url) {
startWebActivity(activity, url, null);
}
/**
* 打开WebActivity
*/
public void startWebActivity(final Activity activity, final String url, final String title) {
// WebView初始化
WebData data = new WebData();
data.url = url;
data.title = title;
startWebActivity(activity, data);
}
/**
* 打开WebActivity
*/
public void startWebActivity(Activity activity, WebData data) {
init(activity);
Bundle bundle = new Bundle();
bundle.putSerializable(WebActivity.WEB_DATA, data);
ActivityUtil.startActivity(activity, WebActivity.class, bundle);
}
}
八、Activity的使用封装
/**
* 封装的WebActivity
*/
public class WebActivity extends AppActivity implements WebChromeClientImpl.OnWebChromeListener {
public static final String WEB_DATA = "WebData";
private FrameLayout mFlWebContainer;
private WebViewInitImpl mWebViewInitializer;
private WebView mWebView;
// Title的封装对象
private DefTitleBar mTitleBar;
private ProgressWebView mProgressWebView;
/**
* JS注入的名称
*/
private static final String JS_NAME = "appCarB";
/**
* 打开页面传递过来的参数
*/
private WebData mWebData;
@Override
protected Object getContentLayout() {
return R.layout.act_web;
}
@Override
protected void initData(Bundle bundle) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
// 获取上个页面传递过来的数据
mWebData = (WebData) getIntent().getSerializableExtra(WEB_DATA);
// WebView初始化对象
mWebViewInitializer = new WebViewInitImpl(this);
// WebView初始化
initWebView();
}
@SuppressLint("JavascriptInterface")
private void initWebView() {
if (mWebView != null) {
mWebView.removeAllViews();
} else {
mProgressWebView = new ProgressWebView(this);
mWebView = mWebViewInitializer.initWebView(mProgressWebView.getWebView());
mWebView.setWebViewClient(mWebViewInitializer.initWebViewClient());
mWebView.setWebChromeClient(mWebViewInitializer.initWebChromeClient());
// 注入JS交互
mWebView.addJavascriptInterface(WebJSInterface.create(this), JS_NAME);
}
}
@Override
protected void initTitle(DefTitleBar titleBar) {
this.mTitleBar = titleBar;
if (mTitleBar != null) {
mTitleBar.setTitleLeftRightPadding(50);
if (mWebData != null && !TextUtils.isEmpty(mWebData.title)) {
mTitleBar.setTitle(mWebData.title);
}
}
}
@Override
protected void initView(View view) {
mFlWebContainer = findViewById(R.id.fl_web_container);
mWebViewInitializer.setOnWebChromeListener(this);
if (mFlWebContainer.getChildCount() > 0) {
mFlWebContainer.removeAllViews();
}
mFlWebContainer.addView(mProgressWebView);
// 加载URL
if (mWebView != null && mWebData != null) {
// 跳转并进行页面加载
WebUtil.getInstance().loadPage(mWebView, mWebData.url);
}
}
// 标题回调
@Override
public void onReceivedTitle(WebView view, String title) {
if (mTitleBar != null) {
if (mWebData != null && !TextUtils.isEmpty(mWebData.title)) {
return;
}
mTitleBar.setTitle(title + "");
}
}
// 页面加载进度回调
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (mProgressWebView == null) {
return;
}
ProgressBar progressbar = mProgressWebView.getProgressbar();
if (progressbar == null) {
return;
}
if (newProgress == 100) {
progressbar.setVisibility(View.GONE);
} else {
if (progressbar.getVisibility() == View.GONE) {
progressbar.setVisibility(View.VISIBLE);
}
progressbar.setProgress(newProgress);
}
}
@Override
public void onPause() {
if (mWebView != null) {
mWebView.onPause();
}
super.onPause();
}
@Override
public void onResume() {
if (mWebView != null) {
mWebView.onResume();
}
super.onResume();
}
@Override
public void onDestroy() {
if (mFlWebContainer != null && mWebView != null) {
mWebView = null;
mProgressWebView = null;
}
super.onDestroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mWebView != null && (keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack(); // 浏览网页历史记录 goBack()和goForward()
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 处理相机相册选择
if (mWebViewInitializer != null) {
mWebViewInitializer.onActivityResult(requestCode, resultCode, data);
}
}
}
九、在其它Activity页面调用WebActivity
WebUtil.getInstance().startWebActivity(this,"https://www.xxx.com");
- 测试页面效果图没有截出来。
- 除了和H5的JS交互未写,至此WebActivity封装完毕。
- WebActivity类中相关类的文章:
打造Android通用的标题栏。
Android Activity基类的抽取AppActivity(二)。
WebView详细使用一(带进度的WebView)。
WebView详细使用二(腾讯X5内核的集成)。