1.背景
我們知道android提供了一個系統截屏功能,就是按住電源鍵和音量減的按鍵0.5秒,系統將執行截屏功能。所以要實現系統截屏的功能,就是要捕獲系統的這兩個按鍵組合下面的函數,然後一層一層的向下挖掘。現在網上找到的版本是在Surface.java檔案下存在ScreenShot()函數,是@hide的。但是這是之前版本的辦法,在android4.3之後已經是不適用的,因為在/frameworks/base/core/java/android/view/的Surface.java下並沒有ScreenShot()函數,我猜google不會這麼絕情,一定會在framework層給開發人員留了介面,只不過寫到了別的地方。所以博主按照前任的思路自行挖掘,最後找到了新版本的ScreenShot函數,在這與大家分享。
2.挖掘過程
(1)Android源碼中對按鍵的捕獲位於檔案PhoneWindowManager.java(\frameworks\base\policy\src\com\android\internal\policy\impl)中
ase KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { if (down) { if (isScreenOn && !mVolumeDownKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mVolumeDownKeyTriggered = true; mVolumeDownKeyTime = event.getDownTime(); mVolumeDownKeyConsumedByScreenshotChord = false; cancelPendingPowerKeyAction(); interceptScreenshotChord(); } } else { mVolumeDownKeyTriggered = false; cancelPendingScreenshotChordAction(); }
我們看到了,如果同步選取電源鍵與音量減會啟動函數,
interceptScreenshotChord();
我們來看下著個函數
private void interceptScreenshotChord() { if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) { final long now = SystemClock.uptimeMillis(); if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { mVolumeDownKeyConsumedByScreenshotChord = true; cancelPendingPowerKeyAction(); mHandler.postDelayed(mScreenshotChordLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); } } }
我們看到handle中的這個函數,應該就是我們要執行的截屏功能
mScreenshotChordLongPress
我們進入這個函數
private final Runnable mScreenshotChordLongPress = new Runnable() { public void run() { takeScreenshot(); } };
查看本欄目更多精彩內容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/extra/
終於讓我們找到了takeScreenShot,不過別急,我們轉到這個函數
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.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { mScreenshotConnection = conn; mHandler.postDelayed(mScreenshotTimeout, 10000); } } }
我們看到它啟動了一個截圖的service( "com.android.systemui.screenshot.TakeScreenshotService")。(這也印證了我一個猜想,android的一切功能都是handle通過sendmessage然後通過service實現的)