Android在第三方应用程序系统应用尽早开始,杀死自己主动的第三方应用程序,以重新启动
1.为什么第三方应用程序可能早于System的app启动?
Android能够查阅了,这里就不细述了,这里不阐述ROM启动还有bootloader。软件启动的大致流程应该是
- 启动kernel
- 执行servicemanager 把一些native的服务用命令启动起来(包含wifi, power, rild, surfaceflinger, mediaserver等等)
- 启动Dalivk中的第一个进程Zygote -> 启动java 层的系统服务system_server(包含PowerManagerService, ActivityManagerService , telephony.registry, DisplayManagerService等等)该服务中的这些部件跟native的那些服务关联在一起
- 启动Luncher和Persistent的App,该程序是系统级的在AndroidManifest.xml里声明android:persistent="true"
- 发出ACTION_BOOT_COMPLETED广播给其它应用。
在这里须要注意的是声明android:persistent属性为true的APP被kill掉后还是会自己主动重新启动的。系统中我们已知android:persistent属性为true的APP肯定有Phone App,也就是说第三方应用应当至少晚于Phone APP启动,怎样推断呢?最简单的办法看其PID的大小,PID值越小越先启动。有其第三方应用能够先于Phone APP启动。我们探其应用的AndroidManifest.xml (PS:怎样看APK的代码,网上有你懂的apktool等),发现其在AndroidManifest里定义的静态Receiver的intent-filter的属性例如以下:
<receiver android:name="com.anguanjia.safe.AAAReceiver">
<intent-filter android:priority="2147483647"></span>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.ANY_DATA_STATE" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.MEDIA_UNMOUNTED" />
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.MEDIA_REMOVED" />
<action android:name="android.intent.action.MEDIA_CHECKING" />
<action android:name="android.intent.action.MEDIA_EJECT" />
<data android:scheme="file" />
</intent-filter>
2147483647 这个值是什么?好大,哦,原来是int的最大值!
我们来看下google 文档
android:priority
The priority that should be given to the parent component with regard to handling intents of the type described by the filter. This attribute has meaning for both activities and broadcast receivers:
It provides information about how able an activity is to respond to an intent that matches the filter, relative to other activities that could also respond to the intent. When an intent could be handled by multiple activities with different priorities,
Android will consider only those with higher priority values as potential targets for the intent.
It controls the order in which broadcast receivers are executed to receive broadcast messages. Those with higher priority values are called before those with lower values. (The order applies only to synchronous messages; it's ignored for asynchronous
messages.)
Use this attribute only if you really need to impose a specific order in which the broadcasts are received, or want to force Android to prefer one activity over others.
The value must be an integer, such as "100". Higher numbers have a higher priority. The default value is 0. The value must be greater than -1000 and less than 1000.
这个值是receiver的优先级,值越大优先级越高,按优先顺序运行,可是文档介绍优先级值大小是-1000~1000. 该应用的是int的最大值, 但android平台没有对android:priority值进行检查。在开机后该应用Receiver的intent-filter的优先级最高,在该filter里的intent被系统发送出来(android.intent.action.MEDIA_MOUNTE,
android.net.wifi.WIFI_STATE_CHANGED等等),这个时候App会依据这个intent而被启动起来。
这里须要注意的是该Receiver是个静态的,一定是要注冊在AndroidManifest里。
当Wifi成功注冊后会发出WIFI_STATE_CHANGED的消息, 或者其它的部件完毕一些事件后也会发出类似的消息。而这些消息的发出又早于属性为persistent的系统级APP的启动, 由此就会发生第三方应用早于系统级APP的启动的情况。
2. 在Android手机上为什么我想全然关闭的程序关不了?
有一种理论是Android手机为了有更好的用户体验。会后台自己主动启动一些程序。 这样我们前台在操作的时候会感觉手机更流畅平滑。
可是假设程序执行过多。对CPU 内存的开销过大,往往会导致系统越用越慢,乃至手机挂掉的问题,在内存管理这快Android有两种机制去解决问题,一个是在framework层在 trimApplication方法中去实现,另外一个就是在kernel里的lowmemorykiller。 这里不再细述。
可是对于用户来说。我就是想全然关闭第三方程序,以免过多使用我的流量或者偷偷的做一些我不希望的操作。貌似没有办法去关闭,那为什么呢? 我这里先讲述当中一种情况。
Service顾名思义是服务。执行在前后台后都能够,即能够执行在当前进程也能够执行在其它的进程里,Service能够为多个APP共享使用,是通过binder机制来实现的。当我Kill掉一个带有服务的进程(没有调用stopService()), 过一会该应用会自己主动重新启动。以下是代码的调用顺序。自下往上查看。
com.android.server.am.ActiveServices.scheduleServiceRestartLocked(ActiveServices.java)
com.android.server.am.ActiveServices.killServicesLocked (ActiveServices.java)
com.android.server.am.ActivityManagerService.cleanUpApplicationRecordLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.handleAppDiedLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.appDiedLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied(ActivityManagerService.java)
从代码流程上我们看出该service被restart。进程也依据该service启动起来, service就执行在重新启动的进程里。
在这样的情况下是不是就真没办法了呢,当然不是。假设我们在service中覆盖onStartCommand这个函数而且返回值为START_NOT_STICKY,在我们kill该进程后则不会自己主动重新启动,我们想关闭的应用也能够全然关闭了。不会再自己主动重新启动了。
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Framwork实现代码
frameworks/base/services/java/com/android/server/am/ActiveServices.java case Service.START_NOT_STICKY: {
// We are done with the associated start arguments.
r.findDeliveredStart(startId, true);
if (r.getLastStartId() == startId) {
// There is no more work, and this service
// doesn't want to hang around if killed.
r.stopIfKilled = true; // 该变量设置为true
}
break;
} if (sr.startRequested && (sr.stopIfKilled || canceled)) { //进入到该条件中
if (sr.pendingStarts.size() == 0) {
sr.startRequested = false;
if (sr.tracker != null) {
sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
if (!sr.hasAutoCreateConnections()) {
// Whoops, no reason to restart!
bringDownServiceLocked(sr); //运行在这里。不会重新启动App
}
}
}
重写onStartCommand方法且返回值为START_NOT_STICKY的代码调用顺序,自下而上查看。
com.android.server.am.ActiveServices.bringDownServiceLocked(ActiveServices.java)
com.android.server.am.ActiveServices.killServicesLocked(ActiveServices.java)
com.android.server.am.ActivityManagerService.cleanUpApplicationRecordLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.handleAppDiedLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.appDiedLocked(Activi tyManagerService.java)
com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied(ActivityManagerService.java)
附上Google doc 对于onStartCommand返回值的说明
For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand():START_STICKY
is used for services that are explicitly started and stopped as needed, whileSTART_NOT_STICKY
orSTART_REDELIVER_INTENT
are used for services that should only remain running while processing any commands sent to them. See the linked documentation for more detail on the semantics.
在这里对这个返回值做下解释:
当服务进程因某种原因(内存不够,强制关闭等)被kill掉时,START_STICKY再次,在系统中创建了后有足够的内存service, 在onStartCommand在handle它是null intent.
START_NOT_STICKY通知系统不会再次创建service. 另一种回报值START_REDELIVER_INTENT再创service而伴随着原intent围棋处理。
Android在第三方应用程序系统应用尽早开始,杀死自己主动的第三方应用程序,以重新启动的更多相关文章
- Android(java)学习笔记219:开发一个多界面的应用程序之两种意图
1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...
- Android系统--输入系统(十五)实战_使用GlobalKey一键启动程序
Android系统--输入系统(十五)实战_使用GlobalKey一键启动程序 1. 一键启动的过程 1.1 对于global key, 系统会根据global_keys.xml发送消息给某个组件 & ...
- Android(java)学习笔记162:开发一个多界面的应用程序之两种意图
1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...
- 关于如何在Android、Java等非微软平台上建立高信任的SharePoint应用程序
关于如何在非微软平台上建立高信任的SharePoint应用程序 原文 :http://blogs.msdn.com/b/kaevans/archive/2014/07/14/high-trust-sh ...
- Android 使用PLDroidPlayer播放网络视频 依据视频角度自己主动旋转
近期由于项目需求 .须要播放网络视频 .于是乎 研究了一番 ,说说我遇到的那些坑 如今市面上有几个比較主流好用的第三方框架 Vitamio ( 体积比較大,有商业化风险 github:https:// ...
- Android中如何像 360 一样优雅的杀死后台Service而不启动
http://my.oschina.net/mopidick/blog/277813 目录[-] 一.已知的 kill 后台应用程序的方法 方法: kill -9 pid 二.终极方法,杀死后台ser ...
- Android开发之 Windows环境下通过Eclipse创建的第一个安卓应用程序(图文详细步骤)
第一篇 windows环境下搭建创建的第一个安卓应用程序 为了方便,我这里只采用了一体包进行演示. 一.下载安卓环境的一体包. 官网下载:安卓官网(一般被墙了) 网盘下载: http://yunpa ...
- 【Android UI设计与开发】3.引导界面(三)实现应用程序只启动一次引导界面
大部分的引导界面基本上都是千篇一律的,只要熟练掌握了一个,基本上也就没什么好说的了,要想实现应用程序只启动一次引导界面这样的效果,只要使用SharedPreferences类,就会让程序变的非常简单, ...
- Android手机平板两不误,使用Fragment实现兼容手机和平板的程序
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8744943 记得我之前参与开发过一个华为的项目,要求程序可以支持好几种终端设备,其 ...
随机推荐
- 【iOS开发-22】navigationBar导航栏,navigationItem建立:获取导航栏中的基本文本和button以及各种跳跃
(1)navigationBar导航栏可以被看作是self.navigationController一个属性导航控制器,它可以由点直接表示self.navigationController.navig ...
- 泛泰A860 Andorid4.4.3 KTU84M (Omni) 图赏
Omni4.4.3 For Pantech A860L/K/S watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3lob3N0/font/5a6L5L2T/ ...
- (二十)unity4.6得知Ugui中国文献-------另外-InputModules
大家好.我是太阳广东. 转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:http://www.unitym ...
- Threejs 它可以在建立其内部房间效果可见
Threejs 中建立可看到其内部的房间效果 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协 ...
- 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }
异常{ 无法将 匿名方法 转换为类型"System.Delegate",因为它不是委托类型 } 委托实际上是把方法名作为参数,但是若有好多个方法时,就要指明是哪个参数 查看如下代 ...
- dev XtraMessageBox按钮显示中文
dev的XtraMessageBox控件使用起来很美观,但默认显示确定的是英文,如下图: 通过下面代码可使“OK”显示为中文:首先创建一个继承自Localizer的类: using DevExpres ...
- Redis源代码分析(23)--- CRC循环冗余算法RAND随机数的算法
他今天就开始学习Redis源代码的一些工具来实现,在任何一种语言工具.算法实现的原理应该是相同的,一些比較经典的算法.比方说我今天看的Crc循环冗余校验算法和rand随机数产生算法. CRC算法全称循 ...
- 好的安排小明(南阳19)(DFS)
擅长排列的小明 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描写叙述 小明十分聪明,并且十分擅长排列计算.比方给小明一个数字5,他能立马给出1-5按字典序的全排列,假设你想 ...
- xCAT在多卡的物理机上装rhel6当需要人工选择网卡
问题叙述性说明 今天装了双网卡的物理机器上rhel5如果一切顺利.但是,在安装rhel6时间不能选择安装自己主动网卡,它会弹出一个窗口,让选择em1依然是em2. 问题原因 原因是我在加入节点的时候使 ...
- 拆除vs发展c++程序开发过程中产生的.ipch和.sdf文件的方法
正在使用Visual Studio 2010发展C++当程序,你会发现,有创建一些奇怪的文件.一个叫ipch的目录,和一个与project同名的.sdf文件.并且ipch以下的文件和.sdf文件都非常 ...