android 4.3中一次完整的android源码截屏事件的捕获

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实现的)

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, android
, 函数
, 系统
, android5.0截屏
, android源码
, 功能
, 4 4 2截屏
, android 音量键 后台
, KeyEvent
, Android截屏
, android崩溃捕获
, android异常捕获
android屏幕截屏
华为手机无法捕获截屏、安卓4.3截屏、android 滚动截屏源码、android5.0截屏源码、android截屏源码,以便于您获取更多的相关知识。

时间: 2024-10-07 20:54:47

android 4.3中一次完整的android源码截屏事件的捕获的相关文章

【android4.3】记一次完整的android源码截屏事件的捕获(不同于网上的老版本)

感谢网友cjd6568358的帮助,新版的Android系统截屏功能已经实现,需要的朋友请移步项目主页:https://github.com/Android-ScreenShot/AndroidScreenShotService(别忘点个star哦) --------------------------------------------------------------------------------------------------------------------- (转载请注明

Android中ListView如何使用,求源码?

问题描述 Android中ListView如何使用,求源码?请详细点,最好能够直接运行的,谢谢 解决方案 user.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" an

android中的设置选项对应的源码怎么修改

问题描述 android中的设置选项对应的源码怎么修改 想在android中的设置里面添加源码,想知道怎么进行修改:我指的是在源码包中 解决方案 参考:http://blog.csdn.net/yzx41099296/article/details/7337264 解决方案二: 把settings.java 代码导到开发工具里改就行,跟普通应用区别不大,关键是编译 pakages/apps/Settings.java 解决方案三: package/app/Settings 设置apk 的代码

GitHub 上有哪些完整的 iOS-App 源码值得参考?

GitHub 上有哪些完整的 iOS-App 源码值得参考? http://mobdevgroup.com/ ProducthuntOSX Mac 上开源的 Product Hunt OSX 客户端软件 GanHuoCode 干货集中营的第三方iOS客户端 ESTMusicPlayer 一款基于 DOUAudioStreamer 开发的一款优雅简洁的音乐播放器. beautifulApp 用Swift做的一个高仿最美应用 Geofancy The Geofancy iOS app. Helpin

Android菜鸟的成长笔记(6)——剖析源码学自定义主题Theme

原文:Android菜鸟的成长笔记(6)--剖析源码学自定义主题Theme 还记得在Android菜鸟的成长笔记(3)中我们曾经遇到了一个问题吗?"这个界面和真真的QQ界面还有点不同的就是上面的标题myFirstApp,怎么去掉这个标题呢?",当时我直接在AndroidMainfest.xml中添加了一个属性: android:theme="@android:style/Theme.NoTitleBar" 可能有的朋友就会迷惑了,为什么添加了这个属性就可以了.这一篇

Linux有问必答:如何在Debian或Ubuntu上安装完整的内核源码

Linux有问必答:如何在Debian或Ubuntu上安装完整的内核源码 问题:我需要为我的Debian或Ubuntu下载并安装完整树结构的内核源码以供编译一个定制的内核.那么在Debian或Ubuntu上有什么可行的方法来下载完整的内核源码呢? 在给你的Linux安装完整内核源码之前,先问问自己是否真的需要这样做.如果你仅仅是尝试去编译一个内核模块或是为内核定制驱动,你并不需要完整的内核源码树.你只需要安装一些与内核对应的头文件,这样就足够了. 只有在你需要生成一个定制的内核,而且内核源码中的

Debian或Ubuntu等linux发型版上安装完整Linux内核源码教程

我需要为我的Debian或Ubuntu下载并安装完整树结构的内核源码以供编译一个定制的内核.那么在Debian或Ubuntu上有什么可行的方法来下载完整的内核源码呢? 在给你的Linux安装完整内核源码之前,先问问自己是否真的需要这样做.如果你仅仅是尝试去编译一个内核模块或是为内核定制驱动,你并不需要完整的内核源码树.你只需要安装一些与内核对应的头文件,这样就足够了.     只有在你需要生成一个定制的内核,而且内核源码中的一些内核默认设置要被你调整了的情况下,你才需要完整的内核源码树. 这里将

Android 用Time和Calendar获取系统当前时间源码分享(年月日时分秒周几)

概述 用Time和Calendar获取系统当前时间(年月日时分秒周几) 效果图 源码: import android.app.Activity; import android.os.Bundle; import android.text.format.Time; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.Calen

Android编程实现QQ表情的发送和接收完整实例(附源码)_Android

本文实例讲述了Android编程实现QQ表情的发送和接收.分享给大家供大家参考,具体如下: 在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下QQ表情,图片资源完全copy的QQ.apk,解压就可以得到,这里不细说. 下面将该应用中的表情模块功能抽离出来,以便自己以后复习回顾.. 先看一下效果图: 首先进入界面:(完全仿照QQ) 点击一下上面的表情图标: 选择一些表情,输入一些文字混合: 点击发送: 可以看到文字和表情图片都一起显示出来了. 下面列出一些关键代码: 表情工具类Exp