web-dev-qa-db-ja.com

Android Webview:レンダリングの終了を検出

WebViewが読み込まれた後にWebViewのスナップショットを作成したいのですが。ただし、onPageFinishedを使用してもレンダリングが完了していないため、返されるビットマップは常にnullです。私はインターネットで検索し、人々はWebView.PictureListener、ただしこの関数はAPI 12で非推奨

一部のコード

public class MainActivity extends Activity {
    private WebView mButterflyWebView;

    /**
     * Gets html content from the assets folder.
     */
    private String getHtmlFromAsset() {
        InputStream is;
        StringBuilder builder = new StringBuilder();
        String htmlString = null;
        try {
            is = getAssets().open(getString(R.string.butterfly_html));
            if (is != null) {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(is));
                String line;
                while ((line = reader.readLine()) != null) {
                    builder.append(line);
                }

                htmlString = builder.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return htmlString;
    }

    /**
     * Initializes views, controls...
     */ 

    private void init() {
        mButterflyWebView = (WebView) findViewById(R.id.butterfly_webview);

        mButterflyWebView.setWebChromeClient(new WebChromeClient() {
        public void onProgressChanged(WebView view, int newProgress) {


            if (newProgress == 100){
                if (capturePictureWebView() != null){
                    saveBitmapToFile(capturePictureWebView());
                }
            }
        }
    });

    }

    /**
     * Loads html page with the content.
     */
    private void loadHtmlPage() {
        String htmlString = getHtmlFromAsset();
        if (htmlString != null)
            mButterflyWebView.loadDataWithBaseURL(
                    "file:///Android_asset/images/", htmlString, "text/html",
                    "UTF-8", null);

        else
            Toast.makeText(this, R.string.no_such_page, Toast.LENGTH_LONG)
                    .show();
    }

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
        loadHtmlPage();
    }

    private Bitmap capturePictureWebView() {
        mButterflyWebView.measure(MeasureSpec.makeMeasureSpec(
                MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        mButterflyWebView.layout(0, 0, mButterflyWebView.getMeasuredWidth(),
                mButterflyWebView.getMeasuredHeight());
        mButterflyWebView.setDrawingCacheEnabled(true);
        mButterflyWebView.buildDrawingCache();

        if (mButterflyWebView.getMeasuredWidth() == 0 || mButterflyWebView.getMeasuredHeight() == 0){
            return null;
        }
        Bitmap bm = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888);

        System.out.println("width=" + mButterflyWebView.getMeasuredWidth());
        System.out.println("height=" + mButterflyWebView.getMeasuredHeight());
        Canvas bigcanvas = new Canvas(bm);
//        bigcanvas.scale(720/mButterflyWebView.getMeasuredWidth(), 1280/mButterflyWebView.getMeasuredHeight());
        Paint paint = new Paint();
        int iHeight = bm.getHeight();
        bigcanvas.drawBitmap(bm, 0, iHeight, Paint);
        mButterflyWebView.draw(bigcanvas);
        return bm;
    }

    private void saveBitmapToFile(Bitmap bitmap) {
        try {

            FileOutputStream out = new FileOutputStream("/storage/sdcard0/a.png");
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
17
lolyoshi

最後に、この問題について非常に詳細に説明しました。これは、常にnullビットマップを返す理由を説明しています。

アプリのすべての変更はユーザーアクションによってトリガーされるため、touchEventの後でのみinvalidate()をトリガーする変更バージョンを思いつきました

ご協力ありがとうございます。

Android WebViewが空白/白でレンダリングされ、CSSの変更またはHTMLの変更でビューが更新されない、アニメーションが途切れる

2
lolyoshi

WebChromeClientを使用してonProgressChangedを実装する必要があります。

http://developer.Android.com/reference/Android/webkit/WebChromeClient.html#onProgressChanged(Android.webkit.WebView 、int)

mButterflyWebView.setWebChromeClient(new WebChromeClient() {

        @Override
        public void onProgressChanged(WebView view, int progress) {
           if (progress == 100) {
               // do screenshot
           }
        }
});

[〜#〜] edit [〜#〜]:onPageStartedが複数回読み込まれているかどうかを確認するには:

mButterflyWebView.setWebViewClient(new WebViewClient() {

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
           Log.d("WebView", "onPageStarted " + url);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
           Log.d("WebView", "onPageFinished " + url);
        }
    });
11
Andros

ページがレンダリングされたかどうかを検出する最良の方法は、API 23から利用可能な onPageCommitVisible コールバックを使用することです。onPageLoadFinishedは配信が早すぎるため(HTMLが処理されるときに) 、まだレンダリングされていません)。

webview.setWebViewClient(new WebViewClient(){

    @Override
     public void onPageCommitVisible (WebView view, 
            String url)
    }

}

5
Daniel Novak

あなたのWebViewでこれを行うことができます:

@Override
public void invalidate() {
    super.invalidate();

    if (getContentHeight() > 0) {
        // WebView has displayed some content and is scrollable.
    }
}

おかげで: https://stackoverflow.com/a/14678910/131034

4
Frank

OnPageFinshedメソッドが呼び出されたとき、または進行状況が100%に達したときにレンダラーはレンダリングを完了しないため、両方のメソッドはビューが完全にレンダリングされたことを保証しません。

しかし、OnLoadResourceメソッドから、既にレンダリングされているものとまだレンダリングされているものを把握できます。そして、このメソッドは数回呼び出されます。

        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
           // Log and see all the urls and know exactly what is being rendered and visible. If you wanna know when the entire page is completely rendered, find the last url from log and check it with if clause and implement your logic there.
            if (url.contains("assets/loginpage/img/ui/forms/")) {
                // loginpage is rendered and visible now.
               // your logic here.

            }
        }
0
shreedhar