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 记得我之前参与开发过一个华为的项目,要求程序可以支持好几种终端设备,其 ...
随机推荐
- C#四舍五入保留两位小数
- 自己定义actionbar
android中的actionbar可提供自己定义view.详细是先写好自己定义view的布局,然后在代码中获取Actionbar对象.调用 setCustomView方法. 可是这样,它还是会显示前 ...
- ps设计资料整理
零基础学会建立一个简单化妆品网站—前台设计篇1[PS画草图] http://xiebiji.com/2008/09/huazhuang4/?wptheme=Plainscape&ie=1 PS ...
- c语言 int (*p)[5] 类型分析
#include<stdio.h> int main() { int i; int b[5]={1,3,5,7,9}; int (*a)[5] = &b ...
- RH033读书笔记(6)-Lab 7 Standard I/O and Pipes
Lab 7 Standard I/O and Pipes 1. [student@stationX ~]$ cat /proc/cpuinfo /proc/meminfo 2. [student@st ...
- 【Java GUI】Java面板基础:JPanel
有两个面板,常见的面板(JPanel)和滚动面板(JScrollPane) Jpanel 面板是一种常见的容器,JPanel的作用是实现接口层次结构,面放入一些组件.也能够在上面绘画,将放有组件和有画 ...
- struts开发步骤
说来惭愧.这是一个简单的struts折腾了很长一段时间,几乎相同的时间量就花了三天时间来解决.下面的步骤总结一下我开发:(我使用的是MyEclipse); 1.新建一个Exercise3的web Pr ...
- 实现DataGridView行的拖动,即实现行的顺序交换
参考:http://blog.csdn.net/soarheaven/article/details/3267379 1.界面准备 (1)首先在form中添加一个DataGridView控件,将默认A ...
- Android使用开源项目Xutils实现多线程下载文件
#1.下载utils项目 https://github.com/wyouflf/xUtils #2布局文件里实现UI <LinearLayout xmlns:android="http ...
- POJ3467(预处理)
Cross Counting Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 1331 Accepted: 375 De ...