summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-09-13 10:54:41 +0300
committerPaul Buetow <paul@buetow.org>2025-09-13 10:54:41 +0300
commitb93fcd57868a53ad0f98ed450bd4c964f370442b (patch)
tree6d2c398496dae417a98e2705dd13f8c7e8bef3f8
parent4f4d430db11f4d7be9cb7c6562d611f088cc01cc (diff)
Android share integration: add overlay manifest and ShareActivity, move Java to android/src/main/java for fyne-cross merge; read shared text from UserCacheDir; load on startup and foreground. Update README for Mage usage.
-rw-r--r--FyneApp.toml2
-rw-r--r--README.md70
-rw-r--r--android/AndroidManifest.xml22
-rw-r--r--android_shared_android.go34
-rw-r--r--android_shared_stub.go6
-rw-r--r--main.go55
6 files changed, 157 insertions, 32 deletions
diff --git a/FyneApp.toml b/FyneApp.toml
index b9c0a16..c0df1e5 100644
--- a/FyneApp.toml
+++ b/FyneApp.toml
@@ -5,4 +5,4 @@ Website = "https://codeberg.org/snonux/quicklogger"
Name = "quicklogger"
ID = "org.buetow.quicklogger"
Version = "0.0.3"
- Build = 42
+ Build = 48
diff --git a/README.md b/README.md
index bedeaaa..a3a8a4b 100644
--- a/README.md
+++ b/README.md
@@ -11,23 +11,67 @@ This are screenshots of the App running on Android and Fedora Linux.
![Screenshot](./screenshot-android.png)
![Screenshot](./screenshot-fedora.png)
-## Installation
+## Build and Run (Mage)
-1. Download and install the Android NDK. I personally installed it to `~/android/android-ndk-r26b` as of this writing.
-2. Clone Quicklogger: `git clone https://codeberg.org/snonux/quicklogger; cd quicklogger`
-3. Build it `./build.sh` - Note, you may need to set the `ANDROID_NDK_HOME` environment variable accordingly.
-4. Copy `quicklogger.apk` to your Android phone and install it (You may need to allow installing APKs from this source - just follow the instructions Android is prompting you with).
+This repo includes Mage tasks to build, run and cross‑compile.
-## Not sure
+Install Mage:
-... not sure that the above is still required, but I now have to do this to complile this on Fedora Linux for Android:
+```sh
+go install github.com/magefile/mage@latest
+```
+
+Clone and enter the repo:
```sh
-sudo systemctl start podman
-DOCKER_HOST=unix:///run/user/1001/podman/podman.sock
-go install github.com/fyne-io/fyne-cross@latest
-fyne-cross android --pull
-fyne-cross android
+git clone https://codeberg.org/snonux/quicklogger
+cd quicklogger
```
-And then install the `.apk` file.
+Common tasks:
+
+```sh
+# Build desktop binary into ./bin
+mage build
+
+# Run the app (shows verbose Go build output)
+mage run
+
+# Clean build artifacts
+mage clean
+```
+
+## Android Builds
+
+Two options exist: local Fyne packaging or containerized cross‑compile.
+
+- Local packaging (requires Fyne CLI and Android NDK):
+
+ ```sh
+ # Install Fyne CLI if needed
+ go install fyne.io/fyne/v2/cmd/fyne@latest
+
+ # Ensure ANDROID_NDK_HOME points to your NDK (e.g. ~/android-ndk/android-ndk-r26b)
+ export ANDROID_NDK_HOME=~/android-ndk/android-ndk-r26b
+
+ # Build APK in the project root as quicklogger.apk
+ mage android
+ ```
+
+- Containerized cross‑compile (recommended, uses fyne-cross with Docker/Podman):
+
+ ```sh
+ # Start Podman if you prefer Podman over Docker
+ sudo systemctl start podman
+
+ # The task auto-detects a user Podman socket; otherwise it uses Docker defaults
+ mage androidcross
+ ```
+
+After cross‑compiling, the APK is located at `fyne-cross/dist/android/quicklogger.apk`.
+Copy it to your device and install it (you may need to allow installing from unknown sources):
+
+```sh
+adb install -r fyne-cross/dist/android/quicklogger.apk
+# or copy manually and install on device
+```
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
new file mode 100644
index 0000000..51edc1b
--- /dev/null
+++ b/android/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.buetow.quicklogger">
+
+ <application>
+ <!-- Share receiver activity: writes text to cache and launches main app -->
+ <activity
+ android:name=".ShareActivity"
+ android:exported="true"
+ android:excludeFromRecents="true"
+ android:taskAffinity=""
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="text/plain" />
+ <data android:mimeType="text/*" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
+
diff --git a/android_shared_android.go b/android_shared_android.go
new file mode 100644
index 0000000..b736fab
--- /dev/null
+++ b/android_shared_android.go
@@ -0,0 +1,34 @@
+//go:build android
+
+package main
+
+import (
+ "os"
+ "path/filepath"
+)
+
+// readSharedFromCache tries to read the shared text written by the Android activity.
+// The activity writes into getCacheDir()/quicklogger-shared.txt; on Go, os.TempDir()
+// maps to the same location in Android (app cache directory).
+func readSharedFromCache() (string, error) {
+ dir, derr := os.UserCacheDir()
+ if derr != nil || dir == "" {
+ dir = os.TempDir()
+ }
+ path := filepath.Join(dir, "quicklogger-shared.txt")
+ b, err := os.ReadFile(path)
+ if err != nil {
+ return "", err
+ }
+ // best-effort cleanup; ignore errors
+ _ = os.Remove(path)
+ return string(b), nil
+}
+
+func debugSharedPath() string {
+ dir, _ := os.UserCacheDir()
+ if dir == "" {
+ dir = os.TempDir()
+ }
+ return filepath.Join(dir, "quicklogger-shared.txt")
+}
diff --git a/android_shared_stub.go b/android_shared_stub.go
new file mode 100644
index 0000000..4e6f27e
--- /dev/null
+++ b/android_shared_stub.go
@@ -0,0 +1,6 @@
+//go:build !android
+
+package main
+
+func readSharedFromCache() (string, error) { return "", nil }
+
diff --git a/main.go b/main.go
index 863a40d..0a32930 100644
--- a/main.go
+++ b/main.go
@@ -58,20 +58,20 @@ func createMainWindow(a fyne.App) fyne.Window {
input.Wrapping = fyne.TextWrapWord
}
input.SetPlaceHolder(placeholderText)
- // Optimization 2: Reduce visible rows on mobile to limit rendering area
- if fyne.CurrentDevice().IsMobile() {
- input.SetMinRowsVisible(10)
- } else {
- input.SetMinRowsVisible(30)
- }
+ // Optimization 2: Reduce visible rows on mobile to limit rendering area
+ if fyne.CurrentDevice().IsMobile() {
+ input.SetMinRowsVisible(10)
+ } else {
+ input.SetMinRowsVisible(30)
+ }
// Optimization 3: Add text length indicator
charCount := widget.NewLabel("0 chars")
- // Optimization 4: Throttle text changes with validation
- input.OnChanged = func(text string) {
- // Update character count
- charCount.SetText(fmt.Sprintf("%d chars", len(text)))
+ // Optimization 4: Throttle text changes with validation
+ input.OnChanged = func(text string) {
+ // Update character count
+ charCount.SetText(fmt.Sprintf("%d chars", len(text)))
// Warn if text is getting too long
if len(text) > maxTextLength {
@@ -96,12 +96,20 @@ func createMainWindow(a fyne.App) fyne.Window {
charCount.SetText("0 chars")
})
- // Optimization 5: Add clear button for quick text clearing
- clearButton := widget.NewButton("Clear", func() {
- input.SetText("")
- charCount.SetText("0 chars")
- window.Canvas().Focus(input)
- })
+ // Optimization 5: Add clear button for quick text clearing
+ clearButton := widget.NewButton("Clear", func() {
+ input.SetText("")
+ charCount.SetText("0 chars")
+ window.Canvas().Focus(input)
+ })
+
+ // If running on Android and shared text file exists, load it into the input
+ if fyne.CurrentDevice().IsMobile() {
+ if txt, err := readSharedFromCache(); err == nil && txt != "" {
+ input.SetText(txt)
+ charCount.SetText(fmt.Sprintf("%d chars", len(txt)))
+ }
+ }
window.SetContent(container.NewVBox(
input,
@@ -114,8 +122,19 @@ func createMainWindow(a fyne.App) fyne.Window {
charCount, // Show character count
),
))
- window.Resize(windowSize)
- window.Canvas().Focus(input)
+ window.Resize(windowSize)
+ window.Canvas().Focus(input)
+
+ // On Android, also check for new shared text whenever app returns to foreground.
+ if lc := a.Lifecycle(); lc != nil {
+ lc.SetOnEnteredForeground(func() {
+ if txt, err := readSharedFromCache(); err == nil && txt != "" {
+ input.SetText(txt)
+ charCount.SetText(fmt.Sprintf("%d chars", len(txt)))
+ window.Canvas().Focus(input)
+ }
+ })
+ }
return window
}