应用程序的插件化

 在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:

[java]  view plain copy
  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.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name="com.tony.reskin.Re_SkinActivity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.   
  17.     </application>  
  18. </manifest>  

2. 布局文件:

[java]  view plain copy
  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.       
  14. </LinearLayout>  

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

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

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

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

清单文件:

[java]  view plain copy
  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.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name=".Re_Skin1Activity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.   
  17.     </application>  
  18. </manifest>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值