您的位置:首页 > 移动开发 > Android开发

Android 实现简单的插件化模块化.

2013-11-26 23:08 375 查看
最近需要实现在android上开发插件,下面把一个简单例子分享一下...

首先我们需要创建两个工程,一个是主程序,一个是插件工程

1.首先在主程序中定义一个接口.

package com.mutour.testplugin;

import android.content.Context;
import android.view.View;

public interface Plugin {

public void load();

public void create(Context context, View view);

public void create(View view);

public void show();

public void hide();

public View getView();
}

2.接着在主程序中创建一个layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<LinearLayout
android:id="@+id/LinearLayoutContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
</LinearLayout>

</LinearLayout>

3.然后把主程序中的interface Plugin打包成jar.

主程序工程右键,Export, 选择Java-JAR file,(注意保存的路径), 一路的next

只选择Plugin.java.



4.把生成的jar文件放到插件工程中

5.在插件工程中写一个layout文件R.layout.activity_number_plugin,随便放点什么控件

6.在插件工程中写插件类

package com.mutour.testplugin.plugin;

import com.mutour.testplugin.Plugin;
import com.mutour.testplugin.plugin.R;

import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;

public class NumberPlugin implements Plugin {

private static final String TAG = "NumberPlugin";
private Context mContext;
private View mView;
private View viewNumber;

/**
* 必须有一个无参构造函数,否则无法用newInstance()获取句柄
*/
public NumberPlugin() {
}

public void setContext(Context context) {

mContext = context;
}

public NumberPlugin(Context context) {
this();
mContext = context;
}

@Override
public void load() {

}

@Override
public void show() {
((LinearLayout) mView).addView(viewNumber);
}

@Override
public void hide() {
if (mView != null)
((LinearLayout) mView).removeAllViews();
}

@Override
public void create(View view) {
mView = view;
viewNumber = View.inflate(mContext, R.layout.activity_number_plugin,
null);
}

@Override
public void create(Context context, View view) {
mContext = context;
this.create(view);
}

@Override
public View getView() {
return viewNumber;
}

}


7.编译工程,把bin目录中的classes.dex文件放入手机的sd卡里.本文中放在sd卡根目录中

8.编写主程序调用插件dex文件

package com.mutour.testplugin;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mutour.testplugin.plugin.QwertyPlugin;

import dalvik.system.DexClassLoader;
import android.os.Bundle;
import android.os.Environment;
import android.annotation.SuppressLint;
import android.app.ActionBar.LayoutParams;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;

@SuppressLint("NewApi")
public class MainActivity extends Activity {

Plugin mPlugin;
private LinearLayout mLinearLayoutContainer;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mLinearLayoutContainer = (LinearLayout) findViewById(R.id.LinearLayoutContainer);

String filepath = Environment.getExternalStorageDirectory().toString()
+ File.separator + "classes.dex";
DexClassLoader cl = new DexClassLoader(filepath, MainActivity.this
.getDir("dex", 0).getAbsolutePath(), null, getClassLoader());
Class libProviderClazz = null;
Plugin plugin = null;
try {
Context pluginContext = createPackageContext(
"com.mutour.testplugin.plugin",
Context.CONTEXT_IGNORE_SECURITY);
libProviderClazz = cl.loadClass("com.mutour.testplugin.plugin"
+ ".NumberPlugin");
plugin = (Plugin) libProviderClazz.newInstance();
if (plugin != null) {
switchPlugin(pluginContext, plugin);
}
} catch (Exception exception) {
exception.printStackTrace();
}

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private void switchPlugin(Context context, Plugin plugin) {
if (mPlugin != null) {
mPlugin.hide();
}
plugin.load();
plugin.create(context, mLinearLayoutContainer);
plugin.show();
mPlugin = plugin;
}

}

大功告成..............

其中有几个需要注意的地方

1..需要先获取dex的路径,使用DexClassLoader加载这个dex,然后使用包名和类名获取Class,然后使用newInstance获取句柄,把类型转换成Plugin

2.必须使用下面的方法获取插件包的Context,否则无法获取到插件包里的layout或其他资源

Context pluginContext = createPackageContext(
"com.mutour.testplugin.plugin",
Context.CONTEXT_IGNORE_SECURITY);


........................................................................................................................................

下面连接是该主程序和插件程序的代码..TestPlugin.rar是主程序 NumberPlugin.rar是插件程序

本方法是使用的dex方式,也可以使用apk方式安装插件.....

http://pan.baidu.com/s/1td9cO
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息