前言
在Android中,有些应用没有通过Service或者Broadcast等启动他,但Application还是被启动了。
经过查阅资料和看代码,发现android:persistent="true"的妙用之处。
实现Application,然后AndroidManifest.xml中注册Application,并在其属下中添加android:persistent="true",如下:
<application
android:allowBackup="true"
android:name="com.water.app.WaterApp"
android:icon="@mipmap/ic_launcher"
android:persistent="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
......
</application>
下面我们来简单的分析一下是不是所有应用设置android:persistent="true"都是有效的。
正文
android:persistent="true"对任何应用有效么?
- ActivityManagerService.java
目录地址:\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
.....
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
.....
}
void startPersistentApps(int matchFlags) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
synchronized (this) {
try {
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
addAppLocked(app, null, false, null /* ABI override */);
}
}
} catch (RemoteException ex) {
}
}
}
- PackageManagerService.java
目录地址:frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
@Override
public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) {
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return ParceledListSlice.emptyList();
}
return new ParceledListSlice<>(getPersistentApplicationsInternal(flags));
}
private @NonNull List<ApplicationInfo> getPersistentApplicationsInternal(int flags) {
final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Package> i = mPackages.values().iterator();
final int userId = UserHandle.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Package p = i.next();
if (p.applicationInfo == null) continue;
final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
&& !p.applicationInfo.isDirectBootAware();
final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
&& p.applicationInfo.isDirectBootAware();
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p))
&& (matchesUnaware || matchesAware)) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
finalList.add(ai);
}
}
}
}
}
return finalList;
}
在PackageManagerService.java解析apk时会把带有ApplicationInfo.FLAG_PERSISTENT的apk解析出来。
上面也有是否是系统应用和安全模式判断,如下代码:
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p))
&& (matchesUnaware || matchesAware)) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
finalList.add(ai);
}
}
}
也就是非系统应用需要再[非安全模式]下才可以是启动,如果是[安全模式]且[非系统应用],即使你设置了persistent属性也是无法被启动Application、
总结
需要android:persistent="true"有效,除了设置了这个属性,还需要满足下面中的一个。
- 非安全模式
- 系统应用
