一、背景

在开发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

/**
* 下载文件到/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文件

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 so lib库远程http下载和动态注册的更多相关文章

  1. android多lib库工程的自动批量构建--准备

    打包这个活儿吧,本来没什么技术含量,千篇一律的更改渠道名称,然后编译,签名即可.但是如果发布渠道比较多的话,这种重复工作让人烦不胜烦.我们的应用发布渠道有30多个,若是手工打包,基本不用做其他的事情了 ...

  2. android多lib库工程的自动批量构建--编写ant脚本

    基本配置--build.properties 首先编写基本配置build.properties ,主要配置如下: android sdk所在目录 编译项目所使用的项目版本 Jdk所在目录 以及签名时, ...

  3. Android 动态注册JNI函数

    1.JNI函数注册方式 在Android开发中,由于种种原因我们需要调用C/C++代码,在这个时候我们就需要使用jni了, jni在使用时要对定义的函数进行注册,这样java才能通过native关键字 ...

  4. Android只能动态注册的广播Action

    只能动态注册的广播(部分): android.intent.action.SCREEN_ON android.intent.action.SCREEN_OFF android.intent.actio ...

  5. 解决android studio引用远程仓库下载慢(转)

    解决android studio引用远程仓库下载慢(JCenter下载慢) 第一种方法 使用开源中国的maven库 阿里云的(速度飞快):http://maven.aliyun.com/nexus/c ...

  6. 如何把一个android工程作为另外一个android工程的lib库

    http://zhidao.baidu.com/question/626166873330652844 一个工程包含另一个工程.相当于一个jar包的引用.但又不是jar包反而像个package 在网上 ...

  7. android studio 引用远程仓库下载慢(JCenter下载慢)的办法

    https://blog.csdn.net/linglingchenchen/article/details/62236723 解决android studio引用远程仓库下载慢(JCenter下载慢 ...

  8. android 如何添加第3方lib库到kernel中

    注意:只能将lib库放在kernel编译到的地方,如下: alps/kernel/ alps/mediatek/custom/common/kernel/ alps/mediatek/custom/$ ...

  9. Android Studio提交库至Bintray jCenter从入门到放弃

    文:http://blog.csdn.net/sk719887916/article/details/52473914 作者:Tamic 详细文章请看:[Gradle系列]Gradle发布module ...

随机推荐

  1. MetaWeblog 同时管理51cto,csdn,sina,163,oschina,cnblogs等博客

    我们技术人一般都会有自己的一个博客,用于记录一些技术笔记,也期望自己的笔记文章可以让更多人知道. 如何让更多人知道自己的博客? 搜索引擎收录,用户通过关键词搜索可能会进入 内容运营,但是一般技术人为了 ...

  2. nRF51822之app_button控制uart的开启和关闭

    为什么要使用app_button来控制uart的开启和关闭 还是先上datesheet中uart开启的时候需要HFCLK,需要消耗大量大电流.所以在我们需要的时候需要通过io来通知nrf51822开启 ...

  3. python join

    # 对序列进行操作 ' '.join(['hello','good','boy','doiido']) hello:good:boy:doiido # 对字符串进行操作 ':'.join(" ...

  4. 轮询、select、 epoll

    网卡设备对应一个中断号, 当网卡收到网络端的消息的时候会向CPU发起中断请求, 然后CPU处理该请求. 通过驱动程序 进而操作系统得到通知, 系统然后通知epoll, epoll通知用户代码.  一. ...

  5. 转:Windows Socket五种I/O模型

    原文转自:  Windows Socket五种I/O模型 Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模 ...

  6. 关于Bitcode的探索

    Bitcode概述         Bitcode is an intermediate representation of a compiled program. Apps you upload t ...

  7. 关于Xib 需要注意的地方

    当你需要写一个繁琐的界面但是又是静态页面时,很可能会用到xib [特例:创建继承于UIView的文件时,不带自动生成xib的勾选项,需要开发人员手动new一个同名的xib文件,在该xib文件右侧的cl ...

  8. Java学习-010-创建文件夹源代码

    此文源码主要为应用 Java 创建文件目录的源码.若有不足之处,敬请大神指正,不胜感激! 创建文件夹源代码如下所示: /** * @function 文件操作:创建文件夹.若文件夹不存在,则级联创建文 ...

  9. POJ1326问题描述

    Description Mileage program of ACM (Airline of Charming Merlion) is really nice for the travelers fl ...

  10. ps、grep和kill联合使用杀掉进程(转)

    例如要杀掉hello这个进程,使用下面这个命令就能直接实现.   ps -ef |grep hello |awk '{print $2}'|xargs kill -9 这里是输出ps -ef |gre ...