现在的位置: 首页 > 综合 > 正文

android 动态加载 插件模型开发

2013年07月16日 ⁄ 综合 ⁄ 共 2798字 ⁄ 字号 评论关闭

目前市面上的应用商店,不管是 apple 还是 android 平台, 一般只有一家商店。
如果要动态添加商店,允许多家商店共存。
搭建一个平台,多家应用商店可以加入。
类似于商场与专卖店的关系。
每个商店的业务由各自实现,但统一由商场来提供接口供用户选择。
下面就来简单做个原型:
1 ClassLoadTestMain  商场
2 ClassLoadTestPlugin 商店

3 PluginInterface 商场提供给商店的接口

接口定义:

package com.pathfindeng.android.test;

public interface  IPlugin {
	
	public int add(int a, int b);

}

商店实现接口:

package com.pathfindeng.android.test.plugin;

import com.pathfindeng.android.test.IPlugin;

public class Plugin implements IPlugin{
	
	public int add(int a, int b){
		return a + b;
	}
}

商场调用商店的实现:

package com.pathfindeng.android.test.main;

import com.pathfindeng.android.test.IPlugin;
import com.pathfindeng.android.test.main.R;

import dalvik.system.DexClassLoader;
import dalvik.system.VMStack;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class ClassLoadTestMainActivity extends Activity {
	
	
	TextView result;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        result = (TextView)findViewById(R.id.result);
        
    }
    
    public void doInPlugin(){
    	
    	String dexPath, dexOutputDir, libPath ,className;
    	ClassLoader parent;
    	
    	dexPath = "/data/app/com.pathfindeng.android.test.plugin-1.apk";
    	dexOutputDir = "/data/data/com.pathfindeng.android.test.main";
    	
    	libPath = "/data/data/com.pathfindeng.android.test.main/lib";
    	
    	parent = ClassLoadTestMainActivity.this.getClassLoader();
    	
    	//parent = VMStack.getCallingClassLoader();
    	
    	DexClassLoader mDexClassLoader = new DexClassLoader(dexPath, dexOutputDir, libPath, parent);
    	
    	className = "com.pathfindeng.android.test.plugin.Plugin";
    	
    	try {
			Class mClass = mDexClassLoader.loadClass(className);
			
			IPlugin mIPlugin = (IPlugin)mClass.newInstance();
			
			int c;
			c = mIPlugin.add(100, 200);
			
			result.setText("from plugin : "+c);
			
			Toast.makeText(ClassLoadTestMainActivity.this, "from plugin : "+c, Toast.LENGTH_LONG);
						
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	
    }

	/* (non-Javadoc)
	 * @see android.app.Activity#onResume()
	 */
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		
		doInPlugin();
	}

	/* (non-Javadoc)
	 * @see android.app.Activity#onDestroy()
	 */
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}
    
}

从上面的代码看,调用插件还是强制定义的,不够人性

接下来做些改进。

插件端 注册 固定 Action Name  

<activity android:name=".商店Activity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="接口指定固定 Action Name" />
            </intent-filter>
</activity>

服务器端 商场

利用 PackageManager 查询所有注册了接口定义的 Action Name 的商店,并获得信息。

Intent intent = new Intent(Constants.ACTION_PLUGIN, null);
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);

这样之前提到的 

DexClassLoader(dexPath, dexOutputDir, libPath, parent)


参数就不需要 手动指定了。

待叙……

抱歉!评论已关闭.