android – Which can replace capturePicture function-ThrowExceptions

Exception or error:

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 function. I meant it can capture entire of the webview (not only the view is displayed)

Thanks

How to solve:

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"
/>

###

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();
    }
});

###

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

Leave a Reply

Your email address will not be published. Required fields are marked *