├── .gitignore
├── .idea
├── copyright
│ └── colin.xml
├── dictionaries
│ ├── ZColin.xml
│ └── fosung.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── bridgewebview_html_demo.html
│ └── bridgewebview_js_demo.js
│ ├── java
│ └── com
│ │ └── zcolin
│ │ └── zx5webview
│ │ └── demo
│ │ ├── InitActivity.java
│ │ ├── MainActivity.java
│ │ ├── WebViewActivity.java
│ │ ├── WebViewVideoActivity.java
│ │ └── app
│ │ └── App.java
│ └── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── layout
│ ├── activity_init.xml
│ ├── activity_main.xml
│ ├── activity_webview.xml
│ └── activity_webview_video.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── text_styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── libZX5WebView
├── .gitignore
├── build.gradle
├── javadoc.gradle
├── libs
│ └── tbs_sdk_thirdapp_v4.3.0.39_43939_sharewithdownloadwithfile_withoutGame_obfs_20200713_223411.jar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── WebViewJavascriptBridge.js
│ ├── java
│ └── com
│ │ └── zcolin
│ │ └── zx5webview
│ │ ├── IPickFile.java
│ │ ├── ZX5ChooseFileWebChromeClientWrapper.java
│ │ ├── ZX5VideoFullScreenWebChromeClient.java
│ │ ├── ZX5WebChromeClientWrapper.java
│ │ ├── ZX5WebView.java
│ │ ├── ZX5WebViewClientWrapper.java
│ │ └── jsbridge
│ │ ├── BridgeHandler.java
│ │ ├── BridgeUtil.java
│ │ ├── BridgeWebView.java
│ │ ├── BridgeWebViewClient.java
│ │ ├── CallBackFunction.java
│ │ ├── DefaultHandler.java
│ │ ├── Message.java
│ │ └── WebViewJavascriptBridge.java
│ ├── jniLibs
│ ├── armeabi-v7a
│ │ └── liblbs.so
│ └── armeabi
│ │ └── liblbs.so
│ └── res
│ ├── drawable-xhdpi
│ └── zwebview_error.png
│ ├── drawable
│ ├── zx5webview_progressbar_circle_bg.xml
│ └── zx5webview_progressbar_horizontal.xml
│ ├── layout
│ ├── zx5webview_view_progressbar_webview.xml
│ ├── zx5webview_view_webview_circle_progressbar.xml
│ ├── zx5webview_view_webview_error.xml
│ ├── zx5webview_view_webview_horizontal_progressbar.xml
│ └── zx5webview_view_webview_video_progress.xml
│ └── values
│ ├── strings.xml
│ └── zx5webview_styles.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/copyright/colin.xml:
--------------------------------------------------------------------------------
1 |
74 |
79 |
84 |
89 |
122 |
124 |
134 |
136 |
145 |
147 |
12 |
16 |
20 | 21 |
22 |23 | 24 |
25 |26 | 28 |
29 |30 | 32 |
33 |34 | 36 |
37 |38 | 39 |
40 |41 | 42 |
43 | 44 | 114 | 115 | -------------------------------------------------------------------------------- /app/src/main/assets/bridgewebview_js_demo.js: -------------------------------------------------------------------------------- 1 | 2 | //以下为android和ios都注册,即可以两平台通用 3 | function setupWebViewJavascriptBridge(callback) { 4 | //android系统需要调用此注册 5 | if (window.WebViewJavascriptBridge) { 6 | callback(WebViewJavascriptBridge) 7 | } else { 8 | document.addEventListener( 9 | 'WebViewJavascriptBridgeReady' 10 | , function() { 11 | callback(WebViewJavascriptBridge) 12 | }, 13 | false 14 | ); 15 | } 16 | 17 | //ios系统需要调用此注册 18 | window.WVJBCallbacks = [callback]; 19 | var WVJBIframe = document.createElement('iframe'); 20 | WVJBIframe.style.display = 'none'; 21 | WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; 22 | document.documentElement.appendChild(WVJBIframe); 23 | setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/zx5webview/demo/InitActivity.java: -------------------------------------------------------------------------------- 1 | package com.zcolin.zx5webview.demo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import androidx.fragment.app.FragmentActivity; 6 | 7 | public class InitActivity extends FragmentActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_init); 13 | 14 | load(); 15 | 16 | Intent intent = new Intent(); 17 | intent.setClass(this, MainActivity.class); 18 | startActivity(intent); 19 | this.finish(); 20 | } 21 | 22 | private void load() { 23 | //TODO 加载数据 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/zx5webview/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zcolin.zx5webview.demo; 2 | 3 | import android.os.Bundle; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import android.widget.Button; 6 | 7 | import com.zcolin.frame.util.ActivityUtil; 8 | 9 | 10 | /** 11 | * 程序主页面 12 | */ 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | private Button btnWebview; 16 | private Button btnWebviewvideo; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_main); 22 | initView(); 23 | } 24 | 25 | private void initView() { 26 | btnWebview = findViewById(R.id.btn_webview); 27 | btnWebviewvideo = findViewById(R.id.btn_webviewvideo); 28 | btnWebview.setOnClickListener(v -> ActivityUtil.startActivity(this, WebViewActivity.class)); 29 | btnWebviewvideo.setOnClickListener(v -> ActivityUtil.startActivity(this, WebViewVideoActivity.class)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/zx5webview/demo/WebViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.zcolin.zx5webview.demo; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import androidx.fragment.app.FragmentActivity; 7 | import androidx.appcompat.app.AlertDialog; 8 | import android.view.View; 9 | import android.view.View.OnClickListener; 10 | import android.widget.Button; 11 | 12 | import com.zcolin.frame.util.GsonUtil; 13 | import com.zcolin.zx5webview.ZX5WebView; 14 | import com.zcolin.zx5webview.jsbridge.DefaultHandler; 15 | 16 | 17 | /** 18 | * 带JsBridge的webview的Demo 19 | */ 20 | public class WebViewActivity extends FragmentActivity implements OnClickListener { 21 | private ZX5WebView webView; 22 | private Button button; 23 | private Activity mActivity; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_webview); 29 | mActivity = this; 30 | 31 | webView = findViewById(R.id.webView); 32 | button = findViewById(R.id.button); 33 | button.setOnClickListener(this); 34 | 35 | initWebView(); 36 | loadUrl(); 37 | 38 | getUserDataFrom_xx(); 39 | } 40 | 41 | public void initWebView() { 42 | webView.setSupportJsBridge(); 43 | webView.setSupportChooseFile(mActivity); 44 | // 如果JS调用send方法,会走到DefaultHandler里 45 | webView.setDefaultHandler(new DefaultHandler()); 46 | webView.registerHandler("submitFromWeb", 47 | (data, function) -> new AlertDialog.Builder(WebViewActivity.this).setMessage( 48 | "监听到网页传入数据:" + data) 49 | .setPositiveButton( 50 | "确定", 51 | (dialog, which) -> function 52 | .onCallBack( 53 | "java 返回数据!!!")) 54 | .create() 55 | .show()); 56 | } 57 | 58 | public void loadUrl() { 59 | webView.loadUrl("file:///android_asset/bridgewebview_html_demo.html"); 60 | } 61 | 62 | public void callJsFunc(String funcName, String strParam) { 63 | webView.callHandler(funcName, 64 | strParam, 65 | data -> new AlertDialog.Builder(WebViewActivity.this).setMessage("网页返回数据:" + data) 66 | .create() 67 | .show()); 68 | //webView.send("hello"); 69 | } 70 | 71 | 72 | @Override 73 | public void onActivityResult(int requestCode, int resultCode, Intent intent) { 74 | super.onActivityResult(requestCode, resultCode, intent); 75 | webView.processResult(requestCode, resultCode, intent); 76 | } 77 | 78 | @Override 79 | public void onClick(View v) { 80 | if (button.equals(v)) { 81 | callJsFunc("functionInJs", "java 调用传入数据"); 82 | } 83 | } 84 | 85 | public void getUserDataFrom_xx() { 86 | User user = new User(); 87 | Location location = new Location(); 88 | location.address = "SDU"; 89 | user.location = location; 90 | user.name = "大头鬼"; 91 | 92 | callJsFunc("functionInJs", GsonUtil.beanToString(user)); 93 | } 94 | 95 | 96 | static class Location { 97 | String address; 98 | } 99 | 100 | static class User { 101 | String name; 102 | Location location; 103 | String testStr; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/zx5webview/demo/WebViewVideoActivity.java: -------------------------------------------------------------------------------- 1 | package com.zcolin.zx5webview.demo; 2 | 3 | import android.os.Bundle; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import android.view.KeyEvent; 6 | 7 | import com.tencent.smtt.sdk.WebView; 8 | import com.tencent.smtt.sdk.WebViewClient; 9 | import com.zcolin.zx5webview.ZX5WebView; 10 | 11 | 12 | /** 13 | * 带JsBridge的webview的Demo 14 | */ 15 | public class WebViewVideoActivity extends AppCompatActivity { 16 | private ZX5WebView webView; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_webview_video); 22 | 23 | webView = findViewById(R.id.webView); 24 | webView.setSupportVideoFullScreen(this); 25 | webView.setSupportHorizontalProgressBar(); 26 | webView.setSupportCircleProgressBar(); 27 | webView.setWebViewClient(new WebViewClient() { 28 | @Override 29 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 30 | return false; 31 | } 32 | }); 33 | 34 | webView.loadUrl("http://app.html5.qq.com/navi/index"); 35 | } 36 | 37 | @Override 38 | public boolean onKeyDown(int keyCode, KeyEvent event) { 39 | if (keyCode == KeyEvent.KEYCODE_BACK) { 40 | if (webView.hideCustomView()) { 41 | return true; 42 | } else if (webView.canGoBack()) { 43 | webView.goBack(); 44 | return true; 45 | } 46 | } 47 | return super.onKeyDown(keyCode, event); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/zcolin/zx5webview/demo/app/App.java: -------------------------------------------------------------------------------- 1 | package com.zcolin.zx5webview.demo.app; 2 | 3 | import com.zcolin.frame.BuildConfig; 4 | import com.zcolin.frame.app.BaseApp; 5 | import com.zcolin.frame.util.LogUtil; 6 | import com.zcolin.zx5webview.ZX5WebView; 7 | 8 | /** 9 | * 程序入口 10 | */ 11 | public class App extends BaseApp { 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | LogUtil.LOG_DEBUG = BuildConfig.DEBUG; 17 | 18 | // 初始化 webview 内核(建议可以放在启动页中初始化) 19 | ZX5WebView.init(this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/ZX5WebView/c1a7592e9aed3f525026a383edb2ba4a2fc27e18/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/ZX5WebView/c1a7592e9aed3f525026a383edb2ba4a2fc27e18/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcolin/ZX5WebView/c1a7592e9aed3f525026a383edb2ba4a2fc27e18/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_init.xml: -------------------------------------------------------------------------------- 1 | 2 |
27 | * webview默认的chromeClient是{@link ZX5WebChromeClientWrapper}
28 | */
29 | public class ZX5ChooseFileWebChromeClientWrapper extends ZX5WebChromeClientWrapper {
30 | private static final int REQUEST_CODE = 5200;
31 |
32 | private ValueCallback
140 | * 默认值支持单选
141 | */
142 | public boolean processResult(int requestCode, int resultCode, Intent intent) {
143 | if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE && intent != null) {
144 | processResult(intent.getData());
145 | return true;
146 | }
147 | processResult((Uri) null);
148 | return false;
149 | }
150 | }
--------------------------------------------------------------------------------
/libZX5WebView/src/main/java/com/zcolin/zx5webview/ZX5VideoFullScreenWebChromeClient.java:
--------------------------------------------------------------------------------
1 | /*
2 | * *********************************************************
3 | * author colin
4 | * company telchina
5 | * email wanglin2046@126.com
6 | * date 18-1-9 上午8:51
7 | * ********************************************************
8 | */
9 |
10 | package com.zcolin.zx5webview;
11 |
12 | import android.app.Activity;
13 | import android.content.pm.ActivityInfo;
14 | import androidx.appcompat.app.ActionBar;
15 | import androidx.appcompat.app.AppCompatActivity;
16 | import android.view.View;
17 | import android.view.WindowManager;
18 | import android.widget.FrameLayout;
19 |
20 | import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient;
21 | import com.tencent.smtt.sdk.WebChromeClient;
22 | import com.tencent.smtt.sdk.WebView;
23 |
24 | /**
25 | * 支持视频播放的WebChormeClient
26 | *
27 | * webview默认的chromeClient是{@link ZX5WebChromeClientWrapper}
28 | */
29 | public class ZX5VideoFullScreenWebChromeClient extends ZX5WebChromeClientWrapper {
30 |
31 | private View videoProgressView;
32 | private View customView;
33 | private WebView webView;
34 | private FrameLayout customViewContainer;
35 | private IX5WebChromeClient.CustomViewCallback customViewCallback;
36 | private CustomViewShowStateListener customViewShowStateListener;
37 | private Activity activity;
38 |
39 | ZX5VideoFullScreenWebChromeClient(WebChromeClient webChromeClient, Activity activity, WebView webView,
40 | FrameLayout customViewContainer, View videoProgressView) {
41 | super(webChromeClient);
42 | this.webView = webView;
43 | this.videoProgressView = videoProgressView;
44 | this.customViewContainer = customViewContainer;
45 | this.activity = activity;
46 | }
47 |
48 | public void setCustomViewShowStateListener(CustomViewShowStateListener customViewShowStateListener) {
49 | this.customViewShowStateListener = customViewShowStateListener;
50 | }
51 |
52 | public boolean isCustomViewShow() {
53 | return customView != null;
54 | }
55 |
56 | @Override
57 | public void onShowCustomView(View view, int requestedOrientation, IX5WebChromeClient.CustomViewCallback callback) {
58 | onShowCustomView(view, callback);
59 | }
60 |
61 | @Override
62 | public void onShowCustomView(View view, IX5WebChromeClient.CustomViewCallback callback) {
63 | super.onShowCustomView(view, callback);
64 | webView.setVisibility(View.INVISIBLE);
65 | if (customView != null) {
66 | callback.onCustomViewHidden();
67 | return;
68 | }
69 |
70 | customView = view;
71 | customViewContainer.setVisibility(View.VISIBLE);
72 | customViewContainer.addView(customView);
73 | customViewCallback = callback;
74 |
75 | toggleFullScreen(true);
76 |
77 | if (customViewShowStateListener != null) {
78 | customViewShowStateListener.show();
79 | }
80 | }
81 |
82 | @Override
83 | public View getVideoLoadingProgressView() {
84 | return videoProgressView;
85 | }
86 |
87 | @Override
88 | public void onHideCustomView() {
89 | super.onHideCustomView();
90 |
91 | if (customView == null) {
92 | return;
93 | }
94 |
95 | webView.setVisibility(View.VISIBLE);
96 | customViewContainer.setVisibility(View.GONE);
97 | customViewContainer.removeView(customView);
98 | customView = null;
99 |
100 | customViewCallback.onCustomViewHidden();
101 |
102 | toggleFullScreen(false);
103 |
104 | if (customViewShowStateListener != null) {
105 | customViewShowStateListener.hide();
106 | }
107 | }
108 |
109 | private void toggleFullScreen(boolean isShowCustomView) {
110 | //横竖屏状态
111 | activity.setRequestedOrientation(isShowCustomView ?
112 | ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE :
113 | ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
114 |
115 | //actionBar显示状态
116 | if (activity instanceof AppCompatActivity) {
117 | ActionBar supportActionBar = ((AppCompatActivity) this.activity).getSupportActionBar();
118 | if (supportActionBar != null) {
119 | if (isShowCustomView) {
120 | supportActionBar.hide();
121 | } else {
122 | supportActionBar.show();
123 | }
124 | }
125 | } else if (activity instanceof Activity) {
126 | android.app.ActionBar actionBar = activity.getActionBar();
127 | if (actionBar != null) {
128 | if (isShowCustomView) {
129 | actionBar.hide();
130 | } else {
131 | actionBar.show();
132 | }
133 | }
134 | }
135 |
136 | //设置全屏状态
137 | WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
138 | if (isShowCustomView) {
139 | attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
140 | attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
141 | } else {
142 | attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
143 | attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
144 | }
145 | activity.getWindow().setAttributes(attrs);
146 |
147 | //activity.getWindow()
148 | // .getDecorView()
149 | // .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
150 | }
151 |
152 |
153 | public interface CustomViewShowStateListener {
154 | void show();
155 |
156 | void hide();
157 | }
158 | }
--------------------------------------------------------------------------------
/libZX5WebView/src/main/java/com/zcolin/zx5webview/ZX5WebChromeClientWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * *********************************************************
3 | * author colin
4 | * company telchina
5 | * email wanglin2046@126.com
6 | * date 18-1-9 上午8:51
7 | * ********************************************************
8 | */
9 | package com.zcolin.zx5webview;
10 |
11 | import android.app.AlertDialog;
12 | import android.graphics.Bitmap;
13 | import android.net.Uri;
14 | import android.os.Build;
15 | import android.os.Message;
16 | import androidx.annotation.RequiresApi;
17 | import android.view.View;
18 | import android.widget.ProgressBar;
19 |
20 | import com.tencent.smtt.export.external.interfaces.ConsoleMessage;
21 | import com.tencent.smtt.export.external.interfaces.GeolocationPermissionsCallback;
22 | import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient;
23 | import com.tencent.smtt.export.external.interfaces.JsPromptResult;
24 | import com.tencent.smtt.export.external.interfaces.JsResult;
25 | import com.tencent.smtt.sdk.ValueCallback;
26 | import com.tencent.smtt.sdk.WebChromeClient;
27 | import com.tencent.smtt.sdk.WebStorage;
28 | import com.tencent.smtt.sdk.WebView;
29 |
30 |
31 | /**
32 | * WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比如
33 | */
34 | class ZX5WebChromeClientWrapper extends WebChromeClient {
35 |
36 | private WebChromeClient webChromeClient;
37 | private ProgressBar horizontalProBar;
38 | /** 是否支持H5定位 */
39 | private boolean isSupportH5Location;
40 | private ZX5WebView.LoadListener loadListener;
41 |
42 | ZX5WebChromeClientWrapper(WebChromeClient webChromeClient) {
43 | this.webChromeClient = webChromeClient;
44 | }
45 |
46 | public WebChromeClient getWebChromeClient() {
47 | return webChromeClient;
48 | }
49 |
50 | public WebChromeClient setWebChromeClient(WebChromeClient webChromeClient) {
51 | this.webChromeClient = webChromeClient;
52 | return this;
53 | }
54 |
55 | public WebChromeClient setLoadListener(ZX5WebView.LoadListener listener) {
56 | this.loadListener = listener;
57 | return this;
58 | }
59 |
60 | public WebChromeClient setHorizontalProgressBar(ProgressBar bar) {
61 | this.horizontalProBar = bar;
62 | return this;
63 | }
64 |
65 | public WebChromeClient setSupportH5Location() {
66 | this.isSupportH5Location = true;
67 | return this;
68 | }
69 |
70 | @Override
71 | public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
72 | if (!webChromeClient.onJsAlert(view, url, message, result)) {
73 | new AlertDialog.Builder(view.getContext()).setTitle("提示")
74 | .setMessage(message)
75 | .setPositiveButton("确定", (dialog, which) -> {
76 | result.confirm();
77 | })
78 | .create()
79 | .show();
80 | }
81 | return true;
82 | }
83 |
84 | @Override
85 | public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
86 | if (!webChromeClient.onJsConfirm(view, url, message, result)) {
87 | new AlertDialog.Builder(view.getContext()).setTitle("提示")
88 | .setMessage(message)
89 | .setPositiveButton("确定", (dialog, which) -> {
90 | result.confirm();
91 | })
92 | .setNegativeButton("取消", (dialog, which) -> result.cancel())
93 | .create()
94 | .show();
95 | }
96 | return true;
97 | }
98 |
99 | /**
100 | * H5定位相关
101 | */
102 | @Override
103 | public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissionsCallback callback) {
104 | if (isSupportH5Location) {
105 | callback.invoke(origin, true, false);
106 | }
107 | super.onGeolocationPermissionsShowPrompt(origin, callback);
108 | }
109 |
110 | @Override
111 | public void onProgressChanged(WebView view, int newProgress) {
112 | if (horizontalProBar != null) {
113 | horizontalProBar.setProgress(newProgress);
114 | }
115 | if (loadListener != null) {
116 | loadListener.onProgress(newProgress);
117 | }
118 | webChromeClient.onProgressChanged(view, newProgress);
119 | }
120 |
121 | @Override
122 | public void onReceivedTitle(WebView view, String title) {
123 | webChromeClient.onReceivedTitle(view, title);
124 | }
125 |
126 | @Override
127 | public void onReceivedIcon(WebView view, Bitmap icon) {
128 | webChromeClient.onReceivedIcon(view, icon);
129 | }
130 |
131 | @Override
132 | public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed) {
133 | webChromeClient.onReceivedTouchIconUrl(view, url, precomposed);
134 | }
135 |
136 | @Override
137 | public void onShowCustomView(View view, IX5WebChromeClient.CustomViewCallback callback) {
138 | webChromeClient.onShowCustomView(view, callback);
139 | }
140 |
141 | @Override
142 | public void onShowCustomView(View view, int requestedOrientation, IX5WebChromeClient.CustomViewCallback callback) {
143 | webChromeClient.onShowCustomView(view, requestedOrientation, callback);
144 | }
145 |
146 | @Override
147 | public void onHideCustomView() {
148 | webChromeClient.onHideCustomView();
149 | }
150 |
151 | @Override
152 | public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
153 | return webChromeClient.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
154 | }
155 |
156 | @Override
157 | public void onRequestFocus(WebView view) {
158 | webChromeClient.onRequestFocus(view);
159 | }
160 |
161 | @Override
162 | public void onCloseWindow(WebView window) {
163 | webChromeClient.onCloseWindow(window);
164 | }
165 |
166 | @Override
167 | public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
168 | return webChromeClient.onJsPrompt(view, url, message, defaultValue, result);
169 | }
170 |
171 | @Override
172 | public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
173 | return webChromeClient.onJsBeforeUnload(view, url, message, result);
174 | }
175 |
176 | @Override
177 | public void onExceededDatabaseQuota(String url, String databaseIdentifier, long quota, long estimatedDatabaseSize,
178 | long totalQuota, WebStorage.QuotaUpdater quotaUpdater) {
179 | webChromeClient.onExceededDatabaseQuota(url,
180 | databaseIdentifier,
181 | quota,
182 | estimatedDatabaseSize,
183 | totalQuota,
184 | quotaUpdater);
185 | }
186 |
187 | @Override
188 | public void onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater) {
189 | webChromeClient.onReachedMaxAppCacheSize(requiredStorage, quota, quotaUpdater);
190 | }
191 |
192 |
193 | @Override
194 | public void onGeolocationPermissionsHidePrompt() {
195 | webChromeClient.onGeolocationPermissionsHidePrompt();
196 | }
197 |
198 |
199 | @Override
200 | public boolean onJsTimeout() {
201 | return webChromeClient.onJsTimeout();
202 | }
203 |
204 | @Override
205 | public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
206 | return webChromeClient.onConsoleMessage(consoleMessage);
207 | }
208 |
209 | @Override
210 | public Bitmap getDefaultVideoPoster() {
211 | return webChromeClient.getDefaultVideoPoster();
212 | }
213 |
214 | @Override
215 | public View getVideoLoadingProgressView() {
216 | return webChromeClient.getVideoLoadingProgressView();
217 | }
218 |
219 | @Override
220 | public void getVisitedHistory(ValueCallback
180 | *
181 | * 需要在Activity的onActivityResult中调用:
182 | *
191 | * pickFile参考如下
192 | * Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
193 | * chooserIntent.setType(acceptType);
194 | * if (fragment != null) {
195 | * fragment.startActivityForResult(chooserIntent, REQUEST_CODE);
196 | * } else if (activity != null) {
197 | * activity.startActivityForResult(chooserIntent, REQUEST_CODE);
198 | * }
199 | */
200 | public ZX5WebView setSupportChooseFile(Activity activity, IPickFile pickFile) {
201 | webChromeClientWrapper = new ZX5ChooseFileWebChromeClientWrapper(webChromeClientWrapper.getWebChromeClient(),
202 | activity,
203 | pickFile);
204 | setWebChromeClient(webChromeClientWrapper.getWebChromeClient());
205 | return this;
206 | }
207 |
208 | /**
209 | * 支持文件选择
210 | *
211 | *
212 | * 需要在Activity的onActivityResult中调用:
213 | *
227 | *
228 | * 需要在Fragment的onActivityResult中调用:
229 | *
237 | * pickFile参考如下
238 | * Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
239 | * chooserIntent.setType(acceptType);
240 | * if (fragment != null) {
241 | * fragment.startActivityForResult(chooserIntent, REQUEST_CODE);
242 | * } else if (activity != null) {
243 | * activity.startActivityForResult(chooserIntent, REQUEST_CODE);
244 | * }
245 | */
246 | public ZX5WebView setSupportChooseFile(Fragment fragment, IPickFile pickFile) {
247 | webChromeClientWrapper = new ZX5ChooseFileWebChromeClientWrapper(webChromeClientWrapper.getWebChromeClient(),
248 | fragment,
249 | pickFile);
250 | setWebChromeClient(webChromeClientWrapper.getWebChromeClient());
251 | return this;
252 | }
253 |
254 | /**
255 | * 支持文件选择
256 | *
257 | *
258 | * 需要在Activity的onActivityResult中调用:
259 | *
273 | * 必须在Activity的manifest文件中指定 android:configChanges="keyboardHidden|orientation|screenSize"
274 | *
275 | *
477 | * 需要声明权限
478 | *
479 | *
183 | * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
184 | * super.onActivityResult(requestCode, resultCode, intent);
185 | * webView.processResult(requestCode, resultCode, intent);
186 | * }
187 | *
188 | *
189 | * @param pickFile 文件选择自定义处理方式
190 | *
214 | * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
215 | * super.onActivityResult(requestCode, resultCode, intent);
216 | * webView.processResult(requestCode, resultCode, intent);
217 | * }
218 | *
219 | */
220 | public ZX5WebView setSupportChooseFile(Activity activity) {
221 | return this.setSupportChooseFile(activity, null);
222 | }
223 |
224 | /**
225 | * 支持文件选择
226 | *
230 | * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
231 | * webView.processResult(requestCode, resultCode, intent);
232 | * }
233 | *
234 | *
235 | * @param pickFile 文件选择自定义处理方式
236 | *
260 | * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
261 | * super.onActivityResult(requestCode, resultCode, intent);
262 | * webView.processResult(requestCode, resultCode, intent);
263 | * }
264 | *
265 | */
266 | public ZX5WebView setSupportChooseFile(Fragment fragment) {
267 | return this.setSupportChooseFile(fragment, null);
268 | }
269 |
270 | /**
271 | * 支持视频全屏
272 | *
276 | * 在Activity的OnKeyDown中如下:
277 | * public boolean onKeyDown(int keyCode, KeyEvent event) {
278 | * if (keyCode == KeyEvent.KEYCODE_BACK) {
279 | * if (webView.hideCustomView()) {
280 | * return true;
281 | * } else if (webView.canGoBack()) {
282 | * webView.goBack();
283 | * return true;
284 | * }
285 | * }
286 | * return super.onKeyDown(keyCode, event);
287 | * }
288 | *
289 | */
290 | public ZX5WebView setSupportVideoFullScreen(Activity activity) {
291 | ViewGroup group = (ViewGroup) this.getParent();
292 | FrameLayout container = new FrameLayout(getContext());
293 | int index = group.indexOfChild(this);
294 |
295 | //将原来的布局之间添加一层,用来盛放webView和视频全屏控件
296 | group.removeView(this);
297 | group.addView(container, index, this.getLayoutParams());
298 | container.addView(this,
299 | new FrameLayout.LayoutParams(AbsoluteLayout.LayoutParams.MATCH_PARENT,
300 | ViewGroup.LayoutParams.MATCH_PARENT));
301 |
302 | //添加视频ViewContainer
303 | FrameLayout flCustomContainer = new FrameLayout(getContext());
304 | flCustomContainer.setVisibility(View.INVISIBLE);
305 | container.addView(flCustomContainer,
306 | new FrameLayout.LayoutParams(AbsoluteLayout.LayoutParams.MATCH_PARENT,
307 | ViewGroup.LayoutParams.MATCH_PARENT));
308 |
309 | View videoProgressView = LayoutInflater.from(activity)
310 | .inflate(R.layout.zx5webview_view_webview_video_progress, null);
311 | webChromeClientWrapper = new ZX5VideoFullScreenWebChromeClient(webChromeClientWrapper.getWebChromeClient(),
312 | activity,
313 | this,
314 | flCustomContainer,
315 | videoProgressView);
316 | setWebChromeClient(webChromeClientWrapper.getWebChromeClient());
317 | return this;
318 | }
319 |
320 | public void setCustomViewShowStateListener(
321 | ZX5VideoFullScreenWebChromeClient.CustomViewShowStateListener customViewShowStateListener) {
322 | if (webChromeClientWrapper != null && webChromeClientWrapper instanceof ZX5VideoFullScreenWebChromeClient) {
323 | ((ZX5VideoFullScreenWebChromeClient) webChromeClientWrapper).setCustomViewShowStateListener(
324 | customViewShowStateListener);
325 | }
326 | }
327 |
328 | /**
329 | * 设置js通讯组件注入完成监听
330 | */
331 | public void setOnInjectFinishListener(BridgeWebViewClient.OnInjectFinishListener listener) {
332 | this.injectFinishListener = listener;
333 | webViewClientWrapper.setOnInjectFinishListener(injectFinishListener);
334 | }
335 |
336 | /**
337 | * 支持显示圆形进度条
338 | */
339 | public ZX5WebView setSupportCircleProgressBar() {
340 | setSupportProgressBar(R.layout.zx5webview_view_webview_circle_progressbar);
341 | return this;
342 | }
343 |
344 | /**
345 | * 支持自定义的圆形进度
346 | */
347 | public ZX5WebView setSupportProgressBar(@LayoutRes int resId) {
348 | setSupportProgressBar(LayoutInflater.from(getContext()).inflate(resId, null));
349 | return this;
350 | }
351 |
352 | /**
353 | * 显示自定义的进度条
354 | */
355 | public ZX5WebView setSupportProgressBar(View view) {
356 | ViewGroup group = (ViewGroup) this.getParent();
357 | RelativeLayout container = new RelativeLayout(getContext());
358 | int index = group.indexOfChild(this);
359 | group.removeView(this);
360 | group.addView(container, index, this.getLayoutParams());
361 | container.addView(this,
362 | new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
363 | ViewGroup.LayoutParams.MATCH_PARENT));
364 | customProBar = view;
365 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
366 | ViewGroup.LayoutParams.MATCH_PARENT);
367 | params.addRule(RelativeLayout.CENTER_IN_PARENT);
368 | container.addView(customProBar, params);
369 | webViewClientWrapper.setCustomProgressBar(customProBar);
370 | return this;
371 | }
372 |
373 | /**
374 | * 支持显示进度条
375 | */
376 | public ZX5WebView setSupportHorizontalProgressBar() {
377 | ViewGroup group = (ViewGroup) this.getParent();
378 | FrameLayout container = new FrameLayout(getContext());
379 | int index = group.indexOfChild(this);
380 | group.removeView(this);
381 | group.addView(container, index, this.getLayoutParams());
382 | container.addView(this,
383 | new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
384 | ViewGroup.LayoutParams.MATCH_PARENT));
385 | horizontalProBar = (ProgressBar) LayoutInflater.from(getContext())
386 | .inflate(R.layout.zx5webview_view_webview_horizontal_progressbar,
387 | null);
388 | container.addView(horizontalProBar,
389 | new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dip2px(getContext(), 3)));
390 | webChromeClientWrapper.setHorizontalProgressBar(horizontalProBar);
391 | webViewClientWrapper.setHorizontalProgressBar(horizontalProBar);
392 | return this;
393 | }
394 |
395 | /**
396 | * 支持显示加载失败view
397 | */
398 | public ZX5WebView setSupportErrorView() {
399 | View errorView = LayoutInflater.from(getContext()).inflate(R.layout.zx5webview_view_webview_error, null);
400 | errorView.findViewById(R.id.ll_container).setOnClickListener(v -> {
401 | reload();
402 | });
403 | setSupportErrorView(errorView);
404 | return this;
405 | }
406 |
407 |
408 | /**
409 | * 支持显示加载失败view
410 | */
411 | public ZX5WebView setSupportErrorView(View view) {
412 | ViewGroup group = (ViewGroup) this.getParent();
413 | RelativeLayout container = new RelativeLayout(getContext());
414 | int index = group.indexOfChild(this);
415 | group.removeView(this);
416 | group.addView(container, index, this.getLayoutParams());
417 | container.addView(this,
418 | new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
419 | ViewGroup.LayoutParams.MATCH_PARENT));
420 | errorView = view;
421 | errorView.setVisibility(GONE);
422 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
423 | ViewGroup.LayoutParams.MATCH_PARENT);
424 | params.addRule(RelativeLayout.CENTER_IN_PARENT);
425 | container.addView(errorView, params);
426 | webViewClientWrapper.setErrorView(errorView);
427 | return this;
428 | }
429 |
430 | /**
431 | * 隐藏errorview
432 | */
433 | public void hideErrorView() {
434 | if (errorView != null) {
435 | errorView.setVisibility(GONE);
436 | }
437 | }
438 |
439 |
440 | @Override
441 | public void reload() {
442 | webViewClientWrapper.reset();
443 | hideErrorView();
444 | super.reload();
445 | }
446 |
447 | /**
448 | * 将dip或dp值转换为px值,保证尺寸大小不变
449 | */
450 | private int dip2px(Context context, float dipValue) {
451 | final float scale = context.getResources().getDisplayMetrics().density;
452 | return (int) (dipValue * scale + 0.5f);
453 | }
454 |
455 | /**
456 | * 设置是否支持JsBridge
457 | */
458 | public void setSupportJsBridge() {
459 | isSupportJsBridge = true;
460 | webViewClientWrapper.setSupportJsBridge();
461 | }
462 |
463 | /**
464 | * 设置是否支持自动缩放
465 | */
466 | public void setSupportAutoZoom() {
467 | WebSettings webSettings = getSettings();
468 | webSettings.setUseWideViewPort(true);//关键点
469 | webSettings.setLoadWithOverviewMode(true);
470 | webSettings.setBuiltInZoomControls(true);
471 | webSettings.setSupportZoom(true);
472 | }
473 |
474 | /**
475 | * 设置是否支持H5定位
476 | *