官网地址:http://www.apkplug.com/
先说下插件的配置,因为主程序要用到
插件的配置
首先在assets目录下添加plugin.xml文件
如下:
<?xml version="1.0" encoding="UTF-8"?>
<plugin-features
Bundle-Name="huanxindemo"
Bundle-SymbolicName="com.easemob.chatuidemo"
Bundle-Version="2.1.6"
date="2015.3.12"
provider-name="Apkplug"
provider-url=""
Bundle-Activator="com.easemob.chatuidemo.SimpleBundle"
Bundle-Activity="com.easemob.chatuidemo.activity.SplashActivity"
>
</plugin-features>
、、、要属性说明
Bundle-Name 插件名称
Bundle-SymbolicName 插件包名 -与应用packagename可一一对应
Bundle-Version 插件版本 -1.0.0
Bundle-Activator 插件入口 -与Appliction 类似
Bundle-Activity 插件界面 -多个Activity可用 , 分割
Bundle-Service 插件Service -多个Service可用 , 分割 (v2.0.0新增)
Bundle-Receiver 插件广播 -多个广播类可用 , 分割 (v2.0.0新增)
第二:添加jar包libs/osgi2.8.0.jar
入口文件com.easemob.chatuidemo.SimpleBundle.java
package com.easemob.chatuidemo;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import com.easemob.chatuidemo.activity.SplashActivity;
import android.content.Intent;
public class SimpleBundle implements BundleActivator
{
private BundleContext mcontext = null;
public void start(BundleContext context) throws Exception
{
System.err.println("你好我是插件,我将为你展示启动acitivty我已经启动了 我的BundleId为:"+context.getBundle().getBundleId());
context.getBundleContext().startActivity(new Intent(context.getBundleContext(), SplashActivity.class));
}
public void stop(BundleContext context)
{
System.err.println("你好我是插件,我被停止了 我的BundleId为:"+context.getBundle().getBundleId());
}
}
第一步,注册登录,就不说了
第二步:登陆后进入如图界面,我们点击上方的--应用授权--申请一个appid。填入对应的包名等即可。
第三:将申请好的appid复制到AndroidManifest.xml文件中。
配置应用权限
主应用需要几个基础的权限配置,请将以下的几个权限加入到主应用的AndroidManifest.xml中<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<meta-data android:name="apkplug-auth" android:value="xxxxxxxx" ></meta-data>
libs/Bundle2.8.1.09-Release.jar
private void initplug(){
try
{
//启动框架
frame=FrameworkFactory.getInstance().start(null,this);
BundleContext context =frame.getSystemBundleContext();
InstallBundle ib=new InstallBundle(context);
ib. install (context, "ChatUIDemo.apk", "1.0.0", new installCallback(){
@Override
public void callback(int arg0, Bundle arg1) {
if(arg0==installCallback.stutas5||arg0==installCallback.stutas7){
Log.d("",String.format("插件安装 %s : %d",arg1.getName(),arg0));
}
else{
Log.d("","插件安装失败 :%s"+arg1.getName());
}
}
},
2, false);
}
catch (Exception ex)
{
System.err.println("Could not create : " + ex);
ex.printStackTrace();
int nPid = android.os.Process.myPid();
android.os.Process.killProcess(nPid);
}
}
附录:InstallBundle.java工具类如下
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apkplug.Bundle.BundleControl;
import org.apkplug.Bundle.OSGIServiceAgent;
import org.apkplug.Bundle.installCallback;
import org.apkplug.app.FrameworkFactory;
import org.apkplug.app.FrameworkInstance;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
/**
* 替代PropertyInstance.AutoStart()的功能
* @author 梁前武
*/
public class InstallBundle {
private SharedPreferences sp;
private SharedPreferences.Editor editor;
public boolean DEBUG=true;
OSGIServiceAgent<BundleControl> agent=null;
public InstallBundle(BundleContext mcontext){
agent=new OSGIServiceAgent<BundleControl>(mcontext,BundleControl.class);
sp = mcontext.getAndroidContext().getSharedPreferences("apkpluginstallconfig.ini",0);
editor=sp.edit();
}
public void putString(String key, String value){
editor.putString(key, value);
editor.commit();
}
public String getString(String key, String value){
return sp.getString(key,value);
}
/**
*
* @param mcontext
* @param plugfile assets目录下的文件名 如 drag-sort-listview.apk
* @param version 当前安装的插件版本号 如下次更新宿主时,可以提高这个版本好,以让框架安装最新宿主assets目录下的插件
* @param callback 安装事件回掉接口
* @param startlevel 插件启动级别 小于2 插件会在框架启动时被自动启动
* @param isCheckVersion 是否对比当前安装的插件与已安装插件的版本好,如果为true时 新插件与已安装插件版本相同将不被更新。如果为false时将不检测版本直接覆盖已安装插件
* @throws Exception
*/
public void install(BundleContext mcontext,String plugfile,String version,installCallback callback,int startlevel,boolean isCheckVersion) throws Exception{
// startlevel设置为2插件不会自启 isCheckVersion不检测插件版本覆盖更新
File f1=null;
try {
if(!DEBUG){
//不是调试模式
String PlugVersion=this.getString(plugfile,null);
if(PlugVersion!=null){
if(PlugVersion.equals(version)){
//如果本地已安装的插件版本等与目前插件的版本,那么就不安装了
return ;
}
}
InputStream in=mcontext.getAndroidContext().getAssets().open(plugfile);
f1=new File(mcontext.getAndroidContext().getFilesDir(),plugfile);
if(!f1.exists()){
copy(in, f1);
}
agent.getService().install(mcontext, "file:"+f1.getAbsolutePath(),callback, startlevel,isCheckVersion,false,false);
//安装完成后删除文件
f1.delete();
//将最新的插件版本号保存到本地
this.putString(plugfile, version);
}else{
InputStream in=mcontext.getAndroidContext().getAssets().open(plugfile);
f1=new File(mcontext.getAndroidContext().getFilesDir(),plugfile);
copy(in, f1);
agent.getService().install(mcontext, "file:"+f1.getAbsolutePath(),callback, startlevel,isCheckVersion,false,false);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
/**
* 将 assets目录下文件拷贝到文件夹中
* @param is
* @param outputFile
* @throws IOException
*/
private void copy(InputStream is, File outputFile)
throws IOException
{
OutputStream os = null;
try
{
os = new BufferedOutputStream(
new FileOutputStream(outputFile),4096);
byte[] b = new byte[4096];
int len = 0;
while ((len = is.read(b)) != -1)
os.write(b, 0, len);
}
finally
{
if (is != null) is.close();
if (os != null) os.close();
}
}
}
第六步,启动,SplashActivity 为插件的启动页面
Intent i=new Intent();
i.setClassName(this,"com.easemob.chatuidemo.activity.SplashActivity");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
说明,上边的启动的类就是我们插件里在 plunin.xml里的参数Bundle-Activity里对应的的activity。我们这里要启动哪个,那里就要写对应的哪个,可以有多个那里。
==============