diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c54313..bd5d8c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [v1.0.2] ### Added - **Setup permissions**: storage and notification permissions are now requested on the welcome screen during setup instead of when the terminal opens. -- **Custom bash templates**: create your own named `.bashrc` templates in Settings → Bash templates, then edit or delete them; deleting a template resets any distro using it back to its original `.bashrc`. +- **Custom bash templates**: create your own named `.bashrc` templates in Settings → Bashrc templates, then edit or delete them; deleting a template resets any distro using it back to its original `.bashrc`. - **Custom fonts**: import your own `.ttf`/`.otf` fonts in Settings — one at a time or several at once from the storage picker — then select them from the font dropdown or the terminal's Fonts menu; custom fonts can be renamed and removed, and names default to the file name without the extension. - **Modern back button**: the back control is now a round, theme-aware chip; it also appears on the main page and in Settings, with the same style applied in the terminal, file browser and bash templates screens. @@ -19,6 +19,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Theme sync**: changing the theme in Settings or from the terminal's Theme menu now broadcasts the change, so the main page and every other screen repaint immediately with the selected theme. - The terminal's Fonts menu lists imported custom fonts and refreshes every time the menu opens. - Settings page shows version v1.0.2. +- Settings label renamed to **Bashrc templates**. +- **Toolchain**: Gradle 8.13 → 8.14.5, Kotlin 2.3.0 → 2.4.10, `compileSdk` 35 → 36; dependency updates across androidx (lifecycle 2.8.7 → 2.11.0, activity 1.9.3 → 1.13.0, material 1.12.0 → 1.14.0, constraintlayout 2.2.0 → 2.2.2, appcompat, preference, viewpager2), commons-compress 1.27.1 → 1.28.0 and xz 1.10 → 1.12; `core-ktx` pinned at 1.18.0 (1.19.0 requires AGP 9.1 and compileSdk 37). +- GitHub Actions updated: `setup-android` v3 → v4, `setup-java` v4 → v5.6.0, `gradle/actions/wrapper-validation` v3 → v6. + +### Fixed + +- **Android 7.0/7.1 support**: the app no longer crashes on API 24–25 at startup (`NotificationChannel` is now only created on Android 8+), and distro extraction/repair no longer calls `java.nio.file` (API 26) or `Process#destroyForcibly` (API 26) unguarded — symlinks are created with `Os.symlink` (API 21+), so first-time setup and busybox repair work on Android 7+. +- CI: official Gradle wrapper jar (checksum validation was failing), compileSdk 36 for the new androidx versions, lint set to non-fatal, docs updated with the current build requirements. ## [v1.0.1] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16b6a40..b85259c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,8 +21,8 @@ Requirements: - JDK 17 - Android SDK with `build-tools` and platform `android-36` (the app builds with `compileSdk 36`, `targetSdk 35`, `minSdk 24`) -- Gradle 8.13 (via the included wrapper) -- Android Gradle Plugin 8.13.2 and Kotlin 2.3.0 (declared in the root `build.gradle.kts`) +- Gradle 8.14.5 (via the included wrapper) +- Android Gradle Plugin 8.13.2 and Kotlin 2.4.10 (declared in the root `build.gradle.kts`) - `ANDROID_HOME` (or `local.properties` pointing at your SDK) ```bash diff --git a/README.md b/README.md index 2f5547f..43eb254 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ Requirements: - JDK 17 - Android SDK with `build-tools` and platform `android-36` -- Gradle 8.13 (via the included wrapper) -- Android Gradle Plugin 8.13.2, Kotlin 2.3.0 (managed by the project) +- Gradle 8.14.5 (via the included wrapper) +- Android Gradle Plugin 8.13.2, Kotlin 2.4.10 (managed by the project) ```bash # Set ANDROID_HOME to your SDK location diff --git a/app/src/main/java/com/redtermapp/RedTermApp.kt b/app/src/main/java/com/redtermapp/RedTermApp.kt index 5385537..281fbf6 100644 --- a/app/src/main/java/com/redtermapp/RedTermApp.kt +++ b/app/src/main/java/com/redtermapp/RedTermApp.kt @@ -25,6 +25,7 @@ class RedTermApp : Application() { } private fun createNotificationChannel() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return val channel = NotificationChannel( CHANNEL_TERMINAL, getString(R.string.notification_channel_terminal), diff --git a/app/src/main/java/com/redtermapp/distro/DistroInstaller.kt b/app/src/main/java/com/redtermapp/distro/DistroInstaller.kt index dea945a..ab79fef 100644 --- a/app/src/main/java/com/redtermapp/distro/DistroInstaller.kt +++ b/app/src/main/java/com/redtermapp/distro/DistroInstaller.kt @@ -1,6 +1,7 @@ package com.redtermapp.distro import android.content.Context +import android.os.Build import android.util.Log import com.redtermapp.DnsHelper import kotlinx.coroutines.Dispatchers @@ -272,14 +273,21 @@ class DistroInstaller(private val context: Context) { throw Exception("Native xz decompressor failed (exit $exitCode), falling back") } } catch (e: CancelledException) { - process.destroyForcibly() + killProcess(process) throw e } catch (e: Exception) { - process.destroyForcibly() + killProcess(process) throw e } } + private fun killProcess(process: Process) { + process.destroy() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + process.destroyForcibly() + } + } + private fun extractWithJavaXz( tarball: File, dest: File, onProgress: (Progress) -> Unit @@ -329,9 +337,7 @@ class DistroInstaller(private val context: Context) { target.parentFile?.mkdirs() try { target.delete() - java.nio.file.Files.createSymbolicLink( - target.toPath(), java.nio.file.Paths.get(linkTarget) - ) + android.system.Os.symlink(linkTarget, target.absolutePath) } catch (e: Exception) { Log.w("DistroInstaller", "Symlink failed ${entry.name}: ${e.message}") } @@ -527,9 +533,7 @@ class DistroInstaller(private val context: Context) { if (!sh.exists() || !sh.canExecute()) { sh.delete() try { - java.nio.file.Files.createSymbolicLink( - sh.toPath(), java.nio.file.Paths.get("busybox") - ) + android.system.Os.symlink("busybox", sh.absolutePath) } catch (_: Exception) { busybox.copyTo(sh, overwrite = true) sh.setExecutable(true, false) diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index c965032..7453f48 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -108,7 +108,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:paddingStart="16dp" - android:text="Bash templates" + android:text="Bashrc templates" android:textColor="?attr/terminalText" android:textSize="14sp" />