1、当前Activity
通过View的getDrawingCache()方法获取View中的图像。
private Bitmapview2Bitmap(ViewparamView)
{
Log.e("ScreenShot","saveFileThread view2Bitmap(Viewview)");
paramView.setDrawingCacheEnabled(true);
paramView.buildDrawingCache();
BitmaplocalBitmap1 = paramView.getDrawingCache();
BitmaplocalBitmap2 = null;
if (localBitmap1 !=null)
{
localBitmap2= Bitmap.createBitmap(localBitmap1);
}
paramView.destroyDrawingCache();
return localBitmap2;
}
缺点:
此方法只限当前视图
此方法不能截取状态栏
此方法不能截取视频播放区域,截取的图片中的播放区域为全黑
2、Service截屏
通过反射实现截屏。获取窗口所有的顶级视图,然后取最上层的视图获取图片。
⑴获取窗口所有顶级视图
private View[]getWindowDecorViews()throws Exception
{
View[] views;
if (android.os.Build.VERSION.SDK_INT >= 14
&&android.os.Build.VERSION.SDK_INT < 17)
{
views =getWindowDecorViewsApi14_16();
} elseif (android.os.Build.VERSION.SDK_INT >= 17)
{
views =getWindowDecorViewsApiUp17();
} else
{
views =getWindowDecorViewsDownApi15();
}
return views;
}
private View[] getWindowDecorViewsDownApi15()throws Exception
{
Class<?> windowManager = Class
.forName("android.view.WindowManagerImpl");
Field viewsField = windowManager.getDeclaredField("mViews");
FieldinstanceField = windowManager.getDeclaredField("mWindowManager");
viewsField.setAccessible(true);
instanceField.setAccessible(true);
Object instance = instanceField.get(null);
View[] viewarray = (View[]) viewsField.get(instance);
return sortViews(viewarray);
}
private View[] getWindowDecorViewsApi14_16()throws Exception
{
Class<?> windowManager = Class
.forName("android.view.WindowManagerImpl");
Field viewsField = windowManager.getDeclaredField("mViews");
Field instanceField = windowManager.getDeclaredField("sWindowManager");
viewsField.setAccessible(true);
instanceField.setAccessible(true);
Object instance = instanceField.get(null);
View[] viewarray = (View[]) viewsField.get(instance);
return sortViews(viewarray);
}
private View[]getWindowDecorViewsApiUp17()throwsException
{
Class<?>windowManager = Class
.forName("android.view.WindowManagerGlobal");
FieldviewsField = windowManager.getDeclaredField("mViews");
FieldinstanceField = windowManager
.getDeclaredField("sDefaultWindowManager");
viewsField.setAccessible(true);
instanceField.setAccessible(true);
Objectinstance = instanceField.get(null);
View[]viewarray = (View[]) viewsField.get(instance);
return viewarray;//sortViews(viewarray);
}
⑵取前端的视图转图
private Bitmap view2Bitmap(View paramView)
{
Log.e("ScreenShot","saveFileThread view2Bitmap(Viewview)");
paramView.setDrawingCacheEnabled(true);
paramView.buildDrawingCache();
BitmaplocalBitmap1 = paramView.getDrawingCache();
BitmaplocalBitmap2 = null;
if (localBitmap1 !=null)
{
localBitmap2= Bitmap.createBitmap(localBitmap1);
}
paramView.destroyDrawingCache();
return localBitmap2;
}
private Bitmap view2Bitmap(View[] paramArrayOfView)
{
CanvaslocalCanvas = null;
PaintlocalPaint = null;
Bitmapnewbitmap = null;
int[]arrayOfInt = newint[2];
if(paramArrayOfView.length > 0)
{
ViewlocalView = paramArrayOfView[paramArrayOfView.length - 1];
BitmaplocalBitmap = view2Bitmap(localView);
newbitmap= localBitmap;
}
return newbitmap;
}
缺点:
此方法不能截取状态栏
此方法不能截取视频播放区域,截取的图片中的播放区域为全黑
3、读取dev/graphics/fb0
读取此文件获取图片,需获得root权限。
⑴读取图形设备文件
publicstaticfinalStringgetPermission="chmod 777 /dev/graphics/fb0\n";
publicstaticfinalStringgivePermission="chmod 660 /dev/graphics/fb0\n";
publicstaticBitmap getScreenBitmap(Context context) throws Exception {
SystemManager.RootCommand(getPermission);
init(context);
byte[] piex =newbyte[width * height *deepth];
InputStreamstream = newFileInputStream(new File(file_name));
DataInputStreamdStream = newDataInputStream(stream);
dStream.readFully(piex);
dStream.close();
stream.close();
SystemManager.RootCommand(givePermission);
int[] data =convertToColor(piex);
return Bitmap.createBitmap(data,width,height, Bitmap.Config.ARGB_8888);
}
⑵转图
publicstaticint[] convertToColor_4byte(byte[] piex) {
int[] colors =newint[width * height];
int len = piex.length;
for (int i = 0; i < len; i +=4) {
int b = (piex[i] &0xFF);
int g = (piex[i + 1] &0xFF);
int r = (piex[i + 2] &0xFF);
int a = (piex[i + 3] &0xFF);
colors[i/ 4] = (a << 24) + (r << 16) + (g << 8) + b;
}
return colors;
}
缺点:
此方法不能截取视频播放区域,截取的图片中的播放区域为全黑
4、系统截屏
在Android4.0系统上,提供截屏功能,但截屏的方法是@hide标记的,暂不支持App端直接调用。如果要使用,需在Android源码环境下进行编译,为app赋予system的share uid和platform签名,就可以实现截屏的功能。
关键步骤:
1)在AndroidManifest.xml中加入android:sharedUserId="android.uid.system"属性
2)在Android.mk中加入platform签名属性,并在源码环境下编译。或者将相关jar包引入到Eclipse中做第3方库引用,并将生成的apk重新打上platform签名
缺点:
源码下编译需platform签名属性,编译好的apk只有在原始的Android系统或者是自己编译的系统中才可以用,不能移植。
综上所述,要实现应用外的截屏功能,只能获取root权限,读取dev/graphics/fb0图形设备文件,目前第三方截屏应用及QQ截屏都是采取此种方法,但视频播放区域都不能截图。