Recently Written · git

ink-update

Ink Update: tells you when Rebind, Ink Recents or Ink Dim has a new version. F-Droid, then Google Play, then GitHub.

git clone https://github.com/equwal/ink-update

Log | Files | Refs


commit 18f2c46cfc92856a7f5bdf1908d39bbeb34799b2
equwal <13551856+equwal@users.noreply.github.com>
2026-10-04 21:00:31 -0700

Treat any installer that opens fdroidrepos:// links as a F-Droid client

 app/src/main/AndroidManifest.xml                   |  5 ++++
 app/src/main/java/dev/equwal/inkupdate/Checker.kt  | 30 ++++++++++++++++++----
 app/src/main/java/dev/equwal/inkupdate/Decide.kt   |  7 +++--
 .../test/java/dev/equwal/inkupdate/DecideTest.kt   | 10 ++++++++
 4 files changed, 45 insertions(+), 7 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 00283e6..845a0c1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -24,6 +24,11 @@
         <package android:name="dev.equwal.inkupdate" />
         <package android:name="org.fdroid.fdroid" />
         <package android:name="com.android.vending" />
+        <!-- Every F-Droid client opens these links. -->
+        <intent>
+            <action android:name="android.intent.action.VIEW" />
+            <data android:scheme="fdroidrepos" />
+        </intent>
     </queries>
 
     <application
diff --git a/app/src/main/java/dev/equwal/inkupdate/Checker.kt b/app/src/main/java/dev/equwal/inkupdate/Checker.kt
index 5956956..bec4e71 100644
--- a/app/src/main/java/dev/equwal/inkupdate/Checker.kt
+++ b/app/src/main/java/dev/equwal/inkupdate/Checker.kt
@@ -3,7 +3,9 @@
 package dev.equwal.inkupdate
 
 import android.content.Context
+import android.content.Intent
 import android.content.pm.PackageManager
+import android.net.Uri
 
 /**
  * The check itself: what is installed, what the two hosts say, and what that
@@ -21,7 +23,8 @@ object Checker {
         val watched: Watched,
         val versionName: String,
         val versionCode: Long,
-        val installer: String?
+        val installer: String?,
+        val byFdroid: Boolean = Decide.fromFdroidClient(installer)
     )
 
     /** A row of the screen: an installed app and what the last check found. */
@@ -39,12 +42,14 @@ object Checker {
             } catch (e: Exception) {
                 null
             } ?: continue
+            val installer = installerOf(pm, w.pkg)
             out.add(
                 Installed(
                     watched = w,
                     versionName = info.versionName ?: "",
                     versionCode = info.longVersionCode,
-                    installer = installerOf(pm, w.pkg)
+                    installer = installer,
+                    byFdroid = fdroidClient(pm, installer)
                 )
             )
         }
@@ -94,12 +99,11 @@ object Checker {
         // Two cases make the GitHub request waste: F-Droid already has a newer
         // build, and the Play store updates the app by itself.
         val github =
-            if (fdroidWins || app.installer == Decide.PLAY_PACKAGE ||
-                Decide.fromFdroidClient(app.installer)) GithubAnswer.None
+            if (fdroidWins || app.installer == Decide.PLAY_PACKAGE || app.byFdroid) GithubAnswer.None
             else askGithub(w)
 
         return Decide.source(
-            app.installer, fdroid, github, app.versionCode, app.versionName
+            app.installer, fdroid, github, app.versionCode, app.versionName, app.byFdroid
         )
     }
 
@@ -125,6 +129,22 @@ object Checker {
         }
     }
 
+    /**
+     * True when the installer is a F-Droid client. There are many clients, and
+     * each one opens fdroidrepos:// links, so the system can tell.
+     */
+    private fun fdroidClient(pm: PackageManager, installer: String?): Boolean {
+        if (installer == null) return false
+        if (Decide.fromFdroidClient(installer)) return true
+        val view = Intent(Intent.ACTION_VIEW, Uri.parse("fdroidrepos://f-droid.org/repo"))
+            .setPackage(installer)
+        return try {
+            pm.queryIntentActivities(view, 0).isNotEmpty()
+        } catch (e: Exception) {
+            false
+        }
+    }
+
     /** The package that installed the app, as the system knows it. */
     private fun installerOf(pm: PackageManager, pkg: String): String? = try {
         pm.getInstallSourceInfo(pkg).installingPackageName
diff --git a/app/src/main/java/dev/equwal/inkupdate/Decide.kt b/app/src/main/java/dev/equwal/inkupdate/Decide.kt
index a346639..1a360de 100644
--- a/app/src/main/java/dev/equwal/inkupdate/Decide.kt
+++ b/app/src/main/java/dev/equwal/inkupdate/Decide.kt
@@ -93,19 +93,22 @@ object Decide {
      * 4. GitHub holds a newer release: take it.
      *
      * @param installer the package that installed the app, from the system.
+     * @param byFdroid the installer is a F-Droid client. Checker also asks the
+     *    system whether the installer opens fdroidrepos:// links.
      */
     fun source(
         installer: String?,
         fdroid: FdroidAnswer,
         github: GithubAnswer,
         installedCode: Long,
-        installedName: String
+        installedName: String,
+        byFdroid: Boolean = fromFdroidClient(installer)
     ): Result {
         if (fdroid is FdroidAnswer.Found && fdroid.versionCode > installedCode) {
             return Result.Update(FDROID, fdroid.versionName, fdroid.page, null)
         }
         if (installer == PLAY_PACKAGE) return Result.LeftToPlay
-        if (fromFdroidClient(installer)) return Result.UpToDate
+        if (byFdroid) return Result.UpToDate
 
         if (github is GithubAnswer.Found) {
             val theirs = Version.parse(github.tag)
diff --git a/app/src/test/java/dev/equwal/inkupdate/DecideTest.kt b/app/src/test/java/dev/equwal/inkupdate/DecideTest.kt
index 8605ff3..2e45f5d 100644
--- a/app/src/test/java/dev/equwal/inkupdate/DecideTest.kt
+++ b/app/src/test/java/dev/equwal/inkupdate/DecideTest.kt
@@ -58,6 +58,16 @@ class DecideTest {
         assertEquals(Result.UpToDate, r)
     }
 
+    /** A client that is not in the list, found by its fdroidrepos:// links. */
+    @Test
+    fun otherFdroidClientInstallNeverOffersGithub() {
+        val r = Decide.source(
+            "com.looker.droidify", FdroidAnswer.NotThere, githubNewer(), 1L, "0.1.0",
+            byFdroid = true
+        )
+        assertEquals(Result.UpToDate, r)
+    }
+
     /** The Play store does not beat a newer build on F-Droid. */
     @Test
     fun fdroidStillWinsOverPlay() {