Android 实现简单的插件化模块化
最近需要实现在android上开发插件,下面把一个简单例子分享一下...
首先我们需要创建两个工程,一个是主程序,一个是插件工程
1.首先在主程序中定义一个接口.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
< 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.在插件工程中写插件类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
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或其他资源
1
2
3
|
Context pluginContext = createPackageContext(
"com.mutour.testplugin.plugin" ,
Context.CONTEXT_IGNORE_SECURITY);
|
........................................................................................................................................
下面连接是该主程序和插件程序的代码..TestPlugin.rar是主程序 NumberPlugin.rar是插件程序
本方法是使用的dex方式,也可以使用apk方式安装插件.....
Android 实现简单的插件化模块化相关推荐
- android 程序开发的插件化
本文为 博客园 黑暗伯爵 原创,转载请注明 http://hangxin1940.cnblogs.com 原文地址:android 程序开发的插件化 模块化方法 之一 框架已经放出: android ...
- Android 基于注解IOC组件化/模块化的架构实践
当前参与的项目历史也很久远,第一行代码据说是写于2014年的某一天,那时Android用的ide还是Eclipse.那时Android还没有很好的架构指导(mvp.mvvm).那时Android最新的 ...
- Android 手写实现插件化换肤框架 兼容Android10 Android11
目录 一.收集所有需要换肤的view及相关属性 二.统一为所有Activity设置工厂(兼容Android9以上) 三.加载皮肤包资源 四.处理支持库或者自定义view的换肤 五.处理状态栏换肤 六. ...
- Android热修复及插件化原理
1.前言 热修复一直是这几年来很热门的话题,主流方案大致有两种,一种是微信Tinker的dex文件替换,另一种是阿里的Native层的方法替换.这里重点介绍Tinker的大致原理. 2.类加载机制 介 ...
- Android 热修复、插件化、双开基本原理
最近几年,安卓热门技术中,有关热修复.插件化.双开等等技术应用的比较广泛.本文从最简单直接的一个例子入手,分析其中的技术原理和构建思路.有3个相关的基本知识点,java中的反射.设计模式中的代理模式. ...
- android开发模式之插件化开发
一.简介 插件化开发是将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk(组件化的每个模块是个lib),最终打包的时候将宿主apk和插件apk分开或者联合打包.由宿主A ...
- android 插件化 模块化开发(apkplug)
经过几个月断断续续的摸索开发,终于有了apkplug的第一个版本,将大部分的业余时间都用于研发这个东东说实话感觉挺累的,不过努力总算没有白费,目前插件平台功能基本还令我满意.在这里写下一个开发demo ...
- Android实战】DroidPlugin插件化应用分析
简介 DroidPlugin 是360手机助手在Android系统上实现的一种新的插件机制:它可以在无需安装.修改的情况下运行APK文件,此机制对改进大型APP的架构,实现多团队协作开发具有一定的好处 ...
- Android插件化:从入门到放弃
喜欢 | 作者 包建强 发布于 2016年7月14日. 估计阅读时间: 1 分钟 | 道AI风控.Serverless架构.EB级存储引擎,尽在ArchSummit!讨论 分享到:微博微信Facebo ...
最新文章
- 【译】 WebSocket 协议第十一章——IANA 注意事项(IANA Considerations)
- Google-Analytics 学习与思考
- android设置控件形状,Android控件自定义形状
- 【linux命令总结】——后续用到的内容持续补充和更新
- Spark: Structured + hive(Jdbc方式)卡死
- layui弹窗自适应变大_layui弹窗宽度固定高度自适应界面
- MATLAB学习笔记——数组
- oa系统源码 python_区块链技术基于springboot的办公oa系统实现源代码
- 【接力题典1800记录】定积分
- 电脑快捷方式变白原因及解决方法——血的教训呜呜呜
- Window系列 (一) — WindowManager 详解
- Qt 实现PC端网易云音乐界面
- Ubuntu grub recuse 修复方法
- 福寿园首席员工系列报道:一雕一琢 人生定格
- matlab中figure的坐标轴label、title、xticklabel的旋转
- mysql语句更新顺序_MySQL的Update语句Set顺序问题
- 微信小程序预览 word、excel、ppt、pdf 等文件
- ground truth解释
- 《精妙的IT》免费公开课
- uml通信图画法_UML通信图参考.ppt
热门文章
- 【Kotlin】Kotlin 自定义组件 ( 自定义 View | 自定义 SurfaceView )
- 【C++ 语言】Visual Studio 配置 FFMPEG 开发环境 ( VS2019 CMake 环境安装 | 下载 FFMPEG 开发包 | 配置 FFMPEG )
- 【Android 系统开发】Android JNI 之 JNIEnv 解析
- 什么样的对象会进入老年代
- IDEA----破解
- BZOJ3261 最大异或和 解题报告(可持久化Trie树)
- PC问题-该虚拟机似乎正在使用中
- JSP/SERVLET(5)——JSP页面单选按钮操作
- 使用beanUtils操纵bean的属性
- ROS学习(十二):ROS URDF-model_state