首页 > 移动平台 > 详细

android平台框架原理

时间:2016-07-13 16:20:50      阅读:189      评论:0      收藏:0      [点我收藏+]

1.理解两个概念 抽象和衍生

抽象:从相似的事物中,抽取出共同点,得到相似的结构

衍生:以抽象结构为基础,添加些其他功能,得到具体的事物。

2. 系统OS,框架,应用程序,用户之间的关系

技术分享

用户操作一个软件的时候,其实中间还隔了一层,那就是系统,例如,用户点击了屏幕上的一个按钮,就会对屏幕产生物理感应,屏幕将这种物理感应交给系统os处理,系统产生相应的事件对象,交给框架处理,框架交给相应的程序,进行相应的处理,然后逆向的将对事件的动作反映在屏幕上。

应用程序是由框架进行管理的,例如Android上,activity的存储,程序的打开,结束,等等都是有框架进行管理的。

看一个现实中的例子:

技术分享

店员就相当于os系统,经理相当于框架,店员直接与客人进行沟通,一般的事情自己就解决了,除非遇到自己不能解决的问题,就去请示经理,有经理决定,在这张图中,与客户互动的细节几乎都有店员处理掉了这样经理就变得很轻松,os与框架之间的关系也可以概括框架和应用程序之间的关系,

技术分享

 

有了经理这个框架,应用程序就变得简单了。

3. 框架的特征

3.1 框架里的函数能够呼叫应用程序之中的函数,通俗的讲是前辈呼叫晚辈,框架先于程序诞生,称之为前辈。程序在框架的基础上诞生,所以称为晚辈。前辈呼叫晚辈,会产生下述几种效果

      3.1.1 框架里要定义很多的预设函数,工应用程序调用或者重写

      3.2.2 程序员的主要作用就是设计各种函数供框架来调用

      3.3.3 如果应用程序中修改或者取代了预设函数,框架就会去调用程序中的函数,反之会去调用预设函数。

3.2 应用框架的典型双向沟通情形

       技术分享

1. 框架中预设了f1(),程序中也定义了f1()。此时优先呼叫晚辈的f1()函数。
2. 框架「虚」设了f2(),亦即f2()是个抽象(abstract)函数。此时您务必
     定义f2()來充实之,并供Linux/Windows 或其它函数呼叫。例如f3()呼叫f2()。
3. 框架预设了f3(),程序并未定义f3()。此时呼叫预设的f3()函数。
4. 框架预设了f4(),您也定义了f4()。此时优先呼叫f4()函数,而f4()可呼叫前辈(预设)的f4()函数。

 

总结:从上图可以看到,框架和应用程序之间,主动权掌握在框架手里,框架决定如何呼叫应用程序中的函数。

======

 Android的系统架构采用了分层架构的思想,如图1所示。从上层到底层共包括四层,分别是应用程序程序层、应用框架层、系统库和Android运行时和Linux内核。

技术分享

      图1:Android系统架构图

      每层功能简要介绍如下:

      一 应用程序层

      该层提供一些核心应用程序包,例如电子邮件、短信、日历、地图、浏览器和联系人管理等。同时,开发者可以利用Java语言设计和编写属于自己的应用程序,而这些程序与那些核心应用程序彼此平等、友好共处。

     二 应用程序框架层

     该层是Android应用开发的基础,开发人员大部分情况是在和她打交道。应用程序框架层包括活动管理器、窗口管理器、内容提供者、视图系统、包管理器、电话管理器、资源管理器、位置管理器、通知管理器和XMPP服务十个部分。在Android平台上,开发人员可以完全访问核心应用程序所使用的API框架。并且,任何一个应用程序都可以发布自身的功能模块,而其他应用程序则可以使用这些已发布的功能模块。基于这样的重用机制,用户就可以方便地替换平台本身的各种应用程序组件。

     三 系统库和Android运行时

     系统库包括九个子系统,分别是图层管理、媒体库、SQLite、OpenGLEState、FreeType、WebKit、SGL、SSL和libc。Android运行时包括核心库和Dalvik虚拟机,前者既兼容了大多数Java语言所需要调用的功能函数,又包括了Android的核心库,比如android.os、android.net、android.media等等。后者是一种基于寄存器的java虚拟机,Dalvik虚拟机主要是完成对生命周期的管理、堆栈的管理、线程的管理、安全和异常的管理以及垃圾回收等重要功能。

     四 Linux内核

     Android核心系统服务依赖于Linux2.6内核,如安全性、内存管理、进程管理、网络协议栈和驱动模型。Linux内核也是作为硬件与软件栈的抽象层。驱动:显示驱动、摄像头驱动、键盘驱动、WiFi驱动、Audio驱动、flash内存驱动、BinderIPC)驱动、电源管理等。

     总结:

     1 Android的系统架构采用分层架构的思想,架构清晰,层次分明,协同工作。

     2 Android的系统架构不仅从宏观上认识了Android系统,同时,也给我们的学习与实践指明了方向。若是从事Android应用开发,那应该研究Android的应用框架层和应用程序层;若是从事Android系统开发,那应该研究Android的系统库和Android运行时;若是从事Android驱动开发,那应该研究Android的Linux内核。总之,找准切入点,实践出真知。


========

前言

最近这一两年,Android App使用插件化技术开发的数量越来越大,其实还是业务地快速膨胀导致,需求越来越多,App越来越臃肿。虽然手机的内存空间不断地的增大,但是太大的安装包给用户也造成了心理压力。于是大家都会想到插件化的开发方式,把App做成一个平台,而不是一个独立的app。平台上可以集成各种各样的功能,功能模块也插件的形式添加进来,这些插件不需要安装,只需要用户按需下载到某个位置,然后使用的时候动态加载进来。

想法都是好的,但是想实现一个相对比较稳定的动态加载框架还是有点难度的,一些大公司都有成熟的动态加载框架,但是他们并没有开源出来。好在2014年知名CSDN博主任玉刚开源了一款名为DL的Android动态加载框架,该框架简单、开源、兼容性都较为好,如果有需要使用插件化开发的朋友可以尝试该框架,另外对该开源项目感兴趣的朋友也可以贡献自己的代码,地址会在文章最后给出。

对于DL的基本情况和使用,本人就不再赘述,作者本人和参与开发的朋友已经有一些较好的文章,详情请参考,APK动态加载框架(DL)解析、DL动态加载框架技术文档、Android 使用动态加载框架DL进行插件化开发。在这里我就简单介绍一下DL的基本结构与原理,希望能够一些需要的朋友提供一些有用的信息。


基本架构

对于Android的动态加载框架来说最重要和最麻烦的点可能基本上有两个,第一是apk如何在不安装的情况下运行起来,并且Activity基本的声明周期能够正常调用;第二就是Activity内部能够以R的形式访问资源文件。关于加载未安装的apk和Android的资源加载机制请参考如下两篇文章,Android动态加载jar、apk的实现、Android源码分析-资源加载机制。我们针对这两个问题依次给出DL的解决方案。

加载未安装apk相对比较简单,就是通过DexClassLoader将apk文件加载到虚拟机中,具体可以参考上文给出的文章。这里我们主要说一下调用Activity生命周期函数的实现。在DL中,有两个Proxy类,分别为DLProxyActivity、DLProxyFragmentActivity,这两个类型分别继承自Activity和FragmentActivity,他们分别代理集成自DLBasePluginActivity和DLBasePluginFragmentActivity的插件Activity类,DLBasePluginActivity和DLBasePluginFragmentActivity又分别继承自Activity和FragmentActivity,我去!这个时候是不是有点乱了?且听我慢慢道来~

按照DL的开发规范,你插件的Activity需要继承自DLBasePluginActivity或者DLBasePluginFragmentActivity,这两个类中封装了一些基本的调用逻辑。这里我们先暂时不用过多理会,重点是看DLProxyActivity、DLProxyFragmentActivity。DL的机制是这样的,真正在DL通过Intent启动的Activity只能是DLProxyActivity、DLProxyFragmentActivity,这两个Activity是在宿主apk中注册了的,因此能够直接通过Intent来启动。而在两个Proxy实际上只是一个躯壳,他们会自己的生命周期函数中调用插件Activity对应的生命周期函数。这是就引入了一个关键的类,DLProxyImpl,这个类负责解析插件apk的资源、ClassLoader、通过反射加载插件Activity,DLProxyImpl加载了插件Activity之后又会调用Proxy Activity的attach方法将插件Activity实例传递给Proxy Activity,这样Proxy Activity就得到了插件Activity的实例,然后就能在自己的声明周期函数中调用插件Activity对应的函数。

DLProxyImpl的launchTargetActivity函数:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
protected void launchTargetActivity() {
    try {
        // mClass就是目标插件Activity的类名
        Class<!--?--> localClass = getClassLoader().loadClass(mClass);
        Constructor<!--?--> localConstructor = localClass.getConstructor(new Class[] {});
        // 通过反射构建插件Activity
        Object instance = localConstructor.newInstance(new Object[] {});
        mPluginActivity = (DLPlugin) instance;
        // 将插件Activity注入给Proxy Activity
        ((DLAttachable) mProxyActivity).attach(mPluginActivity, mPluginManager);
        // 插件activity也获取到Proxy的引用
        mPluginActivity.attach(mProxyActivity, mPluginPackage);
 
        Bundle bundle = new Bundle();
        bundle.putInt(DLConstants.FROM, DLConstants.FROM_EXTERNAL);
        // 调用插件Activity的onCreate函数,启动插件Activity
        mPluginActivity.onCreate(bundle);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

宿主在加载插件apk时会解析该apk的相关信息,比如它的默认启动的Activity,上述形式将apk运行起来,那么在插件apk中的activity跳转则需要通过DLIntent类将目标activity的包名、类名传递给DL框架,DL内部会进行解析以及相应的加载逻辑。


DLProxyActivity核心代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class DLProxyActivity extends Activity implements DLAttachable {
 
    // 插件Activity
    protected DLPlugin mRemoteActivity;
    // DLProxyImpl加载插件Activity和资源等
    private DLProxyImpl impl = new DLProxyImpl(this);
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Proxy onCreate的时候调用DLProxyImpl的onCreate,加载插件Activity
        impl.onCreate(getIntent());
    }
 
    // 加载完插件Activity后将插件Activity传递给Proxy Activity
    @Override
    public void attach(DLPlugin remoteActivity, DLPluginManager pluginManager) {
        mRemoteActivity = remoteActivity;
    }
 
    // 获取资源,DLProxyImpl加载了插件apk的资源,通过这里代理资源操作,这样插件Activity内部就可以通过R访问资源文件了
    @Override
    public Resources getResources() {
        return impl.getResources() == null ? super.getResources() : impl.getResources();
    }
 
    /***********************  以下都是代理插件Activity的生命周期函数  ***********************/
 
    @Override
    protected void onStart() {
        mRemoteActivity.onStart();
        super.onStart();
    }
 
    @Override
    protected void onRestart() {
        mRemoteActivity.onRestart();
        super.onRestart();
    }
 
    @Override
    protected void onResume() {
        mRemoteActivity.onResume();
        super.onResume();
    }
 
    @Override
    protected void onPause() {
        mRemoteActivity.onPause();
        super.onPause();
    }
 
    @Override
    protected void onStop() {
        mRemoteActivity.onStop();
        super.onStop();
    }
 
    @Override
    protected void onDestroy() {
        mRemoteActivity.onDestroy();
        super.onDestroy();
    }
 
    // 代码省略
 
}

下面我们来看另外一个重点,也就是插件apk的资源加载。关于apk的资源加载机制也请参考上面给出的文章,我们直接看代码。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private DexClassLoader createDexClassLoader(String dexPath) {
    File dexOutputDir = mContext.getDir("dex", Context.MODE_PRIVATE);
    dexOutputPath = dexOutputDir.getAbsolutePath();
    // 创建ClassLoader
    DexClassLoader loader = new DexClassLoader(dexPath, dexOutputPath, mNativeLibDir,
            mContext.getClassLoader());
    return loader;
}
 
// 根据插件apk的路径构建AssetManager,将其资源所在的路径添加到AssetManager中,然后通过AssetManager构建一个Resources对象,这个对象就是插件apk的资源对象,插件apk内部访问资源时都是通过这个资源对象
private AssetManager createAssetManager(String dexPath) {
    try {
        AssetManager assetManager = AssetManager.class.newInstance();
        Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
        addAssetPath.invoke(assetManager, dexPath);
        return assetManager;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
 
}
 
private Resources createResources(AssetManager assetManager) {
    Resources superRes = mContext.getResources();
    Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(),
            superRes.getConfiguration());
    return resources;
}

这样,等于是插件Activity的生命周期交给了Proxy Activity代理,而插件的Activity的启动和资源访问则交给了DLProxyImpl代理。这样,通过两个代理就启动了插件Activity,并且资源访问问题也得到了解决。

最后我们通过一张图来看DL的基本结构。

技术分享

DLPluginManager加载、管理插件包,DLIntent是插件之间跳转的信息载体。Base Plugin Activity是插件Activity的基类,封装代理操作。Proxy Activity代理插件Activity的生命周期函数,也是插件Activity的外壳。DLProxy负责加载插件Activity以及资源操作。这么一来,整个动态加载框架就运行起来了,更多的细节有兴趣的朋友自己去看源码吧。


后期特性

1. 支持service、静态广播、ContentProvider

bug

1. 插件透明主题的支持

2. 完整activity api的重写


最后给出DL框架github地址,希望更多的人参与到DL框架的开发中来。



=========



android平台框架原理

原文:http://blog.csdn.net/yue31313/article/details/51894666

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!