Need clarification on how to update a very old app submission

Even after re-saving all of the PNG resources, I’m still getting the lint error “these images have EXIF that must be stripped”. Something else odd about it is that it seems to indicate there are 79 image files, but I only have 40 .png files under app/src/main/res/. There are 26 more image files in doc/, but that’s not part of the app and doesn’t account for the missing 39. If I unzip the .apk file it contains 246 .png files, the vast majority of which I believe are coming from the com.android.support:appcompat-v7 library which is not within my control.

I’ve opened MR #20334. I didn’t check the box for “All related fdroiddata and RFP issues have been referenced in this merge request” since as far as I know it isn’t applicable; I’m not aware of any fdroiddata or RFP issues.

The MR was labeled “waiting-for-upstream”. I posted a question on one of the replies, and pushed a change to address an error flagged by F-Droid Bot. What’s supposed to happen next — are the maintainers still waiting for something from me?

It’s a question of time :slight_smile:

It looks like we finally got the submission issues resolved, so I’ll try to summarize everything here.

Code Building

  • For gradle, it has to use a minimum of Gradle 4.1 and the Android Gradle plugin 3.0.0 as that’s the earliest version available in the Maven repository.

    • Earlier versions of Gradle may not be compatible with later version of Java; see Gradle’s “Compatibility Matrix” for supported versions.
  • Unfortunately I can’t find a definitive source of when Android dropped support for each minSdkVersion; the “SDK build tools release notes” shows when support was added for newer API levels, but not when support was dropped. A Google search for “minSdkVersion x cannot be smaller than version y declared in library” suggests that this limitation doesn’t come from the build tools, but is due to the Android support libraries; therefore the code will need to ensure the libraries it is using are all compatible with the app’s minimum SDK, or make sure that none of the library code is called without first checking Build.VERSION.SDK_INT against the library’s minimum SDK.

  • PNG images included with the app sources must not contain any Exif metadata. Metadata can be stripped from images using exiftool (from the package perl-Image-ExifTool):

    find . -name \*.png | xargs exiftool -all=
    

    (This will modify the images in-place.)

  • For reproducibility, the system must use zlib 1.3 (not zlib-ng) and the APK must be built from the command line using ./gradlew, not from Android Studio.

    • If needed, download the zlib source code and compile it.

      tar -xzf zlib-1.3.1.tar.gz
      cd zlib-1.3.1
      ./configure
      make test
      sudo make install
      export LD_PRELOAD=/usr/local/lib/libz.so.1
      
    • If needed, switch to the supported Java version. (See the system package manifest for the exact location.)

      export JAVA_HOME=/usr/lib/jvm/jre-1.8.0-openjdk
      
    • Build and sign the APK

      ./gradlew clean
      ./gradlew assembleRelease
      ${BUILD_TOOLS_VERSION_DIRECTORY}/apksigner sign \
        --ks ${ANDROID_KEYSTORE} --ks-key-alias ${SIGNING_KEY_ALIAS} \
        --out app/${APP_NAME}-${VERSION}.apk \
        app/build/outputs/apk/release/app-release-unsigned.apk
      

      (The signer will ask for your keystore password.)

F-Droid Requirements

  • Add a “Fastlane” directory structure in the code’s ${PROJECT_ROOT}/fastlane/metadata/android/en-US/ directory to describe the app for F-Droid:
    • title.txt, short_description.txt, and full_description.txt to name and describe the app
    • images/icon.png should be the app’s icon
    • images/phoneScreenshots/#.png should show the app
    • changelogs/versionCode.txt should explain what was changed between each version
  • Fork F-Droid/Data in GitLab (requires a GitLab account if you don’t already have one; see the file CONTRIBUTING.md in this repository for details)
  • Create a branch on the fdroiddata fork, named after the app ID.
  • Modify the metadata in metadata/appId.yml; see the “Build Metadata Reference” document for field descriptions.
    • Update the SourceCode, IssueTracker, Repo, and Binaries links if needed

      • There may be multiple Builds but only one Binaries, so the binaries link should include the app version placeholder (%v for the version name, %c for the version code).
    • Remove any Summary or Description; these should instead be in the Fastline files with the source code.

    • Add a new section to Builds for the new app version.

      • Must include the versionName and versionCode matching the app’s AndroidManifest.xml.

      • Must include commit for the build; this can either be a commit hash or tag.

      • Must include subdir: app, assuming the code follows Android’s recommended directory structure (where the app is a module in the app/ subdirectory.)

      • F-Droid’s build system uses a Debian image with Java 17 (as of this writing). If a different version of Java is required, that needs to be installed in a sudo script:

        sudo:
          - echo "deb http://deb.debian.org/debian sid main" > /etc/apt/sources.list.d/sid.list
          - apt-get update
          - apt-get install -y -t sid openjdk-8-jdk-headless
          - apt-get install -y -t sid openjdk-8-jdk-headless
          - update-java-alternatives --set java-1.8.0-openjdk-amd64
        
      • When using Gradle, this has to be specified in the build section:

        gradle:
          - yes
        
    • Add your APK signing key (the public key, not the private one) as AllowedAPKSigningKeys. This can be obtained from apksigner:

      ${BUILD_TOOLS_VERSION_DIRECTORY}/apksigner verify \
        --print-certs app/${APP_NAME}-${VERSION}.apk
      

      The key to add is the “Signer #1 certificate SHA-256 digest”.

    • To automatically build new versions when a release is tagged, set AutoUpdateMode: Version and UpdateCheckMode: Tags.

    • Update the CurrentVersion and CurrentVersionCode to the version of the most recent release. (These must not be quoted.)

Pushing the update

  1. After updating the F-Droid metadata (on the app branch), commit and push the change (to your fdroiddata fork).
  2. Log in to GitLab, go to your forked project’s pipeline, and check the build jobs.
  3. Address any build or lint errors found.
    • F-Droid’s metadata fields must be in a specific order; if “fdroid lint” shows a diff where the fields got moved, change your working copy of the metadata to match.
  4. If the pipeline completed successfully, go to the original F-Droid/Data project and create a Merge Request.
  5. Use the template for updating an app. Fill in the form and add any notes for the maintainers if needed.
  6. Wait for a maintainer to review the request, and address any issues that come up.

I think that covers it. Let me know if I missed anything.

1 Like

With AutoUpdateMode there’s no need for these, you just tag and build, and F-Droid picks it up.

Wouldn’t I still need to add the new build’s version number and code to the Builds list? As well as the commit, subdir, sudo, and gradle sections?

There’s that need, but fdroid bot takes care of that, eg. bot: Update MedTimer to 1.16.4 (104) (!20552) · Merge requests · F-Droid / Data · GitLab

Okay, there were a couple more issues uncovered with the next update which should round things out. As you said, with AutoUpdateMode set F-Droid Bot should automatically pick up new versions, but there may still be additional work to do.

Code building

  • The buildToolsVersion should be pegged in app/build.gradle to insure the same tools are used on your local development environment and in F-Droid.

Building the APK

  • When using Gradle ≥ 4.2 (and < 9), add android.enableResourceOptimizations=false to prevent the plugin from obfuscating resources.
    • This option is marked “deprecated” and will no longer be available (forced obfuscation) in Gradle ≥ 9! No word yet on how this may impact reproducibility.
  • When using Gradle ≥ 8.3, commit your code before building the release APK! Newer versions of the Android Gradle plugin include your commit hash in META-INF/version-control-info.textproto.
  • If using Android’s build tools version ≥ 35, include the option --alignment-preserved when running apksigner. (The alternative is to run a more complicated postbuild command from the version metadata.)

Auto Update

  • After pushing the new code, check F-Droid/Data’s Merge Request periodically or the F-Droid Monitor to see when it has picked up the new version. _(The title will be “bot: Update App Title to versionName (versionCode)”.) If the merge pipeline shows a successful build, there is nothing left to do.
  • If the bot’s merge did not build successfully, update your fork and pull in the changes to your metadata from the merge request. (You will not have permission to edit the bot‘s fork of the repo.) Then track down and fix the cause of the error.
    • Auto-update copies any extra settings and scriptlets for the build version from the previous version. These may need changing if your code needs different build tools, e.g. another version of Java or postbuild fixes to zip alignment issues.
    • Once the issues have been resolved, leave a comment in the bot’s merge request with the details of any changes needed to the metadata and any new commit hash if changes were needed to the source code.
1 Like