Android开发AndroidAndroid开发

Android动态加载-腾讯SDK定位。动态加载.so文件

2016-09-29  本文已影响1269人  b496178cdc84

最近有个新需求,要求进行定位。但是项目本身用的是动态加载框架,在只更新插件的情况下,做到定位需求。先说说Android定位,由于自带的定位不稳定,我自己测试的时候返现在室内基本都是定位不到,再加上,谷歌服务基本都被大部分厂商砍掉。所以为了准确性和稳定性,暂时只能用第三方应用。
BAT的三个地图SDK,百度和阿里的由于要在AndroidMainfest文件中注入一个定位服务,这就意味着要更新动态加载框架,所以这2个肯定是不能用的,所以选择了腾讯的,精简,size小,实现方便。最重要的是不需要再AndroidMainfest注入服务。但是文档中说要注入一个meta-data 用来写入ID,我的做法是直接改了他的jar包,然后写死id,这样就不需要在AndroidMainfest中注入了。
OK,下一步就是导入腾讯SDK提供的.so文件,

正常方法,在main下建立jniLibs,然后安装的时候,会把jniLibs里面的拷贝到data/app/packageName/libs下。然后运行时候就会根据CPU的类型,到这个目录去加载最匹配的.so文件。

然而,我们是动态加载,并不能使用这种方法,因为我们插件打包的时候并不能指定在data/app/package/下保存.so文件。

所以,一开始有个想法,动态加载.so文件,就是在运行时候,把.so放在assets里面,然后拷贝到data/app/context.getpackage/libs里面,然后加载so,然而尝试了一番,发现并不行,因为data/app/packageName/libs 这个目录只有可读权限。并不能写入。

换方法,了解到,System.load 和 System.loadLibrary 可以动态加载.so,先是尝试了system.loadlibry, 这种不行因为这个方法,固定的加载目录是在data/app/packageName/libs,所以不能使用,于是使用system.load() 指定绝对路径,OK可以了。有一点需要注意的是,system.load方法只能加载在data/app/packageName/libs下的 或者 在私有目录(data/data/package/...)下的,所以,同样采用在assets中存放.so 运行中动态拷贝。
上代码

/** * 初始化location,主要做一些拷贝.so的操作 */
  public void initLoacation() {
    LogUtils.d(Build.CPU_ABI);
    File soFile = null;  
  if (DeviceInfo.getDeviceCpu().equals("armeabi-v7a")) {   
     soFile = new File(mContext.getFilesDir(), "libtencentloc-v7a.so");    
}else if (DeviceInfo.getDeviceCpu().equals("armeabi")) {   
     soFile = new File(mContext.getFilesDir(), "libtencentloc-v7a.so"); 
   } else if (DeviceInfo.getDeviceCpu().equals("x86")) {   
    soFile = new File(mContext.getFilesDir(), "libtencentloc-x86.so"); 
   }  if (soFile.exists()) {  
      System.load(soFile.getAbsolutePath()); 
       startLocation();    
} else { 
       copySoFileToLocal(soFile);    }}

上边就是先判断CPU的架构,然后不同的架构,拷贝不同的.so文件,.So文件我是放在assets目录下

/** * 拷贝.so文件 * * 
@param soFile
 */
private void copySoFileToLocal(final File soFile) {   
 new Thread(new Runnable() { 
       @Override        
     public void run() {           
             try {                
 InputStream inputStream = mContext.getResources().getAssets().open(soFile.getName());                           
 FileOutputStream fos = mContext.openFileOutput(soFile.getName(), Context.MODE_PRIVATE);                
 IOUtils.in2out(inputStream, fos);               
 System.load(soFile.getAbsolutePath());               
 LogUtils.d("had load " + soFile.getAbsolutePath());                
KyxSDKGlobal.runOnMainThread(new Runnable() {                    
@Override                   
 public void run() {   
          startLocation(); }
  }); } catch (IOException e) {  
              e.printStackTrace(); 
               LogUtils.d("error");  
          } }}).start();}

OK,这样就可以把.so加载成功了。然后就可以继续执行腾讯SDK的相关方法

上一篇下一篇

猜你喜欢

热点阅读