Which can replace capturePicture function

前端 未结 3 590
终归单人心
终归单人心 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:04

    Use draw() method of WebView

    Example :

    ImageView imageview;
    WebView webview;
    class Background extends AsyncTask<Void, Void, Bitmap>
    {
        @Override
        protected Bitmap doInBackground(Void... params)
        {
            try
            {
                Thread.sleep(2000);
                Bitmap bitmap = Bitmap.createBitmap(webview.getWidth(), webview.getHeight(), Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
                webview.draw(canvas);
                return bitmap;
            }
            catch (InterruptedException e){}
            catch (Exception e){}
            return null;
        }
        @Override
        protected void onPostExecute(Bitmap result)
        {
            imageview.setImageBitmap(result);
        }
    }
    
    
    webview.setWebChromeClient(new WebChromeClient()
    {
        public void onProgressChanged(WebView view, int progress)  
        {
            if(progress==100)
                new Background().execute();
        }
    });
    
    0 讨论(0)
  • 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
         * <P><P>
         * mark the status for load API {@link #loadData(String, String, String)}
         * & {@link #loadDataWithBaseURL(String, String, String, String, String)}
         * <p>
         * <b>ignored:</b> {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()}
         */
        private AtomicBoolean loadDataFinished = new AtomicBoolean(true);
    
        /**
         * if progress reached 1000
         * <P><P>
         * mark the status for load API {@link #loadData(String, String, String)}
         * & {@link #loadDataWithBaseURL(String, String, String, String, String)}
         * <p>
         * <b>ignored:</b> {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()}
         */
        private AtomicBoolean progressFinished = new AtomicBoolean(true);
    
        /**
         * the request id of load data
         * <P><P>
         * mark the status for load API {@link #loadData(String, String, String)}
         * & {@link #loadDataWithBaseURL(String, String, String, String, String)}
         * <p>
         * <b>ignored:</b> {@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.
         * <p>
         * <b>ignored:</b> {@link #loadUrl(String)}, {@link #loadUrl(String, Map)} and {@link #reload()}
         * <p>
         * <b>Usage:</b> 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.
         * <p>
         * <b>ignored:</b> {@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<BaseWebView> 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

    0 讨论(0)
  • 2020-11-27 18:17

    I finally found out the solution.

    Some of codes

    public class WebViewActivity extends Activity {
    
        private static WebView webView;
    
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.webview);
    
            webView = (WebView) findViewById(R.id.webView1);
            webView.loadUrl("http://developer.android.com/reference/packages.html");
    //      webView.loadUrl("http://developer.android.com/training/basics/firstapp/creating-project.html");
    
            webView.setWebViewClient(new WebViewClient() {
    
                public void onPageFinished(WebView view, String url) {
                    // do your stuff here
                    webView.measure(MeasureSpec.makeMeasureSpec(
                            MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
                            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                    webView.layout(0, 0, webView.getMeasuredWidth(),
                            webView.getMeasuredHeight());
                    webView.setDrawingCacheEnabled(true);
                    webView.buildDrawingCache();
                    Bitmap bm = Bitmap.createBitmap(webView.getMeasuredWidth(),
                            webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    
                    Canvas bigcanvas = new Canvas(bm);
                    Paint paint = new Paint();
                    int iHeight = bm.getHeight();
                    bigcanvas.drawBitmap(bm, 0, iHeight, paint);
                    webView.draw(bigcanvas);
                    System.out.println("1111111111111111111111="
                            + bigcanvas.getWidth());
                    System.out.println("22222222222222222222222="
                            + bigcanvas.getHeight());
    
                    if (bm != null) {
                        try {
                            String path = Environment.getExternalStorageDirectory()
                                    .toString();
                            OutputStream fOut = null;
                            File file = new File(path, "/aaaa.png");
                            fOut = new FileOutputStream(file);
    
                            bm.compress(Bitmap.CompressFormat.PNG, 50, fOut);
                            fOut.flush();
                            fOut.close();
                            bm.recycle();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    }
    

    The layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <WebView  xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    
    0 讨论(0)
提交回复
热议问题