android gradle build resources.arsc文件未压缩问题解决

原创 2015年11月18日 13:23:24

随着google如火如荼的推出android studio IDE和gradle buld工具,很多公司要对build系统做从ant到gradle的升级,不幸的是我被分配负责该任务。


发现一个问题,gralde编译后的apk比ant要大大约1M左右,对于老大之前严格要求控制apk在10M左右的需求,只能说造化弄人。压缩包打开发现gradle build之后的apk resources.arsc没有压缩,导致apk增大很多。

于是乎,设置resource shrink 为true,结果如下:


图一:ant打包之后的详单:


图二:gradle shrinkResources false的详单


图三:gradle shrinkResources true的详单


结果发现:ant打包后的resources.arsc,从1.1M压缩到267K,还是比较狠的。

至于是否shrinkResources,没有什么效果

aapt l -v Client-release-unsigned-ant.apk ,查看apk明细:

发现ant包和gradle包的差异:

 Length   Method    Size  Ratio   Offset      Date  Time  CRC-32    Name
1158688  Deflate  273481  76%   9835381  11-17-15 15:18  04aecb3e  resources.arsc -------- <span style="color:#ff0000;">ant build apk</span>
1158508  Stored  1158508   0%   2899860  11-17-15 15:21  9222ccf9  resources.arsc   -------- <span style="color:#ff0000;">gradle build apk</span>

ant build resources.arsc是deflate method,而gradle build 的是stored method,而且size相差很大。

于是乎,寻找gradle设置deflate模式的配置开关,未果,似乎是硬编码方式,不支持dsl配置,只能从最后的apk包下手,对resources做二次压缩。下面代码:

apply plugin: 'android'


dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile project(':MyProj')
}


android {
    compileSdkVersion 19
    buildToolsVersion '21.1.2'


    lintOptions {
        abortOnError false
    }


    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }


        // Move the tests to tests/java, tests/res, etc...
        instrumentTest.setRoot('tests')


        // Move the build types to build-types/<type>
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        // This moves them out of them default location under src/<type>/... which would
        // conflict with src/ being used by the main source set.
        // Adding new build types or product flavors should be accompanied
        // by a similar customization.
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }


    defaultConfig {
        multiDexEnabled true
    }


    dexOptions {
        javaMaxHeapSize "2g"
        jumboMode true
    }


    buildTypes {
        debug {
            minifyEnabled false
            proguardFile('proguard.cfg')
        }
        release {
            minifyEnabled true
            proguardFile('proguard.cfg')
        }
    }


    packagingOptions {
        exclude('META-INF/DEPENDENCIES')
        exclude('META-INF/NOTICE')
        exclude('META-INF/LICENSE')
    }


    lintOptions {
        // Or, if you prefer, you can continue to check for errors in release builds,
        checkReleaseBuilds false
        // but continue the build even when errors are found:
        abortOnError false
    }
}


import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream


// 打包过程中很多手工zip过程:
// 1,为了压缩resources.arsc文件而对标准产出包重新压缩
// 2,以及各子apk的纯手打apk包
// 但对于音频等文件,压缩会导致资源加载报异常
// 重新打包方法,使用STORED过滤掉不应该压缩的文件们
// 后缀名列表来自于android源码
def repackApk(originApk, targetApk){
    def noCompressExt = [".jpg", ".jpeg", ".png", ".gif",
                         ".wav", ".mp2", ".mp3", ".ogg", ".aac",
                         ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
                         ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
                         ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
                         ".amr", ".awb", ".wma", ".wmv"]


    ZipFile zipFile = new ZipFile(originApk)
    ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(targetApk)))
    zipFile.entries().each{ entryIn ->
        if(entryIn.directory){
            println "${entryIn.name} is a directory"
        }
        else{
            def entryOut = new ZipEntry(entryIn.name)
            def dotPos = entryIn.name.lastIndexOf('.')
            def ext = (dotPos >= 0) ? entryIn.name.substring(dotPos) : ""
            def isRes = entryIn.name.startsWith('res/')
            if(isRes && ext in noCompressExt){
                entryOut.method = ZipEntry.STORED
                entryOut.size = entryIn.size
                entryOut.compressedSize = entryIn.size
                entryOut.crc = entryIn.crc
            }
            else{
                entryOut.method = ZipEntry.DEFLATED
            }
            zos.putNextEntry(entryOut)
            zos << zipFile.getInputStream(entryIn)
            zos.closeEntry()
        }
    }
    zos.finish()
    zos.close()
    zipFile.close()
}


task repack(){


	doLast{
		print "root dir is : $rootDir"
		println "release打包之后,重新压缩一遍,以压缩resources.arsc"


		def oldApkFile = file("$rootDir/projectPath/build/outputs/apk/Client-release-unsigned.apk")


		assert oldApkFile != null : "没有找到release包!"


		def newApkFile = new File("$rootDir/projectPath/build/outputs/apk/Client-release-unsigned-repack.apk")
		print oldApkFile.absolutePath
		print newApkFile.absolutePath
		//重新打包
		repackApk(oldApkFile.absolutePath, newApkFile.absolutePath)


		assert newApkFile.exists() : "没有找到重新压缩的release包!"
	}
}

其实也可以通过java或者python程序终结对apk进行二次处理达到效果,但是不如gradle处理的自然。


done, perfect !

ios截屏后发现图片是空白问题

ios截屏代码: UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);     UIImage *img = UIG...

ios 合并图片显示

代码如下: - (UIImage *)addTwoImageToOne:(UIImage *)oneImg                      twoImage:(UIImage *)tw...
  • zerocnd
  • zerocnd
  • 2012年12月29日 17:22
  • 2130

Android Studio更新后Gradle Build/Refresh失败的问题解决方案

Gradle介绍:Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种...

Android resources.arsc资源文件防护原理分析

主要防止apktool反编译resources.acrs资源文件,从而对资源文件进行保护 resources.acrs资源文件格式主要引用老罗的博客内容Resources.arsc文件格式是由一系列...
  • pwelyn
  • pwelyn
  • 2015年11月20日 12:25
  • 1424

AndroidStudio升级2.3.1gradle无法升级导致build卡主问题解决

那首先要明白一个问题,就是墙和VPN,这个不懂得,自己找度娘问去。 最悲伤的时候就是配置都对了没挂VPN下不动。 无论你是2.2还是升级2.3如果失败了,最好自己去配置下。下面给出...

简易汉化Apk中的resources.arsc文件

  • 2017年12月04日 22:36
  • 377KB
  • 下载

记一次resources.arsc文件hex修改原理分析

需要用到的工具 aapt ShakaApktool或apktool Hex编辑器 文本编辑器 作者:越狱(pwelyn) 样本就不提供了,自己随便找个apk联手吧 感谢@随意 提供样...
  • pwelyn
  • pwelyn
  • 2015年09月01日 16:19
  • 820

解决Android Studio新建或导入工程总是重新下载gradle,以至于新建初始化build缓慢的问题

转载请声明出处:http://blog.csdn.net/u013067166/article/details/52155380         导读:Android Studio从0.9发展...

Android Studio更新2.3后出现Refreshing gradle project.......卡死问题解决方法

最近网速比较好所以决定更新一下Android Studio,本来是AS2.0版本进入的时候有一个update2.3的选项,我点了一下update没什么卵用0.0,被墙给挡住了,只好自己上网站上自己下一...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android gradle build resources.arsc文件未压缩问题解决
举报原因:
原因补充:

(最多只允许输入30个字)