Overlay
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -2,7 +2,14 @@ experiment
|
||||
dist
|
||||
node_modules
|
||||
devAssets
|
||||
|
||||
# Tauri mobile outputs are regenerated from init + the tracked overlay below.
|
||||
src-tauri/gen/android
|
||||
src-tauri/gen/ios
|
||||
src-tauri/gen/schemas
|
||||
|
||||
# Tracked Android overlay reapplied by scripts/prepare-android-gen.sh
|
||||
!src-tauri/android-overlay/
|
||||
!src-tauri/android-overlay/**
|
||||
|
||||
.DS_Store
|
||||
|
||||
@@ -6,27 +6,26 @@ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
||||
REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
|
||||
SOURCE_ICON="$REPO_ROOT/src-tauri/icons/icon.png"
|
||||
ANDROID_OVERLAY_DIR="$REPO_ROOT/src-tauri/android-overlay"
|
||||
ANDROID_APP_DIR="$REPO_ROOT/src-tauri/gen/android/app"
|
||||
ANDROID_RES_DIR="$ANDROID_APP_DIR/src/main/res"
|
||||
ANDROID_VALUES_DIR="$ANDROID_RES_DIR/values"
|
||||
ANDROID_VALUES_NIGHT_DIR="$ANDROID_RES_DIR/values-night"
|
||||
ANDROID_GRADLE_FILE="$ANDROID_APP_DIR/build.gradle.kts"
|
||||
ANDROID_MAIN_ACTIVITY="$ANDROID_APP_DIR/src/main/java/in/cinny/app/MainActivity.kt"
|
||||
ANDROID_BUILDTASK_FILE="$REPO_ROOT/src-tauri/gen/android/buildSrc/src/main/java/in/cinny/app/kotlin/BuildTask.kt"
|
||||
|
||||
if [ ! -f "$SOURCE_ICON" ]; then
|
||||
echo "Missing source icon: $SOURCE_ICON" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$ANDROID_OVERLAY_DIR" ]; then
|
||||
echo "Missing Android overlay directory: $ANDROID_OVERLAY_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$ANDROID_RES_DIR" ]; then
|
||||
echo "Missing Android resources directory: $ANDROID_RES_DIR" >&2
|
||||
echo "Run android init first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$ANDROID_VALUES_DIR" "$ANDROID_VALUES_NIGHT_DIR"
|
||||
|
||||
resize_icon() {
|
||||
size="$1"
|
||||
output="$2"
|
||||
@@ -56,216 +55,9 @@ do
|
||||
resize_icon "$1" "$ANDROID_RES_DIR/$2/ic_launcher_foreground.png"
|
||||
done
|
||||
|
||||
cat > "$ANDROID_GRADLE_FILE" <<'EOF'
|
||||
import java.io.FileInputStream
|
||||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("rust")
|
||||
}
|
||||
|
||||
val tauriProperties = Properties().apply {
|
||||
val propFile = file("tauri.properties")
|
||||
if (propFile.exists()) {
|
||||
propFile.inputStream().use { load(it) }
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = 36
|
||||
namespace = "in.cinny.app"
|
||||
defaultConfig {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||
applicationId = "in.cinny.app"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
|
||||
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
|
||||
}
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["password"] as String
|
||||
storeFile = file(keystoreProperties["storeFile"] as String)
|
||||
storePassword = keystoreProperties["password"] as String
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
getByName("debug") {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
packaging {
|
||||
jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
|
||||
}
|
||||
}
|
||||
getByName("release") {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
*fileTree(".") { include("**/*.pro") }
|
||||
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
|
||||
.toList().toTypedArray()
|
||||
)
|
||||
}
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
rust {
|
||||
rootDirRel = "../../../"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.webkit:webkit:1.14.0")
|
||||
implementation("androidx.appcompat:appcompat:1.7.1")
|
||||
implementation("androidx.activity:activity-ktx:1.10.1")
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.4")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
|
||||
}
|
||||
|
||||
apply(from = "tauri.build.gradle.kts")
|
||||
EOF
|
||||
|
||||
cat > "$ANDROID_MAIN_ACTIVITY" <<'EOF'
|
||||
package `in`.cinny.app
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
|
||||
class MainActivity : TauriActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val content = findViewById<android.view.View>(android.R.id.content)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(content) { view, windowInsets ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
view.updatePadding(
|
||||
left = insets.left,
|
||||
top = insets.top,
|
||||
right = insets.right,
|
||||
bottom = insets.bottom,
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > "$ANDROID_BUILDTASK_FILE" <<'EOF'
|
||||
import java.io.File
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
open class BuildTask : DefaultTask() {
|
||||
@Input
|
||||
var rootDirRel: String? = null
|
||||
@Input
|
||||
var target: String? = null
|
||||
@Input
|
||||
var release: Boolean? = null
|
||||
|
||||
@TaskAction
|
||||
fun assemble() {
|
||||
val executable = """node"""
|
||||
try {
|
||||
runTauriCli(executable)
|
||||
} catch (e: Exception) {
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
runTauriCli("$executable.cmd")
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runTauriCli(executable: String) {
|
||||
val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
|
||||
val target = target ?: throw GradleException("target cannot be null")
|
||||
val release = release ?: throw GradleException("release cannot be null")
|
||||
val tauriCli = File(
|
||||
project.projectDir,
|
||||
"${rootDirRel}/../node_modules/@tauri-apps/cli/tauri.js"
|
||||
).canonicalPath
|
||||
val args = listOf(tauriCli, "android", "android-studio-script")
|
||||
|
||||
project.exec {
|
||||
workingDir(File(project.projectDir, rootDirRel))
|
||||
executable(executable)
|
||||
args(args)
|
||||
if (project.logger.isEnabled(LogLevel.DEBUG)) {
|
||||
args("-vv")
|
||||
} else if (project.logger.isEnabled(LogLevel.INFO)) {
|
||||
args("-v")
|
||||
}
|
||||
if (release) {
|
||||
args("--release")
|
||||
}
|
||||
args(listOf("--target", target))
|
||||
}.assertNormalExitValue()
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > "$ANDROID_VALUES_DIR/colors.xml" <<'EOF'
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="cinny_system_bar_background">#1A1A1A</color>
|
||||
</resources>
|
||||
EOF
|
||||
|
||||
cat > "$ANDROID_VALUES_NIGHT_DIR/colors.xml" <<'EOF'
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="cinny_system_bar_background">#1A1A1A</color>
|
||||
</resources>
|
||||
EOF
|
||||
|
||||
cat > "$ANDROID_VALUES_DIR/themes.xml" <<'EOF'
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.cinny" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="android:statusBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:navigationBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
</style>
|
||||
</resources>
|
||||
EOF
|
||||
|
||||
cat > "$ANDROID_VALUES_NIGHT_DIR/themes.xml" <<'EOF'
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.cinny" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="android:statusBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:navigationBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
</style>
|
||||
</resources>
|
||||
EOF
|
||||
find "$ANDROID_OVERLAY_DIR" -type f | while IFS= read -r overlay_file; do
|
||||
relative_path=${overlay_file#"$ANDROID_OVERLAY_DIR/"}
|
||||
destination="$REPO_ROOT/src-tauri/gen/android/$relative_path"
|
||||
mkdir -p "$(dirname "$destination")"
|
||||
cp "$overlay_file" "$destination"
|
||||
done
|
||||
|
||||
87
src-tauri/android-overlay/app/build.gradle.kts
Normal file
87
src-tauri/android-overlay/app/build.gradle.kts
Normal file
@@ -0,0 +1,87 @@
|
||||
import java.io.FileInputStream
|
||||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("rust")
|
||||
}
|
||||
|
||||
val tauriProperties = Properties().apply {
|
||||
val propFile = file("tauri.properties")
|
||||
if (propFile.exists()) {
|
||||
propFile.inputStream().use { load(it) }
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = 36
|
||||
namespace = "in.cinny.app"
|
||||
defaultConfig {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||
applicationId = "in.cinny.app"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
|
||||
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
|
||||
}
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["password"] as String
|
||||
storeFile = file(keystoreProperties["storeFile"] as String)
|
||||
storePassword = keystoreProperties["password"] as String
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
getByName("debug") {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
packaging {
|
||||
jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
|
||||
}
|
||||
}
|
||||
getByName("release") {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
*fileTree(".") { include("**/*.pro") }
|
||||
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
|
||||
.toList().toTypedArray()
|
||||
)
|
||||
}
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
rust {
|
||||
rootDirRel = "../../../"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.webkit:webkit:1.14.0")
|
||||
implementation("androidx.appcompat:appcompat:1.7.1")
|
||||
implementation("androidx.activity:activity-ktx:1.10.1")
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.4")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
|
||||
}
|
||||
|
||||
apply(from = "tauri.build.gradle.kts")
|
||||
@@ -0,0 +1,24 @@
|
||||
package `in`.cinny.app
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.updatePadding
|
||||
|
||||
class MainActivity : TauriActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val content = findViewById<android.view.View>(android.R.id.content)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(content) { view, windowInsets ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
view.updatePadding(
|
||||
left = insets.left,
|
||||
top = insets.top,
|
||||
right = insets.right,
|
||||
bottom = insets.bottom,
|
||||
)
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="cinny_system_bar_background">#1A1A1A</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.cinny" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="android:statusBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:navigationBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="cinny_system_bar_background">#1A1A1A</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.cinny" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="android:statusBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:navigationBarColor">@color/cinny_system_bar_background</item>
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,56 @@
|
||||
import java.io.File
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
open class BuildTask : DefaultTask() {
|
||||
@Input
|
||||
var rootDirRel: String? = null
|
||||
@Input
|
||||
var target: String? = null
|
||||
@Input
|
||||
var release: Boolean? = null
|
||||
|
||||
@TaskAction
|
||||
fun assemble() {
|
||||
val executable = """node"""
|
||||
try {
|
||||
runTauriCli(executable)
|
||||
} catch (e: Exception) {
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
runTauriCli("$executable.cmd")
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runTauriCli(executable: String) {
|
||||
val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
|
||||
val target = target ?: throw GradleException("target cannot be null")
|
||||
val release = release ?: throw GradleException("release cannot be null")
|
||||
val tauriCli = File(
|
||||
project.projectDir,
|
||||
"${rootDirRel}/../node_modules/@tauri-apps/cli/tauri.js"
|
||||
).canonicalPath
|
||||
val args = listOf(tauriCli, "android", "android-studio-script")
|
||||
|
||||
project.exec {
|
||||
workingDir(File(project.projectDir, rootDirRel))
|
||||
executable(executable)
|
||||
args(args)
|
||||
if (project.logger.isEnabled(LogLevel.DEBUG)) {
|
||||
args("-vv")
|
||||
} else if (project.logger.isEnabled(LogLevel.INFO)) {
|
||||
args("-v")
|
||||
}
|
||||
if (release) {
|
||||
args("--release")
|
||||
}
|
||||
args(listOf("--target", target))
|
||||
}.assertNormalExitValue()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user