時光匆匆,乍一看已半年過去了,通過這半年的埋頭苦幹今天終於有滿血復活了。 java
利用apkplug框架實現動態替換宿主Activity中的UI元素,以達到不用更新應用就能夠更換UI樣式的目的。 git
先看效果圖: 框架
首先理解OSGI服務的基本概念,以下圖 ide
1.首先定義一個java接口(interface)用於規範宿主與插件之間的通信協議 this
interface com.apkplug.osgi.service.showView spa
void showView(Bundle bundle,View v,int index) ; //添加View .net
void removeView(Bundle bundle,View v); //刪除View 插件
2.決定osgi服務提供者和使用者 ,這裏咱們定義是 宿主應用爲"OSGI服務提供者",插件爲"OSGI服務使用者"。 code
注:OSGI服務提供者 註冊服務 OSGI服務使用者 查詢服務 對象
3.宿主應用實現showView接口,相應類爲 com.apkplug.osgi.serviceImp.showViewImp 具體代碼以下:
public class showViewImp implements showView{ private LinearLayout layout =null; /** * @param root 插件 View保存UI容器 */ public showViewImp(View root){ this.layout=(LinearLayout)root; } @Override public void showView(Bundle bundle, View v, int index) { //當插件查找到服務並使用時回調 System.out.println("插件傳來一個View"); layout.addView(v); } @Override public void removeView(Bundle bundle, View v) { System.out.println("插件須要刪除一個View"); layout.removeView(v); } }
4.宿主應用將showViewImp以服務的形式註冊都OSGI中,具體代碼在com.apkplug.osgi.activity.ViewActivator中
注意:
1:咱們將宿主應用也虛擬爲一個OSGI Bundle(插件) ,這樣它便擁有了與其餘插件進行OSGI通信的條件。
2:而且 宿主程序(插件)在框架啓動的時候便被啓動(這樣showView服務就最早被註冊上了,之後其餘插件就能夠查找到)
3:每個OSGI Bundle都有一個實現BundleActivator
ViewActivator implements BundleActivator
public abstract interface BundleActivator { //插件啓動時調用 public abstract void start(BundleContext context) throws Exception; //插件中止時調用 public abstract void stop(BundleContext context) throws Exception; }
因爲ViewActivator代碼較多這裏只貼出與服務註冊相關的代碼
........ public void start(final BundleContext context) { //註冊一個服務給插件調用 m_reg = context.registerService( showView.class.getName(), showView, null); ....... .......
5.編寫插件,在插件的BundleActivator實現類中查詢showView服務,而且初始化一個自身的View作爲參數傳遞給宿主應用
插件的BundleActivator實現類爲: com.apkplug.osgiclient1.SimpleBundle implements BundleActivator
查詢showView服務的相關代碼爲:
//插件自定義View myBtn myBtn=new myBtn(context.getBundleContext()); //查詢主程序提供的showView服務 ServiceReference ref = context.getServiceReference(showView.class.getName()); if (ref != null ) { // 獲取Service實例 showView service = (showView) context.getService(ref); if (service != null ) { // 調用Service方法 service.showView(context.getBundle(), myBtn, 0); // 釋放Service,在此以後不該該再繼續使用Service實例 context.ungetService(ref); } }
總結: 通過以上步驟便完成了插件-->宿主的View對象傳遞並顯示的過程。
結合OSGI服務咱們經過自定義java接口類,而且適當轉換OSGI服務者與使用者的角色來完成咱們所須要的各類互交。
注:OSGI服務除了查詢方式外,還提供監聽器的方式(服務者可在使用者後啓動註冊服務) 詳細demo也可參考osgiService的printLog服務註冊與監聽方式。
最後源碼地址 http://git.oschina.net/plug/OSGIService
QQ交流羣:132433459