U8SDK——打包脚本新思路(jar包级别的渠道SDK接入和配置)
之前有童鞋问我,为什么接好的渠道SDK要在classes.dex级别配置,能否在jar级别配置。否则每次还要在工程中编译生成,然后拷贝bin目录下的classes.dex。而classes.dex文件又包含了所有依赖的jar包和工程本身。导致,如果渠道SDK升级还是需要回到eclipse具体的工程中,替换jar包,然后重新编译生成一个新的classes.dex文件,覆盖到打包脚本中渠道SDK的配置目录下。
我想了一下,觉得这个方式还是有很多优势的,比如
1、可以把具体的SDK接入工程设置为Library模式,不用再生成classes.dex,直接将需要的jar包拷贝到打包脚本的渠道SDK配置目录下即可。
2、避免部分jar包内容重复(之前游戏层和具体的SDK会有重合的部分,因为具体的SDK接入依赖u8sdk抽象层,游戏层也依赖u8sdk抽象层,使得u8sdk抽象层部分重复)
3、SDK升级方便,SDK升级如果不涉及接口的更改,可以直接在打包工具中升级,不用修改具体的SDK接入工程,也不用重新编译生成classes.dex
唯一的不足:打包工具在打包的时候多做了一步,出包时间增加一点点,但是影响不大
那么接下来,我们看看怎么实现
首先我们将需要依赖的jar包,都拷贝到具体的SDK配置目录下的libs目录中,然后具体SDK的接入工程的jar包,放在sdk_config.xml同级目录中
然后,我们在apk_utils.py中,增加一个将jar转换为dex的方法。在拷贝SDK资源之后先将jar包用dx.bat生成一个classes.dex。之后和目前的就都一样了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
def jar2dex(srcDir, dstDir, dextool = "baksmali.jar"): """ compile jar files to dex. """ dexToolPath = file_utils.getFullToolPath("dx.bat") cmd = '"%s" --dex --output="%s" ' % (dexToolPath, dstDir+"/classes.dex") for f in os.listdir(srcDir): if f.endswith(".jar"): cmd = cmd + " " + os.path.join(srcDir, f) for f in os.listdir(os.path.join(srcDir, "libs")): if f.endswith(".jar"): cmd = cmd + " " + os.path.join(srcDir, "libs", f) ret = file_utils.execFormatCmd(cmd) |
之前,apk_utils.py中的copyResource方法中,我们直接将from 拷贝到 to所在的文件夹中。
这里,我们不能直接这么拷贝了。如果from是libs,那么我们需要过滤掉所有的.jar文件。因为我们已经用.jar文件生成了classes.dex了,然后将classes.dex直接反编译之smali目录了,
所以,这里我们干脆过滤掉libs的拷贝,单独写个方法来做Libs的拷贝。将方法中原来这里的逻辑
1 2 3 4 5 6 7 8 9 |
elif child['type'] == 'copy': if child['from'] == None or child['to'] == None: file_utils.printF("The config file is error. copyRes,need from and to attrib.sdk:%s", channel['name']) return 1 copyFrom = file_utils.getFullPath(os.path.join(sdkDir, child['from'])) copyTo = file_utils.getFullPath(os.path.join(decompileDir, child['to'])) copyResToApk(copyFrom, copyTo) |
改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
elif child['type'] == 'copy': if child['from'] == None or child['to'] == None: file_utils.printF("The config file is error. copyRes,need from and to attrib.sdk:%s", channel['name']) return 1 if child['to'] == 'lib': # copy libs ->lib use copyLibs method. here not copy libs. continue copyFrom = file_utils.getFullPath(os.path.join(sdkDir, child['from'])) copyTo = file_utils.getFullPath(os.path.join(decompileDir, child['to'])) copyResToApk(copyFrom, copyTo) |
同时,我们写一个单独拷贝libs的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
def copyLibs(srcDir, dstDir): """ copy shared libraries """ if not os.path.exists(srcDir): return if not os.path.exists(dstDir): os.makedirs(dstDir) for f in os.listdir(srcDir): sourcefile = os.path.join(srcDir, f) targetfile = os.path.join(dstDir, f) if (sourcefile.endswith(".jar")): continue if os.path.isfile(sourcefile): if not os.path.exists(targetfile) or os.path.getsize(targetfile) != os.path.getsize(sourcefile): destfilestream = open(targetfile, 'wb') sourcefilestream = open(sourcefile, 'rb') destfilestream.write(sourcefilestream.read()) destfilestream.close() sourcefilestream.close() if os.path.isdir(sourcefile): copyLibs(sourcefile, targetfile) |
然后,我们在main.py的doPack方法中,在file_utils.copy_files(sdkSourceDir, sdkDestDir)之后调用:
apk_utils.jar2dex(sdkSourceDir, sdkDestDir)
在newPackageName = apk_utils.renamePackageName(decDir, channel[‘suffix’]) 之前调用copyLibs方法:
apk_utils.copyLibs(os.path.join(sdkDestDir, “libs”), os.path.join(decDir, “lib”))
之后,就再也不用每次生成classes.dex文件拷贝到打包工具的配置目录下了,直接将需要依赖的jar包拷贝到SDK配置目录下的libs目录即可。
然后将接入SDK的具体工程作为一个Library,编译生成后,拷贝bin目录下生成的.jar文件到SDK配置目录下即可。
希望童鞋们在使用u8sdk的过程中,有一些好的建议,能够及时反馈给我们哦。我们一起来让u8sdk更加完善和服务大家。
申明:http://www.uustory.com是u8sdk的官方博客,我们致力于分享统一渠道SDK接入的解决方案。任何其他转载请注明出处,谢谢!
本文出自 U8SDK技术博客,转载时请注明出处及相应链接。
本文永久链接: http://www.uustory.com/?p=1629