Android截屏的方式:
- 1.获取DecorView截屏
通过获取DecorView的方式来实现截屏(前提是当前Activity已经加载完成),DecorView为整个Window界面的最顶层View,因此截屏不包含状态栏(SystemUI)部分.
View view = getWindow().getDecorView(); // 获取DecorView
// 方式一:
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap1 = view.getDrawingCache();
// 方式二:
Bitmap bitmap2 = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas();
canvas.setBitmap(bitmap2);
view.draw(canvas);
// 保存 bitmap1 或 bitmap2 均可保存截屏图片
- 2.使用MediaProjection截屏
实现方式与屏幕录制类似 (Android屏幕录制源码Demo下载)
- 3.调用系统源码截屏(推荐使用)
系统截屏(获取当前屏幕的Bitmap)调用的代码如下:
Bitmap mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
由于是hide api,通过反射调用如下:
public Bitmap takeScreenShot() {
Bitmap bmp = null;
mDisplay.getMetrics(mDisplayMetrics);
float[] dims = {(float) mDisplayMetrics.widthPixels, (float) heightPixels};
float degrees = getDegreesForRotation(mDisplay.getRotation());
boolean requiresRotation = degrees > 0;
if (requiresRotation) {
mDisplayMatrix.reset();
mDisplayMatrix.preRotate(-degrees);
mDisplayMatrix.mapPoints(dims);
dims[0] = Math.abs(dims[0]);
dims[1] = Math.abs(dims[1]);
}
try {
Class<?> demo = Class.forName("android.view.SurfaceControl");
Method method = demo.getMethod("screenshot", new Class[]{Integer.TYPE, Integer.TYPE});
bmp = (Bitmap) method.invoke(demo, new Object[]{Integer.valueOf((int) dims[0]), Integer.valueOf((int) dims[1])});
if (bmp == null) {
return null;
}
if (requiresRotation) {
Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels, heightPixels, Bitmap.Config.RGB_565);
Canvas c = new Canvas(ss);
c.translate((float) (ss.getWidth() / 2), (float) (ss.getHeight() / 2));
c.rotate(degrees);
c.translate((-dims[0] / 2), (-dims[1] / 2));
c.drawBitmap(bmp, 0, 0, null);
c.setBitmap(null);
bmp.recycle();
bmp = ss;
}
if (bmp == null) {
return null;
}
bmp.setHasAlpha(false);
bmp.prepareToDraw();
return bmp;
} catch (Exception e) {
e.printStackTrace();
return bmp;
}
}
Android系统自带截屏功能,在Framework层调用即可,普通应用无法调用.系统截屏源码如下:
// PATH: frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
/** {@inheritDoc} */
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode();
// ... ...
if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed()
&& event.isCtrlPressed()) {
if (down && repeatCount == 0) {
int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION
: TAKE_SCREENSHOT_FULLSCREEN;
mScreenshotRunnable.setScreenshotType(type);
mHandler.post(mScreenshotRunnable);
return -1;
}
}
// ... ...
}
拦截截屏的按键事件,触发截屏.
private class ScreenshotRunnable implements Runnable {
private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN;
public void setScreenshotType(int screenshotType) {
mScreenshotType = screenshotType;
}
@Override
public void run() {
takeScreenshot(mScreenshotType);
}
}
private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
调用takeScreenshot()函数截屏.
// Assume this is called from the Handler thread.
private void takeScreenshot(final int screenshotType) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) { //截屏结束会关闭TakeScreenshotService服务和连接
return;
}
final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
SYSUI_SCREENSHOT_SERVICE);
final Intent serviceIntent = new Intent();
serviceIntent.setComponent(serviceComponent);
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != this) {
return;
}
Messenger messenger = new Messenger(service);
Message msg = Message.obtain(null, screenshotType);
final ServiceConnection myConn = this;
Handler h = new Handler(mHandler.getLooper()) {
@Override
public void handleMessage(Message msg) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection == myConn) {
mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
mHandler.removeCallbacks(mScreenshotTimeout);
}
}
}
};
msg.replyTo = new Messenger(h);
msg.arg1 = msg.arg2 = 0;
if (mStatusBar != null && mStatusBar.isVisibleLw())
msg.arg1 = 1;
if (mNavigationBar != null && mNavigationBar.isVisibleLw())