diff --git a/-name *concept* -o -name *build* -o -name *app* -o -name *.md b/-name *concept* -o -name *build* -o -name *app* -o -name *.md new file mode 100644 index 0000000..4a9f4e4 --- /dev/null +++ b/-name *concept* -o -name *build* -o -name *app* -o -name *.md @@ -0,0 +1,63 @@ +commit 04975261a2b7e9f12c49c6c683a6f1b028d665ac (HEAD -> main, origin/main, origin/HEAD) +Author: yve-android +Date: Wed Dec 31 10:02:22 2025 +0100 + + Fix: Pin actions to commit SHA + +commit 7a98bc2688df9966cd75c3682f3342d90b44ac64 +Author: yve-android +Date: Tue Dec 30 11:05:01 2025 +0100 + + tools: add GitHub Actions compliance fixer + +commit 9d34cbf299295fb3e0467ab36c0deb9063851457 +Author: yve-android +Date: Tue Dec 30 10:35:49 2025 +0100 + + Fix: Pin actions to commit SHA + +commit fcf8feee6561f7fda6ee63943caa44acbf8235f1 +Author: Yve-android +Date: Mon Dec 29 01:11:59 2025 +0100 + + Create codeql.yml + +commit 680a047672d79ea8f923905196f2806bed8f14bb +Merge: 741e49e 9bd8483 +Author: Yve-android +Date: Sun Dec 28 23:44:52 2025 +0100 + + Potential fix for code scanning alert no. 1: Workflow does not contain permissions (#30) + + Potential fix for + [https://github.com/yve-android/blacky/security/code-scanning/1](https://github.com/yve-android/blacky/security/code-scanning/1) + + In general, fix this by adding an explicit `permissions:` block that + grants only the minimal scopes needed. Since this workflow only needs to + read repository contents (for `actions/checkout`) and upload an artifact + (which does not require repository write access), `contents: read` is + sufficient. + + The best single fix without changing functionality is to add a + workflow-level `permissions:` block near the top of + `.github/workflows/build-apk.yml`, so it applies to all jobs. Place it + after the `name:` (line 1) and before `on:` (line 3), with: + + ```yaml + permissions: + contents: read + ``` + + No additional imports, methods, or definitions are needed because this + is purely a YAML configuration change within the workflow file. + + + _Suggested fixes powered by Copilot Autofix. Review carefully before + merging._ + +commit 9bd84833464685f7b911eac0752f3bddb5d4cba5 +Merge: d1f07bf 741e49e +Author: Yve-android +Date: Sun Dec 28 23:44:43 2025 +0100 + + Merge branch 'blacky' into alert-autofix-1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..6d5e9d6 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,47 @@ +name: Build Blacky APK + +on: + push: + branches: [ main, blacky ] + pull_request: + branches: [ main, blacky ] + 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: Cache Gradle packages + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Build with Gradle + run: ./gradlew assembleDebug --stacktrace --no-daemon + + - name: Upload APK + uses: actions/upload-artifact@v3 + if: success() + with: + name: blacky-apk + path: app/build/outputs/apk/debug/*.apk + retention-days: 30 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e943e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Android Studio +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +*.apk +*.ap_ +*.dex + +# Gradle +.gradle/ +build/ + +# Local configuration +local.properties + +# Log Files +*.log diff --git a/android_setup.py b/android_setup.py new file mode 100644 index 0000000..ce3f5e5 --- /dev/null +++ b/android_setup.py @@ -0,0 +1,397 @@ +#!/usr/bin/env python3 +""" +Android Projekt Komplett-Setup Script +Erstellt eine vollständige Android-Projektstruktur von Grund auf +""" + +import os +import sys +from pathlib import Path + +class AndroidProjectSetup: + def __init__(self, repo_path=".", package_name="com.yve.blacky"): + self.repo_path = Path(repo_path) + self.package_name = package_name + self.package_path = package_name.replace(".", "/") + self.app_name = "Blacky" + + def log(self, message, level="INFO"): + print(f"[{level}] {message}") + + def create_directory_structure(self): + """Erstellt die komplette Android-Verzeichnisstruktur""" + self.log("Erstelle Android-Verzeichnisstruktur...") + + directories = [ + "app/src/main/java/" + self.package_path, + "app/src/main/res/layout", + "app/src/main/res/values", + "app/src/main/res/mipmap-hdpi", + "app/src/main/res/mipmap-mdpi", + "app/src/main/res/mipmap-xhdpi", + "app/src/main/res/mipmap-xxhdpi", + "app/src/main/res/mipmap-xxxhdpi", + "app/src/androidTest/java/" + self.package_path, + "app/src/test/java/" + self.package_path, + ] + + for directory in directories: + dir_path = self.repo_path / directory + dir_path.mkdir(parents=True, exist_ok=True) + self.log(f"✓ {directory}", "SUCCESS") + + def create_root_build_gradle(self): + """Erstellt root build.gradle""" + self.log("Erstelle root build.gradle...") + + content = """// 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 + id 'com.android.library' version '8.2.0' apply false + id 'org.jetbrains.kotlin.android' version '1.9.20' apply false +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} +""" + + build_gradle = self.repo_path / "build.gradle" + build_gradle.write_text(content) + self.log("✓ build.gradle erstellt", "SUCCESS") + + def create_settings_gradle(self): + """Erstellt settings.gradle""" + self.log("Erstelle settings.gradle...") + + content = """pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "Blacky" +include ':app' +""" + + settings_gradle = self.repo_path / "settings.gradle" + settings_gradle.write_text(content) + self.log("✓ settings.gradle erstellt", "SUCCESS") + + def create_app_build_gradle(self): + """Erstellt app/build.gradle""" + self.log("Erstelle app/build.gradle...") + + content = f"""plugins {{ + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +}} + +android {{ + namespace '{self.package_name}' + compileSdk 34 + + defaultConfig {{ + applicationId "{self.package_name}" + 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_17 + targetCompatibility JavaVersion.VERSION_17 + }} + + kotlinOptions {{ + jvmTarget = '17' + }} + + buildFeatures {{ + viewBinding true + }} +}} + +dependencies {{ + implementation 'androidx.core:core-ktx:1.12.0' + 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' +}} +""" + + app_build_gradle = self.repo_path / "app" / "build.gradle" + app_build_gradle.write_text(content) + self.log("✓ app/build.gradle erstellt", "SUCCESS") + + def create_android_manifest(self): + """Erstellt AndroidManifest.xml""" + self.log("Erstelle AndroidManifest.xml...") + + content = f""" + + + + + + + + + + + + + +""" + + manifest_path = self.repo_path / "app" / "src" / "main" / "AndroidManifest.xml" + manifest_path.write_text(content) + self.log("✓ AndroidManifest.xml erstellt", "SUCCESS") + + def create_main_activity(self): + """Erstellt MainActivity.kt""" + self.log("Erstelle MainActivity.kt...") + + content = f"""package {self.package_name} + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import android.widget.TextView + +class MainActivity : AppCompatActivity() {{ + + override fun onCreate(savedInstanceState: Bundle?) {{ + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val textView = findViewById(R.id.textView) + textView.text = "Welcome to {self.app_name}!" + }} +}} +""" + + main_activity_path = self.repo_path / "app" / "src" / "main" / "java" / self.package_path / "MainActivity.kt" + main_activity_path.write_text(content) + self.log("✓ MainActivity.kt erstellt", "SUCCESS") + + def create_layout_files(self): + """Erstellt Layout-Dateien""" + self.log("Erstelle Layout-Dateien...") + + # activity_main.xml + activity_main_content = """ + + + + + +""" + + layout_path = self.repo_path / "app" / "src" / "main" / "res" / "layout" / "activity_main.xml" + layout_path.write_text(activity_main_content) + self.log("✓ activity_main.xml erstellt", "SUCCESS") + + def create_string_resources(self): + """Erstellt strings.xml""" + self.log("Erstelle strings.xml...") + + content = f""" + + {self.app_name} + +""" + + strings_path = self.repo_path / "app" / "src" / "main" / "res" / "values" / "strings.xml" + strings_path.write_text(content) + self.log("✓ strings.xml erstellt", "SUCCESS") + + def create_color_resources(self): + """Erstellt colors.xml""" + self.log("Erstelle colors.xml...") + + content = """ + + #FF000000 + #FFFFFFFF + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + +""" + + colors_path = self.repo_path / "app" / "src" / "main" / "res" / "values" / "colors.xml" + colors_path.write_text(content) + self.log("✓ colors.xml erstellt", "SUCCESS") + + def create_proguard_rules(self): + """Erstellt proguard-rules.pro""" + self.log("Erstelle proguard-rules.pro...") + + content = """# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. + +# Keep common Android classes +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider + +# Keep Kotlin metadata +-keep class kotlin.Metadata { *; } +""" + + proguard_path = self.repo_path / "app" / "proguard-rules.pro" + proguard_path.write_text(content) + self.log("✓ proguard-rules.pro erstellt", "SUCCESS") + + def create_gitignore(self): + """Erstellt/erweitert .gitignore""" + self.log("Erstelle/erweitere .gitignore...") + + gitignore_content = """# Android Studio +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +*.apk +*.ap_ +*.dex + +# Gradle +.gradle/ +build/ + +# Local configuration +local.properties + +# Log Files +*.log +""" + + gitignore_path = self.repo_path / ".gitignore" + if gitignore_path.exists(): + existing = gitignore_path.read_text() + if "*.iml" not in existing: + gitignore_path.write_text(existing + "\n" + gitignore_content) + self.log("✓ .gitignore erweitert", "SUCCESS") + else: + self.log("✓ .gitignore bereits vorhanden", "SUCCESS") + else: + gitignore_path.write_text(gitignore_content) + self.log("✓ .gitignore erstellt", "SUCCESS") + + def run_setup(self): + """Führt das komplette Setup aus""" + self.log("=" * 60) + self.log("🚀 Starte Android Projekt Setup") + self.log("=" * 60) + self.log(f"Package: {self.package_name}") + self.log(f"App Name: {self.app_name}") + self.log("") + + self.create_directory_structure() + self.log("") + + self.create_root_build_gradle() + self.create_settings_gradle() + self.create_app_build_gradle() + self.log("") + + self.create_android_manifest() + self.create_main_activity() + self.log("") + + self.create_layout_files() + self.create_string_resources() + self.create_color_resources() + self.log("") + + self.create_proguard_rules() + self.create_gitignore() + + self.log("") + self.log("=" * 60) + self.log("✅ Android Projekt Setup abgeschlossen!") + self.log("=" * 60) + self.log("") + self.log("📋 Nächste Schritte:") + self.log("1. Führe './gradlew build' aus") + self.log("2. Prüfe mit 'ls -la app/'") + self.log("3. Teste mit './gradlew assembleDebug'") + self.log("4. Führe dann das repair_actions.py Script aus") + self.log("5. Committe alles: git add . && git commit -m 'Initial Android project setup'") + self.log("") + +if __name__ == "__main__": + repo_path = sys.argv[1] if len(sys.argv) > 1 else "." + package_name = sys.argv[2] if len(sys.argv) > 2 else "com.yve.blacky" + + setup = AndroidProjectSetup(repo_path, package_name) + setup.run_setup() diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..5da31c6 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,50 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} + +android { + namespace 'com.yve.blacky' + compileSdk 34 + + defaultConfig { + applicationId "com.yve.blacky" + 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_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' + } + + buildFeatures { + viewBinding true + } +} + +dependencies { + implementation 'androidx.core:core-ktx:1.12.0' + 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..0fe4414 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,13 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. + +# Keep common Android classes +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider + +# Keep Kotlin metadata +-keep class kotlin.Metadata { *; } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..73e91c0 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/yve/blacky/MainActivity.kt b/app/src/main/java/com/yve/blacky/MainActivity.kt new file mode 100644 index 0000000..f43650e --- /dev/null +++ b/app/src/main/java/com/yve/blacky/MainActivity.kt @@ -0,0 +1,16 @@ +package com.yve.blacky + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import android.widget.TextView + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val textView = findViewById(R.id.textView) + textView.text = "Welcome to Blacky!" + } +} 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..010890c --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..7aaab4c --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FF000000 + #FFFFFFFF + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..bdaa186 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Blacky + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..7c23bdf --- /dev/null +++ b/build.gradle @@ -0,0 +1,12 @@ +// 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 + id 'com.android.library' version '8.2.0' apply false + id 'org.jetbrains.kotlin.android' version '1.9.20' apply false +} + + +task clean(type: Delete) { + delete rootProject.buildDir +} +// Build configuration for Blacky APK diff --git a/build.gradle~ b/build.gradle~ new file mode 100644 index 0000000..5853c52 --- /dev/null +++ b/build.gradle~ @@ -0,0 +1,17 @@ +// 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 + id 'com.android.library' version '8.2.0' apply false + id 'org.jetbrains.kotlin.android' version '1.9.20' apply false +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..4f9766b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,12 @@ +# Project-wide Gradle settings +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.daemon=true + +# AndroidX +android.useAndroidX=true +android.enableJetifier=true + +# Kotlin +kotlin.code.style=official diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..61285a6 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..1af9e09 --- /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.5-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..73987ab --- /dev/null +++ b/gradlew @@ -0,0 +1,11 @@ +#!/bin/sh + +############################################################################## +# Gradle startup script for UN*X +############################################################################## + +# Resolve links: $0 may be a link +APP_HOME="${0%/*}" +cd "$APP_HOME" || exit + +exec java -classpath "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9978290 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,11 @@ +@echo off +@rem Gradle startup script for Windows + +setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. + +java -classpath "%DIRNAME%\gradle\wrapper\gradle-wrapper.jar" org.gradle.wrapper.GradleWrapperMain %* + +:end diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..946c551 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "Blacky" +include ':app' diff --git a/settings.gradle~ b/settings.gradle~ new file mode 100644 index 0000000..3aa9687 --- /dev/null +++ b/settings.gradle~ @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "Blacky" +include ':app'