d.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:566)
E AndroidRuntime: at android.app.LoaderManagerImpl.initLoader(LoaderManager.java:619)
E AndroidRuntime: at com.android.settings.search.DynamicIndexableContentMonitor.register(DynamicIndexableContentMonitor.java:136)
E AndroidRuntime: at com.android.settings.SettingsActivity.onStart(SettingsActivity.java:868)
E AndroidRuntime: at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1249)
E AndroidRuntime: at android.app.Activity.performStart(Activity.java:6737)
E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2628)
E AndroidRuntime: ... 9 more
通过堆栈信息,可以知道PrintManager.getPrintServices出现了空指针。这里也不用看代码就能猜到,因为我们开机没有启动打印服务,所以肯定get不到这个服务的。
然后考虑修改方案,增加非空保护是不是就可以了?Naive!我们的目的是裁剪打印服务,所以我们的修改点并不在这个服务本身,而是删除所以调用这个服务的地方。
所以堆栈显示的PrintManager,PrintServicesLoader什么的统统不要改,我们要看代码结构,看看是怎么调用进来的。通过阅读代码,了解到系统里有很多Loader类型的对象,其中一个子类就是PrintServicesLoader。然后这些Loader是由LoaderManager管理启动的。而LoaderManager在DynamicIndexableContentMonitor.java出现过一次初始化操作。
看下DynamicIndexableContentMonitor.java代码:
public void register(Activity activity, int loaderId) {
...
boolean hasFeaturePrinting = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING);
...
if (hasFeaturePrinting) {
activity.getLoaderManager().initLoader(loaderId, null, this);
}
...
有木有发现一个熟悉的代码?
对,代码里再次出现了一个有关SystemFeature的判断!上一次出现时SystemServer启动服务前也做了相同的判断。
所以要裁剪掉打印机服务,我们只需要将FEATURE_PRINTING关闭即可。
通过修改SystemFeature判断后,在SystemServer里面的裁剪代码就可以不再添加了。但是有些服务的裁剪Android并没有添加系统特性的处理,所以还是建议使用我的方法进行裁剪。
SystemFeature加载流程
先看一看FEATURE_PRINTING
PackageManager.java
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device supports printing.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_PRINTING = "android.software.print";
/**
* Get a list of features that are available on the
* system.
*
* @return An array of FeatureInfo classes describing the features
* that are available on the system, or null if there are none(!!).
*/
public abstract FeatureInfo[] getSystemAvailableFeatures();
/**
* Check whether the given feature name is one of the available features as
* returned by {@link #getSystemAvailableFeatures()}. This tests for the
* presence of <em>any</em> version of the given feature name; use
* {@link #hasSystemFeature(String, int)} to check for a minimum version.
*
* @return Returns true if the devices supports the feature, else false.
*/
public abstract boolean hasSystemFeature(String name);
/**
* Check whether the given feature name and version is one of the available
* features as returned by {@link #getSystemAvailableFeatures()}. Since
* features are defined to always be backwards compatible, this returns true
* if the available feature version is greater than or equal to the
* requested version.
*
* @return Returns true if the devices supports the feature, else false.
*/
public abstract boolean hasSystemFeature(String name, int version);
都是抽象方法,我们去PMS查找对应的实现
PackageManagerService.java
public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() {
synchronized (mPackages) {
final A