Recently Written · git

ink-recents

Ink Recents: a recent-apps switcher drawn for e-ink readers. No animation, swipe up to close, swipe down to close the others.

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

Log | Files | Refs


commit ab2e8ea23d1b8b1cf1b698697ad1741d269f28a9
truex <truex@equwal.com>
2026-09-21 03:42:57 -0700

Add screenshots and the debug screen renderer

The README and the store metadata have two pictures. ShotApp is in the
debug build only: an e-ink panel gives a black frame to screencap, so
each screen draws its own view tree to a PNG.

 README.md                                          |   7 ++-
 app/src/debug/AndroidManifest.xml                  |   9 ++++
 .../java/dev/equwal/inkrecents/debug/ShotApp.kt    |  53 +++++++++++++++++++++
 docs/screenshots/recents.png                       | Bin 0 -> 73095 bytes
 docs/screenshots/settings.png                      | Bin 0 -> 88177 bytes
 .../android/en-US/images/phoneScreenshots/1.png    | Bin 0 -> 73095 bytes
 .../android/en-US/images/phoneScreenshots/2.png    | Bin 0 -> 88177 bytes
 7 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 3f15fb3..00e0e64 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,12 @@ Android 12 or later.
 
 ## Screenshots
 
-To be added.
+<p>
+  <img src="docs/screenshots/recents.png" width="260" alt="One app card, the icon strip, and the two close buttons">
+  <img src="docs/screenshots/settings.png" width="260" alt="Settings: usage access, Shizuku, about">
+</p>
+
+The pictures are from a Viwoods AiPaper Reader.
 
 ## Install
 
diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..aa16e64
--- /dev/null
+++ b/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Debug builds only. An e-ink panel can be driven outside SurfaceFlinger, and
+    then `adb shell screencap` gives a black frame. ShotApp has each screen draw
+    its own view tree to a PNG. None of this is in a release build.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+    <application android:name=".debug.ShotApp" />
+</manifest>
diff --git a/app/src/debug/java/dev/equwal/inkrecents/debug/ShotApp.kt b/app/src/debug/java/dev/equwal/inkrecents/debug/ShotApp.kt
new file mode 100644
index 0000000..bfbb690
--- /dev/null
+++ b/app/src/debug/java/dev/equwal/inkrecents/debug/ShotApp.kt
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+package dev.equwal.inkrecents.debug
+
+import android.app.Activity
+import android.app.Application
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.util.Log
+import java.io.File
+
+/**
+ * Screenshots for the README, for a device that cannot take them. Debug builds only.
+ *
+ * A second after any screen comes to the front, its view tree is drawn into a
+ * bitmap and written to the app's external files directory:
+ *
+ *   adb pull /sdcard/Android/data/dev.equwal.inkrecents.debug/files/shots
+ */
+class ShotApp : Application() {
+
+    override fun onCreate() {
+        super.onCreate()
+        val main = Handler(Looper.getMainLooper())
+        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
+            override fun onActivityResumed(a: Activity) {
+                main.postDelayed({ if (!a.isFinishing) shoot(a) }, 2500L)
+            }
+            override fun onActivityCreated(a: Activity, b: Bundle?) = Unit
+            override fun onActivityStarted(a: Activity) = Unit
+            override fun onActivityPaused(a: Activity) = Unit
+            override fun onActivityStopped(a: Activity) = Unit
+            override fun onActivitySaveInstanceState(a: Activity, b: Bundle) = Unit
+            override fun onActivityDestroyed(a: Activity) = Unit
+        })
+    }
+
+    private fun shoot(a: Activity) {
+        val v = a.window.decorView
+        if (v.width == 0 || v.height == 0) return
+        val bmp = Bitmap.createBitmap(v.width, v.height, Bitmap.Config.ARGB_8888)
+        val canvas = Canvas(bmp)
+        canvas.drawColor(Color.WHITE)
+        v.draw(canvas)
+        val dir = File(getExternalFilesDir(null), "shots").apply { mkdirs() }
+        val out = File(dir, a.javaClass.simpleName + ".png")
+        out.outputStream().use { bmp.compress(Bitmap.CompressFormat.PNG, 100, it) }
+        Log.i("InkRecents", "shot " + out.absolutePath)
+    }
+}
diff --git a/docs/screenshots/recents.png b/docs/screenshots/recents.png
new file mode 100644
index 0000000..10f94fa
Binary files /dev/null and b/docs/screenshots/recents.png differ
diff --git a/docs/screenshots/settings.png b/docs/screenshots/settings.png
new file mode 100644
index 0000000..359e38a
Binary files /dev/null and b/docs/screenshots/settings.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
new file mode 100644
index 0000000..10f94fa
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
new file mode 100644
index 0000000..359e38a
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png differ