1、背景java
在開發Android應用程序的實現,有時候須要引入第三方so lib庫,但第三方so庫比較大,例如開源第三方播放組件ffmpeg庫, 若是直接打包的apk包裏面, 整個應用程序會大不少.通過查閱資料和實驗,發現經過遠程下載so文件,而後再動態註冊so文件時可行的。主要須要解決下載so文件存放位置以及文件讀寫權限問題。android
2、主要思路網絡
一、首先把so放到網絡上面,好比測試放到:http://codestudy.sinaapp.com/lib/test.soapp
二、應用啓動時,啓動異步線程下載so文件,並寫入到/data/data/packageName/app_libs目錄下面異步
三、調用System.load 註冊so文件。因路徑必須有執行權限,咱們不能加載SD卡上的so,但能夠經過調用context.getDir("libs", Context.MODE_PRIVATE)把so文件寫入到應用程序的私有目錄/data/data/packageName/app_libs。ide
3、代碼實現測試
一、網絡下載so文件,並寫入到應用程序的私有目錄/data/data/PackageName/app_libsurl
/** * 下載文件到/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(); } } } }
二、調用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();
4、須要解決的問題code
一、so文件下載以及註冊時機。測試發現libffmpeg.so 8M的文件單線程下載須要10-13s左右
二、so下載失敗或者註冊失敗該怎麼處理。例如so播放組件是否嘗試採用android系統原生MediaPlayer進行播放
三、當初次so尚未下載完註冊成功時,進入播放頁面時,須要友好提示用戶,好比loading 視頻正在加載等等
四、無網絡狀況等等狀況
5、說明
上面的demo通過3(2.3/4.2/4.4)實際機型測試能夠正常使用,而後根據第四點列舉問題完善如下,便可使用。