Repository navigation
Everything Obtainium does, and more - #1
Merged
Merged
Conversation
Obtainium reads 18 stores and single-app sites that Tern skipped on import. Each now has a source of its own, registered where detection tries it, allowed in an export, and handed its entries by an Obtainium import instead of being skipped by name. Until a source can read its site it recognises no address, so detection passes it by. A source can now say three more things. Where to fetch a file right now, for stores whose download addresses expire within minutes; the registry takes only an https address back and never a header that carries credentials. That it only follows releases, for sites whose owners forbid downloads by others. And that it republishes apps somebody else built, so the person can be told before adding one. A source can also be searched by name through Searchable.
Some stores answer a download request with a redirect whose Location is the file, and the address is what the source wants to know. A request can now ask for the redirect itself. Every other request follows redirects as before, each hop still checked.
Some stores answer only a POST. A request can now carry a body with its content type. A redirect with 307 or 308 repeats it as it was, and 301 to 303 turn it into a GET without the body, as browsers do.
An APKPure address Tern cannot read as an app is still skipped, and the summary now says so in the words the import gives.
Settings, Installing, now asks what installs: Android's installer as before, Shizuku or Sui, root, or another installer app the person picks. Shizuku and root run pm as a user that may install without asking. The first install of an app is then silent too, and so is every update on Android 10 and 11. pm gets exactly the files the gate passed, streamed into one session made for the user Tern runs as, with Tern named as the installer so later updates through Android's installer stay silent as well. Where the person wants it, Google Play is named instead, for apps that only run when they believe the Play store installed them. pm's answer is read into the status PackageInstaller would have given, so the rest of Tern cannot tell the two apart. Another installer app is handed a read-only copy of the checked file, or of the split files as one .apks, and always asks, so it never runs in the background. It says nothing back, so a package that changed is the sign: the install counts when the package has the version handed over and the certificate the gate verified. When the chosen installer cannot be used, because Shizuku is not running or su said no, Android's installer is used meanwhile, and the settings row says why. The Shizuku client library is new and held to its hash like every other dependency; it adds the permission Shizuku asks of its clients, which check-apk.sh now expects.
A list could come from Obtainium but not go back. ObtainiumExport writes Obtainium's export schema 2: each app under the source name Obtainium keeps for it, its settings under the keys Obtainium reads, and the pinned certificates as the hashes Obtainium blocks on. What Obtainium has no key for stays behind, and a GitHub Actions app, which Obtainium cannot read, is named as left out. The test writes three apps and reads them back through Tern's own Obtainium import, which has to give the same apps.
The list can be ordered by name, developer, date added, release date, the last check or the source, either way round, and grouped by category or by source under headings that fold away. Updates stay on top unless that is switched off, and apps that are not installed can go to the bottom. The choices are kept. A favourite, from Obtainium's pinned apps or set here, stays at the top of the list and carries a star. The filter chips gain favourites, track only, problems and one per source, and every word of a search has to be found somewhere in the app. Selected apps can now also become favourites, get the same update mode, be shared as a list of addresses or as an export in Tern's format or Obtainium's, and be uninstalled, Android asking about each in turn. A row can be swiped towards the end to run its action and towards the start to remove the app, which the snackbar can take back. Settings switches this off, and a device without touch never has it. An app's page gains a star and a menu: check now, the release page, share its address, a link that opens it in Tern, or an export, and Android's own app info and uninstall. The page also says when the app was last checked, and what the source says the app is.
AddressList takes every https address from a list typed one a line, an OPML file of feeds, or a page of notes, in the order they first appear, without the punctuation that ends a sentence and with & read as &. A bracket that belongs to the address stays. Plain http is left out.
The import screen takes a list of addresses, pasted or read from any text file such as an OPML list. Every address is shown ticked, and adding looks at each the way a single link is looked at, one after the other, with the same summary starred repositories get. An obtainium://apps link, which carries several apps with their settings, was refused. It now opens as a list with one pick for each app, and each pick shows that app's carried settings before anything is added. tern://refresh checks every app, as obtainium://refresh does when Obtainium's links are switched on; with ?id= and a package it checks that one app. A check only reads the sources.
An export can now be kept up to date on its own: a moment after the list or an app's settings change, it is written again, in Download/Tern or in a folder the person picked. Exports may carry the portable settings (the look, the list, notifications and checks, never a token, the proxy or the installer) and may leave out apps that are not installed. Settings may also export in Obtainium's format, and an import takes the settings a file carries.
… and search F-Droid Each follows what the site offers: Telegram's own channel of releases, NeutronCode's file pages, itch.io's download flow, LiteAPKs' WordPress records with a timed token, Apk4Free's download pages grouped by the version in the file names, and RockMods for tracking only. Files are only taken from each site's own hosts. F-Droid's search finds apps by name.
…and RuStore Each store is read through the same interface its own pages use: the Galaxy Store's stub with a device model and CSC of the person's choice, vivo's and Tencent's app records, CoolApk's API with its token, the AppGallery handshake and RuStore's signed session. Links that expire are asked for again when the file is fetched. Addresses the stores route after a '#' are read as typed, and icons may come from each store's own image hosts. AppGallery, vivo and RuStore can be searched by name.
Stores whose links expire, or that hand out a file only to a request with the right headers, are asked for a fresh link right before a file is read or downloaded. A kept file is now named by its release as well as its address, so a store that serves every version at one address cannot hand an old file to a new release, and a download cut short resumes from a fresh link. A token still only goes to its own host.
…e settings Background checks can now run from every 15 minutes to every 30 days. New settings: check when Tern opens, check an app when its page opens, check only installed and tracked apps, remove apps uninstalled outside Tern, a file filter for every app without one of its own, run the background check now, start with groups folded, haptic feedback, always use the phone layout, a minimal list without icons, and older versions when Let Me Downgrade is installed. Settings now travel in exports for Obtainium and come in from Obtainium's exports under Tern's names.
APKPure's version history gives every variant with its size and hash, Aptoide's API the app's latest file, Uptodown's pages a file fetched through the site's own session, APKCombo's download page a signed link asked for again when the file is fetched, and Farsroid's download box its files. APKMirror's feed is read for tracking only. Files only come from each store's own hosts, and Aptoide and Uptodown can be searched.
…cked A search by name now asks every place picked above the results: GitHub, Codeberg and GitLab, F-Droid, and the stores that can be searched, such as AppGallery, vivo, RuStore, Aptoide and Uptodown. The choice is kept for the next search. Each place may fail without sinking the others, and every hit is cleaned the same way before it is shown.
Settings has a place for categories: each can be given one of sixteen colours, renamed or deleted for every app filed under it, and new ones can be made before any app is filed under them. A category without a colour of its own always takes the same one. The colours show on the list's filters and on the headings of groups, travel in exports, and come in from Obtainium's exports.
A notification about updates now carries a button: Update for one app, Update all for several, which run the same checks as the buttons in Tern. A notification about one app opens its page. New releases of apps that are only tracked get a channel of their own, and a quiet notification can show while a background check runs.
The activity log can be shared as plain text, one line an entry with a time every reader can order, all of it or only the problems. Settings offers to add Tern's own releases to the list, where they are checked and verified like any other app's.
…ives Tern now has three ways in that Obtainium has not: a home-screen widget that says how many updates there are and offers Check and Update all, a Quick Settings tile that checks and shows the count, and launcher shortcuts to check, update everything or add an app. Releases that come as a tar or tar.gz archive are opened: their APKs go through the same checks as those of a zip, and a filter can pick among them. The Add screen now says when a store republishes other people's apps, and plainly when a site offers apps someone else changed. The APK budget rises to 6 MiB, which every source, the privileged installers and the widget took it past.
An app's page now shows its notes, written in Markdown and carried by exports, as Obtainium's About did, with a way to add and edit them. Its categories are chips in their colours: a tap files the app under one or takes it out, and a new one can be named there. The Add screen lists every source Tern reads, by kind, with those that can be searched and those that are for tracking only, and links to the configurations Obtainium's users share.
… seen Each file an app's page offers can be saved to Download/Tern as it was downloaded, as Obtainium's release asset download does; the page says that Tern checks a file when it installs it. Selected apps can have their files saved at once, and new releases of selected tracked apps can be marked as seen at once.
…ping its icon A row carries a thin band in the colour of each category the app is filed under, as Obtainium's rows do. A double tap on the icon of an installed app opens it; a single tap still opens its page.
Where Obtainium can open the source's web page in a web view, Tern reads the project's README from GitHub, GitLab or Forgejo and shows it as text, with the HTML a forge would draw taken out. Nothing is asked of the forge until the page is opened, and no script runs.
…th file formats Releases can take their version from the tag, the title or the date, name the group of the version pattern to use or a template of several, be ordered by version, date, name or as the source lists them, stay a release or more behind, and be filtered by their version. The release a forge marks as latest comes first, and GitHub and Forgejo can check it and date a release by its newest file. Archives can be picked, with a filter for the files inside them. An app can have a name and an author of its own, be muted, be checked again before a download, and name Google Play as its installer. HTML and direct links take request headers and a way to tell files apart when the address never changes, and the HTML reader can take the first link, order by the last part of the address, and find links outside anchors. Obtainium's names for all of this are read on import and written on export, and a trip through its format leaves an app as it was.
An app's page now sets its own name and author, where to read the version from and which release is newest, a group or template of the version pattern, a filter on the version, how many releases to stay behind, archives and a filter for the files inside them, muting, a check before each download and Google Play as the installer, and it can offer a skipped version again. The chosen name and author show everywhere a name does, in notifications too. A muted app makes no sound when it has an update, a check runs before a download where asked, the filter for files inside archives picks what is installed, and the release a forge marks as latest and the archives that hold an app are kept with the stored releases. Links and imports that carry any of these say so before the app is added.
What Obtainium calls a source's additional options can now be set per app: for GitHub and Forgejo, asking which release is latest and dating releases by their newest file; the workflow and branch of GitHub Actions; the device model and region the Galaxy Store is asked for; and for a web page or a direct link, the link filter, the pages to go through first, the order, where the version is read, links outside link tags, request headers and how files are told apart without a version. Headers that carry credentials are refused before they are saved. After a change the source is read again from the start.
The header of an app's page sits on a wash of the icon's main colour that fades into the page. The colour is the mean of the icon's coloured pixels, weighed by how coloured each is, so a white mark on a coloured shape gives the shape; an icon of greys, or an app without one, takes its letter's colour.
…s in place with Shizuku or root - A file of a release can stand for a base and its splits, each fetched from its own address. The parts are packed in the staging folder and go through every check of a bundle, then install in one session. - RuStore is asked for its splits, as Obtainium does, so an app it only publishes in parts installs whole. - OBB files in an archive are taken out and, after Android installed the app, written to Android/obb/<package> through the Shizuku or root installer. With any other installer the activity says where they are. A name that could leave that folder refuses the archive.
…OBB files are handled An OBB file's name comes from the archive and goes into the command that writes it, so it may now hold only what OBB files are named of. The security model says how a store's separate parts become one bundle and where OBB files go.
…e, follow a SourceForge folder, and let the package name be set on an app's page An app without a package name now leaves in Obtainium's format with an id Obtainium replaces at the first install, and comes back without one.
…y which version was installed, and offer new apps to Verified Apps first Saving goes on after the page is left and shows in the Downloads notification. A problem notification names each app with its reason, and a tap opens what went wrong. The installer app can be picked with its icon and the way in to use.
…ied Apps and the installer picker are handled
…dish and Esperanto
…asked, with every secret taken out first A switch under Settings, Activity log, off at first. Each check notes what started it, how many apps, what it found and how long it took. Entries are marked and coloured by level, have a filter of their own, and are capped at 500 apart from the apps' own history. Addresses lose their query and any name and password, and tokens, keys, passwords and email addresses become an ellipsis, before anything is kept.
…the certificate the checks verified Dhizuku lends its device owner role to apps the person lets in, and a device owner installs without a prompt. Tern speaks Dhizuku's protocol itself, asks only the owner's own provider, and relays through it just the calls about a session Dhizuku owns; the files go from Tern to Android. The few non-SDK calls this needs are reached through HiddenApiBypass for eight named classes, and only once Dhizuku is chosen. Dhizuku never falls back to another installer, and every failure says what is missing.
…nd that every install is held to the verified certificate
…Turkish and the Asian languages
Malayalam Dhizuku wording, and any log strings written so far.
…e log strings' wording
munzzyy
added a commit
that referenced
this pull request
Sep 30, 2026
Tern now covers Obtainium's feature list and adds its own on top. docs/COMPARISON.md goes through it point by point, and CHANGELOG.md lists everything under Unreleased. - Sources: every store and site Obtainium reads, F-Droid's author and changelog, APKMirror's changes and file size, SourceForge folders, web pages with up to ten steps, tags for projects without releases, private GitHub projects, a hubproxy, "Read as", and search across forges and stores. - Installing: Shizuku (and Sui), Dhizuku, root or another installer app, Google Play as installer of record, RuStore's splits and OBB files, tar archives with gzip, bzip2 and xz, downgrades with Let Me Downgrade, and Verified Apps first. Every install counts only when the installed app carries the certificate the checks verified. - Settings and background: checks every 15 minutes to 30 days, retries and rate limits waited out, optional certificate pinning, a language picker, colour codes and schemes measured for contrast. - List, pages, import and export: sorting, grouping, combined filters, swipes, favourites, bulk actions, address lists and obtainium:// links, settings shared as links Obtainium opens, any file of any release saved, richer notifications, and Tern's own messages in the log with secrets taken out. - Beyond Obtainium: a home-screen widget, a Quick Settings tile, launcher shortcuts, a crash report at the next start, and the project's README on an app's page. - Every new string in all 28 languages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tern now covers Obtainium's feature list, item by item, and adds its own on top.
docs/COMPARISON.mdgoes through Obtainium's features one by one and lists where the two still differ.CHANGELOG.mdhas the full list under Unreleased.Sources
/p/addresses.Installing
Settings and background
rustore.ruonly.List, pages, import and export
obtainium://appslinks. An app's settings can be shared as a link Obtainium opens too, without tokens. The kept export can use Obtainium's format and a custom name.Beyond Obtainium
Translations
Every new string is in all 28 languages, machine-translated and checked by
tools/strings.py. Korean and Turkish now take the right endings after the name Tern.Checks
Core (1171) and app (674) unit tests, the device-test compile, release build, lint, the Java API check against API 29, the APK checks (6,937,650 bytes against a budget raised to 7 MiB, permissions as documented), the network-door check, the handoff page check and the site check. Dhizuku has been checked against Android's sources for 10 to 16 and not yet on a device.
Merging
The branch holds many small commits; a squash or rebase merge keeps main's history tidy.