Using ProGuard WITHOUT Android Studio

1.6k views Asked by At

I would like to know how to run ProGuard from the command line.

I've built a hybrid app using Cordova with the Ionic Framework. One of the recommendations made to me was using ProGuard to obfuscate the java code and to remove the Log calls.

I'm not currently using Android Studio or Eclipse, I just have the project build out in Ionic Framework and Angular 1.X with the Cordova plugins I need for functionality on devices. I have Jenkins build my releases via command line.

I tried to follow the steps laid out here: https://developer.android.com/studio/build/shrink-code.html#keep-code and here: Disable LogCat Output COMPLETELY in release Android app?

As well as combing through various questions/answers to find applicable bits.

My build.gradle is kept in ./vendor directory and copied to overwrite the autogenerated/default build.gradle from Ionic. It has this for enabling ProGuard:

    buildTypes {
        debug {
            debuggable true
            minifyEnabled false
        }

        release {
            signingConfig signingConfigs.release
            debuggable false
            minifyEnabled true
            runProguard true
            proguardFile 'customProGuard.txt'
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 
                'proguard-android.txt'
        }
    }

I've also tried various versions of this line in my project.properties file: proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt or proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt

It doesn't appear to be doing anything. I thought my apk file size changed at one point, but when I look at the classes in JD-GUI I can still clearly discern things. So I don't think it's running. Any help would be appreciated.

Jenkins runs the following commands:

cp -R vendor/build.gradle platforms/android/build.gradle
ionic resources
ionic prepare android
ionic build android --release
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $KEYSTORE platforms/android/build/outputs/apk/android-release-unsigned.apk
-keypass $KEY_PASSWORD -storepass $KEYSTORE_PASSWORD $ALIAS && \ ./zipalign -v 4 platforms/android/build/outputs/apk/android-release-unsigned.apk "build/appNameHere.apk"

While 'ionic build android --release' eventually calls ./platforms/android/cordova/lib/builders/GradleBuilder.js which has several lines referencing build.gradle, but I think the main most vital one being var buildGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8'); in which it reads in the file to use with GradleBuilder.build:

GradleBuilder.prototype.build = function(opts) {
    var wrapper = path.join(this.root, 'gradlew');
    var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
    return Q().then(function() {
        return spawn(wrapper, args, {stdio: 'inherit'});
    });
};
1

There are 1 answers

0
Mathew Ostrander On

After much trial and error, the answer turned out to be that I needed this block of code to be located in a different segment of my build.gradle file.

    release {
        signingConfig signingConfigs.release
        debuggable false
        minifyEnabled true
        proguardFile 'customProGuard.txt'
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 
            'proguard-android.txt'
    }

As it was, it was never being reached. By putting it in the android { } block, but not in any other functions or if statements, it consistently runs and behaves as expected.

Unfortunately, due to the way Ionic uses reflection, I'm not able to get much obfuscation use out of it (Apache Jira Bug). ProGuard can still be used to remove the console logs as per the linked article above though.