实现Android 动态载入APK(Fragment or Activity实现)
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38565345
近期由于项目太大了。导致编译通只是(Android对一个应用中的方法个数貌似有限制),所以一直琢磨着是否能将某些模块的APK不用安装,动态载入,通过在网上查找资料和网友的帮助,最终实现了APK的动态载入。网络上介绍APK动态载入的文章许多,可是我觉得写得很好的就是这位大牛的,我基本上就是使用他的这样的方案,然后增加了自己的元素。这位大牛是通过Activity实现的。我稍作改动。通过Fragment实现动态载入,我个人觉得使用Fragmnet更加简单。由于使用Fragment实现不须要考虑Fragment的生命周期。
文章地址:http://blog.csdn.net/singwhatiwanna/article/details/22597587
http://blog.csdn.net/singwhatiwanna/article/details/23387079
一定要读了这两篇文章之后再来读我这篇,由于我是借鉴了这篇文章的思想的。
首先我们须要明确。实现动态载入就是要解决两个问题:(假设使用Fragments实现,则是一个问题)
1、Activity生命周期的管理。
2、动态载入的apk的资源怎样获取。
第一个问题是由于在java中不论什么一个程序要执行起来,必须通过类载入器将某个类增加内存,当我们通过一个类载入器将Activity增加内存时,事实上这个Activity就是一个普通的类。它已经没有生命周期的概念了,在Android系统中,Activity的生命周期是通过ActivityManager来控制的,假设我们通过动态载入的方式载入这个Activity,那么ActivityManager根本就不知道这个Activity的存在。所以我们必须处理好这个Activity的生命周期。至于第二个问题,在Android中。我们获取资源都是通过Context拿到的。而动态载入的APK是没有Context的。所以我们不能和曾经一样那样来拿。
前面的两篇文章推荐的方法已经能够很好的解决以上两个问题,因此实现了APK的动态载入。
我先来描写叙述一下大牛博客中实现动态载入的思路吧:
创建一个ProxyActivity,通过名字知道。它就是一个代理Activity,我们调用不论什么一个Activity都是通过调用ProxyActivity实现的,我仅仅须要传入动态载入apk的路径和须要动态载入的类名,比方载入了一个Activity之后。通过反射机制读取到Activity的全部的生命周期函数以及onActivityResult等函数,并保存在一个列表中。在ProxyActivity的onCreate中通过反射调用动态载入的Activity的onCreate,由于ProxyActivity是一个正常的Activity,它的生命周期是正常的,所以在ProxyActivity的生命周期函数中调用动态载入Activity的生命周期函数就ok了,从而实现动态载入的Activity也有生命周期了。
同一时候尽然是代理。那么就代理彻底一点。就干脆把动态载入的Activity中的全部的逻辑都转入到ProxyActivity中。
那么这就要求被载入的Activity有一个ProxyActivity的引用,这个能够让全部动态载入的Activity继承一个BaseActivity,这个BaseActivity中有一个setProxy方法。用来设置ProxyActivity。所以不是不论什么APK。都能够动态载入的。一般仅仅有动态载入自己编写的apk,动态载入别人的apk不太现实。
看了上面的思路,是不是有点借腹生子的感觉,事实上就是把动态载入的Activity的逻辑转移到了ProxyActivity
解决资源訪问的问题方法就是造ProxyActivity中重载者两个函数
public abstract AssetManager getAssets();
public abstract Resources getResources();
至于为什么能解决资源的问题,我还是推荐几篇文章大家去学习一下吧:
本人的另外一篇文章:http://blog.csdn.net/yuanzeyao/article/details/12955459
解说Android资源载入机制的一篇文章:http://blog.csdn.net/singwhatiwanna/article/details/24532419
好了,上面就是通过Activity实现的动态载入apk,以下看看我是怎么通过Fragment来实现动态载入的,假设熟悉Fragment的同学们应该知道。Fragment就相当于一个有生命周期的View,它的生命周期被所在的Activity的生命周期管理。即使我们通过类载入器把一个Fragment增加到内存,它和曾经我们使用的Fragment没有什么两样。仅仅要我们将这个Fragment增加到ProxyActivity,ProxyActivity就会自己主动的管理好这个Fragment的生命周期。
所以我们就不须要操心Fragment的生命周期,以下就来看看代码实现吧:
1、BaseFragment.java
public class BaseFragment extends Fragment implements IConstant
{
private static final String TAG = "BaseFragment";
protected String mDexPath;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle bundle=this.getArguments();
//动态载入apk的路径
mDexPath=bundle.getString(DEX_PATH);
} //在Fragment中启动另外一个Fragment
protected void replaceFragmentByProxy(String name)
{
if(mDexPath==null)
return;
//PROXY_VIEW_ACTION 是ProxyActivity的action
Intent intent=new Intent(PROXY_VIEW_ACTION);
//传递apk路径
intent.putExtra(DEX_PATH, mDexPath);
//是启动Fragment还是启动Fragment,这里启动的是Fragment
intent.putExtra(START_TYPE, TYPE_FRAGMENT);
//须要载入的fragment的类名
intent.putExtra(CLASS_NAME, name);
this.startActivity(intent); }
}
全部须要动态载入的Fragment都须要继承这个BaseFragment,每次启动一个Fragment,仅仅须要传递apk的路径就可以。
以下是我写的一个MyFragment,用来使用BitmapFun载入网络图片的,这里仅仅是载入并显示图片。没有考虑其它的。假设想深入了解BitmapFun的使用,请看我的另外一篇文章:
http://blog.csdn.net/yuanzeyao/article/details/38355719
public class MyFragment extends BaseFragment
{
private static final String TAG = "MyFragment"; private static final String IMAGE_CACHE_DIR = "thumbs";
private ImageFetcher mImageFetcher; private GridView mGridView;
private Context context;
private Button btn; @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ImageCacheParams cacheParams = new ImageCacheParams(getActivity(), IMAGE_CACHE_DIR); cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory // The ImageFetcher takes care of loading images into our ImageView children asynchronously
mImageFetcher = new ImageFetcher(getActivity(), 200);
mImageFetcher.setLoadingImage(R.drawable.empty_photo);
mImageFetcher.addImageCache(getActivity().getSupportFragmentManager(), cacheParams);
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//这里事实上能够直接使用R.layout.fragment
Resources mResources=this.getActivity().getResources();
return inflater.inflate(mResources.getIdentifier("fragment", "layout", "com.dl.client"), container,false);
} @Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
mGridView=(GridView) view.findViewById(R.id.gridView);
btn=(Button)view.findViewById(R.id.btn_fragment);
btn.setOnClickListener(new View.OnClickListener()
{ @Override
public void onClick(View arg0)
{
//在Fragment中动态载入另外一个Fragment
replaceFragmentByProxy("com.dl.client.TempFragment");
}
});
context=this.getActivity();
mGridView.setAdapter(new BaseAdapter()
{ @Override
public View getView(int position, View contentView, ViewGroup arg2)
{
ImageView mImg;
if(contentView==null)
{
contentView=LayoutInflater.from(context).inflate(R.layout.item,null);
}
mImg=(ImageView)contentView.findViewById(R.id.img_11);
//mImg.setImageResource(R.drawable.empty_photo);
mImageFetcher.loadImage(Images.imageThumbUrls[position], mImg);
return contentView;
} @Override
public long getItemId(int arg0)
{
return 0;
} @Override
public Object getItem(int arg0)
{
return Images.imageThumbUrls[arg0];
} @Override
public int getCount()
{
return Images.imageThumbUrls.length;
}
});
}
}
以下看看这个应用的效果吧:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
最后须要注意的一点就是动态载入的apk不能和宿主应用包括同样的jar包,不然会报错的。。
。
实现Android 动态载入APK(Fragment or Activity实现)的更多相关文章
- 深入浅出Android动态载入jar包技术
在实际项目中.因为某些业务频繁变更而导致频繁升级client的弊病会造成较差的用户体验,而这也恰是Web App的优势,于是便衍生了一种思路.将核心的易于变更的业务封装在jar包里然后通过网络下载下来 ...
- Android动态载入Dex机制解析
1.什么是类载入器? 类载入器(class loader)是 Java™中的一个非常重要的概念.类载入器负责载入 Java 类的字节代码到 Java 虚拟机中. Java 虚拟机使用 Java 类的方 ...
- Android动态载入JAR包的实现方法
有时候我们须要使用动态更新技术,简单来说就是:当我们把开发jar包发送给用户后.假设后期升级了部分代码.这时让用户的jar包自己主动更新,而不是用户主动手动地去更新的技术就是动态更新.这个须要使用的技 ...
- Android进阶(十二)Fragment VS Activity
Fragment VS Activity Android是在Android 3.0 (API level 11)开始引入Fragment的. 可以把Fragment想成Activity中的模块,这 ...
- Android开发之旅-Fragment和Activity之间onCreateOptionsMenu的联系
Fragment和Activity一样,可以重写onCreateOptionsMenu方法来设定自己的菜单,其实这两个地方使用onCreateOptionsMenu的目的和效果都是完全一样的,但是由于 ...
- 动态载入Layout 与 论Activity、 Window、View的关系
1)动态载入Layout的代码是 getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main, null)); ...
- Android 使用EventBus进行Fragment和Activity通信
本文介绍EventBus的基本使用,以及用于Fragment和Activity之间通信. github地址: https://github.com/greenrobot/EventBus 版本是 Ev ...
- android 直接添加一个Fragment到activity,不需要额外setContentView
getSupportFragmentManager().beginTransaction().replace(android.R.id.content,new ArticleListFragment( ...
- 插件化开发—动态载入技术载入已安装和未安装的apk
首先引入一个概念,动态载入技术是什么?为什么要引入动态载入?它有什么优点呢?首先要明确这几个问题.我们先从 应用程序入手,大家都知道在Android App中.一个应用程序dex文件的方法数最大不能超 ...
随机推荐
- 原生js-拉勾网首页效果
拉勾网首页公司广告位的悬浮划过效果着实很吸引我.如下(不会做动图!--,感兴趣的可以去拉勾看看): 此处最吸引我的地方在于将鼠标划过上面一排公司列表时,感觉像是绿色的区块跟着你的鼠标移动一样,颇有动感 ...
- 各版本IIS安装方法
各版本IIS安装方法 Windows 2000 V5.0 将操作系统安装光盘放入光驱,打开“控制面板”→“添加或删除程序”→“添加/删除 Windows 组件”,勾选“Internet信息服务(I ...
- phpmyadmin导出数据库为什么是php文件
你的迅雷在作怪,把它卸载了,或者在迅雷的高级设置中,关闭监听浏览器,就不会触发迅雷下载,就没问题了.或者360浏览器的话,把急速模式改为兼容模式
- 方形布局SquareLayout
public class SquareLayout extends RelativeLayout { public SquareLayout(Context context, AttributeSet ...
- 【转】#include,#import,@class的区别
#include #include <> :用于对系统文件的引用,编译器会在系统文件目录下去查找该文件. #include "xx.h ...
- MapReduce UnitTest
通常情况下,我们需要用小数据集来单元测试我们写好的map函数和reduce函数.而一般我们可以使用Mockito框架来模拟OutputCollector对象(Hadoop版本号小于0.20.0)和Co ...
- sqoop 1.4.4-cdh5.1.2快速入门
一.快速入门 (一)下载安装 1.下载并解压 wget http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.4-cdh5.1.2.tar.gz tar - ...
- 1.2 Coin 项目
自2009年起,Coin便是Java 7(和Java 8)中一个开源的子项目.创建Coin项目是为了反映Java语言中的微小变动: 修改Java语言,按不同的修改方式及其复杂度依次分为:类库.工具提供 ...
- HTML5 canvas图像绘制方法与像素操作属性和方法
图像绘制方法 drawImage() 向画布上绘制图像.画布或视频 像素操作属性和方法 width 返回 ImageData ...
- VS2010 IE10 调试时报“未能将脚本调试器附加到计算机”,已经附加了一个进程
解决办法:以管理员身份打开CMD,运行:regsvr32.exe "%ProgramFiles(x86)%\Common Files\Microsoft Shared\VS7Debug\ms ...