To avoid my API keys from getting committed on source control (git) I have made an XML resource file called api_keys.xml under the values directory. This file is listed under .gitignore.
I access these string resources the usual way by using #string/.. or .getString(R.string...). This approach works everywhere but in the manifest.xml file.
I have fabric set-up and in the manifest file this is how I try to pass the key -
<meta-data
android:name="io.fabric.ApiKey"
android:value="#string/FABRIC_API_KEY" />
But, when I try to build the APK I get the following error -
Error:Execution failed for task ':app:fabricGenerateResourcesDebug'.
Crashlytics Developer Tools error.
This error goes away if I replace #string/FABRIC_API_KEY with the actual key.
Is there a way I can fix this? Or any other approach I can use to prevent my API keys form getting published on the source control.
Related
We have a problem with uploading the next version of the application. We use code transparency for bundle and when we try to upload to Google Store it returns an error:
An error occurred while running bundletool build-apks on your uploaded App Bundle. Ensure that your App Bundle is valid by running bundletool build-apks locally and try again. Learn more. Error: Verification failed because code was modified after transparency metadata generation. Files deleted after transparency metadata generation: [] Files added after transparency metadata generation: [/com/android/tools/build/bundletool/archive/dex/1_8_2/classes.dex] Files modified after transparency metadata generation: []
It took the previous (and first) version normally. At first I thought it was due to obfuscation, see documentation:
Known limitations
Apps using anti-tamper protection or any other service that makes code changes after the code transparency file is generated will cause the code transparency verification to fail.
So I tried turning it off, but it didn't help. I tried to generate APKS locally, that was no problem, as well as the local code-transparency verification went fine. Unfortunately, I couldn't find any mention of this problem anywhere at all.
TL;DR: You can either:
upgrade the bundletool that generates your app bundle to 1.13.1, OR (since upgrading wasn't possible in my case) follow these steps to disable the storeArchive feature in your app project, and then regenerate the .aab file.
I had this exact same issue. This is an issue with bundletool version 1.13.1, and not the app bundle (.aab) or its code transparency file. The Google Play Console must have updated to 1.13.1 recently and that's why it's failing.
I went through the source code and here's why this is happening:
The .aab and code transparency file of your app correctly match. The .aab does not have a file at 1_8_2/classes.dex, and thus the code transparency file says there is no file at 1_8_2/classes.dex. The code transparency files list is empty.
When bundletool 1.13.1 validates the code transparency file, it creates a the list of files in the bundle, and then artificially adds 1_8_2/classes.dex to this list. This did not happen in version 1.11.0.
bundletool checks the bundle file's list it created in Step 2 against the code transparency file in Step 1. The code transparency file is empty, eg. it has no record of 1_8_2/classes.dex. However the list from Step 2 contains this file, and only because the tool added it. So it spits out the error message saying that someone added that file to your bundle after the transparency file was generated.
According to the source code, you can keep Step 2 from happening by disabling the storeArchive feature. There are multiple ways to do this, but I simply added
res/xml/com_android_vending_archive_opt_out.xml to my app:
<?xml version="1.0" encoding="utf-8"?>
<optOut />
Then I regenerated my app bundle and was able to upload successfully to the Google Play Console.
I am using this library for displaying directions: https://github.com/akexorcist/Android-GoogleDirectionLibrary/blob/master/app/src/main/java/com/akexorcist/googledirection/sample/SimpleDirectionActivity.java. Previously I created a google maps activity, and the google_maps_api.xml was generated. I deleted this file because I don't believe I need it anymore, but now I get an error in my manifest file saying
"No resources found that match the given name(at 'value' with value '#string/google_maps_key') Can I simply delete the meta data tage seen below or is there a better option to clean things up?
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
I have a problem with one of my jenkins build.
I have configured in my global credentials, a keystore for one of my android build. This keystore is needed for when I have to sign my apk in order to distribute my app on Google Play for example.
So in the job, I have configured a Secret file binding to allow jenkins to copy the keystore file to a temporary location and sets a variable, let's call it SECRET_PATH, to that location. I can then provide gradle with the value of this variable on the command line when invoking the gradle script (in the switches section).
But then the build fails each time :
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':myapp:packageRelease'.
> Failed to read key ******** from store "/home/jenkins/slave/secretFiles/3607aab3-6e27-497a-b198-7d9a3aeb2913/keystore": Keystore was tampered with, or password was incorrect
it is as if the location /home/jenkins/slave/secretFiles/3607aab3-6e27-497a-b198-7d9a3aeb2913/keystore didn't even exist.
In the job configuration, the help tip on the Bindings sections also mentions this :
Warning: if the master or slave node has multiple executors, any other build running concurrently on the same node will be able to read the contents of this file.
It is exactly as if another concurrent build were running and deleted the location where the keystore was. This is really weird.
One more thing, I am using a master/slave topology where everything is dockerized. Not sure the docker itself is involved though. I think it's purely a Jenkins issue but I am giving this information so that you guys have some context.
Have you guys ever experienced this weird behaviour where jenkins seems to be unable to "resolve" the secret file bindings ?
Any help would be really appreciated.
thanks in advance,
Failed to read key ******** from store "/home/jenkins/slave/secretFiles/3607aab3-6e27-497a-b198-7d9a3aeb2913/keystore": Keystore was tampered with, or password was incorrect
it is as if the location /.../keystore didn't even exist.
No, the error message is correct — the file does exist, but most likely the store password or key password you are providing is incorrect.
If the keystore did not exist, you would get an error something like:
File '/.../release.keystore' specified for property 'signingConfig.storeFile' does not exist.
You can double check this by running file $SECRET_PATH/keystore, or ls -l $SECRET_PATH/keystore, or using keytool or something similar.
You don't mention injecting the keystore and key password(s) at all into the job — how are you doing that?
First make sure that building and signing the release version works as expected with Gradle from the command line.
Then you could try doing the same in Jenkins, by passing in the filename and password via the Gradle step (though this isn't a great idea if you're using the Job Config History plugin, for example).
Once that works, you can use the credential binding plugin to inject the file, and to inject the password.
I hit this error and found no hits for the error message, so I thought I'd share the solution I came up with to save anyone else facing the problem repeating my work.
When writing a new Android library (apklib) for use in a (large) application, I'm getting the following error during dexing when I add my new project as a dependency:
trouble writing output: Too many field references: 70185; max is 65536.
You may try using --multi-dex option.
References by package:
<...long list of packages with field counts elided...>
The particular build step it fails on is:
java -jar $ANDROID_SDK/build-tools/19.0.3/lib/dx.jar --dex \
--output=$PROJECT_HOME/target/classes.dex \
<... long list of apklib and jar dependencies elided ...>
Using --multi-dex as recommended by the error message might be a solution, but I'm not the owner of the application project and it already has a large complex build process that I would hesitate to change regardless.
I can reproduce this problem with a no-op test library project that has literally no fields, but in the error output it's listed as having 6000+ fields. Of the packages listed in the error output, there are a handful with similar 6k+ field counts, but then the vast majority have more plausible <1k field counts.
This problem is similar to the "Too many methods" problem that Facebook famously hacked their way around. The FB solution seems insane, and the only other solutions I've found (e.g., this Android bug ticket, or this one, this SO answer, this other SO answer) all involve changing the main app's code which is well beyond the scope of what I want to do.
Is there any other solution?
The solution was to change the package in the AndroidManifest to match the main application's package.
A manifest like this:
<manifest package="com.example.testlibrary" ...
resulted in 6k+ fields and build failure. Changing it to match the main application's package
<manifest package="com.example.mainapplication" ...
resulted in the project building successfully.
Note that only the package in the manifest is changing, I did not make any changes to the library's Java source or its layout (the Java package was still com.example.testlibrary with directory structure to match).
I hypothesize that the different package name is causing all the Android fields to be included again under that package. All the packages in the error listing with 6k+ fields had a different package name than the main application.
I also (later, grr), found this blog post which details the same problem and the eventual same solution.
Can someone share with me the steps executed by the Android OS on an newly downloaded APK for its bundled AndroidManifest file?
Actually I keen to know that what does Android OS do after downloading and before confirming installation successful. how it reads the AndroidManifest and whats the sequence of that...?
Install time parsing
PackageManager is a system component that runs on Android devices (in system_server) and plays a key role in the installation process, and the one that concerns itself with parsing the AndroidManifest.xml file of the package being installed.
Precisely the parsing is happening in PackageParser.java.
UPDATE:
While on Android R PackageParser.java still remains in place and contains the code for parsing, that code is effectively "deprecated" in favour of ParsingPackageUtils.java
Build time parsing
There is also another parsing of the AndroidManifest.xml that happens when Android package file (.apk) is being built. When the aapt2 (Android Asset Packaging Tool) links compiled resource files it also takes, parses and validates the AndroidManifest.xml file. This happens in ManifestFixer.cpp. It also parses the AndroidManifest.xml extracted from an .apk file when aapt2 dump badging or aapt2 dump permissions are executed - DumpManifest.cpp
Actually you could find more directly in android source code:
$ find sdk/sdkmanager/* -name "*Manifest*.java"
sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java
sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/ManifestData.java
sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifestParser.java
sdk/sdkmanager/libs/sdklib/tests/com/android/sdklib/xml/AndroidManifestParserTest.java
ManifestData.java is quite important, and acts a fundamental role, recommend you to read further.
Appendix: this directory has four java source codes:
$ ls sdk/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/
AndroidManifest.java AndroidXPathFactory.java
AndroidManifestParser.java ManifestData.java