说明:准备把之前工作中涉及到的的Framework相关的东西整理一下,记到博客里只为防止自己忘掉,记到本子里,不是一直方便查阅,还可能丢失。一直记到私人博客,总感觉好像鬼鬼祟祟。因为是回忆并且也参考了网上的文章,如有雷同,请轻轻走过。但是文字绝对是一点一点记的,绝没有直接copy。
起因:需要修改截屏模式,包括截屏发出的声音,截屏文件的保存路径等,所以需要修改。
截屏从“音量-”+power键同时按下的延时事件监听和发送开始。这里因为不是需求里要改的,所以也没有研究过,查阅网上文章后记录的。
这部分是在\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java 文件里完成,最后调用的是takeScreenshot(final int screenshotType)函数,然后启动TakeScreenshotService。如果对截屏的按键触发需要修改,应该改这里。但是触发到调用到takeScreenshot函数之间还有一段。
这里有两处可能的触发,因为手上现在没有测试条件,同时记录等以后有机会再更正:
1. 在interceptPowerKeyDown函数里
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
... ...
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordPowerKeyTriggered = true;
mScreenshotChordPowerKeyTime = event.getDownTime();
interceptScreenshotChord();
}
2. 在interceptKeyBeforeQueueing函数里
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
... ...
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (interactive && !mScreenshotChordVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeDownKeyTriggered = true;
mScreenshotChordVolumeDownKeyTime = event.getDownTime();
mScreenshotChordVolumeDownKeyConsumed = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
interceptAccessibilityShortcutChord();
}
总之调用了interceptScreenshotChord()。
然后
private void interceptScreenshotChord() {
... ...
mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable();
private class ScreenshotRunnable implements Runnable {
... ...
@Override
public void run() {
takeScreenshot(mScreenshotType);
}
最后就到了takeScreenshot函数,然后
private static final String SYSUI_SCREENSHOT_SERVICE = "com.android.systemui.screenshot.TakeScreenshotService";
private void takeScreenshot(final int screenshotType) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
return;
}
final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
SYSUI_SCREENSHOT_SERVICE);
流程就转到
\frameworks\base\packages\SystemUI\src\com\android\systemui\screenshot\TakeScreenshotService.java
这里其实没做什么只是调用了它的同目录下的GlobalScreenshot.java,真正的截屏处理就在GlobalScreenshot.java里
if (mScreenshot == null) {
mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
}
当然如果想写自己的截屏功能,同时不想直接更改原来的截屏功能,可以仿造GlobalScreenshot.java创建新的截屏处理类,同时在TakeScreenshotService.java里调用自己的。
在\frameworks\base\packages\SystemUI\src\com\android\systemui\screenshot\GlobalScreenshot.java这里是保存路径,直接替换mScreenshotDir的路径就好。具体当初怎么改的,没有手边的资料,等以后找到,再补充。
SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
NotificationManager nManager) {
Resources r = context.getResources();
// Prepare all the output metadata
mParams = data;
mImageTime = System.currentTimeMillis();
String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
mScreenshotDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), SCREENSHOTS_DIR_NAME);
mImageFilePath = new File(mScreenshotDir, mImageFileName).getAbsolutePath();