Merge third-party SDK code in apk master package
- When we need to merge some third-party SDK codes into our own apk master package, the general process is to unzip the aar file of the third-party SDK, then merge the resource files inside, copy and merge the assets and res directories directly, and merge the jni directory into the libs directory of apk, androidmanifest XML files need to merge XML elements according to the actual situation. Some elements or attributes cannot be merged. Classes Jar and the jar file under libs need to use DX Jar or D8 Jar into a dex file, and then use baksmali Jar is converted into a smali file, and finally it can be merged into the smali directory of the parent package apk
- When merging jar files, we need to pay special attention to whether the jar file also contains assets, unknown and other resource files to prevent us from omitting when merging manually. For the merging of unknown resource files, please refer to this article: Android reverse development processes unknown files & classes in appsflyer library a -, b-resource merging in jar_ Lin ciqiao's blog - CSDN blog
Use DX Jar converts the jar in the aar package into a dex file
- First enter DX Jar directory
- Then enter cmd in the file directory and press enter to directly enter the cmd command window. You can see that DX has been located Jar directory
- In order to facilitate the test, we create a new modul e in AS, and then write some code, which uses the lambda expression of java8, and the compilation environment of java8 is configured in gradle. In this way, we build an aar package
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
package com.test.lib; import android.util.Log; import java.io.FileFilter; public class Test { public void fun() { FileFilter fileFilter = file -> false; Log.e("test", fileFilter.toString()); } }
- We will generate X7 Copy AAR package to DX Jar directory, and then set X7 Change AAR to X7 Zip, and then unzip it to the X7 directory. Then we execute the java jar command. Before executing the command, we need to configure the java environment variables. Otherwise, when we need to execute the command, we need to enter java Exe, and then execute the command: java - jar DX jar --dex --output=x7/my. dex x7/classes. jar
H:\Sdk\build-tools\28.0.3\lib>java -jar dx.jar --dex --output=/my.dex x7/classes.jar Uncaught translation error: com.android.dx.cf.code.SimException: ERROR in com.test.lib.Test.fun:()V: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13) 1 error; aborting
- Unfortunately, the conversion of jar to DEX failed. There is a prompt: invalid opcode ba - invokeddynamic requirements -- min SDK version > = 26 (currently 13). We try to add -- min SDK version = 26 parameter to the command, and then execute the command: Java - jar DX jar --dex --min-sdk-version=26 --output=x7/my. dex x7/classes. jar
H:\Sdk\build-tools\28.0.3\lib>java -jar dx.jar --dex --min-sdk-version=26 --output=x7/my.dex x7/classes.jar
- OK, it seems that the implementation is successful. Let's have a look
- Next, we need to add my DEX to smali file, we will baksmali Copy the jar file to DX Jar is in the same directory, which is convenient for us to execute the command, and then execute the command: Java - jar baksmali jar -o x7_ smalid x7/my.dex
H:\Sdk\build-tools\28.0.3\lib>java -jar baksmali.jar -o x7_smalid x7/my.dex Exception in thread "main" org.jf.util.ExceptionWithContext: x7\my.dex is not an apk, dex file or odex file. at org.jf.dexlib2.DexFileFactory.loadDexFile(DexFileFactory.java:111) at org.jf.dexlib2.DexFileFactory.loadDexFile(DexFileFactory.java:54) at org.jf.baksmali.main.main(main.java:252)
- As a result, the conversion to smali failed. It seems that there is still a problem with the dex file generated by adding -- min SDK version = 26. Baksmali Jar is not recognized. The main reason for this problem is that the lambda expression of java8 is used in our source code. If it is changed to non lambda expression to execute DX Jar command will not fail, but it is impossible for us to let the third-party SDK change the code, so we still need other solutions to solve this problem. Fortunately, google provided us with a D8 Jar tool, which can be used to deal with the failure of converting jar to dex generated by the new java8 syntax. The following is the command description of d8 tool:
H:\Sdk\build-tools\28.0.3\lib>java -jar d8.jar Usage: d8 [options] <input-files> where <input-files> are any combination of dex, class, zip, jar, or apk files and options are: --debug # Compile with debugging information (default). --release # Compile without debugging information. --output <file> # Output result in <outfile>. # <file> must be an existing directory or a zip file. --lib <file> # Add <file> as a library resource. --classpath <file> # Add <file> as a classpath resource. --min-api # Minimum Android API level compatibility --intermediate # Compile an intermediate result intended for later # merging. --file-per-class # Produce a separate dex file per input class --no-desugaring # Force disable desugaring. --main-dex-list <file> # List of classes to place in the primary dex file. --version # Print the version of d8. --help # Print this message.
- To execute the d8 command:
H:\Sdk\build-tools\28.0.3\lib>java -jar d8.jar --output H:\Sdk\build-tools\28.0.3\lib\x7 x7/classes.jar Warning in x7\classes.jar:com/test/lib/Test.class: Type `android.util.Log` was not found, it is required for default or static interface methods desugaring of `void com.test.lib.Test.fun()` Warning in synthesized for lambda desugaring: Interface `java.io.FileFilter` not found. It's needed to make sure desugaring of `com.test.lib.-$$Lambda$Test$3pJU-DzmeoaW6KjvNrGLr3KT1RM` is correct. Desugaring will assume that this interface has no default method.
- You can see that a class has been generated DEX file, although there are warnings, but the execution is successful. We will use baksmali Jar tool to generate smali files
H:\Sdk\build-tools\28.0.3\lib>java -jar baksmali.jar -o x7_smali x7\classes.dex test
OK successfully generates the smali file, so that we can merge the smali file into the parent package apk
- If required, baksmali The jar tool can be downloaded here: baksmali tool, which is used to convert dex files into smali files - Android document resources - CSDN Download
Another method of generating smali files
- If we don't want dx Upgrade the jar tool to D8.0 What should I do? One way to take the edge is to introduce an empty project, only the code of the third-party SDK, then generate apk files, and then decompile them with apktool to obtain smali and other code resource files
- However, gradle needs to be configured with minSdkVersion greater than or equal to 24, otherwise there will be other problems. Interested students can try it by themselves