Skip to content

Instantly share code, notes, and snippets.

@delthas
Last active July 4, 2024 07:02
Show Gist options
  • Save delthas/6622402e3849130a03c79db24c3b0305 to your computer and use it in GitHub Desktop.
Save delthas/6622402e3849130a03c79db24c3b0305 to your computer and use it in GitHub Desktop.
making a F-droid repo for Google Play apps

making a F-droid repo for Google Play apps

with support for downloading both free and paid apps you own

summary

  • set up a token dispenser, used to get a login cookie to use the google play unofficial api
  • run gplaycli to download the apks (uses the token dispenser)
  • run fdroid to generate all the filed and metadata from the apks
  • serve the output directory with an http server
  • the token dispenser is a trivially small http server/api to generate authentication tokens from google play
  • gplaycli can either use a public token dispenser instance, or a private local instance
  • to be able to use paid apps you own, you need to login with your own account; for this you need to host your own instance
  • the token dispenser needs to store an account password, using either a mongo db, a password file, or environment variables (see the README)
  • it might be safer to use a Google application password rather than the main google account password

setup

git clone https://github.com/matlink/token-dispenser
cd token-dispenser

# edit the config file before compiling
# storage= can be either mongo, plaintext or env
nano src/main/resources/config.properties

# by default token dispenser will output its log to a file
# change the logger properties to change this (i use stdout)
nano src/main/resources/simplelogger.properties

mvn clean package
# output file is target/token-dispenser.jar

note: token-dispenser is currently broken, see this comment for a fix

running

always keep it running, for example as a systemd service

java -jar target/token-dispenser.jar

if using the plaintext password storage, beware of placing the passwords file relative to the working directory of the process

  • gplaycli is a command line tool to download APKs from the google play store using both the token dispenser and the google play unofficial API

setup

pip3 install gplaycli --user

# edit the config file; a sample is available at:
# https://github.com/matlink/gplaycli/blob/master/example_token.conf
# edit token_url to point to the url and port of your token dispenser
nano gplaycli.conf

running

to download one APK:

gplaycli -c gplaycli.conf -d com.my.package -v -y

to update all APKs in a folder:

gplaycli -c gplaycli.conf -u folder/ -v -y

note: gplaycli caches the token it gets from token dispenser, sometimes for too long, and gets login issues. i found that clearing the token before calling gplaycli fixes the issue:

rm -f ~/.cache/gplaycli/token
  • fdroid is a command line tool to generate fdroid indexes and metadata from APKs
  • fdroid will output the fdroid repository (APK and metadata files) in repo/

setup

install fdroid

fdroid init

# edit the fdroid config file
nano config.py

mkdir repo/

running

fdroid update -c -v

http server

  • the repo/ folder will contain all the APK and metadata files
  • then, just add the url you served the folder to in your fdroid app repositories

putting it all together: update_fdroid.sh

  • this is a shell script that i use to update (or download) my fdroid repository
  • the script is run hourly by a systemd timer
  • the script assumes that you have a file list.txt containing one full package name per line and a folder static containing any additional APKs you might want to add to your f-droid repository
  • the script will download any new APKs not currently downloaded, and update any outdated ones
  • the script will output (and update atomically-ish) the final repository content in repo_prod, to be served by an HTTP server
#!/bin/bash -eux

rm -fr repo
mkdir -p repo
mkdir -p apk
rm -f ~/.cache/gplaycli/token

echo "Updating apps in apk/"
gplaycli -c gplaycli.conf -u apk/ -v -y

echo "Downloading new apps to apk/"
while read -r line || [[ -n "$line" ]]; do
  if [ ! -f "apk/${line}.apk" ]; then
    echo "Downloading new app: ${line}"
    gplaycli -c gplaycli.conf -d "$line" -f apk/ -v -y
  fi
done < list.txt

echo "Linking to repo/"
for f in static/*.apk; do ln -s "../static/${f##*/}" "repo/static_${f##*/}"; done
for f in apk/*.apk; do ln -s "../apk/${f##*/}" "repo/${f##*/}"; done

echo "Updating F-Droid"
fdroid update -c -v

rm -rf metadata srclibs

echo "Replacing repo_prod"
rm -fr repo_prod
mv repo repo_prod
  • example content of list.txt:
com.bandcamp.android
com.spotify.music
net.nurik.roman.muzei
co.vine.android
com.soundcloud.android
com.reddit.frontpage
org.mozilla.firefox_beta
com.Slack

note: make sure to leave a blank newline at the end (pretty standard)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment