美文网首页对移动开发有帮助Android开发之路
Android Studio 将项目中封装好的 Module 打

Android Studio 将项目中封装好的 Module 打

作者: 王学宏 | 来源:发表于2018-11-20 17:07 被阅读176次

    一、Android Studio 默认自动生成的 jar 包

    众所周知 Android Studio 会在 library 所依赖的 app运行 或 build 之后自动生成 jar 包,路径为 Module根目录/build/intermediates/packaged-classes/debug/classes.jar,这样生成的jar是可以用的,但不是我们可以控制的,所以我们需要通过其他方式来生成jar包。


    注意:
    若发现 Android Studio 项目 packaged-classes 文件夹下没有 release 目录,可能是没有将 module 添加到主 module 依赖中。

    方式1:主module右键 --> 倒数第二个Open Module Setting--> 上面最后一个选项Dependencies-->右边绿色加号-->Module dependency......然后确定

    方式2:主 Module 的 gradle 的 dependencies(平时添加第三方库的地方)中加上 implementation project(':librarytest')
    点击 assembleRelease 生成 release 包,packaged-classes 目录下就会生成 release 目录了


    assembleRelease

    二、自定义生成 jar 包

    方式 A :点击 Android Studio 右侧(一般在这个位置)的 Gradle 面板,在项目或者该类库的目录中找到 Tasks -> other -> makeJar 命令,双击这个makeJar之后等一会就会编译好jar包。
    打包成功后:在配置的指定目录下生成jar包

    方式 B :通过 cmd 命令行,在项目根目录下,执行 gradlew makeJar 命令,看到编译完成的信息以后就OK了,也能生成一样的jar包,和直接使用①中的方式是等价的。

    注意:使用此方式前要配置好 gradle 的“ 环境变量 ”,否则直接在项目根目录下找不到这个命令。使用 cmd 比较费劲,不推荐。

    方式 C :在 Android Studio 终端窗口中输入 gradlew makeJar 命令。
    首先,需要将待打包 module 项目中的 build.gradle 文件进行修改,如下图:


    module build.gradle

    其次,在 library 的 app:build.gradle 中添加如下代码:

    方法一:

    // 方法一
    def _BASENAME = "LibraryT"; //  jar包名字可以自由更改
    def _VERSION = "_V1.0";
    def _DestinationPath = "build"; //生成jar包的位置
    def zipFile = file('build/intermediates/packaged-classes/debug/classes.jar'); // 待打包文件位置
    
    task deleteBuild(type:Delete){
        delete _DestinationPath + _BASENAME + _VERSION + ".jar"
    }
    task makeJar(type:Jar){
        from zipTree(zipFile)
        from fileTree(dir:'src/main',includes:['assets/**']) //将assets目录打入jar包
        baseName = _BASENAME + _VERSION
        destinationDir = file(_DestinationPath)
    }
    makeJar.dependsOn(deleteBuild, build)
    
    LibraryT_V1.0.jar

    方法二:

    首先,在方法一的基础上把在 library 的 app:build.gradle 中添加的代码修改为如下:

    task clearJar(type: Delete) {
        delete 'build/libs/LibraryT.jar'
        delete 'libs/LibraryT.jar'
    }
    //打包任务
    task makeJar(type: Jar) {
        //指定生成的jar名
        baseName 'LibraryT'
        //从哪里打包class文件
        from('build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/example/eagleview/librarytest')
        //release 路径,这个classes的路径不一定是从javac文件下,也有可能在 intermediates 目录下,所以只要找到相应的路径修改即可 
    //    from('build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/example/eagleview/librarytest')
        //打包到jar后的目录结构
        into('com/example/eagleview/librarytest/')
        //去掉不需要打包的目录和文件
        exclude('BuildConfig.class', 'R.class')
        //去掉R$开头的文件
        exclude { it.name.startsWith('R$'); }
    }
    makeJar.dependsOn(clearJar, build)
    
    
    LibraryT.jar

    这个方法可以解决com.android.dex.DexException: Multiple dex files define 此类的错误
    原因是sdk 的jar包中打入了BuildConfig.class,解决方法很简单:解包,删除里面的 BuildConfig.class,然后重新打包 jar。
    具体如下:

    1. 解压jar包: jar xf xxx.jar
    2. 删除解压后目录里面的//BuildConfig.class
    3. 重新打包: jar cvf xxx.jar *
      当然这样的方法有点粗糙,而且我们也绝对不希望给其他开发者带来困扰,所以我们可以有选择的将我们需要的class文件打包,把类似 BuildConfig.class / R.class ......文件排除在打包,完美解决问题

    在proguard-rules.pro文件中配置混淆文件

    # 表示混淆时不使用大小写混合类名
    -dontusemixedcaseclassnames
    
    # 表示不跳过library中的非public的类
    -dontskipnonpubliclibraryclasses
    
    # 打印混淆的详细信息
    -verbose
    
    # Optimization is turned off by default. Dex does not like code run
    # through the ProGuard optimize and preverify steps (and performs some
    # of these optimizations on its own).
    -dontoptimize
    
    # 表示不进行校验,这个校验作用 在java平台上的
    -dontpreverify
    # Note that if you want to enable optimization, you cannot just
    # include optimization flags in your own project configuration file;
    # instead you will need to point to the
    # "proguard-android-optimize.txt" file instead of this one from your
    # project.properties file.
    #使用注解需要添加
    -keepattributes *Annotation*
    -keep public class com.google.vending.licensing.ILicensingService
    -keep public class com.android.vending.licensing.ILicensingService
    
    # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
    #指定不混淆所有的JNI方法
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    # keep setters in Views so that animations can still work.
    # see http://proguard.sourceforge.net/manual/examples.html#beans
    #所有View的子类及其子类的get、set方法都不进行混淆
    -keepclassmembers public class * extends android.view.View {
       void set*(***);
       *** get*();
    }
    
    # We want to keep methods in Activity that could be used in the XML attribute onClick
    # 不混淆Activity中参数类型为View的所有方法
    -keepclassmembers class * extends android.app.Activity {
       public void *(android.view.View);
    }
    
    # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
    # 不混淆Enum类型的指定方法
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    # 不混淆Parcelable和它的子类,还有Creator成员变量
    -keepclassmembers class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator CREATOR;
    }
    
    # 不混淆R类里及其所有内部static类中的所有static变量字段
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    
    # The support library contains references to newer platform versions.
    # Don't warn about those in case this app is linking against an older
    # platform version.  We know about them, and they are safe.
    # 不提示兼容库的错误警告
    -dontwarn android.support.**
    
    # Understand the @Keep support annotation.
    -keep class android.support.annotation.Keep
    
    -keep @android.support.annotation.Keep class * {*;}
    
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <methods>;
    }
    
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <fields>;
    }
    
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <init>(...);
    }
    
    
    ###########################以下是需要手动的混淆配置协议###############################
    
    
    -libraryjars "C:\Program Files\Java\jre1.8.0_191\lib\rt.jar"
    #-libraryjars "C:\Users\admin\AppData\Local\Android\sdk\platforms\android-26\android.jar"
    # 注意:以上两个路径需要将以上路径是自己jar包的位置,需要根据自己情况进行修改,如果报重复配置的错误,注释掉即可
    
    #代码迭代优化的次数,默认5
    -optimizationpasses 5
    #混淆时不会产生形形色色的类名
    -dontusemixedcaseclassnames
    
    
    #忽略警告
    -ignorewarnings
    #以下是不需要混淆的文件
     -keep class com.android.sdk.demo.LogUtils{
         *;
     }
     -keep class com.android.sdk.demo.StorageUtils{
         *;
     }
    

    三、直接使用 aar 包

    将被嵌入的应用打包成 aar 包,这也是 Android Studio 的一种新特性,可以将应用所使用的资源性文件一起打包。编译即可打包生成 aar 包,而且也不用担心漏掉资源问题。

    如果Project 中 Module 是一个应用,则在 Module 的 build.gradle 文件中定义属性为:apply plugin: 'com.android.application';而如果 Mudule 是一个被引用的依赖 lib 库的话,则在 Module 的 build.gradle 文件中定义属性为: apply plugin: 'com.android.library;所以当我们将应用 Module 打包出 aar 文件的时候,需要修改类型属性。正常情况下,直接重新编译 Module,生成的 aar 包在 Module 根目录的/build/outputs/aar/,如下图:


    aar 包

    下面介绍将 aar 包添加到其他 Android 工程:
      首先,将 aar 包复制到 libs 目录下
      其次,配置build.gradle文件:
    在 要调用aar 包的 build.gradle 中加入:

    apply plugin: 'com.android.application'  
      
    android {  
        ...
        repositories {  
            flatDir {  
                dirs 'libs'  
            }  
        }  
    }  
      
    dependencies {  
        ...
        compile(name:'librarytest-release', ext:'aar')  
    }
    
    

    最后,clean一下工程,重新编译。

    相关文章

      网友评论

        本文标题:Android Studio 将项目中封装好的 Module 打

        本文链接:https://www.haomeiwen.com/subject/zshlfqtx.html