We have a unique situation where we are deploying a Xamarin.Android app to China to 33 app stores. Hence, our solution has 33 application projects, and we setup Jenkins (running on Windows) to package and sign all our apks (otherwise it would be crazy to make builds).
We also need to modify android:versionCode and android:versionName in the manifest file, by using the ${SVN_REVISION} value from Jenkins. Is there a way to pass these values command line to MSBuild?
Normally we would hand edit this value, but it's not possible because of so many application projects.
Our build parameters right now look like this in Jenkins:
/p:Configuration=Release;AndroidKeyStore=True;AndroidSigningKeyStore=ourkeystore.keystore;AndroidSigningStorePass=ourpassword;AndroidSigningKeyAlias=ouralias;AndroidSigningKeyPass=ourpassword /t:SignAndroidPackage
Add this to the end of your *.csproj file, before the ending </Project> tag:
<Target Name="BeforeBuild" Condition=" '$(JENKINS)' == '1' ">
<XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="<Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' />" Query="manifest/#android:versionCode" Value="$(SVN_REVISION)" />
<XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="<Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' />" Query="manifest/#android:versionName" Value="2.0.$(SVN_REVISION)" />
</Target>
I have Jenkins configured to pass JENKINS=1 and SVN_REVISION. When it goes to build, it modifies AndroidManifest.xml before the build.
I don't know if this will work on xbuild on a Mac or not, depends on if XmlPoke is implemented. I should do a blog post on this.
No. You'll have to manipulate the android:versionCode and android:versionName yourself. Personally, I use a rake task to handle this particular detail.
Related
If I don't create a src/android/AndroidManifest.xml file in my Gluon project, then the mvn gluonfx:package command creates one for me with some relatively sensible defaults. However, I need to make some changes to the generated AndroidManifest.xml for my app (such as indicating support for multiple screen resolutions, and I need to add the BILLING permission).
If I copy the generated AndroidManifest.xml to src/android/AndroidManifest.xml as suggested during gluonfx:package, then Gluon no longer updates the version code and version name fields for me. I'm also not sure if there any any other side-effects to manually editing the AndroidManifest.xml file.
So my questions are:
What's the best practice when it comes to managing AndroidManifest.xml for a Gluon project?
How do folks deal with updating the version code and version name in a manually edited file as part of a CI/CD pipeline, where I don't want to have to manually edit AndroidManifest.xml for each build?
Are there any pitfalls to managing the AndroidManifest.xml outside the gluonfx:package command?
As documented here, you should use <releaseConfiguration/> to define the values that are required or need to be updated for each new release.
For Android, besides the keystore signing properties, you can also define:
version code
version name
app label
like:
<plugin>
<groupId>com.gluonhq</groupId>
<artifactId>gluonfx-maven-plugin</artifactId>
<version>${gluonfx.maven.plugin.version}</version>
<configuration>
<target>${gluonfx.target}</target>
<releaseConfiguration>
<versionCode>2</versionCode>
<versionName>3.0</versionName>
<appLabel>MyHelloFX</appLabel>
</releaseConfiguration>
...
So in case you need to add the AndroidManifest to src/Android (the one that was generated in target/gluonfx/aarch64-android/gensrc/android/AndroidManifest.xml), in order to add/modify part of it, it will be always updated for those three values, whenever you change them in the pom.
About CI/CD, have a look at the HelloGluon CI sample.
It doesn't have a custom manifest, but it shows how to deal with ReleaseConfiguration and updating release values in a CI environment.
The pom defines some properties that are used by the releaseConfiguration block:
<properties>
...
<main.class>com.gluonhq.hello.HelloGluonApp</main.class>
<app.identifier>${main.class}</app.identifier>
<app.description>The HelloGluon app</app.description>
<version.code/>
<provided.keystore.path/>
</properties>
...
<plugin>
<groupId>com.gluonhq</groupId>
<artifactId>gluonfx-maven-plugin</artifactId>
<version>${gluonfx.maven.plugin.version}</version>
<configuration>
...
<releaseConfiguration>
<vendor>Gluon</vendor>
<description>${app.description}</description>
<packageType>${package.type}</packageType>
<!-- for macOS/iOS -->
<macAppStore>${mac.app.store}</macAppStore>
<bundleShortVersion>${bundle.short.version}</bundleShortVersion>
<bundleVersion>${bundle.version}</bundleVersion>
<!-- for Android -->
<versionCode>${version.code}</versionCode>
<providedKeyStorePath>${provided.keystore.path}</providedKeyStorePath>
...
These properties are ultimately defined for each profile:
<profile>
<id>android</id>
<properties>
<gluonfx.target>android</gluonfx.target>
<app.identifier>com.gluonhq.samples.hellogluon</app.identifier>
<version.code>${env.GITHUB_RUN_NUMBER}</version.code>
...
When running the Android job, the required variables and secrets are used:
- name: Gluon Build
run: mvn -Pandroid gluonfx:build gluonfx:package
env:
GLUON_ANDROID_KEYSTOREPATH: ${{ steps.android_keystore_file.outputs.filePath }}
...
Just read this question (Android facebook applicationId cannot be null) and really hoped it would fix my issue too.
It is similar, however, I'm working with ANT and added the App ID's in the build.xml.
The build runs fine, the logs don't show anything weird. I see that the somehow adding the App ID in the Manifest tricks Android into thinking it's an Integer, while it should actually be a String. And whatever I try, I still get the same error and the app keeps crashing.
applicationId cannot be null
I tried escaping the application id's when specifying them, like so:
<property
name="fb_app_id_a"
value="\ XXXXXXXXXXXX" />
But it resulted in the same error. So I tried to be smart and added the escaping later, but to no avail:
<replaceregexp
file="AndroidManifest.xml"
flags="g"
match="android:value="#string/app_id""
replace="android:value="\ ${fb_app_id_a}"" />
I try to replace the conventional implementation with the build.xml, because we have to use several app ID's. Although the logs of the build I ran look fine, still it's giving me hell to get the build automation done because of this issue. Am I doing something wrong, or should I be doing it differently?
Does anybody have experience with build automation and the use of multiple app ID's for Facebook?
Thanks a bunch!
What I use to change some value in the manifests file is:
<replaceregexp file="AndroidManifest.xml" match='android:label=".*"'
replace='android:label="my new value"'/>
With this, I will change android:label="some value" to android:label="my new value"
I guess that in your case will be:
<property name="fb_app_id_a" value="some value" />
<replaceregexp file="AndroidManifest.xml" match='property name="fb_app_id_a" value=".*"'
replace='property name="fb_app_id_a" value="your new value"'/>
Also, to decomple the apk and see the AndroidManifest.xml helped me a lot
I want to auto-increment the versionCode and versionName of the manifest file of the android app when I click on Export (to export a new version of the app)
I found the second answer here (Auto increment version code in Android app) extremely useful (comment include .exe programs to auto increment Android versionCode) , however, they made it run on Build, I want it to run when I click on File -> Export , see image please
You might consider modifying the File -> Export button to execute a builder to increment the version code (as shown in the post you mentioned) in addition to that button's usual functionality. The org.eclipse.ui.menus extension point seems like a good starting point. (Disclaimer: I haven't tried this.)
However, it might be good to keep the following xkcd in mind here:
I have done this with a ton of custom ant steps.
First, you need to extract the build number into a properties file. Let's call it version.properties
Then, the step to increment the version code is:
<target name="increment-version-code">
<propertyfile file="version.properties">
<entry key="versionCode" type="int" default="0" operation="+" value="1" />
</propertyfile>
</target>
This will read the entry versionCode, increment it and save it back to version.properties.
So far, so good. The last step is to get that versionCode into the AndroidManifest.xml file and unfortunately now it gets messy.
The way I solved it was to regenerate the manifest from a template on every build using the filtering functionality in ant.
<target name="generate-manifest">
<filter filtersfile="version.properties"/>
<copy todir="${source.dir}" overwrite="true" verbose="true" filtering="true">
<fileset dir="${source.dir}" casesensitive="false">
<include name="**/*.base"/>
</fileset>
<mapper type="glob" from="*.base" to="*" />
</copy>
</target>
Then, all you have left to do is move your AndroidManifest.xml to AndroidManifest.xml.base and replace your versionCode attribute to read android:versionCode="#versionCode#" . You can then run the increment-version-code target to bump the versionCode in version.properties and the generate-manifest target to convert the .base template into the final manifest.
These can then be easily added as build steps to your Eclipse project or as dependencies to exported ant builds. Unfortunately, there's no easy hook for the Export functionality (though, there is for "After Clean", which I find good enough).
Of course, with Gradle on the horizon, all of this would have to be rewritten soon. :(
In my Android app I:
generate an incrementing build number (integer) using a script as part of my build (uses Integer from SVN revision)
I generate an Android resource file with it defined as an integer:
399
I show that on the UI using the resource generated above
I reference the integer in the Manifest for the versionCode element
All that works fine, but when I attempt to upload to Market I get this error:
"The file is invalid: ERROR getting 'android:versionCode' attribute: attribute is not an integer value "
Question:
For Market, does the versionCode have to be a "literal" integer directly inside the manifest, or is there some way to reference an externally generated integer and not be touching my manifest all the time (manually or automatically).
thanks
(BTW: I have just realized that scheme might cause me issues with patch releases, so I will probably generate a bigger number or something, but would still like the answer to this question)
In the end, this is what I have done:
I create a tag in my version control system with the numbe rof the release in this format
X.YY.ZZ where they are all integers, like 1.20.00, and reserve the last two digits for unplanned patch releases maybe made on a branch after a later release is made....
So if I release 1.20.00 then 1.23.00, I can still go back and do a patch release to 1.22.00 called 1.22.01.
I have a build step that gets the tag name and generates a string resource "1.22.00" for Android that I use in the UI. It also generates it as a number 12200 and I use this as the version number.
BUT, I don't try and include this version number directly in the manifest, I set it for the package by setting an ant property for version code that the ant build picks up if defined and uses to create the .apk.
So I get an always increasing integer for Android Market, but a user with an older version can install a patch release, but you cannot install a patch release if you have a newer official release.
i.e. if you have 1.20.00 you can install patch 1.20.01, but if a user has moved onto 1.23.00 they cannot install the 1.20.01 patch...
To set the property you can use;
project.setProperty("version.name", versionName);
project.setProperty("version.code", versionCode);
if those properties are set, then the Android build system (both old and newer) will pick-up the property value and use it, no need to do anything else special.
Just make sure you set it using one of the pre-build/pre-compile ant extension points.
In the new build system (Platform Tools >= 12) in custom_rules.xml I have added
<project name="custom" default="help">
<import file="build_info.xml" />
<target name="-pre-build" depends="build-info" />
</project>
where build_info is my own ant project that calculates the version name/number from the Tag name (if you are building in a tag....).
From everything I've read, Google Play currently requires android:versionCode to be a 32-bit integer, not a resource. Like you, I also initialize android:versionCode with an #integer resource.
To work around the market's limitation, our build script parses the #integer value and injects it directly into android:versionCode for release builds. This was a simple solution for us. There's far more involved ways to achieve this using ant.properties and the build.xml -pre-build option, however, that is beyond my needs.
For more on that, see:
Reference an integer resource for Android manifest versionCode
https://groups.google.com/d/msg/android-developers/1dt0yxyNPsk/c9c6PlG84iwJ
i'm trying to get android running on a gumstix overo system.
since i'm not planning to use the final "product" as a phone, i asked my self if it is possible to exclude applications like the phone/dialer-app from the kernel build-process (any config parameter probably?)
Just remove (or comment) these lines:
<project path="packages/apps/Phone" name="platform/packages/apps/Phone" />
<project path="packages/apps/VoiceDialer" name="platform/packages/apps/VoiceDialer" />
(and others if needed) from the platform manifest (default.xml) :
https://android.googlesource.com/platform/manifest/+/master/default.xml
Removing the app declarations in the repo manifest did not work for me, as there are other libraries that reference them that then fail to compile. The build system approach to this problem is to create/modify your product definition makefile to not include the specific apps.
So, for the overo you probably already have a products/overo.mk product file. You can manually set the PRODUCT_PACKAGES variable to which applications you want to ship. You will also want to take a look at the PRODUCT_POLICY variable, as it defines sets of applications for your product type.
It can take some fiddling to get everything to build correctly, due to interdependencies between applications, but the Android build output does a pretty good job of explaining the problems when they arise.