android监听电源键
Ⅰ 9按android手机的电源键来黑屏和点亮屏幕,可以对app的功能产生影响,这里应用的技术是
消除 activity 启动时白屏、黑屏问题
安卓源代码修改之framework下面长按power键,修改安卓原生的关机、重启界面(二)
修改Android系统长按关机时间,或禁用长按关机
Android 实现KeyguardView 锁屏界面横屏显示
Android源码解析(二十八)-->电源开关机按键事件
Ⅱ Android启动过程深入解析
当按下Android设备电源键时究竟发生了什么?
Android的启动过程是怎么样的?
什么是linux内核?
桌面系统linux内核与Android系统linux内核有什么区别?
什么是引导装载程序?
什么是Zygote?
什么是X86以及ARM linux?
什么是init.rc?
什么是系统服务?
当我们想到Android启动过程时,脑海中总是冒出很多疑问。本文将介绍Android的启动过程,希望能帮助你找到上面这些问题的答案。
Android是一个基于Linux的开源操作系统。x86(x86是一系列的基于intel 8086 CPU的计算机微处理器指令集架构)是linux内核部署最常见的系统。然而,所有的Android设备都是运行在ARM处理器(ARM 源自进阶精简指令集机器,源自ARM架构)上,除了英特尔的Xolo设备(http://xolo.in/xolo-x900-features)。Xolo来源自凌动1.6GHz x86处理器。Android设备或者嵌入设备或者基于linux的ARM设备的启动过程与桌面版本相比稍微有些差别。这篇文章中,我将解释Android设备的启动过程。深入linux启动过程是一篇讲桌面linux启动过程的好文。
当你按下电源开关后Android设备执行了以下步骤。
此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader(多谢@jameslast 提醒)
第一步:启动电源以及系统启动
当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。
第二步:引导程序
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。
引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。
Android引导程序可以在找到。
传统的加载器包含的个文件,需要在这里说明:
init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签。
更多关于Android引导程序的可以在这里了解。
第三步:内核
Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。
第四步:init进程
init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。
init进程可以在/system/core/init找到。
init.rc文件可以在/system/core/rootdir/init.rc找到。
readme.txt可以在/system/core/init/readme.txt找到。
对于init.rc文件,Android中有特定的格式以及规则。在Android中,我们叫做Android初始化语言。
Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
语法
1
2
3
4
5
; html-script: false ]
on <trigger>
<command>
<command>
<command>
Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
语法
1
2
3
4
5
; html-script: false ]
service <name> <pathname> [<argument>]*
<option>
<option>
...
Options(选项)
选项是对服务的描述。它们影响init进程如何以及何时启动服务。
咱们来看看默认的init.rc文件。这里我只列出了主要的事件以及服务。
Table
Action/Service
描述
on early-init
设置init进程以及它创建的子进程的优先级,设置init进程的安全环境
on init
设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点
on fs
挂载mtd分区
on post-fs
改变系统目录的访问权限
on post-fs-data
改变/data目录以及它的子目录的访问权限
on boot
基本网络的初始化,内存管理等等
service servicemanager
启动系统管理器管理所有的本地服务,比如位置、音频、Shared preference等等…
service zygote
启动zygote作为应用进程
在这个阶段你可以在设备的屏幕上看到“Android”logo了。
第五步
在java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。
Zygote加载进程
加载ZygoteInit类,源代码:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
registerZygoteSocket()为zygote命令连接注册一个服务器套接字。
preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在/frameworks/base找到“preloaded-classes”文件。
preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载。
在这个阶段,你可以看到启动动画。
第六步:系统服务或服务
完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。
Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。
核心服务:
启动电源管理器;
创建Activity管理器;
启动电话注册;
启动包管理器;
设置Activity管理服务为系统进程;
启动上下文管理器;
启动系统Context Providers;
启动电池服务;
启动定时管理器;
启动传感服务;
启动窗口管理器;
启动蓝牙服务;
启动挂载服务。
其他服务:
启动状态栏服务;
启动硬件服务;
启动网络状态服务;
启动网络连接服务;
启动通知管理器;
启动设备存储监视服务;
启动定位管理器;
启动搜索服务;
启动剪切板服务;
启动登记服务;
启动壁纸服务;
启动音频服务;
启动耳机监听;
启动AdbSettingsObserver(处理adb命令)。
第七步:引导完成
一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。
Ⅲ 如何在android 中service后台监听按键,比如监听音量键
为了实现键盘的监控,从新开发一个输入法是不现实的,一般的操作就是在系统的输入法机制中添加接口回调。我们知道,再应用程序中拿到按键的回调一般是监听onKeyDown的接口,如下所示:publicbooleanonKeyDown(intkeyCode,KeyEventevent)开发者就可以根据回调方法中的参数,keyCode与KeyEvent来判断具体事件。但是,由于事件的回调机制在其的沙箱中运行,在其他应用中是无法拿到当前应用事件回调的。那么我们就从上到下,具体的看看事件的传递机制。如下图所示,用户点击后,软键盘或物理按键的输入驱动就会产生一个中断,且向/dev/input/event*中写入一个相应的信号量。Android操作系统则会循环的读取其中的事件,再分发给WindowManagerServer。由WindowManagerServer根据事件的来源分发到各个不同的ViewGroup与View中,从而产生不同的OnClick、OnKeyDown和OnTouch等事件。这个时候很自然的想到,黑客们希望做键盘监控,一定会向Linux底层增加自定义的事件。这里我们使用的是Linux中的getevent获得/dev/input/eventX设备汇报的事件,这个命令还会输出所有event设备的基本信息。包括触屏、按键、耳机插入等等。其基本用法如下:Usage:getevent[-t][-n][-sswitchmask][-S][-v[mask]][-d][-p][-i][-l][-q][-ccount][-r][device]-t:showtimestamps-n:don'tprintnewlines-s:printswitchstatesforgivenbits-S:printallswitchstates-v:verbositymask(errs=1,dev=2,name=4,info=8,vers=16,pos.events=32,props=64)-d:showHIDdescriptor,ifavailable-p:showpossibleevents(errs,dev,name,pos.events)-i:-l:-q:quiet(clearverbositymask)-c:-r:printrateeventsarereceived键入getevent后,我们能够看到设备中的一些列输入硬件驱动信息,同样下面会出现很多输入指令信号,通常情况下,这些信号量都在刷屏,如下图所示:这些信号量的表示我们无法直接看懂,输入getevent–l加入Label我们能够看到一些添加的标签,如下所示:其实这些Lable已经在其input.h头文件中定义好,其中type的定义如下:/**Eventtypes*/#defineEV_SYN0x00#defineEV_KEY0x01#defineEV_REL0x02#defineEV_ABS0x03#defineEV_MSC0x04#defineEV_SW0x05#defineEV_LED0x11#defineEV_SND0x12#defineEV_REP0x14#defineEV_FF0x15#defineEV_PWR0x16#defineEV_FF_STATUS0x17#defineEV_MAX0x1f#defineEV_CNT(EV_MAX+1)一般来说,常用的是EV_KEY、EV_REL、EV_ABS、EV_SYN,分别对应键盘按键、相对坐标、绝对坐标、同步事件。EV_SYN则表示一组完整事件已经完成,需要处理,EV_SYN的code定义事件分发的类型。
Ⅳ android物理键
一般都是4个物理键。系统本身要求至少2个。
(
或导航键没算。)
有【 菜单,返回,搜索,小房子。】
菜单和返回好像是必须的。但是也可以做成不要物理键的。
Ⅳ Android 电源管理相关逻辑之PMS
PowerManagerService是负责管理、协调设备电源管理的系统服务之一,设备常见功能如亮灭屏、亮度调节、低电量模式、保持CPU唤醒等,都会通过PMS的协调和处理。其继承自SystemService,因此具有SystemService子类的共性:具有生命周期方法,由SystemServer启动、注册到系统服务中,通过Binder和其他组件进行交互等。
和SystemService的其他子类一样,PMS由SystemServer通过反射的方式启动,看一下PMS的构造方法:
通过上面可以看到,在构造方法中首先创建了一个HandlerThread;其次获取了两个Suspend锁,SuspendBlocker是一种锁机制,只用于系统内部,上层申请的Wakelock锁在PMS中都会反映为SuspendBlocker锁。这里获取的两个Suspend锁在申请Wakelock时会用到;最后调用了native方法,这几个方法会通过JNI层调用到HAL层。
在该方法中,首先对该服务进行Binder注册和本地注册,当进行Binder注册后,在其他模块中就可以通过Binder机制获取其实例,同理,当进行本地注册后,只有在System进程才能获取到其实例;最后设置Watchdog的监听。
在这个方法中,设置mBootCompleted为true,表示启动完成,将mDirty置位,mDirty是一个二进制的标记位,用来表示电源状态哪一部分发生了改变,通过对其进行置位(|操作)、清零(~操作),得到二进制数各个位的值(0或1),进行不同的处理 ,然后执行updatePowerStateLocked()方法,这是整个PMS中最重要的方法,这块会在下文中具体功能中进行详细分析。
该方法内主要有5个重要功能 :
a.获取各类本地服务和远程服务,如屏保(DreamMangerService)、窗口(PhoneWindowManager)、电池状态监听服务(BatteryService)等服务,用于进行交互;
b.注册用于和其他Sytem交互的广播;
c.调用updateSettingsLocked()方法更新Settings中值的变化;
d.调用readConfigurationLocked()方法读取配置文件中的默认值;
e.注册SettingsObserver监听;
当通过系统设置等进行屏幕亮度调节时,会调用到PMS内部的updatePowerStateLocked(),通过该方法进行接下来的逻辑执行,最终通过HAL层来设置屏幕亮度,本文基于 Android 8.1 版本进行分析:
当亮度调节时,处理逻辑主要是在phase 2,即updateDisplayPowerStateLocked(dirtyPhase2),一起看一下该方法:
该方法内部主要做了两件事:
a.封装DisplayPowerRequest实例mDisplayPowerRequest,包括通过
getDesiredScreenPolicyLocked()获取policy,此处为DisplayPowerRequest. POLICY_BRIGHT ;还有screenBrightness等;
b.调用DisplayManagerInternal的requestPowerState(),上步封装的DisplayPowerRequest作为参数传入,mDisplayManagerInternal是在systemReady()内部获取的;
DisplayManagerInternal内部的requestPowerState为抽象方法,因此会调用到实现类中,具体是在DisplayManagerService内部的LocalService,看一下具体实现:
最终会调用到DisplayPowerController内部的requestPowerState()方法:
在该方法内部先将传入的DisplayPowerRequest对象赋值给mPendingRequestLocked,后续会使用;接着执行sendUpdatePowerStateLocked(),在该方法内部会发送异步消息 MSG_UPDATE_POWER_STATE ,对应处理方法为updatePowerState();
该方法内部主要干了6件事:
a.将要更新的DisplayPowerRequest实例赋值给mPowerRequest;
b.如果为首次执行的话,需要执行initialize()来执行初始化操作,创建DisplayPowerState实例mPowerState、RampAnimator实例mScreenBrightnessRampAnimator等;
c.根据mPowerRequest.policy来更新state,此处为Display. STATE_ON ;
d.执行animateScreenStateChange(state, performScreenOffTransition)来更新DisplayPowerState;
e.根据策略进行选择,最终确定要更新的brightness值;
f.执行animateScreenBrightness(brightness,slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast)来进行更新;
可以看到,在animateTo()内部会执行mProperty.setValue(mObject, target),mProperty对应的是
DisplayPowerState. SCREEN_BRIGHTNESS, mObject对应的是mPowerState,都是在DisplayPowerController内部的initialize()内部传入的,接下来就进入了DisplayPowerState内部了 ;
scheleScreenUpdate()会执行到postScreenUpdateThreadSafe(),然后会post mScreenUpdateRunnable;
可以看到,在执行setState()后,最终会执行mBlanker.requestDisplayState(state, backlight),mBlanker是DisplayBlanker实例,初始化是在DisplayPowerController构造方法内,在DisplayPowerController内部的initialize()内部传入的,根据调用关系会追溯到DisplayMangerService的LocalService的initPowerManagerment()方法,该方法是在PowerManagerService的systemReady()方法内执行的;
由于传入的state为Display. STATE_ON ,执行到(state, brightness),根据调用关系最终会执行到updateDisplayStateLocked()获取Runnable实例;
根据调用关系看到,会通过DisplayDevice的requestDisplayStateLocked()来获取到Runnable;
在DisplayManagerService的onStart()内发送消息来执行registerDisplayAdapterLocked(new LocalDisplayAdapter())加载 BUILT_IN_DISPLAY_IDS_TO_SCAN对应 的LocalDisplayDevice(继承DisplayDevice),加载成功后存入mDisplayDevices列表内进行管理;
在创建LocalDisplayDeivce时会通过lights.getLight(LightsManager. LIGHT_ID_BACKLIGHT )获取mBackLight,对应的是LightsService内部的LightImpl继承light;
在通过LocalDisplayDevice获取到Runnable后接着执行run(),会执行到setDisplayBrightness();
在setDisplayBrightness()内部会执行到mBacklight.setBrightness(brightness),具体实现逻辑是在LightsService内部;
最终通过native方法调用到HAL层对屏幕的背光进行设置。
不同的调节方式对应不同的入口及判断逻辑,只分析调用入口及涉及的关键策略来选择最终目标brightness值逻辑;
系统设置在调节屏幕亮度时,会实时更新Settings. SCREEN_BRIGHTNESS 值,DisplayPowerController在监听到该值变化后会执行handleSettingsChanged()方法:
监听到变化后,先通过getScreenBrightnessSetting()来获取到当前值,然后赋值给,接下来执行sendUpdatePowerState(),最终执行updatePowerState()方法:
结论:系统设置会根据的值来设置对应的目标brightness值;
快速设置来滑动进度条来调节屏幕亮度时,会调用PowerManagerService的()方法:
跟随调用关系,调用到DisplayPowerController的setTemporaryBrightness()方法,发送 MSG_SET_TEMPORARY_BRIGHTNESS 消息,设置mTemporaryScreenBrightness为传入的值,然后执行updatePowerState():
结论:快速设置会根据mTemporaryScreenBrightness的值来设置对应的目标brightness值;
在视频播放界面可以通过左侧上下滑动来调节屏幕亮度,具体实现方式如下:
Window是activity对应的Window,通过getWindow()可以得到,设置WindowManager.LayoutParams内部的screenBrightness后执行window.setAttributes(lp)可以来调节屏幕亮度;
Window执行setAttributes()会执行到Activity的onWindowAttributesChanged()方法,调用到WindowManagerGlobal的updateViewLayout()最终调用到ViewRootImpl的setLayoutParams来执行重新绘制;
绘制流程就不陈述了,最终会执行到RootWindowContainer内部的performSurfacePlacement()方法,接下来通过handleNotObscuredLocked()获取到对应WindowState的w.mAttrs.screenBrightness赋值给mScreenBrightness,然后在performSurfacePlacement()发送 SET_SCREEN_BRIGHTNESS_OVERRIDE消息, 最终通过WindowManagerService来调用到PowerManagerService内部的()方法:
可以看到,在Internal()内部会将brightness赋值给,然后执行updatePowerStateLocked(),先看
updateDisplayPowerStateLocked()方法:
可以看到,screenBrightness会设置为,该值默认为-1,经过设置后screenBrightness>0,接着执行到DisplayPowerController的updatePowerState()方法:
结论:Window属性调节会根据的值来设置对应的目标brightness值;
设置屏幕亮度时,主要是在DisplayPowerController内部的 updatePowerState() 来对目标screenBrightness进行设置,screenBrightness默认值为PowerManager.BRIGHTNESS_DEFAULT = -1,会根据DisplayPowerRequest及其他策略进行选择,顺序依次为:
a.if (brightness < 0 && mPowerRequest.screenBrightness >= 0): 通过设置Window属性来进行调节(视频播放界面)
b.if (mTemporaryScreenBrightness > 0): 通过快速设置滑动来进行调节
c.if (brightness < 0) {brightness = clampScreenBrightness()}: 通过系统设置滑动调节
当系统设置内部设置了自动进入屏保时间后,如果在此段时间后满足进入条件,会进入屏保,该逻辑入口是在PMS内部的updatePowerStateLocked(),一起看一下:
本流程只分析满足条件后进入屏保的整个过程,关于条件判断会在下一节中进行分析,先从updatePowerStateLocked()看起:
在该方法内部首先循环执行了三个方法:
a.updateWakeLockSummaryLocked():根据mWakeLocks来计算得到mWakeLockSummary的值;
b.():计算得到mUserActivitySummary以及何时进行下一次check;
c.updateWakefulnessLocked():判断是否可以进入屏保及更新mWakefulness状态;
d.updateDreamLocked():根据当前状态选择是否进入屏保;
当mWakefulness为 WAKEFULNESS_AWAKE 时,且isItBedTimeYetLocked(),即:副驾满足进入屏保的条件,看一下该方法的逻辑:
当满足以上条件后,执行napNoUpdateLocked():
设置mSandmanSummoned为true,更新当前mWakefulness状态 WAKEFULNESS_DREAMING ,最后返回true;
前面的循环中当结果返回true时,会执行下一次循环,重新计算mWakeLockSummary和mUserActivitySummary,最终返回false,执行break退出循环,执行updateDreamLocked();
满足条件后执行scheleSandmanLocked()来发送异步消息,执行handleSandman(),mDisplayReady是在updateDisplayPowerStateLocked()内部最终通过DisplayPowerController内部返回的;
在handleSandman()先进行判断,满足条件后即startDreaming为true时,执行stopDream()、startDream(),接下来再执行wakeUpNoUpdateLocked(),一起看一下该方法的实现:
将mWakefulness更新为 WAKEFULNESS_AWAKE ;然后再执行 userActivityNoUpdateLocked()来更新user activity相关信息,接着上面进行分析,执行startDream()进入屏保;
在startDream()逻辑执行过程中首先获取到本地屏保实现的ComponentName,通过在core/res/res/values/config.xml内进行配置:
接下来最终通过DreamController的startDream()来启动;
可以看到在startDream()内部通过bindService()来启动本地实现的屏保服务SevenDreamService;
Ⅵ android10编程如何摸拟电源键
有root可以用一键锁屏软件,加音量键唤醒。就可以代替了。现在的手机一般都有智能唤醒,你可以找找,就是双击唤醒和上滑唤醒
Ⅶ 如何监听Android电源键长按
如果要执行长按事件的话,必须先执行event.startTracking(); 然后onKeyLongPress(int, KeyEvent)才能被调到。更多内容 欢迎访问:
是说在dispatchkeyevent里先执行event.startTracking(); 然后才super.dispatchKeyE……
你可以这样子做:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode, event);
if(keyCode == KeyEvent.KEYCODE_POWER){
event.startTracking();
}
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
return super.onKeyLongPress(keyCode, event);
}
这样子你的onKeyLongPress方法就会被执行到了。
希望能对你有用!
Ⅷ Android同时监听电源键和音量上键
下面两种都可以获取到音量键
测试的时候,发现KeyEvent.KEYCODE_VOLUME_UP 一直按住的时候
三星的一款平板计数到200,就不在触发该事件;
所以改为 KeyEvent.ACTION_DOWN 时启动一个方法用来计数, KeyEvent.ACTION_UP的停止技数;
Ⅸ Android怎么获取屏幕被点亮的动作
复制参考的别人的希望对你有帮助,总的来说就是监听intent.action.SCREEN_ON广播
在manifest文件里面注册一个receiver
<receiver android:name="com.test.check.MyReceiver">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF"></action>
<action android:name="android.intent.action.SCREEN_ON"></action>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"></action>
<action android:name="android.intent.action.ACTION_SHUTDOWN"></action>
</intent-filter>
</receiver>
代码部分这样监听:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
Log.v("#@%@%#", "Power button is pressed.");
Toast.makeText(arg0, "power button clicked",Toast.LENGTH_LONG).show();
//perform what you want here
}
}
希望这个连接能帮助你 http://hi..com/doyee/item/2f0f4d142c3455721009b548
Ⅹ 安卓怎么修改home键,使home键双击进后台(也就是像iPhone那样)
这个不能修改的,只能这样。
不过安卓可以安装虚拟Home键。下载Easy Touch,功能和苹果的AssistiveTouch一样的功能,可以自定义相关的操作,可以很好的模拟实体的HOME键。在各大应用商城都可以下载。
在苹果中按一次home键,返回主界面。双击home键,出现后台运行程序。长按home键,在iPhone 3GS(第三代)和iPhone4(第四代)中会开启“语音控制”,在iPhone4S(第五代)、iPhone5(第六代)、第三代与第四代iPad中将会开启Siri语音助手。按电源键3秒后,同时按住home键10秒,松开电源键,保持home键15秒,进入DFU模式(越狱用)。连按3下home键的功能可以自定义。