手记

so文件!有坑!注意!!!

原文链接:http://www.apkbus.com/blog-561682-62706.html

写此文的目的在于最近发现了不同平台下的so文件存在着不同的坑,特别是百度地图的so文件!

 

关于so动态链接库文件的坑,这里有几篇不错的文章,在这里推荐下!

so文件的长年大坑剖析:

https://zhuanlan.zhihu.com/p/21359984

 

极光平台与百度地图平台不会互斥的方法:

http://blog.csdn.net/wuqilianga/article/details/51509853

 

armeabi-v7a armeabi arm64-v8a 三个主要芯片平台的区别:

http://blog.csdn.net/mao520741111/article/details/50328669

 

安卓动态加载so文件方法:

http://www.jianshu.com/p/9609e1fb8756

http://www.cnblogs.com/sevenyuan/p/4202834.html

http://baladuu.com/2016/09/13/20160913/

===========================Start========================================

这里简单的做几个总结(主要以百度地图,百度导航、百度定位、极光,bugly,mob短信推送):

1.关于so文件,我们一般第一想到的就是要放 armeabi-v7a armeabi arm64-v8a这三个平台,因为这三个平台基本上支持了百分80的安卓主流机型,而只有intel、联发科等早期芯片才会出现x86架构!

2.而 mips、mips64基本上已被淘汰,可以不计入范围!

3.由于百度平台的动态链接库文件开始做统一平台,因此导致了它不再区分不同芯片(armeabi-v7a armeabi arm64-v8a等),主要代表有百度地图,百度导航,以及百度定位!

这会带来一个什么问题?

显而易见,肯定是与其它平台的库文件不兼容咯!

那我们应该怎么解决呢?

  • .以eclipse平台为例!

 我们先从库文件的目录入手,如下图所示,为现如今的库文件存放方法

这是目前集成了百度地图,百度导航,百度定位,极光推送,mob短信推送,以及腾讯bugly的so文件存放

其中百度so文件就占了18个之多(红框标注),可见百度地图的so文件是多么繁杂?

  • 这么放有什么问题?

我们可以联想的到,极光平台只放了一个armeabi,这是对老型号芯片平台,缺少浮点数计算的手机所设计的,那么当今大多数手机都是高通,联发科,大多数芯片是支持浮点计算的,那么就必须我们放armeabi-v7a平台吗?  

不!so文件在安卓平台里有个兼容趋势,即64位兼容32位,32位又可以横向兼容,只有少部分比较特别的机型会不支持横向兼容,而一半如果支持armeabi-v7a的就一定可以支持armeabi!

 

但阿杰发现,在极光的so文件无论放了几个平台,也无法适应努比亚z11mini机型, 这在其它手机型号上是无法看到的现象!即便我用了动态加载so文件的方法,还是不行,然而其余的so文件却可以!所以这有可能是极光自己的坑!


  • 如果有些机型无法横向兼容,那该怎么办?


用动态加载so文件方法啊,不能兼容是因为,so文件没被找到,它找到了 armeabi-v7a就不再继续找了,那你就动态的去找到这个so文件去加载,至于怎么动态加载,以上文章已有详细的方法,
基本上步骤就是,

把so文件存在本地或者app内部资源文件夹、

然后把so文件加载到应用内部的lib目录、

再用system.load()的方法去load那个文件!

[代码]java代码:

?


package com.intrecar.utils; import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream; import android.content.Context; public class SoFileInitUtil {     public void initAssetsFile(Context mContext) {         boolean needCopy = false;        String libType = "armeabi";// 要加在的库文件平台,32位还是64位         // 先判断CPU类型来加载so文件        // if        // (CheckCPUType.getArchType(mContext).equals(CheckCPUType.CPU_ARCHITECTURE_TYPE_32))        // {        // LogUtils.PrintJay5("cpu is 32---");        // libType = "armeabi";        // } else if        // (CheckCPUType.getArchType(mContext).equals(CheckCPUType.CPU_ARCHITECTURE_TYPE_64))        // {        // LogUtils.PrintJay5("cpu is 64---");        // libType = "arm64-v8a";        // }        // if (CheckCPUType.isLibc64()) {        // libType = "arm64-v8a";        // } else {        // libType = "armeabi";        // }        // 创建data/data目录        File soFile = mContext.getDir("libs", Context.MODE_PRIVATE);        String soPath = soFile.toString() + "/";         // 遍历assets目录下所有的文件,是否在data/data目录下都已经存在        try {            String[] fileNames = mContext.getAssets().list(libType);            for (int i = 0; fileNames != null && i < fileNames.length; i++) {                if (!isFileExit(soPath + fileNames[i])) {                    needCopy = true;                    break;                }            }         } catch (IOException e) {            e.printStackTrace();        }         if (needCopy) {            copyFilesFassets(mContext, libType, soPath);        }    }     private void copyFilesFassets(Context context, String oldPath, String newPath) {        try {             // 获取assets目录下的所有文件及目录名            String fileNames[] = context.getAssets().list(oldPath);             // 如果是目录名,则将重复调用方法递归地将所有文件            if (fileNames.length > 0) {                File file = new File(newPath);                file.mkdirs();                for (String fileName : fileNames) {                    copyFilesFassets(context, oldPath + "/" + fileName, newPath + "/" + fileName);                }            }            // 如果是文件,则循环从输入流读取字节写入            else {                if (oldPath.contains(".so")) {                    InputStream is = context.getAssets().open(oldPath);                    FileOutputStream fos = new FileOutputStream(new File(newPath));                    byte[] buffer = new byte[1024];                    int byteCount = 0;                    while ((byteCount = is.read(buffer)) != -1) {                        fos.write(buffer, 0, byteCount);                    }                    fos.flush();                    is.close();                    fos.close();                }            }        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }     private boolean isFileExit(String path) {        if (path == null) {            return false;        } else {            try {                File f = new File(path);                if (f.exists()) {                    return true;                }            } catch (Exception e) {                e.printStackTrace();            }             return false;        }    }     public void InitSo(Context mContext, String soFilaName) {        File soFile = mContext.getDir("libs", Context.MODE_PRIVATE);        String soPath = soFile.toString() + "/";        if (new File(soPath + soFilaName).exists()) {            LogUtils.PrintJay5("load  so--" + soPath + soFilaName);            System.load(soPath + soFilaName);        }    }     public void InitBaiduNaviSo(Context mContext) {        // InitSo(mContext, "libapp_BaiduNaviApplib.so");         // InitSo(mContext, "libaudiomessage-jni.so");        // InitSo(mContext, "libbd_etts.so");        // InitSo(mContext, "libbds.so");        // InitSo(mContext, "libBDSpeechDecoder_V1.so");        // InitSo(mContext, "libbdtts.so");        // InitSo(mContext, "libcurl.so");        // InitSo(mContext, "libetts_domain_data_builder.so");        // InitSo(mContext, "libgnustl_shared.so");        // InitSo(mContext, "libapp_BaiduVIlib.so");        // InitSo(mContext, "liblocnaviSDK.so");    } }
  • 如果是AS平台,so文件我们要怎么设置?

在AS平台下的so文件,放置平台问题相对于安卓会比较简单,因为它可以指定程序要去加载哪个平台的so文件,而不至于芯片自动索引会出现索引so文件出错的现象;



==========================End=========================



0人推荐
随时随地看视频
慕课网APP