在android的项目开发中,都会遇到后期功能拓展增强与主程序代码变更的现实矛盾,也就是程序的灵活度。 由于linux平台的安全机制,再加上dalvik的特殊机制,各种权限壁垒,使得开发一个灵活多变的程序,变得比较困难,不像pc平台下那么容易。

这里实际上可以借鉴传统软件中扩展程序的方法: 也就是插件的实现. 如目前所有的浏览器,比如我们使用的eclipse,以及很多优秀的软件,都使用了此种方式. 这样轻松实现了软件的功能扩展,而升级功能时只用更新对应插件, 而不是需要更新整个应用,降低了程序的耦合度.

而在Android中的实现思路,即为将一个较大的APK,分离为一个主程序的APK,和其他各种较小的APK.

典型的应用为手机QQ换肤的实现方式:

QQ的皮肤是一个无界面APK应用,这个皮肤应用中的资源和主程序的资源命名一致,通过主程序和皮肤程序共享进程实现主程序对皮肤程序中资源的访问,在程序运行时通过代码显示指定皮肤资源,缺点是在主程序中每个activity要增加复杂的使用哪种皮肤逻辑

本例实现效果如下:

下面分析下具体思路:

android下,默认的情况是,每个apk相互独立的,基本上每个应用都是一个dalvik虚拟机,都有一个uid,再配合上linux本身的权限机制,使得apk互通很难直接进行。但作为一个独立应用的集成,不管多少个apk,都可以并为一个单独的dalvik虚拟机,直观的反映给开发人员就是在shell下列出进程,那几个apk同时加载后,会一个进程存在。

可以在清单文件中加入如下配置:

     android:sharedUserId="com.tony.test"

android:sharedUserId是指共用一个uid,也就是,凡是这个属性相同的工程,都会共用同一个uid,这样,权限壁垒就消除了,dalvik也会融合为一个,可以测试一下,写几个工程,没有这个属性和有这个属性的情况下,同时运行,在列出当前进程,就直观的说明了。

下面还是用代码说明,一共分为两部分. 主程序 Re_Skin和皮肤程序Re_Skin1

首先是主应用程序代码:

1. 清单文件AndroidManifest.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.tony.reskin"
  4. android:versionCode="1"
  5. android:versionName="1.0" <span style="color:#FF0000;">android:sharedUserId="com.tony.skin"</span>>
  6. <uses-sdk android:minSdkVersion="7" />
  7. <application android:icon="@drawable/icon" android:label="@string/app_name">
  8. <activity android:name="com.tony.reskin.Re_SkinActivity"
  9. android:label="@string/app_name">
  10. <intent-filter>
  11. <action android:name="android.intent.action.MAIN" />
  12. <category android:name="android.intent.category.LAUNCHER" />
  13. </intent-filter>
  14. </activity>
  15. </application>
  16. </manifest>

2. 布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:id="@+id/layout"    >
  7. <TextView
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="@string/hello"
  11. />
  12. <Button android:text="Set" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
  13. </LinearLayout>

3. Re_SkinActivity;(主要的皮肤更换逻辑实现类)

  1. package com.tony.reskin;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.content.pm.PackageManager.NameNotFoundException;
  5. import android.os.Bundle;
  6. import android.os.Handler;
  7. import android.view.View;
  8. import android.view.View.OnClickListener;
  9. import android.widget.Button;
  10. import android.widget.LinearLayout;
  11. public class Re_SkinActivity extends Activity {
  12. private LinearLayout layout;
  13. private Button btnSet;
  14. <span style="color:#FF0000;">private Context friendContext;</span>
  15. /** Called when the activity is first created. */
  16. @Override
  17. public void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. setContentView(R.layout.main);
  20. btnSet = (Button)findViewById(R.id.button1);
  21. layout = (LinearLayout)findViewById(R.id.layout);
  22. layout.setBackgroundResource(R.drawable.bg);
  23. try {
  24. <span style="color:#FF0000;">friendContext =  createPackageContext("com.tony.reskin1", Context.CONTEXT_IGNORE_SECURITY);</span>
  25. } catch (NameNotFoundException e) {
  26. e.printStackTrace();
  27. }
  28. btnSet.setOnClickListener(new OnClickListener() {
  29. @Override
  30. public void onClick(View v) {
  31. new Handler().post(new Runnable() {
  32. @Override
  33. public void run() {
  34. layout.setBackgroundDrawable(<span style="color:#FF0000;">friendContext.getResources().getDrawable(R.drawable.bg</span>));
  35. }
  36. });
  37. }
  38. });
  39. }
  40. }

皮肤应用中不需要界面显示

这个皮肤应用中的资源和主程序的资源命名一致即可.

清单文件:

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    3. package="com.tony.reskin1"
    4. android:versionCode="1"
    5. android:versionName="1.0" <span style="color:#FF0000;">android:sharedUserId="com.tony.skin"</span>>
    6. <uses-sdk android:minSdkVersion="7" />
    7. <application android:icon="@drawable/icon" android:label="@string/app_name">
    8. <activity android:name=".Re_Skin1Activity"
    9. android:label="@string/app_name">
    10. <intent-filter>
    11. <action android:name="android.intent.action.MAIN" />
    12. <category android:name="android.intent.category.LAUNCHER" />
    13. </intent-filter>
    14. </activity>
    15. </application>
    16. </manifest>

Android 打造自己的个性化应用(三):应用程序的插件化的更多相关文章

  1. Android 插件化开发(三):资源插件化

    在前面的文章中我们成功的加载了外部的Dex(Apk)并执行了插件的Bean代码.这时我们会想,能不能加载并运行插件Apk的Activity.答案当然是能,否则后续我们的研究就没意义了,但是想实现Act ...

  2. Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压

    上一篇中提到对于Zip包的解压和压缩需要借助Ant 实现,我经过参考了其他的资料,整理后并加上了一些自己的看法: 这里就具体地讲下如何使用Ant进行解压缩及其原因: java中实际是提供了对  zip ...

  3. Android 打造自己的个性化应用(四):仿墨迹天气实现-->自定义扩展名的zip格式的皮肤

    在这里谈一下墨迹天气的换肤实现方式,不过首先声明我只是通过反编译以及参考了一些网上其他资料的方式推测出的换肤原理, 在这里只供参考. 若大家有更好的方式, 欢迎交流. 墨迹天气下载的皮肤就是一个zip ...

  4. Android 打造自己的个性化应用(二):应用程序内置资源实现换肤功能

    通过应用程序内置资源实现换肤,典型的应用为QQ空间中换肤的实现. 应用场景为: 应用一般不大,且页面较少,风格相对简单,一般只用实现部分资源或者只用实现背景的更换. 此种换肤方式实现的思路: 1. 把 ...

  5. Android 打造自己的个性化应用(一):应用程序换肤主流方式的分析与概述

    Android平台api没有特意为换肤提供一套简便的机制,这可能是外国的软件更注重功能和易用,不流行换肤.系统不提供直接支持,只能自行研究. 换肤,可以认为是动态替换资源(文字.颜色.字体大小.图片. ...

  6. Android插件化开发

    客户端开发给人的印象往往是小巧,快速奔跑.但随着产品的发展,目前产生了大量的门户型客户端.功能模块持续集成,开发人员迅速增长.不同的开发小组开发不同的功能模块,甚至还有其他客户端集成进入.能做到功能模 ...

  7. android插件化之路

    概论  插件式开发通俗的讲就是把一个很大的app分成n多个比较小的app,其中有一个app是主app.基本上可以理解为让一个apk不安装也可以被运行.只不过这个运行是有很多限制的运行,所以才叫插件. ...

  8. Android 插件化开发(四):插件化实现方案

    在经过上面铺垫后,我们可以尝试整体实现一下插件化了.这里我们先介绍一下最简单的实现插件化的方案. 一.最简单的插件化实现方案 最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下: 1). 合 ...

  9. Android插件化开发---执行未安装apk中的Service

    欢迎各位增加我的Android开发群[257053751​] 假设你还不知道什么叫插件化开发.那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从总体角度分析了一下 ...

随机推荐

  1. asp.net cookie和session的详细使用

    cookie使用代码: //设置Cookie HttpCookie setCookie = new HttpCookie("test"); setCookie.Values.Add ...

  2. REST 相关

    REST 相关 REST:Representational State Transfer,表现层状态转化(出现在阮一峰的博客 理解RESTful架构 中,但是,很明显,Representational ...

  3. Oracle内链接+外连接详解

    inner join(内连接) 内连接也称为等同连接,返回的结果集是两个表中所有相匹配的数据,而舍弃不匹配的数据.也就是说,在这种查询中,DBMS只返回来自源表中的相关的行,即查询的结果表包含的两源表 ...

  4. Light oj 1030 概率DP

    D - Discovering Gold Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:32768 ...

  5. shell中的case表达式

    语法格式 case var in pattern1 | patter2) command1 command2;; pattern3) command1 command2;; *) default co ...

  6. php的一些小笔记-文件函数(1)

    ---恢复内容开始--- 与文件操作相关的函数有一部分可以和linux命令比较,但是我觉得可能还是linux上使用的比较频繁 如:chown,chmod,chgrp,rename,touch,link ...

  7. apt软件包管理

    apt软件包管理 ----   http://wiki.ubuntu.org.cn/UbuntuHelp:AptGet/Howto/zh APT HOWTO  ----    http://www.d ...

  8. sqlserver2008 case when then else end

    在写sql语句的时候,有时候我们需要对字段的只进行判断计算.查看了下相关文档在sql2012.sql2014里边可以使用  IIF 函数直接完成. 但是现在我需要在sql2008版本中完成最字段的计算 ...

  9. 给div中动态添加节点并设置样式

    前端IOS今天需要动态的在图片前面添加一个按钮 主要是在使用 bt.setAttribute("class","aaa"); 可以对创建的节点使用setAttr ...

  10. Tomcat 6.0.32 +Spring dbcp datasource关闭Tomcat出现严重异常

    异常如下: 信息: Pausing Coyote HTTP/ -- :: org.apache.catalina.core.StandardService stop 信息: Stopping serv ...