Which can replace capturePicture function

前端 未结 3 671
终归单人心
终归单人心 2020-11-27 17:56

I have a question. At this time, the capturePicture of WebView is deprecated.

I want to ask if there is a way to replace the funct

3条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-27 18:12

    Just extends BaseWebView below:

    public abstract class BaseWebView extends WebView {
        private static final String TAG = "BaseWebView";
    
        private static final int DELAY_MS_MAX = 1000;
        private static final int DELAY_MS_DRAW = 100;
    
        private static final long REQUEST_ID_INIT = 0;
    
        public BaseWebView(Context context) {
            super(context);
            init();
        }
    
        public BaseWebView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public BaseWebView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        /**
         * to make sure to set {@link #loadDataFinished} to true at last
         * in {@link #DELAY_MS_MAX} ms later.
         */
        private static final int MSG_LOAD_DATA_FINISH_DEF = 0;
        /**
         * to set {@link #loadDataFinished} to true in {@link #DELAY_MS_DRAW} ms later.
         */
        private static final int MSG_LOAD_DATA_FINISH_DRAW = 1;
    
        private String description;
    
        /**
         * if load data finished
         * 

    * mark the status for load API {@link #loadData(String, String, String)} * & {@link #loadDataWithBaseURL(String, String, String, String, String)} *

    * ignored: {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()} */ private AtomicBoolean loadDataFinished = new AtomicBoolean(true); /** * if progress reached 1000 *

    * mark the status for load API {@link #loadData(String, String, String)} * & {@link #loadDataWithBaseURL(String, String, String, String, String)} *

    * ignored: {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()} */ private AtomicBoolean progressFinished = new AtomicBoolean(true); /** * the request id of load data *

    * mark the status for load API {@link #loadData(String, String, String)} * & {@link #loadDataWithBaseURL(String, String, String, String, String)} *

    * ignored: {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()} */ private AtomicLong loadDataTimestamp = new AtomicLong(REQUEST_ID_INIT); private Handler handler = new MyHandler(this); /** * clear status for load API {@link #loadData(String, String, String)} * & {@link #loadDataWithBaseURL(String, String, String, String, String)}, set to false. *

    * ignored: {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()} *

    * Usage: call in load API {@link #loadData(String, String, String)} * & {@link #loadDataWithBaseURL(String, String, String, String, String)} */ private void clearLoadDataStatus() { DLog.d(TAG, "clearLoadDataStatus: set false, obj=" + this.hashCode()); loadDataFinished.set(false); progressFinished.set(false); // generates a new load request id loadDataTimestamp.set(System.currentTimeMillis()); } private void setLoadDataFinished(long requestId) { DLog.d(TAG, "setLoadDataFinished: id=" + requestId + ", loadDataTimestamp=" + loadDataTimestamp.get() + ", obj=" + this.hashCode()); if (!progressFinished.get() || requestId != loadDataTimestamp.get()) { return; } loadDataFinished(); } private void loadDataFinished() { DLog.d(TAG, "loadDataFinished: set true, obj=" + this.hashCode()); loadDataFinished.set(true); // clear load request id loadDataTimestamp.set(REQUEST_ID_INIT); } /** * get status for load API {@link #loadData(String, String, String)} * & {@link #loadDataWithBaseURL(String, String, String, String, String)}, set to false. *

    * ignored: {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()} */ public boolean isLoadDataFinished() { return loadDataFinished.get(); } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } private void handleLoadDataFinished(int what) { if (loadDataTimestamp.get() == REQUEST_ID_INIT) { // there is no load data actions //DLog.w(TAG, "handleLoadDataFinished: there is no load data actions, obj=" // + this.hashCode()); return; } DLog.d(TAG, "handleLoadDataFinished: obj=" + this.hashCode()); int delay = 0; long requestId = loadDataTimestamp.get(); if (what == MSG_LOAD_DATA_FINISH_DEF) { delay = DELAY_MS_MAX; } else if (what == MSG_LOAD_DATA_FINISH_DRAW) { delay = DELAY_MS_DRAW; } handler.removeMessages(what); handler.sendMessageDelayed(Message.obtain(handler, what, (Object) requestId), delay); } private void init() { this.setWebChromeClient(new DefWebChromeClient()); this.setHorizontalScrollBarEnabled(false); this.setVerticalScrollBarEnabled(false); this.description = onGetDescription(); } /** * a description of this WebView */ abstract public String onGetDescription(); @Override public void loadDataWithBaseURL( @Nullable String baseUrl, String data, @Nullable String mimeType, @Nullable String encoding, @Nullable String historyUrl) { clearLoadDataStatus(); super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl); } @Override public void loadData(String data, @Nullable String mimeType, @Nullable String encoding) { clearLoadDataStatus(); super.loadData(data, mimeType, encoding); } @Override public void stopLoading() { super.stopLoading(); loadDataFinished(); } @Override public void setWebChromeClient(WebChromeClient client) { if (!(client instanceof DefWebChromeClient)) { throw new IllegalArgumentException( "the WebChromeClient must be an instance of " + DefWebChromeClient.class); } super.setWebChromeClient(client); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //Log.d(TAG, "onDraw: " + this.hashCode()); if (progressFinished.get()) { // set load data finished in DELAY_MS_DRAW. // !!! Notice that the Runnable will not be exec if this WebView is not to show, // and this will cause the `loadDataFinished` being `false` all the time, // if you want that executing whatever, plz use `handle.post()`. post(new Runnable() { @Override public void run() { handleLoadDataFinished(MSG_LOAD_DATA_FINISH_DRAW); } }); } } class DefWebChromeClient extends WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); if (newProgress == 100) { progressFinished.set(true); // set load data finished in DELAY_MS_MAX as def. // !!! Notice that the Runnable will not be exec if this WebView is not to show, // and this will cause the `loadDataFinished` being `false` all the time, // if you want that executing whatever, plz use `handle.post()`. post(new Runnable() { @Override public void run() { handleLoadDataFinished(MSG_LOAD_DATA_FINISH_DEF); } }); } Log.d(TAG, "onProgressChanged: " + newProgress + ", desc=" + description + ", obj=" + view.hashCode()); } } static class MyHandler extends Handler { WeakReference mViewReference; MyHandler(BaseWebView webView) { mViewReference = new WeakReference<>(webView); } @Override public void handleMessage(Message msg) { final BaseWebView webView = mViewReference.get(); if (webView == null) { return; } // handle msg if (msg.what == MSG_LOAD_DATA_FINISH_DEF || msg.what == MSG_LOAD_DATA_FINISH_DRAW) { webView.setLoadDataFinished((Long) msg.obj); } } } }

    === END ===

    Notice that only loadData() & loadDataWithBaseURL() works above, you can add loadUrl(), reload() by yourself if needed.

    Demo:https://github.com/zhaoya188/completed-load-webview

提交回复
热议问题