gradle的几个实用技巧让你爽歪歪

本文章由情随事迁收集编写,转载请说明出处

混淆文件收集技巧

自动备份 mapping 混淆发布后对应的真实代码比对文件

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            if (variant.getBuildType().isMinifyEnabled()) {
                variant.assemble.doLast{
                    copy {
                        from variant.mappingFile
                        into "${projectDir}/mappings"
                        rename { String fileName ->
                            "mapping-${variant.name}-${variant.versionName}_${variant.versionCode}.txt"
                        }
                    }
                }
            }
        }
    }

除此之外还可以切换test目录
将会在项目根目录/mappings/生成文件mapping-release-1.1_2.txt,这样解决了每次发布版本总是需要在build/outputs/release/mapping.txt中找到并移动出来进行备份的问题.
文件自定义字符串混淆的套路

android.applicationVariants.all {
    variant ->
        variant.each() {
            //buildTypeName:debug,app
        println("buildTypeName:" + variant.buildType.name+","+ this.project.name);
    }
        variant.each {myeach->
            //buildTypeName:release,myeach:release
            println("buildTypeName:" + variant.buildType.name+",myeach:"+myeach.name+",dir:"+myeach.outputs);
        }

        variant.outputs.each { output ->
            def fileName = "appname_v${variant.versionName}_release_${variant.flavorName}.apk"
            if (variant.buildType.isDebuggable()) {
                fileName = "appname_v${variant.versionName}_debug_${variant.flavorName}.apk"
            }
            println("fileName:"+fileName);
//            output.outputFile = new File(output.outputFile.parent, fileName)
        }
        variant.outputs.each {}
}

设置编译时间

buildConfigField "long", "BUILD_TIME", System.currentTimeMillis() + "L"

设置这个之后方便查看编译时间,哪怕是开发xposed插件 用这个可以方便查看是否更新生效,根据编译时间来判断.

设置各种目录仿造eclipse目录结构


    //高仿eclipse结构
    sourceSets {
        main {
//            manifest.srcFile 'AndroidManifest.xml'
//            java.srcDirs = ['src']
//            resources.srcDirs = ['src']
//            aidl.srcDirs = ['src']
//            res.srcDirs = ['res']
//            assets.srcDirs = ['assets']

            jniLibs.srcDirs=['libs']
        }
    }

合并support版本

作用:解决第三方sdk无法修改但是不得不使用问题

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")
                    && !requested.name.startsWith("exifinterface")) {
                details.useVersion '24.2.1'
                //不设置24.2.1但是设置到了25就找不到布局,全部不管好像又冲突设置24.2.1 那么 要么冲突 要么       java.lang.NoSuchFieldError: No field notification_template_lines of type
            }
        }
    }
}

优化so库压缩体积排除其他平台可自动兼容

     ndk {
            //APP的build.gradle设置支持的SO库架构

            abiFilters 'armeabi-v7a'
        }

这样的话夜神模拟器和真机测试时没毛病的,体积也节省了不少,QQ也是这样做的哈!
缺点就是开发工具会对于没有所指定的会强制不让运行,但是不这样指定的话,如果极光有5个so,但是自己只有一个armebi-v7a的,没法放开,放开也会崩溃,所以还是得下面得方法。

排除指定文件不打包

packagingOptions {
        exclude "lib/arm64-v8a/libimagepipeline.so"
        exclude "lib/x86/libsmssdk.so"
        exclude "lib/x86_64/libsmssdk.so"
        exclude "lib/mips/libsmssdk.so"
        exclude "lib/mips64/libqssq.so"
    }

只保留armebi-v7a

      packagingOptions {
            exclude "lib/arm64-v8a/**"
            exclude "lib/x86/**"
            exclude "lib/armeabi/**"
            exclude "lib/mips/**"
            exclude "lib/mips64/**"
            exclude "lib/x86_64/**"
        }

这里只是演示排除非 armeabi-v7a 目录的so文件,除了排除so还可以排除资源文件哦!

统一协议标准跳转

      manifestPlaceholders = [
                APP_SCHEME: "xxx", //
        ]

xml对应代码

        <activity
            android:name=".activity.EditUserInfoActivity"

            android:screenOrientation="portrait">

            <intent-filter>
                <action android:name="android.intent.action.VIEW"></action>

                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="android.intent.category.BROWSABLE"></category>

                <data
                    android:host="profile"
                    android:scheme="${APP_SCHEME}"></data>

            </intent-filter>
        </activity>

java对应代码

Intent intent=new Intent("xxx://profile");
startActivity(intent);

xml代码引用包名

${applicationId}这个变量就可以自动读取包名,版本号也是可以的哈.

  <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">

            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path" />
        </provider>

多个源代码文件夹指定

    sourceSets {
        main {
            jniLibs.srcDirs = ['jniLibs']
            res.srcDirs = [
                    'src/main/res',
                    'src/main/res_qssq'
            ]

        }
    }

   sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jni/'] } }

这样以后如果某个模块不要了,删除图片和布局文件,操作速度也是非常快的.
编译生成版本号

编译修改app-release.apk为app应用名称-版本名-版本号.apk

网上有些方法实际上是有bug的,需要经常刷新,每次改版本的时候或者时间变化的时候需要重新build,我这个方法没有bug.

        archivesBaseName = "情迁神器${versionName} build_${versionCode}".replace(' ', '_')

这个东西放到defaultConfig节点下即可.

debug包自动签名

    signingConfigs {
        debug {
            Properties properties = new Properties()
            properties.load(project.rootProject.file('d:/sign/sign.properties').newDataInputStream())
            def keyPwd = properties.getProperty("signingConfigs.keyPwd")
            def keyName = properties.getProperty("signingConfigs.keyName")
            def keyPath = properties.getProperty("signingConfigs.path")
            storeFile file(keyPath)
            storePassword keyPwd
            keyAlias keyName
            keyPassword keyPwd
            v2SigningEnabled false
        }


    }

解决无法编译问题常见的几个配置

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
    }

    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }

让android studio debug模式编译多套so跑模拟器而打包则只编译v7

  buildTypes {
            debug {
          
   externalNativeBuild {
                        cmake {
                            cppFlags ""
                            abiFilters 'x86', 'armeabi-v7a'
                        }

                        //APP的build.gradle设置支持的SO库架构
                    }


        }

生成arr到指定目录


    libraryVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.aar')) {
                def fileName = "${archivesBaseName}-${rootProject.version}-${variant.name}.aar"
                output.outputFile = new File(outputFile.parent, fileName)
                def folderName = rootProject.projectDir.toString() + new String("/arr-output")
                output.outputFile = new File(folderName, fileName)
            }
        }
    }

导入根目录文件夹的某个文件夹所有arr

     flatDir{
            dirs "${rootProject.projectDir}/arr_out"
        }

取出不需要的资源

variantData.outputs.each {
    def apFile = it.packageAndroidArtifactTask.getResourceFile();

    it.packageAndroidArtifactTask.doFirst {
        def arscFile = new File(apFile.parentFile, "resources.arsc");
        JarUtil.extractZipEntry(apFile, "resources.arsc", arscFile);

        def HashMap<String, ArrayList<DuplicatedEntry>> duplicatedResources = findDuplicatedResources(apFile);

        removeZipEntry(apFile, "resources.arsc");

        if (arscFile.exists()) {
            FileInputStream arscStream = null;
            ResourceFile resourceFile = null;
            try {
                arscStream = new FileInputStream(arscFile);

                resourceFile = ResourceFile.fromInputStream(arscStream);
                List<Chunk> chunks = resourceFile.getChunks();

                HashMap<String, String> toBeReplacedResourceMap = new HashMap<String, String>(1024);

                // 处理arsc并删除重复资源
                Iterator<Map.Entry<String, ArrayList<DuplicatedEntry>>> iterator = duplicatedResources.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, ArrayList<DuplicatedEntry>> duplicatedEntry = iterator.next();

                    // 保留第一个资源,其他资源删除掉
                    for (def index = 1; index < duplicatedEntry.value.size(); ++index) {
                        removeZipEntry(apFile, duplicatedEntry.value.get(index).name);

                        toBeReplacedResourceMap.put(duplicatedEntry.value.get(index).name, duplicatedEntry.value.get(0).name);
                    }
                }

                for (def index = 0; index < chunks.size(); ++index) {
                    Chunk chunk = chunks.get(index);
                    if (chunk instanceof ResourceTableChunk) {
                        ResourceTableChunk resourceTableChunk = (ResourceTableChunk) chunk;
                        StringPoolChunk stringPoolChunk = resourceTableChunk.getStringPool();
                        for (def i = 0; i < stringPoolChunk.stringCount; ++i) {
                            def key = stringPoolChunk.getString(i);
                            if (toBeReplacedResourceMap.containsKey(key)) {
                                stringPoolChunk.setString(i, toBeReplacedResourceMap.get(key));
                            }
                        }
                    }
                }

            } catch (IOException ignore) {
            } catch (FileNotFoundException ignore) {
            } finally {
                if (arscStream != null) {
                    IOUtils.closeQuietly(arscStream);
                }

                arscFile.delete();
                arscFile << resourceFile.toByteArray();

                addZipEntry(apFile, arscFile);
            }
        }
    }
}
通过这种方式可以有效减少重复资源

还有更多技巧欢迎吐槽哦!!!
更多参考推荐
http://blog.csdn.net/s402178946/article/details/54140200

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • 转载注明出处:http://www.jianshu.com/p/5255b100930e 0. 前言 完全由个人翻...
    王三的猫阿德阅读 2,509评论 0 4
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,014评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • 观看完影片【怒海潜将】,看完后心情久久不能平静。静下来又给了我们很多的思绪。男主人公卡尔那份矢志不渝的精神深深地震...
    毕姥姥阅读 439评论 0 0
  • 刚才在公司楼下给同事带饭,前台收银的小姐姐和我年龄差不多,一直在哭,哭的很伤心,旁边有个服务员阿姨在安慰她,大概意...
    混泥土少女阅读 180评论 0 1