Building Two Versions of the Same Android App
2012-11-23 10:58
411 查看
There are good reasons to want to build two versions of the same Android application. The most common scenario is to produce a free demo/reduced-functionality version of a non-free app. You could achieve
this by maintaining two separate source trees but the duplication would make most developers wince. So the question is how to build two differing apps without duplicating the code and resources?
the Android Ant build system is fairly painless to use. If you want to customise it though you’ll have to do a fair bit of digging as it doesn’t appear to be documented anywhere. The first place to look is the <sdk_dir>/platforms/<target_dir>/templates/android_rules.xml
file that is used by the build.xml that the Android tools generate for you. This will give you a good idea of the various stages of the build but if you want to experiment with the Android Ant tasks you’ll have to look at
the source to see what attributes they support (making sure that the version you are looking at is the same as the version you are using). The AaptExecLoopTask is just a simple wrapper around the aapt tool but the ApkBuilderTask is non-trivial.
The outline of a minimal Ant build for an Android app looks something like this:
Generate the R.java file from the resources using the the
exec task and the aapt tool with the -J option.
Compile all of the app source, including the class generated in step 1.
Use the dx tool to convert the Java bytecode into a .dex (Dalvik executable) file.
Use the aapt tool (either via the exec task or via the provided AaptExecLoopTask) to package the resources.
Build the .apk package using the ApkBuilderTask.
If you are building a release package rather than a debug package, sign the .apk file using thesignjar task.
Use exec to run the zipalign tool on the .apk file.
More advanced applications will involve additional steps, such as running the aidl tool.
Once you have the outline of your build in place, you can start to customise it using your standard issue Ant prowess.
is useless without the full set of resources so there is no danger of somebody hacking the demo version into a fully functioning version. In other words, I don’t need to worry about excluding certain classes from one version or the other.
I do however only want to include a subset of the resources in the demo version. The way I have achieved this is to replace the default res directory with three directories: res-common, res-demo and res-full.
I then use the Ant copy task to construct the res directory from the appropriate pair of directories prior to building.
that the Android tools get upset if the file is not called AndroidManifest.xml, even if you explicitly specify which file to use. This just means that I have to copy the chosen manifest so that it has the correct name.
The biggest problem with building two versions from the same tree is resolving conflicts in the application package name. Each Android application must have a unique application package. This is specified
in the manifest. You can just use the same package name for both versions but users will run into problems if they ever try to install both versions at the same time. They will likely end up not being able to use either. Despite the drawbacks, this method
seems to be widely used judging by the number of apps in the Android Market that warn users to uninstall the demo version first.
So we’ll just change the package name in one of the manifests then? Yeah, that would be nice. The problem is that the package name specified in the manifest is the package into which the R class is generated.
If the two versions of your application have their R classes in different packages then common classes will not compile for both versions.
Android 2.1 introduces the --custom-package option for the aapt tool which allows you to over-ride where R.java will be generated. So the idea is to set the application package differently in one of the manifests
but then to use this option to make sure that R.java is still in the same place as in the other version. I tried this and it resolved my compile problems but there were resource problems at runtime. I didn’t fully investigate what was wrong because I found
another approach that appears to work.
The aapt tool also has the --rename-manifest-package option. Leaving the application package the same in both manifests and then using this option at step 4 above, I was
able to generate a working demo version and full version from the same source tree and have them both functional when installed at the same time.
The whole custom Ant build exercise was not nearly as straightforward as I would have liked, mostly due to lack of documentation, but it is at least a working solution to the problem. Another, probably more
recommended, way of achieving something similar would be to use
library projects.
this by maintaining two separate source trees but the duplication would make most developers wince. So the question is how to build two differing apps without duplicating the code and resources?
Building Android Apps with Custom Ant Scripts
The answer is Ant. Maybe it’s also possible with Eclipse. I doubt it but I don’t know and I don’t care to find out. As Imentioned previously,the Android Ant build system is fairly painless to use. If you want to customise it though you’ll have to do a fair bit of digging as it doesn’t appear to be documented anywhere. The first place to look is the <sdk_dir>/platforms/<target_dir>/templates/android_rules.xml
file that is used by the build.xml that the Android tools generate for you. This will give you a good idea of the various stages of the build but if you want to experiment with the Android Ant tasks you’ll have to look at
the source to see what attributes they support (making sure that the version you are looking at is the same as the version you are using). The AaptExecLoopTask is just a simple wrapper around the aapt tool but the ApkBuilderTask is non-trivial.
The outline of a minimal Ant build for an Android app looks something like this:
Generate the R.java file from the resources using the the
exec task and the aapt tool with the -J option.
Compile all of the app source, including the class generated in step 1.
Use the dx tool to convert the Java bytecode into a .dex (Dalvik executable) file.
Use the aapt tool (either via the exec task or via the provided AaptExecLoopTask) to package the resources.
Build the .apk package using the ApkBuilderTask.
If you are building a release package rather than a debug package, sign the .apk file using thesignjar task.
Use exec to run the zipalign tool on the .apk file.
More advanced applications will involve additional steps, such as running the aidl tool.
Once you have the outline of your build in place, you can start to customise it using your standard issue Ant prowess.
Different Resources for Different Versions
In my scenario I don’t mind shipping all of the code with both versions of the application. The difference is just the initial Activity that each uses. It doesn’t add much bloat to the package and the codeis useless without the full set of resources so there is no danger of somebody hacking the demo version into a fully functioning version. In other words, I don’t need to worry about excluding certain classes from one version or the other.
I do however only want to include a subset of the resources in the demo version. The way I have achieved this is to replace the default res directory with three directories: res-common, res-demo and res-full.
I then use the Ant copy task to construct the res directory from the appropriate pair of directories prior to building.
Different Manifests
Because I want to invoke different activities, I need to define the AndroidManifest.xml differently for each version. My first idea was to just have two different files with different names but I discoveredthat the Android tools get upset if the file is not called AndroidManifest.xml, even if you explicitly specify which file to use. This just means that I have to copy the chosen manifest so that it has the correct name.
The biggest problem with building two versions from the same tree is resolving conflicts in the application package name. Each Android application must have a unique application package. This is specified
in the manifest. You can just use the same package name for both versions but users will run into problems if they ever try to install both versions at the same time. They will likely end up not being able to use either. Despite the drawbacks, this method
seems to be widely used judging by the number of apps in the Android Market that warn users to uninstall the demo version first.
So we’ll just change the package name in one of the manifests then? Yeah, that would be nice. The problem is that the package name specified in the manifest is the package into which the R class is generated.
If the two versions of your application have their R classes in different packages then common classes will not compile for both versions.
Android 2.1 introduces the --custom-package option for the aapt tool which allows you to over-ride where R.java will be generated. So the idea is to set the application package differently in one of the manifests
but then to use this option to make sure that R.java is still in the same place as in the other version. I tried this and it resolved my compile problems but there were resource problems at runtime. I didn’t fully investigate what was wrong because I found
another approach that appears to work.
The aapt tool also has the --rename-manifest-package option. Leaving the application package the same in both manifests and then using this option at step 4 above, I was
able to generate a working demo version and full version from the same source tree and have them both functional when installed at the same time.
The whole custom Ant build exercise was not nearly as straightforward as I would have liked, mostly due to lack of documentation, but it is at least a working solution to the problem. Another, probably more
recommended, way of achieving something similar would be to use
library projects.
相关文章推荐
- (转)Building Two Versions of the Same Android App
- How to Have Two Versions of the Same App on Your Device
- It is not possible to run two different versions of ASP.NET in the same IIS process.问题的解决
- Appliation Loader上传App 莫名其妙的错误 The CFBundleExecutable of two bundles may not point to the same file.
- It is not possible to run two different versions of ASP.NET in the same IIS process:IIS
- [android引用他人包出现的错误]All versions of the libraries must be the same at this time.以及It is indirectly re
- It is not possible to run two different versions of ASP.NET in the same IIS process
- Android Studio添加AAR文件报错:the versions of the android gradle plugin and gradle are not compatible,plea
- URAL - 1721 Two Sides of the Same Coin
- [android警告]AndroidManifest.xml警告 Not targeting the latest versions of Android
- Error running app: This version of Android Studio is incompatible with the Gradle Plugin used. Try d
- CXF报错[1 counts of IllegalAnnotationExceptions]and[Two classes have the same XML type name]and[Use @XmlType.name and @XmlType.namespace to assign different names to them]
- Error running app: This version of Android Studio is incompatible with the Gradle Plugin used. Try d
- Two more complicated dead-lock issues of android app
- URAL 1721 Two Sides of the Same Coin(二分匹配)
- 102 For which two database objects can the VERSIONS clause of the Flashback Versions Query be used?
- Android 解决Error running app: This version of Android Studio is incompatible with the Gradle Plugin
- Error running app: This version of Android Studio is incompatible with the Gradle Plugin used.
- Error running app: This version of Android Studio is incompatible with the Gradle Plugin used. Try d
- Error:A problem was found with the configuration of task ':app:packageRelease'. > File 'F:\AndroidSt