Finishing my first Android project, I ran into the problem of the lack of sufficient flexibility when building a release.
Initially, the build is supposed to use ant. When creating a project, the platform kindly creates you
build.xml . As a rule, the entire configuration consists of specifying the path to the Android SDK in the local.properties file. There may also be a desire to specify the key.store and key.alias parameters there so that the application subscribes automatically when building. Google doesn’t recommend doing this in the documentation because the proposed password input for the key during the build process is logged in Shell.
But what if during assembly you need to do something extra? In my case, it was necessary to exclude some files from the final package that are located in the
assets / test folder. These files store the paths to test web services and data for authorization. It is completely useless to include them in the final application. The solution was not found quickly, despite the simplicity. The problem is a small amount of documentation. I suggest to look inside to save time in the future.
')
If you look inside the
build.xml , then you can find there some commented out elements for customization:
After there is an instruction
<setup />
It imports the contents of the
SDK / tools / ant / main_rules.xml . If you look inside the specified file, you can see the whole process of building the project. Unfortunately, from there we see that using -pre-build, -pre-compile or -post-compile is not suitable for the problem to be solved. The process of packing assets into a .apk file looks like this:
<target name="-package-resources"> <echo>Packaging resources</echo> <aapt executable="${aapt}" command="package" versioncode="${version.code}" debug="${build.packaging.debug}" manifest="AndroidManifest.xml" assets="${asset.absolute.dir}" androidjar="${android.jar}" apkfolder="${out.absolute.dir}" resourcefilename="${resource.package.file.name}" resourcefilter="${aapt.resource.filter}"> <res path="${resource.absolute.dir}" /> </aapt> </target>
<target name="-package-resources"> <echo>Packaging resources</echo> <aapt executable="${aapt}" command="package" versioncode="${version.code}" debug="${build.packaging.debug}" manifest="AndroidManifest.xml" assets="${asset.absolute.dir}" androidjar="${android.jar}" apkfolder="${out.absolute.dir}" resourcefilename="${resource.package.file.name}" resourcefilter="${aapt.resource.filter}"> <res path="${resource.absolute.dir}" /> <!-- <nocompress /> forces no compression on any files in assets or res/raw --> <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw --> </aapt> </target>
Obviously, something needs to be changed in this task. Logically, I saw two options:
1. Somehow set exceptions that filter out unnecessary assets when packing.
2. Add one more step: delete unnecessary files from the already finished apk.
The most difficult was to find documentation on. Obviously, the task is based on the aapt platform tool. But all that is there is a formal reference in Shell and a piece of text in the documentation:
It is a rule that we can call it, it can be a little bit different, such as aidl, aapt, dexdump, and dx. As a general rule, you shouldn’t need it.
From the header
task-def in
main-rules.xml, we see that this aapt is nothing more than the
com.android.ant.AaptExecLoopTask class. Find the
source code class. From it we see that the task is nothing more than a narrow layer for standard packing using the aapt command line utility. You can customize the paths and names, but deeper flexibility is not incorporated, as it is not incorporated in the aapt itself when working with assets. The tool only allows you to specify the directory, but not manage the file lists. If you still see the options - I will be glad to read them in the comments.
Therefore, I decide to leave the packing in the form in which it is, and go the second way: delete unnecessary files after packing. To do this, inside our
build.xml we override the dependencies for the task.
"-package-release" which relies on the packing task:
<target name="-package-release" depends="-dex, -package-resources, -package-removetestassets"> <package-helper output.filepath="${out.unsigned.file}"/> </target>
<target name="-package-release" depends="-dex, -package-resources, -package-removetestassets"> <package-helper output.filepath="${out.unsigned.file}"/> </target>
Now this target will be used instead of the original one from main_rules.xml. It adds a new dependency
-package-removetestassets . Add a simple task that will remove unnecessary assets:
<target name="-package-removetestassets"> <echo>Excluding test assets from apk</echo> <exec executable="${aapt}"> <arg value="remove"/> <arg value="${out.absolute.dir}/${resource.package.file.name}"/> <arg value="assets/test/*.*"/> </exec> </target>
<target name="-package-removetestassets"> <echo>Excluding test assets from apk</echo> <exec executable="${aapt}"> <arg value="remove"/> <arg value="${out.absolute.dir}/${resource.package.file.name}"/> <arg value="assets/test/*.*"/> </exec> </target>
The result is achieved, with the minimum possible changes in build.xml. And this is very important, because reduces the risks when switching to new versions of Android.
I hope that the note will be useful.