使用以下代码:
Bitmap bitmap; View v1 = MyView.getRootView(); v1.setDrawingCacheEnabled(true); bitmap = Bitmap.createBitmap(v1.getDrawingCache()); v1.setDrawingCacheEnabled(false);
这MyView
是View
我们需要在屏幕中包含的内容.你也可以DrawingCache
通过View
这种方式获得(没有getRootView()
).
还有另一种方式..
如果我们ScrollView
以root身份查看,那么最好使用以下代码,
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); FrameLayout root = (FrameLayout) inflater.inflate(R.layout.activity_main, null); // activity_main is UI(xml) file we used in our Activity class. FrameLayout is root view of my UI(xml) file. root.setDrawingCacheEnabled(true); Bitmap bitmap = getBitmapFromView(this.getWindow().findViewById(R.id.frameLayout)); // here give id of our root layout (here its my FrameLayout's id) root.setDrawingCacheEnabled(false);
这是getBitmapFromView()
方法
public static Bitmap getBitmapFromView(View view) { //Define a bitmap with the same size as the view Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888); //Bind a canvas to it Canvas canvas = new Canvas(returnedBitmap); //Get the view's background Drawable bgDrawable =view.getBackground(); if (bgDrawable!=null) //has background drawable, then draw it on the canvas bgDrawable.draw(canvas); else //does not have background drawable, then draw white background on the canvas canvas.drawColor(Color.WHITE); // draw the view on the canvas view.draw(canvas); //return the bitmap return returnedBitmap; }
它将显示整个屏幕,包括隐藏在ScrollView
更新中的内容20-04-2016
还有另一种更好的截屏方式.
我在这里截了屏幕截图WebView
.
WebView w = new WebView(this); w.setWebViewClient(new WebViewClient() { public void onPageFinished(final WebView webView, String url) { new Handler().postDelayed(new Runnable(){ @Override public void run() { webView.measure(View.MeasureSpec.makeMeasureSpec( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight()); webView.setDrawingCacheEnabled(true); webView.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(), webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); int height = bitmap.getHeight(); canvas.drawBitmap(bitmap, 0, height, paint); webView.draw(canvas); if (bitmap != null) { try { String filePath = Environment.getExternalStorageDirectory() .toString(); OutputStream out = null; File file = new File(filePath, "/webviewScreenShot.png"); out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 50, out); out.flush(); out.close(); bitmap.recycle(); } catch (Exception e) { e.printStackTrace(); } } } }, 1000); } });
希望这可以帮助..!
使用以下代码:
Bitmap bitmap; View v1 = MyView.getRootView(); v1.setDrawingCacheEnabled(true); bitmap = Bitmap.createBitmap(v1.getDrawingCache()); v1.setDrawingCacheEnabled(false);
这MyView
是View
我们需要在屏幕中包含的内容.你也可以DrawingCache
通过View
这种方式获得(没有getRootView()
).
还有另一种方式..
如果我们ScrollView
以root身份查看,那么最好使用以下代码,
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); FrameLayout root = (FrameLayout) inflater.inflate(R.layout.activity_main, null); // activity_main is UI(xml) file we used in our Activity class. FrameLayout is root view of my UI(xml) file. root.setDrawingCacheEnabled(true); Bitmap bitmap = getBitmapFromView(this.getWindow().findViewById(R.id.frameLayout)); // here give id of our root layout (here its my FrameLayout's id) root.setDrawingCacheEnabled(false);
这是getBitmapFromView()
方法
public static Bitmap getBitmapFromView(View view) { //Define a bitmap with the same size as the view Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888); //Bind a canvas to it Canvas canvas = new Canvas(returnedBitmap); //Get the view's background Drawable bgDrawable =view.getBackground(); if (bgDrawable!=null) //has background drawable, then draw it on the canvas bgDrawable.draw(canvas); else //does not have background drawable, then draw white background on the canvas canvas.drawColor(Color.WHITE); // draw the view on the canvas view.draw(canvas); //return the bitmap return returnedBitmap; }
它将显示整个屏幕,包括隐藏在ScrollView
更新中的内容20-04-2016
还有另一种更好的截屏方式.
我在这里截了屏幕截图WebView
.
WebView w = new WebView(this); w.setWebViewClient(new WebViewClient() { public void onPageFinished(final WebView webView, String url) { new Handler().postDelayed(new Runnable(){ @Override public void run() { webView.measure(View.MeasureSpec.makeMeasureSpec( View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight()); webView.setDrawingCacheEnabled(true); webView.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(), webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); int height = bitmap.getHeight(); canvas.drawBitmap(bitmap, 0, height, paint); webView.draw(canvas); if (bitmap != null) { try { String filePath = Environment.getExternalStorageDirectory() .toString(); OutputStream out = null; File file = new File(filePath, "/webviewScreenShot.png"); out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 50, out); out.flush(); out.close(); bitmap.recycle(); } catch (Exception e) { e.printStackTrace(); } } } }, 1000); } });
希望这可以帮助..!
AFAIK,目前捕获android截图的所有方法都使用/ dev/graphics/fb0 framebuffer.这包括ddms.它确实需要root才能从此流中读取.ddms使用adbd来请求信息,因此不需要root,因为adb具有从/ dev/graphics/fb0请求数据所需的权限.
帧缓冲包含2 +"帧"的RGB565图像.如果您能够读取数据,则必须知道屏幕分辨率才能知道获取图像需要多少字节.每个像素为2个字节,因此如果屏幕分辨率为480x800,则必须为该图像读取768,000个字节,因为480x800 RGB565图像具有384,000个像素.
对于较新的Android的平台,一个可以执行的系统工具screencap
中/system/bin
获得无root权限的屏幕截图.您可以尝试/system/bin/screencap -h
在adb或任何shell下查看如何使用它.
顺便说一句,我认为这种方法只适用于单个快照.如果我们想要捕获多个帧以进行屏幕播放,那么它将会太慢.我不知道是否存在更快的屏幕捕获方法.
[基于Android源代码:]
在C++方面,SurfaceFlinger实现了captureScreen API.这通过活页夹IPC界面公开,每次返回包含来自屏幕的原始像素的新ashmem区域.实际截图是通过OpenGL获取的.
对于系统C++客户端,该接口通过
为Android <4.1 定义的ScreenshotClient类公开; 对于Android> 4.1使用
在JB之前,要在C++程序中截取屏幕截图,这就足够了:
ScreenshotClient ssc; ssc.update();
使用JB和多个显示器,它会变得稍微复杂一些:
ssc.update( android::SurfaceComposerClient::getBuiltInDisplay( android::ISurfaceComposer::eDisplayIdMain));
然后你可以访问它:
do_something_with_raw_bits(ssc.getPixels(), ssc.getSize(), ...);
使用Android源代码,您可以编译自己的共享库以访问该API,然后通过JNI将其公开给Java.要从您的应用创建屏幕截图,该应用必须拥有该READ_FRAME_BUFFER
权限.但即便如此,显然您只能从系统应用程序创建屏幕截图,即使用与系统相同的密钥签名的应用程序.(这部分我还是不太明白,因为我对Android Permissions系统不够熟悉.)
这是JB 4.1/4.2的一段代码:
#include#include #include #include #include static void do_save(const char *filename, const void *buf, size_t size) { int out = open(filename, O_RDWR|O_CREAT, 0666); int len = write(out, buf, size); printf("Wrote %d bytes to out.\n", len); close(out); } int main(int ac, char **av) { android::ScreenshotClient ssc; const void *pixels; size_t size; int buffer_index; if(ssc.update( android::SurfaceComposerClient::getBuiltInDisplay( android::ISurfaceComposer::eDisplayIdMain)) != NO_ERROR ){ printf("Captured: w=%d, h=%d, format=%d\n"); ssc.getWidth(), ssc.getHeight(), ssc.getFormat()); size = ssc.getSize(); do_save(av[1], pixels, size); } else printf(" screen shot client Captured Failed"); return 0; }
您可以尝试以下库:Android屏幕截图库(ASL)支持以编程方式从Android设备捕获屏幕截图,而无需具有root访问权限.相反,ASL使用在后台运行的本机服务,每次设备启动时通过Android调试桥(ADB)启动一次.
根据这个链接,可以在android sdk的tools目录中使用ddms进行屏幕截图.
要在应用程序中执行此操作(而不是在开发期间),还有一些应用程序可以执行此操作.但正如@ zed_0xff指出的那样,肯定需要root.
帧缓冲似乎是要走的路,它并不总是包含Ryan Conrad提到的2+帧.就我而言,它只包含一个.我想这取决于帧/显示尺寸.
我试图连续读取帧缓冲区,但似乎返回固定数量的字节读取.在我的情况下是(3 410 432)字节,这足以存储854*480 RGBA(3 279 360字节)的显示帧.是的,从fb0输出的二进制帧是我设备中的RGBA.这很可能取决于设备.这对你解码它很重要=)
在我的设备/ dev/graphics/fb0中,权限是只有root和组图形用户才能读取 fb0.graphics是一个受限制的组,因此您可能只使用su命令使用root电话访问fb0.
Android应用具有用户ID (uid)app _ ##和组ID (guid)app _ ##.
adb shell有uid shell和guid shell,它拥有比app更多的权限.您可以在/system/permissions/platform.xml中实际检查这些权限
这意味着您将能够在没有root的情况下读取adb shell中的fb0,但是如果没有root,您将无法在app中读取它.
此外,在AndroidManifest.xml上提供READ_FRAME_BUFFER和/或ACCESS_SURFACE_FLINGER权限对常规应用程序无效,因为这些仅适用于"签名"应用程序.
如果你想从Android应用程序AFAIK中的Java代码进行屏幕截图,你必须有Root的权限.