插件加载---之二

7.3 PackageParser

插件的解析就是将获取插件的信息填到对应的变量中。

PluginPackageParser构造方法主要逻辑如下,

1,构造PackageParser对象,

mParser = PackageParser.newPluginParser(hostContext);

2,解析插件

mParser.parsePackage(pluginFile, 0);

3,获取插件的信息,例如四大组件信息,

mPackageName = mParser.getPackageName();
mHostPackageInfo = mHostContext.getPackageManager().getPackageInfo(mHostContext.getPackageName(), 0);

List datas = mParser.getActivities();
•••

PackageParser的newPluginParser方法如下,

if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) {
   if ("1".equals(SystemPropertiesCompat.get("ro.build.version.preview_sdk", ""))) {
         return new PackageParserApi22Preview1(context);
   } else {
         return new PackageParserApi22(context);//API 20
   }
} else if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
   return new PackageParserApi21(context);//API 21
}
•••

根据当前的android系统版本构建不同的子类对象PackageParser。

以API21 为例论述,对应于android 5.0.

PackageParserApi21的构造方法如下,

public PackageParserApi21(Context context) throws Exception {
    super(context);
    initClasses();
}

initClasses方法主要是为变量赋值,如下,

sPackageParserClass = Class.forName("android.content.pm.PackageParser");
sActivityClass = Class.forName("android.content.pm.PackageParser$Activity");
sServiceClass = Class.forName("android.content.pm.PackageParser$Service");
sProviderClass = Class.forName("android.content.pm.PackageParser$Provider");
sInstrumentationClass = Class.forName("android.content.pm.PackageParser$Instrumentation");
sPermissionClass = Class.forName("android.content.pm.PackageParser$Permission");
sPermissionGroupClass = Class.forName("android.content.pm.PackageParser$PermissionGroup");
        try {
            sArraySetClass = Class.forName("android.util.ArraySet");
        } catch (ClassNotFoundException e) {
        }
•••

那么这些变量有何作用呢?

在android系统中,解析apk主要是通过PackageParser.java这个类完成的,打开这个类看看就可以很清楚了。

这些变量就是为了调用PackageParser的方法,获取获取PackageParser.java的解析信息。

解析插件通过调用PackageParser 的parsePackage方法完成, PackageParserApi21实现该方法如下,

public void parsePackage(File file, int flags) throws Exception {
/* public Package parsePackage(File packageFile, int flags) throws PackageParserException*/
    mPackageParser = sPackageParserClass.newInstance();
    mPackage = MethodUtils.invokeMethod(mPackageParser, "parsePackage", file, flags);
}

利用反射调用PackageParser.java的parsePackage方法完成。

PackageParser.java指代android系统中的PackageParser类,

PackageParser指DroidPlugin框架中的PackageParser类。因为这两个类的名字完全一样,所以有点不好区分。

7.4 Activity解析

调用PackageParser.java的parsePackage方法之后,插件的所有信息都保存在PackageParser.java的相关变量中, PackageParser中解析

四大组件其实就是利用反射将PackageParser.java 的相关变量读取出来然后保存在自己的变量中。

PluginPackageParser的构造方法中有关Activity解析的代码主要逻辑如下,

1,获取插件中所有的Activity,然后逐个获取Activity的其他信息。

List datas = mParser.getActivities();
PackageParserApi21的getActivities方法如下,
public List getActivities() throws Exception {
     /*PackageParser.Package.activities*/
    return (List) FieldUtils.readField(mPackage, "activities");
}

其实就是利用反射获取PackageParser.java的内部类Package的activities变量,定义如下,

public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);

public final ArrayList<String> requestedPermissions = new ArrayList<String>();
public final ArrayList<Boolean> requestedPermissionsRequired = new ArrayList<Boolean>();

其实获取其他信息也完全一样。

2,获取Activity的ComponentName并保存在mActivityObjCache中,

ComponentName componentName = new ComponentName(mPackageName, mParser.readNameFromComponent(data));
synchronized (mActivityObjCache) {
     mActivityObjCache.put(componentName, data);
}

PackageParserApi21的readNameFromComponent方法如下,

public String readNameFromComponent(Object data) throws Exception {
        return (String) FieldUtils.readField(data, "className");
    }

其实就是获取PackageParser.java的内部类Component的className变量。

 

3,获取Activity其他相关信息,并放入mActivityInfoCache变量中。

synchronized (mActivityInfoCache) {
   ActivityInfo value = mParser.generateActivityInfo(data, 0);
   fixApplicationInfo(value.applicationInfo);
   if (TextUtils.isEmpty(value.processName)) {
        value.processName = value.packageName;
   }
   mActivityInfoCache.put(componentName, value);
}

PackageParserApi21的generateActivityInfo方法如下,

public ActivityInfo generateActivityInfo(Object activity, int flags) throws Exception {
  /*   public static final ActivityInfo generateActivityInfo(Activity a, int flags,
            PackageUserState state, int userId) */
  Method method = MethodUtils.getAccessibleMethod(sPackageParserClass, "generateActivityInfo", sActivityClass, int.class, sPackageUserStateClass, int.class);
  return (ActivityInfo) method.invoke(null, activity, flags, mDefaultPackageUserState, mUserId);
}

直接调用PackageParser.java的generateActivityInfo方法获取对应的ActivityInfo信息。

4,获取Activity的IntentFilter信息,保存在mActivityIntentFilterCache变量中,

List<IntentFilter> filters = mParser.readIntentFilterFromComponent(data);
synchronized (mActivityIntentFilterCache) {
  mActivityIntentFilterCache.remove(componentName);
  mActivityIntentFilterCache.put(componentName, new ArrayList<IntentFilter>(filters));
}

PackageParserApi21的readIntentFilterFromComponent方法如下,

public List<IntentFilter> readIntentFilterFromComponent(Object data) throws Exception {
        return (List) FieldUtils.readField(data, "intents");
    }

其实就是获取PackageParser.java的内部类Component的intents变量,定义如下,

public final ArrayList<II> intents;

7.5 组件解析

PluginPackageParser的构造方法中对其他组件的解析和Activity的完全相同,整个套路流程完全一样。关于Services 解析如下,

datas = mParser.getServices();
        for (Object data : datas) {
            ComponentName componentName = new ComponentName(mPackageName, mParser.readNameFromComponent(data));
            synchronized (mServiceObjCache) {
                mServiceObjCache.put(componentName, data);
            }
            synchronized (mServiceInfoCache) {
                ServiceInfo value = mParser.generateServiceInfo(data, 0);
                fixApplicationInfo(value.applicationInfo);
                if (TextUtils.isEmpty(value.processName)) {
                    value.processName = value.packageName;
                }
                mServiceInfoCache.put(componentName, value);
            }

            List<IntentFilter> filters = mParser.readIntentFilterFromComponent(data);
            synchronized (mServiceIntentFilterCache) {
                mServiceIntentFilterCache.remove(componentName);
                mServiceIntentFilterCache.put(componentName, new ArrayList<IntentFilter>(filters));
            }
        }

其他的在此不赘述了。

主要是利用反射调用android系统中的PackageParser.java。

将PluginPackageParser的相关变量填写完整。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值