Android中persistent属性用法详解
本文实例讲述了Android中persistent属性用法。分享给大家供大家参考,具体如下:
前段时间在研究telephony时,一直没有在framework下发现对telephony的初始化(PhoneFactory.Java中的makeDefaultPhones函数)的调用。结果全局搜索之后发现在applicationPhoneApp(packages/apps/Phone)中调用了。但是applicationPhoneApp既没有被Broadcast唤醒,也没有被其他service调用,那么是Android是通过什么方式来启动PhoneApp,所以就发现了属性android:persistent。
在AndroidManifest.xml定义中,application有这么一个属性android:persistent,根据字面意思来理解就是说该应用是可持久的,也即是常驻的应用。其实就是这么个理解,被android:persistent修饰的应用会在系统启动之后被AM启动。
AM首先去PM(PackageManagerService)中去查找设置了Android:persistent的应用
publicvoidsystemReady(finalRunnablegoingCallback){
if(mFactoryTest!=SystemServer.FACTORY_TEST_LOW_LEVEL){
try{
Listapps=AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if(apps!=null){
intN=apps.size();
inti;
for(i=0;i<N;i++){
ApplicationInfoinfo
=(ApplicationInfo)apps.get(i);
if(info!=null&&
!info.packageName.equals("Android")){
addAppLocked(info);
}
}
}
}catch(RemoteExceptionex){
//pmisinsameprocess,thiswillneverhappen.
}
}
}
假如该被Android:persistent修饰的应用此时并未运行的话,那么AM将调用startProcessLocked启动该app,关于startProcessLocked不再描述,另外一篇文章《HowtostartanewprocessforAndroid?》中做了详细的介绍(这篇英文文档小编就不翻译了,感兴趣的朋友可以搜到看一看)。
app的启动过程就是启动app所在的package对应的进程。
finalProcessRecordaddAppLocked(ApplicationInfoinfo){
ProcessRecordapp=getProcessRecordLocked(info.processName,info.uid);
if(app==null){
app=newProcessRecordLocked(null,info,null);
mProcessNames.put(info.processName,info.uid,app);
updateLruProcessLocked(app,true,true);
}
if((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
==(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)){
app.persistent=true;
app.maxAdj=CORE_SERVER_ADJ;
}
if(app.thread==null&&mPersistentStartingProcesses.indexOf(app)<0){
mPersistentStartingProcesses.add(app);
startProcessLocked(app,"addedapplication",app.processName);
}
returnapp;
}
面介绍app所在的package对应的进程启动完成之后,app是如何被create的。
从文章《HowtostartanewprocessforAndroid?》中可知,zygote在创建新的进程均会启动它的mainThreadandroid.app.ActivityThread,因此我们从ActivityThread的main函数中接着分析app的create过程。
在main中有下面这个操作
thread.attach(false);
在attach过程中,ActivityThread会将对应的applicationattach到AM中去,交与AM去管理。这里需要注意一个变量
finalApplicationThreadmAppThread=newApplicationThread();
mAppThread是一个ApplicationThread对象,mAppThread可以看作是当前进程主线程的核心,它负责处理本进程与其他进程(主要是AM)之间的通信,同时通过attachApplication将mAppThread的代理Binder传递给AM。
privatefinalvoidattach(booleansystem){
sThreadLocal.set(this);
mSystemThread=system;
if(!system){
ViewRoot.addFirstDrawHandler(newRunnable(){
publicvoidrun(){
ensureJitEnabled();
}
});
Android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManagermgr=ActivityManagerNative.getDefault();
try{
mgr.attachApplication(mAppThread);
}catch(RemoteExceptionex){
}
}
}
上面的attach代码中,我们顺着IPC调用AM的attachApplication过程再往下看。
在该过程中,AM调用到了IPC通信调用mAppThread的bindApplication;
privatefinalbooleanattachApplicationLocked(IApplicationThreadthread,
intpid){
thread.bindApplication(processName,app.instrumentationInfo!=null
?app.instrumentationInfo:app.info,providers,
app.instrumentationClass,app.instrumentationProfileFile,
app.instrumentationArguments,app.instrumentationWatcher,testMode,
isRestrictedBackupMode||!normalMode,
mConfiguration,getCommonServicesLocked());
updateLruProcessLocked(app,false,true);
app.lastRequestedGc=app.lastLowMemory=SystemClock.uptimeMillis();
}
mAppThread的bindApplication再通过消息机制向ActivityThread自身维护的handler发送BIND_APPLICATION消息。下面看看ActivityThread自身维护的handler对消息BIND_APPLICATION的处理,最终会调用到handleBindApplication函数
你会发现在handleBindApplication函数中有这么一句
mInstrumentation.callApplicationOnCreate(app);
我们最终在绕了好大一圈之后,调用了app的onCreate函数来启动这个application。
PS:更多关于AndroidManifest.xml配置项及其功能可参考本站在线工具:
AndroidManifest功能与权限描述大全:
http://tools.jb51.net/table/AndroidManifest
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android数据库操作技巧总结》、《Android编程之activity操作技巧总结》、《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》、《Android视图View技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。