一,原理(以浏览器为例)

本质:

1, 主程序直接加载插件的Extension类(这样他们就在同一个进程里了,就相当于主程序和Extension合为一个新的大app),通过接口来交互。

2, 插件Extension需要实现接口IExt

接口包括(部分):/* for browser activity */

public void onBrowserCreate(Bundle bundle);

public void onBrowserResume();

public void onBrowserPause();

public void onBrowserDestory();

3, 主程序需要实现IBrowserActivity接口

接口包括(部分):public boolean showToast(String pkgname, String content);

public boolean showProgressDialog(String pkgname,

PopupProgressDialogParams params);

public void dismissProgressDialog(String pkgname);

public IPopupProgressDialog getProgressDialog(String pkgname);

public boolean showPopupDialog(String pkgname, PopupDialogParams params);

public void dismissPopupDialog(String pkgname);

4, 通过一个类BrowserActivityImpl来执行,它持有主程序的Context,保存各个插件的各种数据(每个插件的Extension)。设计上BrowserActivity是单例模式,且为弱引用。

架构的示意图如下:

流程示例:

1, 主程序的onCreate()方法如何传给Addon

1-1 在主程序Activity的onCreate中,获得BrowserActivityImpl的实例

调用实例的traverseCreateActivityCallback()方法

1-2 在BrowserActivityImpl对象持有每个插件的Extension 的实例。

在此,会调用Extension中的onCreate()方法。

BrowserActivityImpl

2, Addon如何让主程序显示PopupDialog

1-1 初始化

主程序启动,Addon Extension获得BrowserActivityImpl的对象mBrowserActivityImpl

1-2 调用

Addon中,mBrowserActivity调用方法:

mBrowserActivityImpl.showProgressDialog(PKGNAME, mLoadingParams);

二,要点

1, 插件Extension类的加载

比较2.3和4.1的源码,Classloader和PathClassloader之间有所不同。

所以分别处理。4.1中,PathClassloader可以直接加载class,2.3中,通过load一个错误的class name,让PassClassloader获得的mDex文件的数据,然后通过mdex文件,加载类,相关源码,不给出,请自行查看。给出实现代码供参考:public class ExtClassLoader extends ClassLoader {

private static Field dexField;

private DexFile[] mDexs;

private final ClassLoader mLoader;

private static boolean ICE_OR_ABOVE = Build.VERSION.SDK_INT >= 14;

static {

if(!ICE_OR_ABOVE){

Class classLoader = PathClassLoader.class;

try {

dexField = classLoader.getDeclaredField("mDexs");

dexField.setAccessible(true);

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

}

}

}

public ExtClassLoader(Context base,PackageInfo pi, String extPkg,

ClassLoader mainClassLoader) {

super(mainClassLoader);

Context extContext = null;

try {

extContext = base.createPackageContext(

extPkg,

Context.CONTEXT_INCLUDE_CODE

| Context.CONTEXT_IGNORE_SECURITY);

} catch (NameNotFoundException e1) {

e1.printStackTrace();

}

if(ICE_OR_ABOVE){

String codePath = extContext.getPackageCodePath();

String dir = pi.applicationInfo.nativeLibraryDir;

mLoader = new PathClassLoader(codePath, dir, mainClassLoader);

}else{

mLoader = extContext.getClassLoader();

}

}

@Override

protected Class> loadClass(String className, boolean arg1)

throws ClassNotFoundException {

if(ICE_OR_ABOVE)

return super.loadClass(className, arg1);

Class> c = findLoadedClass(className);

if (c != null)

return c;

try {

c = getParent().loadClass(className);

if (c == null)

c = findClass(className);

} catch (ClassNotFoundException e) {

c = findClass(className);

}

return c;

}

@Override

protected Class> findClass(String className)

throws ClassNotFoundException {

if(mLoader == null)

return null;

if(ICE_OR_ABOVE)

return mLoader.loadClass(className);

Class> c = null;

if (mLoader instanceof PathClassLoader)

c = loadClassFromDexFile(className);

else

c = mLoader.loadClass(className);

return c;

}

private Class> loadClassFromDexFile(String className) {

DexFile[] dfs = getDexFiles();

if (dfs != null) {

for (int i = 0; i < dfs.length; i++) {

if (dfs[i] != null) {

Class> c = dfs[i].loadClass(className, this);

if (c != null)

return c;

}

}

}

return null;

}

private DexFile[] getDexFiles() {

if (mDexs != null)

return mDexs;

try {

mLoader.loadClass("all.money.go.my.home");

} catch (Exception e) {

e.printStackTrace();

Log.e(ExtMgrConstants.LOGTAG, "getDexFiles " + e.toString());

}

try {

mDexs = (DexFile[]) dexField.get(mLoader);

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

return mDexs;

}

}

2, 进程的处理

根据以上的说明,即Addon的Extension类与主程序属于同一进程。但是Addon的其他类,则不属于主程序进程。

2-1 两个进程之间切换,需要sync

2-2 如果使用SharedPreference,需要使用多进程的构造方法。

2-3 友盟统计,如果要单独统计为Addon的数据。需要从Extension单起一个service来统计,因为Extension在主程序的进程中,统计的数据会到主程序。

三:项目

插件是特定应用(例如浏览器)提供的开放api的实现。开发者主要关注的是功能, 交互和UI。当然,需要注意第二部分给出的要点。

我参与了两个插件的开发,中间隔了很长的时间,会觉得再次进入需要一些熟悉的时间。觉得可以优化的地方,就是给出开发步骤文档。一些记忆性质的code flow可以避免。开发效率可以提高。

android MDE工程师,Android Application Addon(插件) 架构及管理相关推荐

  1. 如何成为android开发工程师,android开发工程师薪资 如何成为一名合格的android开发工程师?...

    行业薪酬的影响因素包括行业内.外部因素及员工个人的因素,同样,在IT行业中,要想了解android开发工程师的薪资待遇情况如何,我们也可以从这几个因素入手,加以了解.android开发工程师薪资,如何 ...

  2. android MDE工程师,JustModeling: An MDE Approach to Develop Android Business Applications

    摘要: The continuous growth of the Android market has resulted in greater demand for applications and ...

  3. android MDE工程师,【MDE工作内容|工作职责|MDE做什么】-看准网

    要求A Manage development, selection, implementation & optimization of secondary operations for mec ...

  4. android软件工程师/android中间件开发

    Android平台及中间件工程师 职责描述: 1 设计,集成和优化验证基于Android平台以下软件运行库 Multimedia: Video Middleware (OpenMAX, GStream ...

  5. android camera工程师,Android从Camera中获取图片的两种方法

    方法一: 此方法会由Camera直接产生照片回传给应用程序,但是返回的是压缩图片,显示不清晰 /**   启动Camera */ private void intentCamera(){ try { ...

  6. Android开发工程师vs运维工程师

    关于我 目录 1.什么是运维工程师 2.什么是Android开发工程师 未完待续 1.什么是运维工程师 对于初创公司,运维工程师的工作可能需要从申请域名开始,购买/租用服务器,上架,调整网络设备的设置 ...

  7. android 类加载器 DexClassLoader的用法,以及引出的插件架构

    1.android 类加载器(DexClassLoader的用法),调用其他apk的类中的方法: 方式一: 然后在Host中利用下面的方式调用 PackageManager pm = getPacka ...

  8. Android魔镜:方法耗时统计插件Mirror-基础篇

    晓锋,曾在PPTV工作,饿了么资深Android工程师,专注于Android单元测试.架构设计.性能优化.以及最新技术分享,个人博客:michaelzhong. 注:本篇是<Android魔镜: ...

  9. Android Framework中的Application Framework层介绍

    Android的四层架构相比大家都很清楚,老生常谈的说一下分别为: Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework. Framework层为我们开 ...

最新文章

  1. 小明分享|8ms平台下工程源码分析
  2. java math max_Java Math类静态double max(double d1,double d2)示例
  3. 在国外当程序员爽吗?
  4. JS打开新窗口的2种方式
  5. Oracle | oracle11g安装环境变量配置
  6. tp-link无线网卡linux下的驱动,Ubuntu14下安装无线网卡驱动(TP-LINK TL-WN823N)
  7. ldap 统一认证 java_LDAP统一用户认证
  8. Python批量检测域名是否被注册
  9. 哔哩哔哩2018校招前端笔试
  10. english_搭配
  11. [生存志] 第141节 秦魏风俗掌故
  12. sql substr oracle,Substr也可以使用索引吗?
  13. 解决了计算机处理汉字的问题,计算机处理汉字必须解决的三个问题分别是汉字...
  14. 最小公倍数和最大公约数的三种算法
  15. inter酷睿后缀含义
  16. 车辆识别号(VIN)验证
  17. USACO 2021 January Contest, BronzeProblem 3. Just Stalling题解
  18. Password Management: Hardcoded Password
  19. Java(SpringMVC03)(SSM整合1)
  20. 可信时间戳服务,如何确保电子数据法律效力?

热门文章

  1. 不愿意和别人打交道_一个人不愿意和同事打交道,大多是这3个原因,你了解吗...
  2. Tomcat使用过滤器实现页面的限制访问,登录才能访问受限页面
  3. DC-DC升压和降压电路电感参数选择详解
  4. Unity视频播放的脚本控制
  5. 在阿里云国内搭建一个纯净的 kubernetes 环境
  6. 基于多重继承与信息内容的知网词语相似度计算 - 论文及代码讲解
  7. Android新机系统要求,原神手机端最低配置要求
  8. PrimoCache2.2.0汉化程序与2.0.0的交叉使用
  9. IGRP和EIGRP为什么是距离矢量协议
  10. GPRS优点介绍及GPRS上网相关知识(转)