summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-08 00:05:39 +0300
committerPaul Buetow <paul@buetow.org>2026-05-08 00:05:39 +0300
commit3e4bacb7b939b1de98a2fb07115f638750637357 (patch)
tree0897a6854d1c3ca3b1d0252657e992abbba061ba /android
parent665b150727ee7259e398d38d1f6bc51b4c2d4a1c (diff)
Rewrite as Flutter app and rename to Quicklogmain
Drop the Go/Fyne implementation and replace it with a native Flutter app targeting Android (primary) and Linux desktop (development). Rename quicklogger -> quicklog throughout (project, applicationId, MethodChannel, cache filename, AppBar title, Linux binary). Storage on Android moves to /Android/data/org.buetow.quicklog/files/ so MANAGE_EXTERNAL_STORAGE is no longer required. Share-intent receive is preserved via a Kotlin ShareActivity that writes shared text to the app cache, which Dart reads through a MethodChannel on app resume; MainActivity also accepts SEND directly so launchers that prefer the main target work. New since the Fyne version: an entry browser screen with read-only viewer and long-press delete. Cross-compiling to Android ARM from amd64 Linux no longer needs Docker / fyne-cross / NDK -- flutter build apk emits ARM binaries directly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Diffstat (limited to 'android')
-rw-r--r--android/.gitignore14
-rw-r--r--android/AndroidManifest.xml36
-rw-r--r--android/app/build.gradle.kts44
-rw-r--r--android/app/src/debug/AndroidManifest.xml7
-rw-r--r--android/app/src/main/AndroidManifest.xml56
-rw-r--r--android/app/src/main/kotlin/org/buetow/quicklog/MainActivity.kt56
-rw-r--r--android/app/src/main/kotlin/org/buetow/quicklog/ShareActivity.kt54
-rw-r--r--android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.pngbin0 -> 26129 bytes
-rw-r--r--android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.pngbin0 -> 15260 bytes
-rw-r--r--android/app/src/main/res/drawable-v21/launch_background.xml12
-rw-r--r--android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.pngbin0 -> 38865 bytes
-rw-r--r--android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.pngbin0 -> 67448 bytes
-rw-r--r--android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.pngbin0 -> 98799 bytes
-rw-r--r--android/app/src/main/res/drawable/launch_background.xml12
-rw-r--r--android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml9
-rw-r--r--android/app/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 9013 bytes
-rw-r--r--android/app/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 5127 bytes
-rw-r--r--android/app/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 13086 bytes
-rw-r--r--android/app/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 22244 bytes
-rw-r--r--android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin0 -> 32096 bytes
-rw-r--r--android/app/src/main/res/values-night/styles.xml18
-rw-r--r--android/app/src/main/res/values/colors.xml4
-rw-r--r--android/app/src/main/res/values/styles.xml18
-rw-r--r--android/app/src/profile/AndroidManifest.xml7
-rw-r--r--android/build.gradle.kts24
-rw-r--r--android/gradle.properties2
-rw-r--r--android/gradle/wrapper/gradle-wrapper.properties5
-rw-r--r--android/settings.gradle.kts26
28 files changed, 368 insertions, 36 deletions
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..be3943c
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,14 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+.cxx/
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/to/reference-keystore
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
deleted file mode 100644
index 0e6115e..0000000
--- a/android/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- package="org.buetow.quicklogger">
-
- <application>
- <!-- Also accept SEND on the main Go activity (some launchers prefer direct targets) -->
- <activity
- android:name="org.golang.app.GoNativeActivity"
- android:exported="true"
- tools:node="merge">
- <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>
-
- <!-- Share receiver activity: writes text to cache and launches main app -->
- <activity
- android:name=".ShareActivity"
- android:exported="true"
- android:excludeFromRecents="true"
- android:launchMode="singleTask"
- 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/app/build.gradle.kts b/android/app/build.gradle.kts
new file mode 100644
index 0000000..3333b8a
--- /dev/null
+++ b/android/app/build.gradle.kts
@@ -0,0 +1,44 @@
+plugins {
+ id("com.android.application")
+ id("kotlin-android")
+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+ id("dev.flutter.flutter-gradle-plugin")
+}
+
+android {
+ namespace = "org.buetow.quicklog"
+ compileSdk = flutter.compileSdkVersion
+ ndkVersion = flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+
+ kotlinOptions {
+ jvmTarget = JavaVersion.VERSION_17.toString()
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId = "org.buetow.quicklog"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://flutter.dev/to/review-gradle-config.
+ minSdk = flutter.minSdkVersion
+ targetSdk = flutter.targetSdkVersion
+ versionCode = flutter.versionCode
+ versionName = flutter.versionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig = signingConfigs.getByName("debug")
+ }
+ }
+}
+
+flutter {
+ source = "../.."
+}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6eddff0
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,56 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <application
+ android:label="Quicklog"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:taskAffinity=""
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <!-- Some launchers prefer routing SEND directly to the main activity. -->
+ <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>
+ <!-- Translucent share receiver: writes shared text to cache then hands off to MainActivity. -->
+ <activity
+ android:name=".ShareActivity"
+ android:exported="true"
+ android:excludeFromRecents="true"
+ android:launchMode="singleTask"
+ 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>
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+ <queries>
+ <intent>
+ <action android:name="android.intent.action.PROCESS_TEXT"/>
+ <data android:mimeType="text/plain"/>
+ </intent>
+ </queries>
+</manifest>
diff --git a/android/app/src/main/kotlin/org/buetow/quicklog/MainActivity.kt b/android/app/src/main/kotlin/org/buetow/quicklog/MainActivity.kt
new file mode 100644
index 0000000..426589f
--- /dev/null
+++ b/android/app/src/main/kotlin/org/buetow/quicklog/MainActivity.kt
@@ -0,0 +1,56 @@
+package org.buetow.quicklog
+
+import android.content.Intent
+import android.os.Bundle
+import io.flutter.embedding.android.FlutterActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodChannel
+import java.io.File
+
+class MainActivity : FlutterActivity() {
+ private val channelName = "org.buetow.quicklog/share"
+ private val cacheFilename = "quicklog-shared.txt"
+
+ override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelName)
+ .setMethodCallHandler { call, result ->
+ when (call.method) {
+ "readSharedTextFromCache" -> result.success(readCache())
+ "clearSharedTextCache" -> {
+ clearCache()
+ result.success(null)
+ }
+ else -> result.notImplemented()
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ captureSendIntent(intent)
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ captureSendIntent(intent)
+ }
+
+ private fun captureSendIntent(intent: Intent?) {
+ if (intent?.action == Intent.ACTION_SEND && intent.type?.startsWith("text/") == true) {
+ intent.getStringExtra(Intent.EXTRA_TEXT)?.let { text ->
+ File(cacheDir, cacheFilename).writeText(text)
+ }
+ }
+ }
+
+ private fun readCache(): String? {
+ val f = File(cacheDir, cacheFilename)
+ return if (f.exists()) f.readText() else null
+ }
+
+ private fun clearCache() {
+ val f = File(cacheDir, cacheFilename)
+ if (f.exists()) f.delete()
+ }
+}
diff --git a/android/app/src/main/kotlin/org/buetow/quicklog/ShareActivity.kt b/android/app/src/main/kotlin/org/buetow/quicklog/ShareActivity.kt
new file mode 100644
index 0000000..15261e6
--- /dev/null
+++ b/android/app/src/main/kotlin/org/buetow/quicklog/ShareActivity.kt
@@ -0,0 +1,54 @@
+package org.buetow.quicklog
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import java.io.File
+
+class ShareActivity : Activity() {
+ companion object {
+ private const val TAG = "QuicklogShare"
+ private const val CACHE_FILENAME = "quicklog-shared.txt"
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ handleShare(intent)
+ launchMain()
+ finish()
+ }
+
+ private fun handleShare(intent: Intent?) {
+ if (intent == null) return
+ val type = intent.type
+ if (intent.action == Intent.ACTION_SEND && type != null && type.startsWith("text/")) {
+ val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT)
+ if (sharedText != null) {
+ try {
+ val f = File(cacheDir, CACHE_FILENAME)
+ f.writeText(sharedText)
+ Log.i(TAG, "Wrote shared text to ${f.absolutePath}")
+ } catch (e: Exception) {
+ Log.e(TAG, "Error writing shared text", e)
+ }
+ }
+ }
+ }
+
+ private fun launchMain() {
+ try {
+ val launch = Intent(this, MainActivity::class.java).apply {
+ action = Intent.ACTION_MAIN
+ addCategory(Intent.CATEGORY_LAUNCHER)
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or
+ Intent.FLAG_ACTIVITY_SINGLE_TOP or
+ Intent.FLAG_ACTIVITY_CLEAR_TOP or
+ Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
+ }
+ startActivity(launch)
+ } catch (t: Throwable) {
+ Log.e(TAG, "Failed to launch main activity", t)
+ }
+ }
+}
diff --git a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..a454844
--- /dev/null
+++ b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
Binary files differ
diff --git a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..7a9bc40
--- /dev/null
+++ b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
Binary files differ
diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..7badce7
--- /dev/null
+++ b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
Binary files differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..5ed2063
--- /dev/null
+++ b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
Binary files differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..089a22a
--- /dev/null
+++ b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
Binary files differ
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..c79c58a
--- /dev/null
+++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/ic_launcher_background"/>
+ <foreground>
+ <inset
+ android:drawable="@drawable/ic_launcher_foreground"
+ android:inset="16%" />
+ </foreground>
+</adaptive-icon>
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..f75d22f
--- /dev/null
+++ b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..d24ba69
--- /dev/null
+++ b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..b49236f
--- /dev/null
+++ b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..a20c849
--- /dev/null
+++ b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..9a1fafa
--- /dev/null
+++ b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..c5d5899
--- /dev/null
+++ b/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="ic_launcher_background">#FFFFFF</color>
+</resources> \ No newline at end of file
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/android/build.gradle.kts b/android/build.gradle.kts
new file mode 100644
index 0000000..dbee657
--- /dev/null
+++ b/android/build.gradle.kts
@@ -0,0 +1,24 @@
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+val newBuildDir: Directory =
+ rootProject.layout.buildDirectory
+ .dir("../../build")
+ .get()
+rootProject.layout.buildDirectory.value(newBuildDir)
+
+subprojects {
+ val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
+ project.layout.buildDirectory.value(newSubprojectBuildDir)
+}
+subprojects {
+ project.evaluationDependsOn(":app")
+}
+
+tasks.register<Delete>("clean") {
+ delete(rootProject.layout.buildDirectory)
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..fbee1d8
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
+android.useAndroidX=true
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e4ef43f
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts
new file mode 100644
index 0000000..ca7fe06
--- /dev/null
+++ b/android/settings.gradle.kts
@@ -0,0 +1,26 @@
+pluginManagement {
+ val flutterSdkPath =
+ run {
+ val properties = java.util.Properties()
+ file("local.properties").inputStream().use { properties.load(it) }
+ val flutterSdkPath = properties.getProperty("flutter.sdk")
+ require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
+ flutterSdkPath
+ }
+
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+plugins {
+ id("dev.flutter.flutter-plugin-loader") version "1.0.0"
+ id("com.android.application") version "8.11.1" apply false
+ id("org.jetbrains.kotlin.android") version "2.2.20" apply false
+}
+
+include(":app")