[Android4.3] recording a complete screenshot capture of the android source code (different from the old version on the Internet)

Source: Internet
Author: User

(Reprinted please indicate the source: http://blog.csdn.net/buptgshengod) 1. Background

We know that android provides a system screenshot function, that is, to press and hold the power key and the volume reduction button for 0.5 seconds, the system will execute the screenshot function. Therefore, to implement the system screenshot function, capture the functions under the two key combinations of the system, and then drill down one by one. The ScreenShot () function exists under the Surface. java file, which is @ hide. But this is the method of the previous version. It is not applicable after android4.3, because the Surface of/frameworks/base/core/java/android/view. there is no ScreenShot () function in java. I guess google won't be so bad. It will definitely leave an interface for developers at the framework layer, but it will be written elsewhere. As a result, the blogger explored his own ideas and finally found the new ScreenShot function. Here, I will share it with you.

2. Mining Process (1) the key capture in the Android source code is in the file 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();                    }

We can see that if you press the power button and the volume reduction at the same time, the function will be started,

interceptScreenshotChord();

Let's look at the next function.

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());            }        }    }

We can see that this function in handle is the screenshot function we want to execute.

mScreenshotChordLongPress

We enter this function

private final Runnable mScreenshotChordLongPress = new Runnable() {        public void run() {            takeScreenshot();        }    };

We finally found the takeScreenShot, but don't worry. Let's go to this function.

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);            }        }    }

We can see that it starts a service ("com. android. systemui. screenshot. TakeScreenshotService "). (This also confirms my conjecture that all android functions are implemented by handle through sendmessage and then through service)


(2) Find the service

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();    }}

We can see that the GlobalScreenshot-like object performs the function.


(3) Enable GlobalScreenshot

 /**     * Takes a screenshot of the current display and shows an animation.     */    void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {        // We need to orient the screenshot correctly (and the Surface api seems to take screenshots        // only in the natural orientation of the device :!)        mDisplay.getRealMetrics(mDisplayMetrics);        float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};        float degrees = getDegreesForRotation(mDisplay.getRotation());        boolean requiresRotation = (degrees > 0);        if (requiresRotation) {            // Get the dimensions of the device in its native orientation            mDisplayMatrix.reset();            mDisplayMatrix.preRotate(-degrees);            mDisplayMatrix.mapPoints(dims);            dims[0] = Math.abs(dims[0]);            dims[1] = Math.abs(dims[1]);        }        // Take the screenshot        mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);        if (mScreenBitmap == null) {            notifyScreenshotError(mContext, mNotificationManager);            finisher.run();            return;        }        if (requiresRotation) {            // Rotate the screenshot to the current orientation            Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,                    mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);            Canvas c = new Canvas(ss);            c.translate(ss.getWidth() / 2, ss.getHeight() / 2);            c.rotate(degrees);            c.translate(-dims[0] / 2, -dims[1] / 2);            c.drawBitmap(mScreenBitmap, 0, 0, null);            c.setBitmap(null);            // Recycle the previous bitmap            mScreenBitmap.recycle();            mScreenBitmap = ss;        }        // Optimizations        mScreenBitmap.setHasAlpha(false);        mScreenBitmap.prepareToDraw();        // Start the post-screenshot animation        startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,                statusBarVisible, navBarVisible);    }

Let's take a look at this sentence. We finally found screenshot (), which is changed with the android source code of the lower version. The previous surface operation was written to the surface class, now this surfacecontrol class is added to control the surface.

// Take the screenshot        mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);

(4) Now we open the surfacecontrol class at/frameworks/base/core/java/android/view.

At the beginning of the code, we can see that this class is hidden by google, so it cannot be called directly. If you want to use the screenshot function, you must compile it in the source code. As for how to call this function, we will talk about it later, have fun!

/** * SurfaceControl *  @hide */


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.