Use apktool, aapt2, bundletool to convert apk to aab (Android App Bundle)

Scenarios encountered in development

  • In the previous article, we talked about the summary of the use of the AAPT2 command line. There is a usage scenario in which is to convert the apk to an aab file. The aab file is the specified package format for the application on Google Play. Let’s practice it below.
  • If we have such a scenario requirement, a game or application is connected to the aggregation SDK we developed, and then provides us with an apk package. We can use the packaging tool to integrate the specific channel SDK or plug-in with this apk package. Now we need This package is released overseas, so only the aab package will be released.
  • We first print out the integrated apk package through the packaging tool, and then further process the apk

Tools used in practice

Implemented using the command line

  • First choose a directory, copy the downloaded apktool, aapt2, bundletool, android.jar and other tools to this directory, so that we can execute commands, and prepare a packaged apk to change the directory, such as my newly created directory D:\ workspace\LCQ\apk-aab:
  • Next, we enter cmd in the file address bar and press Enter to enter the cmd command interface
  • Use the apktool command to decompile the app-release.apk package and execute the command
    java -jar apktool_2.6.1.jar d app-release.apk -s -o decode_apk

    We focus on the res folder after decompilation. The resource files in res need to be compiled with aapt2 to generate files that meet Google's protocol buffer format requirements.

  •  We use the compile command of aapt2 to compile the res folder

    aapt2 compile --dir decode_apk\res -o compiled_resources.zip

    You can see that the generated zip archive contains binary files with the suffix .flat or arsc.flat

  • We then use the link command of aapt2 to generate a base.apk

    aapt2 link --proto-format -o base.apk -I android.jar --manifest decode_apk\AndroidManifest.xml -R compiled_resources.zip --auto-add-overlay

    We decompress the base.apk file, create a new manifest folder, move the AndroidManifest.xml file into it, and then copy the assets and lib in the directory (decode_apk) generated by apktool decompilation to base, and add the .dex suffix Copy all the files to module/dex, copy unknown and kotlin to module/root, and the final directory will look like this

  • Then we select all the files and directories under the module and compress them into a .zip file, as shown in the figure

    Please make sure that the base directory is not compressed after the compressed zip file is opened, we copy the compressed base.zip to the same directory as bundletool, 

  • When we copy, we must pay attention not to mistake the directory generated by decompilation and the decompressed base directory resource generated by aapt2 link, otherwise the bundletool command will fail, such as InvalidProtocolBufferException

    [BT:1.12.1] Error: com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
    java.io.UncheckedIOException: com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
            at com.android.tools.build.bundletool.model.BundleModule$Builder.addEntry(BundleModule.java:418)
            at com.android.tools.build.bundletool.model.BundleModule$Builder.addEntries(BundleModule.java:399)
            at com.android.tools.build.bundletool.model.utils.BundleModuleParser.parseBundleModuleInternal(BundleModuleParser.java:66)
            at com.android.tools.build.bundletool.model.utils.BundleModuleParser.parseAppBundleModule(BundleModuleParser.java:41)
            at com.android.tools.build.bundletool.validation.BundleModulesValidator.lambda$validate$0(BundleModulesValidator.java:75)
            at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
            at java.base/java.util.Collections$2.tryAdvance(Collections.java:4747)
            at java.base/java.util.Collections$2.forEachRemaining(Collections.java:4755)
            at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
            at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
            at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
            at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
            at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
            at com.android.tools.build.bundletool.validation.BundleModulesValidator.validate(BundleModulesValidator.java:76)
            at com.android.tools.build.bundletool.commands.BuildBundleCommand.execute(BuildBundleCommand.java:231)
            at com.android.tools.build.bundletool.BundleToolMain.main(BundleToolMain.java:78)
            at com.android.tools.build.bundletool.BundleToolMain.main(BundleToolMain.java:54)
    Caused by: com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
            at com.google.protobuf.InvalidProtocolBufferException.invalidEndTag(InvalidProtocolBufferException.java:129)
            at com.google.protobuf.CodedInputStream$StreamDecoder.checkLastTagWas(CodedInputStream.java:2124)
            at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:217)
            at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:232)
            at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:237)
            at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:48)
            at com.google.protobuf.GeneratedMessageV3.parseWithIOException(GeneratedMessageV3.java:339)
            at com.android.aapt.Resources$XmlNode.parseFrom(Resources.java:44493)
            at com.android.tools.build.bundletool.model.BundleModule$SpecialModuleEntry$1.addToModule(BundleModule.java:459)
            at com.android.tools.build.bundletool.model.BundleModule$Builder.addEntry(BundleModule.java:416)
            ... 16 more
    
  • Next we use the bundletool command to generate the aab file, execute the command

    java -jar bundletool-all-1.12.1.jar build-bundle --modules=base.zip --output=module.aab

    You can see that the aab file has been generated. Now it is impossible to use the bundletool tool to directly install and test it, because it has not been signed yet. The aab signature can only be signed by jarsigner, not apksigner 

  • Use the jarsigner command to sign base.aab

    jarsigner -digestalg SHA1 -sigalg SHA1withRSA -keystore 你的签名文件.jks -storepass 秘钥文件密码 -keypass 秘钥密码 base.aab 别名
    
  • You can see that the signature is successful, and the META-INF directory is generated, which contains the signature information file

     The signed base.aab file can be used to test and upload google play

  • If you want to test the aab file, you also need to use the command line of bundletool. Let us first let adb connect to the device and generate the device information json file

    java -jar bundletool-all-1.12.1.jar get-device-spec --output=./device-spec.json
  • Then generate apks

    java -jar bundletool-all-1.12.1.jar build-apks --bundle=base.aab --output=abase.apks --overwrite --ks=你的签名文件.jks --ks-pass=pass:"111111" --ks-key-alias=别名--key-pass=pass:"111111"
    
  • Then install the apks to the corresponding device

    ava -jar bundletool-all-1.12.1.jar install-apks --apks=base.apks

Tip: Since we use the apk to generate aab by ourselves, there may be file omissions in the middle processing process, special cases that have not been processed, etc. It must be that the aab generated by AS is more reliable, and it is recommended to use the aab generated by AS to put your own on the shelf application

Guess you like

Origin blog.csdn.net/qq_19942717/article/details/127716913