动态加载android
‘壹’ 如何动态加载android的so文件,如何压缩apk尺寸
在Android中调用动态库文件(*.so)都是通过jni的方式,而且往往在apk或jar包中调用so文件时,都要将对应so文件打包进apk或jar包,工程目录下图: 以上方式的存在的问题: 1、缺少灵活性比较类似静态加载了(不是静态加载),能加载的so文件绑定死了; 2、但so文件很多或很大时,会导致对应的apk和jar包很大; 3、不能动态的对so文件更新; Android中加载so文件的提供的API: void System.load(String pathName); 说明: 1、pathName:文件名+文件路劲; 2、该方法调用成功后so文件中的导出函数都将插入的系统提供的一个映射表(类型Map); 看到以上对System.load(String pathName);的函数说明可定有人会想到将so文件放到一个指定的目录然后再通过参数pathName直接引用该目录的路劲和对应的so文件问题不就解决了吗? 这里有个问题被忽略了,那就是System.load只能加载两个目录路劲下的so文件: 1、/system/lib ; 2、安装包的路劲,即:/data/data/<packagename>/… 而且这两个路劲又是有权限保护的不能直接访问; 问题解决方法: 先从网络下载so文件到手机目录(如:/test/device/test.so) –> 将test.so加载到内存(ByteArrayOutputStream) –> 然后保存到对用安装包目录; 具体代码如下: try { String localPath = Environment.getExternalStorageDirectory() + path; Log.v(TAG, "LazyBandingLib localPath:" + localPath); String[] tokens = mPatterns.split(path); if (null == tokens tokens.length <= 0 tokens[tokens.length - 1] == "") { Log.v(TAG, "非法的文件路径!"); return -3; } // 开辟一个输入流 File inFile = new File(localPath); // 判断需加载的文件是否存在 if (!inFile.exists()) { // 下载远程驱动文件 Log.v(TAG, inFile.getAbsolutePath() + " is not fond!"); return 1; } FileInputStream fis = new FileInputStream(inFile); File dir = context.getDir("libs", Context.MODE_PRIVATE); // 获取驱动文件输出流 File soFile = new File(dir, tokens[tokens.length - 1]); if (!soFile.exists()) { Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists"); FileOutputStream fos = new FileOutputStream(soFile); Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:" + tokens[tokens.length - 1]); // 字节数组输出流,写入到内存中(ram) ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while ((len = fis.read(buffer)) != -1) { baos.write(buffer, 0, len); } // 从内存到写入到具体文件 fos.write(baos.toByteArray()); // 关闭文件流 baos.close(); fos.close(); } fis.close(); Log.v(TAG, "### System.load start"); // 加载外设驱动 System.load(soFile.getAbsolutePath()); Log.v(TAG, "### System.load End"); return 0; } catch (Exception e) { Log.v(TAG, "Exception " + e.getMessage()); e.printStackTrace(); return -1; }
‘贰’ android 下如何动态加载触摸屏驱动
TP驱动实现
1 修改ProjectConfig.mk
修改mediatek\config\prj\ProjectConfig.mk下的CUSTOM_KERNEL_TOUCHPANEL
其值由GT818B改为msg2133
2 增加ms2133驱动文件夹
根据TP厂家提供的驱动,我们在\mediatek\custom\common\kernel\touchpanel增加msg2133触摸屏驱动文件夹msg2133,并做下面一些简单修改正常使用。
(1) Msg2133接口的初始化
1) CHIP_EN片选使能引脚
mt_set_gpio_mode(GPIO_CTP_MSG2133_EN_PIN,GPIO_CTP_MSG2133_EN_PIN_M_GPIO);
mt_set_gpio_dir(GPIO_CTP_MSG2133_EN_PIN,GPIO_DIR_OUT);
mt_set_gpio_out(GPIO_CTP_MSG2133_EN_PIN,GPIO_OUT_ONE);</span>
msg2133芯片使能引脚配置为GPIO模式、输出高电平使能。
2) INT中断引脚
mt_set_gpio_mode(GPIO_CTP_MSG2133_EINT_PIN,GPIO_CTP_MSG2133_EINT_PIN_M_EINT);
mt_set_gpio_dir(GPIO_CTP_MSG2133_EINT_PIN,GPIO_DIR_IN);
mt_set_gpio_pull_enable(GPIO_CTP_MSG2133_EINT_PIN,GPIO_PULL_ENABLE);
mt_set_gpio_pull_select(GPIO_CTP_MSG2133_EINT_PIN,GPIO_PULL_UP);</span>
配置为中断模式、输入、使能上下拉功能和设置为上拉。
(2) IIC地址
Msg2133的iic读写地址,我从数据手册上没有找到是如何确定这两个地址的,驱动厂家在驱动代码中提供,如果想要具体是怎么确定的,可咨询厂家。
#defineFW_ADDR_MSG21XX (0xC4>>1)
#defineFW_ADDR_MSG21XX_TP (0x4C>>1)//write,0x26
#defineFW_UPDATE_ADDR_MSG21XX (0x92>>1)//read,0x49</span>
(3) 增加TP的虚拟按键(virtual key)
要在TP上增加虚拟按键,需要在tp对应的头文件添加下面的设置:
1) 定义TPD_HAVE_BUTTON
2) 定义TPD_BUTTON_HEIGHT、TPD_KEY_COUNT、TPD_KEYS和TPD_KEYS_DIM,分别用于定义button被识别的纵向坐标、虚拟按键个数、对应的功能键和每个功能键的坐标
#defineTPD_HAVE_BUTTON
#defineTPD_BUTTON_HEIGHT 800
#defineTPD_KEY_COUNT 4
#defineTPD_KEYS { KEY_BACK, KEY_SEARCH,KEY_MENU, KEY_HOMEPAGE }
#define TPD_KEYS_DIM {{200,900,10,10},{260,900,10,10},{40,900,10,10},{120,900,10,10}}</span>
其中,{200,900,10,10}对应了KEY_BACK的坐标, (200,900)是该key center的坐标,10是该键的宽度,10是该键的高度。
3) 根据显示屏分辨率修改相关的宏定义
#defineTPD_RES_X 480 // (320)
#defineTPD_RES_Y 800 //(480)</span>
把常用的实体按键(导航按键)映射到触屏区域的快捷方式,不强制要求一定要有物理按键来支持用户操作,这对开发全触摸屏的产品非常有利。
‘叁’ android 怎么动态加载jar
核心类 1.1 DexClassLoader类 可以加载jar/apk/dex,可以从SD卡中加载为安装的apk。 1.2 PathClassLoader类 只能加载已经安装到Android系统中的apk文件。 一、正文 1.1 类似于eclipse的插件化实现, 首先定义好接口, 用户实现接口功能后即可通过动态加载的方式载入jar文件, 以实现具体功能。 注意 , 这里的jar包需要经过android dx工具的处理 , 否则不能使用。
‘肆’ Android怎样动态加载代码技术
在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码。 实现这个任务的一般方法是:// 加载类clsContext pluginContext = mainContext.createPackageContext(PLUGIN_PKG, Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);ClassLoader loader = pluginContext.getClassLoader();Class<?> cls = loader.loadClass(CLASS_NAME);// 通过反射技术,调用cls中的方法,下面是一个示例,实际代码因情况而定Object obj = cls.newInstance();Method method = cls.getDeclaredMethod("someMethod");method.invoke(obj); 但是,这个方法在Android 4.1及之后的系统中存在一些问题:对于收费应用,Google Play会将其安装在一个加密目录之下(具体就是/data/app-asec),而不是一个普通目录之下(具体就是/data/app);安装在加密目录中的应用,我们是无法使用上述方法来加载并执行代码的;而实际情况是,我们经常就是依靠插件应用来收费的。 解决上述问题的一个方案是:将插件的二进制代码拷贝到SD卡中,主程序从SD卡中加载并执行其代码。 实现这个任务的具体方法是:Class<?> cls = null;try { // 尝试第一种方法 cls = loadClass1(mainContext, pkg, entryCls);} catch (Exception e) { // 尝试第二种方法 cls = loadClass2(mainContext, pkg, entryCls);}// 示例代码Object obj = cls.newInstance();Method method = cls.getDeclaredMethod("someMethod");method.invoke(obj);// 第一种加载方法private Class<?> loadClass1(Context mainContext, String pkg, String entryCls) throws Exception { Context pluginContext = mainContext.createPackageContext(pkg, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); ClassLoader loader = pluginContext.getClassLoader(); return loader.loadClass(entryCls); }//
‘伍’ 如何在Android开发中动态加载的list列表数据
Android中加载list列表数据主要是通过Adapter实现,可用显示列表的控件如下:
Listview
GridView
ExpandListview
显示具体的数据需要通过Adapter实现,Android目前有4种Adapter:
ArrayAdapter
SimpleAdapter
SimpleCursorAdapter
BaseAdapter ( 自定义Adapter)
具体操作步骤 ( 以自定义Adapter为例):
在xml中定义Listview布局
在代码中通过ID找到Listview控件
构建Adapter对象,新建一个类继承自BaseAdapter,重写它的四个方法,具体如下代码
构造好适配器后设置Listview的adapter对象为新建的适配器,界面即可显示数据
在数据变动的地方,只需要调用adapter的notifyDataSetChanged方法即可刷新界面
java">packagecom.beryl.gougou;
importandroid.content.Context;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.BaseAdapter;
importjava.util.List;
/**
*Createdbyyton16/11/14.
*/
{
privateList<String>datalist;
privateLayoutInflaterinflater;
publicMyAdapter(Contextcontext,List<String>datalist){
this.datalist=datalist;
inflater=LayoutInflater.from(context);
}
@Override
publicintgetCount(){
returndatalist.size();
}
@Override
publicObjectgetItem(intposition){
returndatalist.get(position);
}
@Override
publiclonggetItemId(intposition){
returnposition;
}
@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
//此处参考网上的view缓存机制,示例demo不多说明
returnnull;
}
}
‘陆’ Android动态加载架包
先确认一下作为第三方库引用的项目有没有问题,然后再看打成架包是否正确,最后确认导入新项目是否正确。
‘柒’ android动态加载布局更耗费资源吗
不会的。动态加载其实是一种优化。很多时候我们都会在布局文件中加入一些不常使用的控件,但是我们又真的很少使用它们,但是它们在进行初始化的时候,一样会消耗我们的系统资源,因此我们应该考虑通过ViewStub来优化他,只在真正需要的时候使用它。
有时候,你的布局中会有一些比较复杂但是又很少用到的控件。不管他是消息详情,进度条还是未完成的提示信息,你都可以直到真正需要的时候再加载他们,以降低你的内存消耗,提升渲染效率。
‘捌’ Android动态加载调用方法时方法的参数里面带有接口,如何获取接口的回调
在Android中到处可见接口回调机制,尤其是UI事件处理方面,本文给大家介绍android接口回调机制,涉及到android接口回调相关知识,对本文感兴趣的朋友可以参考下本篇文章
在使用接口回调的时候发现了一个经常犯的错误,就是回调函数里面的实现有可能是用多线程或者是异步任务去做的,这就会导致我们期望函数回调完毕去返回一个主函数的结果,实际发现是行不通的,因为如果回调是多线程的话你是无法和主函数同步的,也就是返回的数据是错误的,这是非常隐秘的一个错误。那有什么好的方法去实现数据的线性传递呢?先介绍下回调机制原理。
回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
开发中,接口回调是我们经常用到的。
接口回调的意思即,注册之后并不立马执行,而在某个时机触发执行。
举个例子:
A有一个问题不会,他去问B,B暂时解决不出来,B说,等我(B)解决了再告诉你(A)此时A可以继续先做别的事情。
那么就只有当B解决完问题后告诉A问题解决了,A才可以能解决这个问题。
代码中比如最常用的:
一个Activity中给按钮一个接口回调方法,只有用户点击了这个按钮,告诉按钮被点击了,才会执行按钮接口回调的方法
‘玖’ android的动态加载和静态加载的区别
两者区别:
一,静态库的使用需要:
1
包含一个对应的头文件告知编译器lib文件里面的具体内容
2
设置lib文件允许编译器去查找已经编译好的二进制代码
二,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库
三,依赖性:
静态链接表示静态性,在编译链接之后,
lib库中需要的资源已经在可执行程序中了,
也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供
需要的
动态库,有依赖性,
运行时候没有找到库就不能运行了
四,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
五:
首先纠正所谓“静态连接就是把需要的库函数放进你的exe之中”的说法。在真实世界中,有三个概念:Use
static
libary,
static
linked
DLL,
dynamic
linked
DLL.
多数人混淆了static
libary
和
static
linked
DLL的概念,当然他们有似是而非的“相似之处”,比如都用到.lib,下面具体说明。
使用静态库(Use
static
libary)是把.lib和其他.obj一起build在目标文件中,目标文件可以是.exe,也可以是.dll或.oxc等。一般情况下,可以根本就没有“对应的”.dll
文件,如C
Run
Time(CRT)库。一个例子就是,写一个main(){},build出来并不是只有几个字节,当然有人会说那还有exe文件头呢?是,即使加上文件头的尺寸,build出的执行文件仍然“莫名的大”。实际上那多出来的部分就是CRT静态库。姑且可以把静态库.lib理解成外部程序的obj文件比较合理,它包含了函数的实现。
‘拾’ android中怎么动态的加载一个布局
由于前段时间项目需要,需要在一个页面上加载根据不同的按钮加载不同的布局页面,当时想到用 tabhot 。不过美工提供的界面图完全用不上tabhot ,所以想到了动态加载的方法来解决这一需求。在这里我整理了一下,写了一个 DEMO 希望大家以后少走点弯路。
首先,我们先把界面的框架图画出来,示意图如下: