【问题标题】:How can I programmatically take a screenshot of a webview, capturing the full page?如何以编程方式截取 webview 的屏幕截图,捕获整个页面?
【发布时间】:2019-12-29 03:28:23
【问题描述】:

我认为标题几乎涵盖了它,但我的活动中有一个 webview。我已将 url 加载到 webview 中,我想截取整个页面的屏幕截图(视口中的任何内容以及“首屏下方”的内容)。

我有用于快照视口的代码,我知道这可以在 iOS 中通过在创建快照之前放大 webview 来完成。我在这里尝试使用相同的技术:

    WebView browserView = (WebView) findViewById(R.id.browserView);

    //Resize the webview to the height of the webpage
    int pageHeight = browserView.getContentHeight();
    LayoutParams browserParams = browserView.getLayoutParams();
    browserView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, pageHeight));

    //Capture the webview as a bitmap
    browserView.setDrawingCacheEnabled(true);
    Bitmap bitmap = Bitmap.createBitmap(browserView.getDrawingCache());
    browserView.setDrawingCacheEnabled(false);

    //Create the filename to use
    String randomFilenamepart = String.valueOf(new SecureRandom().nextInt(1000000));
    String filename = Environment.getExternalStorageDirectory().toString() + "/Screenshot_" + randomFilenamepart + ".jpg";
    File imageFile = new File(filename);
    //Stream the file out to external storage as a JPEG
    OutputStream fout = null;
    try {
        fout = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
        fout.flush();
        fout.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        browserView.setLayoutParams(browserParams);
    }

但我仍然只捕获视口。忽略诸如由于页面太大而耗尽内存之类的事情,有谁知道我做错了什么或如何将部分包含在视口之外?

【问题讨论】:

  • 我不确定这是不是重复的。那里描述的方法有一个大问题,不推荐使用 PictureListener.onNewPicture() 。根据文档 - “由于内部变化,图片不包括复合层,例如固定位置元素或可滚动 div。虽然 PictureListener API 仍可用于检测 WebView 内容的变化,但建议您不要使用它,直到在未来的 Android 版本中提供了替代品”。这听起来不像是我要获取页面上的所有元素。

标签: android webview screenshot


【解决方案1】:

试试这个

import java.io.FileOutputStream;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.os.Bundle;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    WebView w;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        w = new WebView(this);
        w.setWebViewClient(new WebViewClient() {
            public void onPageFinished(WebView view, String url) {
                Picture picture = view.capturePicture();
                Bitmap b = Bitmap.createBitmap(picture.getWidth(),
                        picture.getHeight(), Bitmap.Config.ARGB_8888);
                Canvas c = new Canvas(b);

                picture.draw(c);
                FileOutputStream fos = null;
                try {

                    fos = new FileOutputStream("mnt/sdcard/yahoo.jpg");
                    if (fos != null) {
                        b.compress(Bitmap.CompressFormat.JPEG, 100, fos);

                        fos.close();
                    }
                } catch (Exception e) {

                }
            }
        });

        setContentView(w);
        w.loadUrl("http://search.yahoo.com/search?p=android");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

在 AndroidManifest.xml 文件中添加 INTERNET PERMISSION 和 WRITE_EXTERNAL_STORAGE。

如果应用在 Marshmallow 之上或之上运行,则需要在运行时请求文件写入权限。

【讨论】:

  • 谢谢。也为我工作。投票!如何摆脱捕获图像中的额外空白。请告诉我。我在这里发布了一个问题:stackoverflow.com/questions/14833051/…
  • @avinash thakur 我不断收到致命异常。我试图从您的个人资料中获取您的电子邮件,但找不到任何电子邮件。请您再分享一点,然后在此处列出。我真的需要尽快解决这个问题。提前致谢
  • 这段代码确实有效,你只是忘了添加
  • 它在 Android L 和 M 中不起作用,除非你把它放在 setContentView() 之前:if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { WebView.enableSlowWholeDocumentDraw(); }
  • capturePicture 现已弃用
【解决方案2】:

webview.capturePicture() 已弃用,使用以下方式即可:

Bitmap bitmap = Bitmap.createBitmap(webview.getWidth(), webview.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webview.draw(canvas);
return bitmap;

【讨论】:

  • 这似乎没有捕捉到长页面上屏幕底部看不见的内容,除非我遗漏了什么?
  • 继续我的最后一条评论,以防万一它对将来的任何人有用 - 我发现使用 webView.getContentHeight() 而不是 getHeight() 可以得到很好的结果。另外 - 这对于 Android 9+ 来说很好。对于早期版本,需要一种稍微不同的技术,其中 webview 需要在框架布局中以编程方式滚动,并随着滚动的进行合并单独的图像。
【解决方案3】:

@avinash thakur 代码确实有效,您只是忘记提及添加 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 在 Android Manifest 文件中,否则,android 将不允许您的流在设备上写入数据/文件。

干杯。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    相关资源
    最近更新 更多