最近有个新需求,要求进行定位。但是项目本身用的是动态加载框架,在只更新插件的情况下,做到定位需求。先说说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的相关方法
网友评论