leadcore Android4.4
在PhoneWindowManager中处理组合键事件,原理:按下音量-时延迟响应事件,在这个延迟时间内如果power键也被按了,并且等两个按键按下的时间都超过一定值时就开始处理截屏流程。
private void takeScreenshot() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
return;
}
ComponentName cn = new ComponentName("com.android.systemui",
"com.android.systemui.screenshot.TakeScreenshotService");
Intent intent = new Intent();
intent.setComponent(cn);
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, 1);
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())
msg.arg2 = 1;
try {
messenger.send(msg);
} catch (RemoteException e) {
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
if (mContext.bindServiceAsUser(
intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
mScreenshotConnection = conn;
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
}
}
接着通过com.android.systemui.screenshot.TakeScreenshotService里面的Handler接收消息调用GlobalScreenshot的takeScreenshot()开始截屏
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
final Messenger callback = msg.replyTo;
if (mScreenshot == null) {
mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
}
mScreenshot.takeScreenshot(new Runnable() {
@Override public void run() {
Message reply = Message.obtain(null, 1);
try {
callback.send(reply);
//send intent to update Screenshot Folder
Log.v(TAG,"send broadcast to filemanager to update ScreenShot");
Intent intent = new Intent();
intent.setAction(UPDATE_SCREENSHOT_FOLDER);
sendBroadcast(intent);
} catch (RemoteException e) {
}
}
}, msg.arg1 > 0, msg.arg2 > 0);
}
}
};
@Override
public IBinder onBind(Intent intent) {
return new Messenger(mHandler).getBinder();
}
以上可以看出,只要启动service就能调用截屏了。
截屏核心代码
// Take the screenshot
mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);