一、背景
?
? ?在开发Android应用程序的实现,有时候需要引入第三方so lib库,但第三方so库比较大,例如开源第三方播放组件ffmpeg库, 如果直接打包的apk包里面, 整个应用程序会大很多.经过查阅资料和实验,发现通过远程下载so文件,然后再动态注册so文件时可行的。主要需要解决下载so文件存放位置以及文件读写权限问题。
?
二、主要思路
?
1、首先把so放到网络上面,比如测试放到:http://codestudy.sinaapp.com/lib/test.so
2、应用启动时,启动异步线程下载so文件,并写入到/data/data/packageName/app_libs目录下面
3、调用System.load 注册so文件。因路径必须有执行权限,我们不能加载SD卡上的so,但可以通过调用context.getDir("libs", Context.MODE_PRIVATE)把so文件写入到应用程序的私有目录/data/data/packageName/app_libs。
?
三、代码实现
?
?1、网络下载so文件,并写入到应用程序的私有目录/data/data/PackageName/app_libs
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 | /** ????? * 下载文件到/data/data/PackageName/app_libs下面 ????? * @param context ????? * @param url ????? * @param fileName ????? * @return ????? */ ???? public ?static ?File downloadHttpFileToLib(Context context, String url, String fileName) { ???????? long ?start = System.currentTimeMillis(); ???????? FileOutputStream outStream =? null ; ???????? InputStream is =? null ; ???????? File soFile =? null ; ???????? try ?{ ???????????? HttpClient client =? new ?DefaultHttpClient(); ???????????? HttpGet get =? new ?HttpGet(url); ???????????? HttpResponse response = client.execute(get); ???????????? HttpEntity entity = response.getEntity(); ???????????? File dir = context.getDir( "libs" , Context.MODE_PRIVATE); ???????????? soFile =? new ?File(dir, fileName); ???????????? outStream =? new ?FileOutputStream(soFile); ???????????? is = entity.getContent(); ???????????? if ?(is !=? null ) { ???????????????? byte [] buf =? new ?byte [ 1024 ]; ???????????????? int ?ch = - 1 ; ???????????????? while ?((ch = is.read(buf)) >? 0 ) { ???????????????????? outStream.write(buf,? 0 , ch); ???????????????????? //Log.d(">>>httpDownloadFile:", "download 进行中...."); ???????????????? } ???????????? } ???????????? outStream.flush(); ???????????? long ?end = System.currentTimeMillis(); ???????????? Log.d( ">>>httpDownloadFile cost time:" ,? (end-start)/ 1000 ?+? "s" ); ???????????? Log.d( ">>>httpDownloadFile:" ,? "download success" ); ???????????? return ?soFile; ???????? }? catch ?(IOException e) { ???????????? Log.d( ">>>httpDownloadFile:" ,? "download failed" ?+ e.toString()); ???????????? return ?null ; ???????? }? finally ?{ ???????????? if ?(outStream !=? null ) { ???????????????? try ?{ ???????????????????? outStream.close(); ???????????????? }? catch ?(IOException e) { ???????????????????? e.printStackTrace(); ???????????????? } ???????????? } ???????????? if ?(is !=? null ) { ???????????????? try ?{ ???????????????????? is.close(); ???????????????? }? catch ?(IOException e) { ???????????????????? e.printStackTrace(); ???????????????? } ???????????? } ???????? } ???? } |
?
?2、调用System.load 注册so文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | new ?Thread( new ?Runnable() { ?????? @Override ?????? public ?void ?run() { ?????????? File soFile = FileUtils.downloadHttpFileToLib(getApplicationContext(),? "http://codestudy.sinaapp.com//lib/test.so" ,? "test.so" ); ?????????? if ?(soFile !=? null ) { ???????????? try ?{ ??????????????????? Log.d( ">>>loadAppFile load path:" , soFile.getAbsolutePath()); ??????????????????? System.load(soFile.getAbsolutePath()); ????????????? }? catch ?(Exception e) { ????????????????? Log.e( ">>>loadAppFile load error:" ,? "so load failed:" ?+ e.toString()); ????????????? } ??????????? } ?????? } }).start(); |
四、需要解决的问题
?
1、so文件下载以及注册时机。测试发现libffmpeg.so ?8M的文件单线程下载需要10-13s左右
2、so下载失败或者注册失败该怎么处理。例如so播放组件是否尝试采用android系统原生MediaPlayer进行播放
3、当初次so还没有下载完注册成功时,进入播放页面时,需要友好提示用户,比如loading 视频正在加载等等
4、无网络情况等等情况
五、说明
?
?上面的demo经过3(2.3/4.2/4.4)实际机型测试可以正常使用,然后根据第四点列举问题完善以下,即可使用。
Android KSOAP2调用.net webservice
jQuery教程(8)-DOM树操作之使用反向插入方法
android学习笔记(34)使用AlertDialog创建简单对话框
android学习笔记(33)画廊视图(Gallery)的功能和用法
android navidgation drawer 在导航抽屉中如何改变List选中项的...
?