From 28a92d1831ed63c3b519b5da7cae52884b2756ad Mon Sep 17 00:00:00 2001 From: amos Date: Mon, 1 Jun 2026 19:46:33 +0800 Subject: [PATCH] Initial Android CI project with Gitea Actions --- .gitea/workflows/android-build.yml | 75 +++++++++++++++++++ .gitignore | 67 +++++++++++++++++ README.md | 59 +++++++++++++++ app/build.gradle | 38 ++++++++++ app/proguard-rules.pro | 5 ++ app/src/main/AndroidManifest.xml | 19 +++++ .../java/com/example/demo/MainActivity.java | 12 +++ app/src/main/res/layout/activity_main.xml | 19 +++++ app/src/main/res/values/colors.xml | 10 +++ app/src/main/res/values/strings.xml | 4 + app/src/main/res/values/themes.xml | 11 +++ build.gradle | 4 + gradle.properties | 3 + gradle/wrapper/gradle-wrapper.properties | 7 ++ gradlew | 13 ++++ settings.gradle | 16 ++++ 16 files changed, 362 insertions(+) create mode 100644 .gitea/workflows/android-build.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/example/demo/MainActivity.java create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 settings.gradle diff --git a/.gitea/workflows/android-build.yml b/.gitea/workflows/android-build.yml new file mode 100644 index 0000000..2fad833 --- /dev/null +++ b/.gitea/workflows/android-build.yml @@ -0,0 +1,75 @@ +name: Android Build + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build + + - name: Build Debug APK + run: ./gradlew assembleDebug + + - name: Upload APK + uses: actions/upload-artifact@v4 + with: + name: app-debug + path: app/build/outputs/apk/debug/app-debug.apk + + release: + needs: build + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: gradle + + - name: Decode Keystore + if: ${{ env.ANDROID_KEYSTORE_BASE64 }} + run: | + echo $ANDROID_KEYSTORE_BASE64 | base64 -d > keystore.jks + env: + ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} + + - name: Build Release APK + run: ./gradlew assembleRelease + env: + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: app/build/outputs/apk/release/app-release.apk + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..533b4f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +# Built application files +*.apk +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/ +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +.idea/caches +.idea/modules.xml + +# Keystore files +*.jks +*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ + +# Android Profiling +*.hprof diff --git a/README.md b/README.md new file mode 100644 index 0000000..6955f8f --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# Android CI Demo + +基于 Gitea Actions 的 Android 自动编译项目 + +## 功能 + +- ✅ 自动编译 Android APK +- ✅ 缓存 Gradle 依赖 +- ✅ 签名 APK(可选) +- ✅ 发布 Release + +## 快速开始 + +1. 在 Gitea 上创建新仓库 +2. 推送代码: + ```bash + git remote add origin https://gitea.kg8.net/amos/android-ci-demo.git + git push -u origin master + ``` +3. 触发 CI:推送代码或手动运行 workflow + +## 项目结构 + +``` +android-ci-demo/ +├── .gitea/ +│ └── workflows/ +│ └── android-build.yml # Gitea Actions 工作流 +├── app/ +│ ├── build.gradle # App 模块构建配置 +│ └── src/ +│ └── main/ +│ ├── AndroidManifest.xml +│ ├── java/ +│ │ └── com/ +│ │ └── example/ +│ │ └── demo/ +│ │ └── MainActivity.java +│ └── res/ +│ └── layout/ +│ └── activity_main.xml +├── build.gradle # 项目级构建配置 +├── settings.gradle # 项目设置 +├── gradle.properties # Gradle 属性 +└── gradlew # Gradle Wrapper +``` + +## 配置签名(可选) + +在 Gitea 仓库设置中添加 Secrets: + +- `ANDROID_KEYSTORE_BASE64`: Keystore 文件的 Base64 编码 +- `ANDROID_KEYSTORE_PASSWORD`: Keystore 密码 +- `ANDROID_KEY_ALIAS`: Key 别名 +- `ANDROID_KEY_PASSWORD`: Key 密码 + +## License + +MIT diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..da4356b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.example.androidcidemo' + compileSdk 34 + + defaultConfig { + applicationId "com.example.androidcidemo" + minSdk 24 + targetSdk 34 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.11.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..c18a71d --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,5 @@ +# Add project specific ProGuard rules here. +-keepattributes *Annotation* +-keepclassmembers class * { + @android.webkit.JavascriptInterface ; +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..deeca60 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/app/src/main/java/com/example/demo/MainActivity.java b/app/src/main/java/com/example/demo/MainActivity.java new file mode 100644 index 0000000..3e855a2 --- /dev/null +++ b/app/src/main/java/com/example/demo/MainActivity.java @@ -0,0 +1,12 @@ +package com.example.androidcidemo; + +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; + +public class MainActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..abcd8d4 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..ca1931b --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..1bc453a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Android CI Demo + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..e9f0a01 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,11 @@ + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..8df2f08 --- /dev/null +++ b/build.gradle @@ -0,0 +1,4 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id 'com.android.application' version '8.2.0' apply false +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..cc18a0c --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +android.useAndroidX=true +android.enableJetifier=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..62f495d --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..e8c9f5a --- /dev/null +++ b/gradlew @@ -0,0 +1,13 @@ +#!/bin/bash +# Gradle Wrapper Script (Simplified for CI) +# In production, use: gradle wrapper + +GRADLE_VERSION="8.2" +GRADLE_HOME="${GRADLE_HOME:-/opt/gradle}" + +if [ ! -d "$GRADLE_HOME" ]; then + echo "Gradle not found, using system gradle..." + exec gradle "$@" +fi + +exec "$GRADLE_HOME/bin/gradle" "$@" diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..61a0a68 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +rootProject.name = "AndroidCIDemo" +include ':app'