Android手机同时按住Volume Down键+power键,就会进行截屏,跟Android L源码得知此操作的处理是在frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java中处理的,当用户按住Volume Down键或者power键都好去调用interceptScreenshotChord()这个方法:
//SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS=150
private void interceptScreenshotChord() {
if (mScreenshotChordEnabled
&& mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
&& !mScreenshotChordVolumeUpKeyTriggered) {
final long now = SystemClock.uptimeMillis();
if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS//此处判断当前时间跟处理Volume Down键的时间
&& now <= mScreenshotChordPowerKeyTime+ SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {//此处判断当前时间跟处理power键的时间
mScreenshotChordVolumeDownKeyConsumed = true;
cancelPendingPowerKeyAction();
mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
}
}
}
以上方法中SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS=150,当判断此两个键的处理时间都少于150ms时才会进行截屏操作
mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
private final Runnable mScreenshotRunnable = new Runnable() {
@Override
public void run() {
takeScreenshot();
}
};
再进入takeScreenshot();方法
final Object mScreenshotLock = new Object();
ServiceConnection mScreenshotConnection = null;
final Runnable mScreenshotTimeout = new Runnable() {
@Override public void run() {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
}
}
}
};
// Assume this is called from the Handler thread.
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);
}
}
}
在takeScreenshot方法中利用夸进程通信连接com.android.systemui.screenshot.TakeScreenshotService,告知TakeScreenshotService要截屏了
而在frameworks\base\packages\SystemUI\src\com\android\systemui\screenshot\TakeScreenshotService.java的处理如下:
public class TakeScreenshotService extends Service {
private static final String TAG = "TakeScreenshotService";
private static GlobalScreenshot mScreenshot;
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);
} catch (RemoteException e) {
}
}
}, msg.arg1 > 0, msg.arg2 > 0);
}
}
};
@Override
public IBinder onBind(Intent intent) {
return new Messenger(mHandler).getBinder();
}
}
在Handler处理消息是直接调用frameworks\base\packages\SystemUI\src\com\android\systemui\screenshot\GlobalScreenshot.java的
takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible){
}
截图完成后不管是否截图成功运行finisher,statusBarVisible截图是否显示statusBar,true为显示,false不显示;navBarVisible表示是否显示NavigationBar,true为显示,false不显示