maksonnie
maksonnie

Reputation: 743

How to convert the crash log into a readable form when using minifyEnabled and proguard?

My project has the following settings:

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

Crash logs sometimes come from application users, for example:

l.c.b.c0.a.g
l.c.b.a0.z.j$a.a
l.c.b.i.c
l.c.b.i.b
k.a.a.f.a.i.a
n.m0.g.e$a.run
java.util.concurrent.ThreadPoolExecutor.runWorker ThreadPoolExecutor.java:1167
java.util.concurrent.ThreadPoolExecutor$Worker.run ThreadPoolExecutor.java:641
java.lang.Thread.run Thread.java:919

but how can I understand what is written here? There should be a reverse conversion.

I would be grateful for any help!

Upvotes: 0

Views: 790

Answers (1)

Perraco
Perraco

Reputation: 17380

To get back readable code first you must ensure to always keep a copy of the mapping files, generated with each build that has minifyEnabled set to true. Note that the mapping files are overwritten every time you make a build, so is imperative to get them right away after a build, otherwise the mappings will no longer correspond to your target binary.

The mapping files are generated under:

<your-module-name>/build/outputs/mapping/<build-type>/ 

Then you can use the ReTrace tool located under:

<your-android-sdk-location>\tools\proguard\lib\proguardgui.jar

ReTrace screenshot, (the tool works for both proguard and R8):

enter image description here

To see any crash un-obfuscated stacktrace directly within android's developers console, after finishing to publish a new release, go to the "App Bundle Explorer" section, select "Downloads", and upload the corresponding mapping file. See screenshot:

enter image description here

• Bonus

The next gradle script will copy the mapping files to the same location as your output build, so you don't need to browse for them every time you make a release:

task copyMappings() {

    android.applicationVariants.all { variant ->

        variant.outputs.all { output ->
            variant.getAssembleProvider().configure() {
                it.doLast {
                    if (variant.getBuildType().isMinifyEnabled()) {

                        def mappingProvider = variant.getMappingFileProvider()

                        if (mappingProvider != null) {

                            def files = mappingProvider.get().files

                            if (!files.isEmpty()) {

                                def mappingFile = files.iterator().next()

                                if (mappingFile != null && mappingFile.exists()) {
                                    copy {
                                        from mappingFile
                                        into variant.getPackageApplicationProvider().get().outputDirectory
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Upvotes: 3

Related Questions