diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a83ef38 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: github-actions + directory: / + schedule: + interval: daily diff --git a/.github/workflows/attach_debug_apk_to_release.yml b/.github/workflows/attach_debug_apk_to_release.yml deleted file mode 100644 index 2a42147..0000000 --- a/.github/workflows/attach_debug_apk_to_release.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Attach Debug APK To Release - -on: - release: - types: - - published - -jobs: - attach-apks: - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Clone repository - uses: actions/checkout@v2 - with: - ref: ${{ env.GITHUB_REF }} - - - name: Build and attach APK to release - shell: bash {0} - run: | - exit_on_error() { - echo "$1" - echo "Deleting '$RELEASE_VERSION_NAME' release and '$GITHUB_REF' tag" - hub release delete "$RELEASE_VERSION_NAME" - git push --delete origin "$GITHUB_REF" - exit 1 - } - - echo "Setting vars" - RELEASE_VERSION_NAME="${GITHUB_REF/refs\/tags\//}" - if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then - exit_on_error "The versionName '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html." - fi - - APK_DIR_PATH="./app/build/outputs/apk/debug" - APK_VERSION_TAG="$RELEASE_VERSION_NAME+github-debug" - APK_BASENAME_PREFIX="termux-float_$APK_VERSION_TAG" - - echo "Building APK for '$RELEASE_VERSION_NAME' release" - export TERMUX_FLOAT_APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle - if ! ./gradlew assembleDebug; then - exit_on_error "Build failed for '$RELEASE_VERSION_NAME' release." - fi - - echo "Validating APK" - if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then - files_found="$(ls "$APK_DIR_PATH")" - exit_on_error "Failed to find built APK at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found" - fi - - echo "Generating sha25sums file" - if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > sha256sums); then - exit_on_error "Generate sha25sums failed for '$RELEASE_VERSION_NAME' release." - fi - - echo "Attaching APK to github release" - if ! hub release edit \ - -m "" \ - -a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk" \ - -a "$APK_DIR_PATH/sha256sums" \ - "$RELEASE_VERSION_NAME"; then - exit_on_error "Attach APK to release failed for '$RELEASE_VERSION_NAME' release." - fi diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml deleted file mode 100644 index 88fe227..0000000 --- a/.github/workflows/debug_build.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Build - -on: - push: - branches: - - master - pull_request: - branches: - - master - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v2 - - - name: Build APK - shell: bash {0} - run: | - exit_on_error() { echo "$1"; exit 1; } - - echo "Setting vars" - # Set RELEASE_VERSION_NAME to "+" - CURRENT_VERSION_NAME_REGEX='\s+versionName "([^"]+)"$' - CURRENT_VERSION_NAME="$(grep -m 1 -E "$CURRENT_VERSION_NAME_REGEX" ./app/build.gradle | sed -r "s/$CURRENT_VERSION_NAME_REGEX/\1/")" - RELEASE_VERSION_NAME="v$CURRENT_VERSION_NAME+${GITHUB_SHA:0:7}" # The "+" is necessary so that versioning precedence is not affected - if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then - exit_on_error "The versionName '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html." - fi - - APK_DIR_PATH="./app/build/outputs/apk/debug" - APK_VERSION_TAG="$RELEASE_VERSION_NAME-github-debug" # Note the "-", GITHUB_SHA will already have "+" before it - APK_BASENAME_PREFIX="termux-float_$APK_VERSION_TAG" - - # Used by attachment steps later - echo "APK_DIR_PATH=$APK_DIR_PATH" >> $GITHUB_ENV - echo "APK_VERSION_TAG=$APK_VERSION_TAG" >> $GITHUB_ENV - echo "APK_BASENAME_PREFIX=$APK_BASENAME_PREFIX" >> $GITHUB_ENV - - echo "Building APK for '$RELEASE_VERSION_NAME' build" - export TERMUX_FLOAT_APP_VERSION_NAME="${RELEASE_VERSION_NAME/v/}" # Used by app/build.gradle - export TERMUX_FLOAT_APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle - if ! ./gradlew assembleDebug; then - exit_on_error "Build failed for '$RELEASE_VERSION_NAME' build." - fi - - echo "Validating APK" - if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then - files_found="$(ls "$APK_DIR_PATH")" - exit_on_error "Failed to find built APK at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found" - fi - - echo "Generating sha25sums file" - if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > sha256sums); then - exit_on_error "Generate sha25sums failed for '$RELEASE_VERSION_NAME' release." - fi - - - name: Attach files - uses: actions/upload-artifact@v2 - with: - name: ${{ env.APK_BASENAME_PREFIX }} - path: | - ${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}.apk - ${{ env.APK_DIR_PATH }}/sha256sums - ${{ env.APK_DIR_PATH }}/output-metadata.json diff --git a/.github/workflows/github_action_build.yml b/.github/workflows/github_action_build.yml new file mode 100644 index 0000000..9134698 --- /dev/null +++ b/.github/workflows/github_action_build.yml @@ -0,0 +1,75 @@ +name: GitHub Action Build + +on: + push: + branches: + - master + pull_request: + branches: + - master + schedule: + - cron: "15 0 1 */2 *" + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Build + shell: bash {0} + run: | + exit_on_error() { echo "$1"; exit 1; } + + echo "Setting vars" + + if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then + GITHUB_SHA="${{ github.event.pull_request.head.sha }}" # Do not use last merge commit set in GITHUB_SHA + fi + + # Set RELEASE_VERSION_NAME to "+" + CURRENT_VERSION_NAME_REGEX='\s+versionName "([^"]+)"$' + CURRENT_VERSION_NAME="$(grep -m 1 -E "$CURRENT_VERSION_NAME_REGEX" ./app/build.gradle | sed -r "s/$CURRENT_VERSION_NAME_REGEX/\1/")" + RELEASE_VERSION_NAME="v$CURRENT_VERSION_NAME+${GITHUB_SHA:0:7}" # The "+" is necessary so that versioning precedence is not affected + if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then + exit_on_error "The release version '${RELEASE_VERSION_NAME/v/}' generated from current version '$CURRENT_VERSION_NAME' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html." + fi + + APK_DIR_PATH="./app/build/outputs/apk/debug" + APK_VERSION_TAG="$RELEASE_VERSION_NAME.github.debug" # Note the ".", GITHUB_SHA will already have "+" before it + APK_BASENAME_PREFIX="termux-float-app_$APK_VERSION_TAG" + + # Used by upload step later + echo "APK_DIR_PATH=$APK_DIR_PATH" >> $GITHUB_ENV + echo "APK_VERSION_TAG=$APK_VERSION_TAG" >> $GITHUB_ENV + echo "APK_BASENAME_PREFIX=$APK_BASENAME_PREFIX" >> $GITHUB_ENV + + echo "Building APK file for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag" + export TERMUX_FLOAT_APP__BUILD__APP_VERSION_NAME="${RELEASE_VERSION_NAME/v/}" # Used by app/build.gradle + export TERMUX_FLOAT_APP__BUILD__APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle + if ! ./gradlew assembleDebug; then + exit_on_error "Build failed for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag." + fi + + echo "Validating APK file" + if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then + files_found="$(ls "$APK_DIR_PATH")" + exit_on_error "Failed to find built APK file at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found" + fi + + echo "Generating checksums-sha256.txt file" + if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > checksums-sha256.txt); then + exit_on_error "Generate checksums-sha256.txt file failed for '$RELEASE_VERSION_NAME' release." + fi + echo "checksums-sha256.txt:"$'\n```\n'"$(cat "$APK_DIR_PATH/checksums-sha256.txt")"$'\n```' + + - name: Upload files to action + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APK_BASENAME_PREFIX }} + path: | + ${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}.apk + ${{ env.APK_DIR_PATH }}/checksums-sha256.txt + ${{ env.APK_DIR_PATH }}/output-metadata.json diff --git a/.github/workflows/github_release_build.yml b/.github/workflows/github_release_build.yml new file mode 100644 index 0000000..1ac69ba --- /dev/null +++ b/.github/workflows/github_release_build.yml @@ -0,0 +1,64 @@ +name: GitHub Release Build + +on: + release: + types: + - published + +jobs: + build: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + ref: ${{ env.GITHUB_REF }} + + - name: Build and upload files to release + shell: bash {0} + run: | + exit_on_error() { + echo "$1" + echo "Deleting '$RELEASE_VERSION_NAME' release and '$GITHUB_REF' tag" + hub release delete "$RELEASE_VERSION_NAME" + git push --delete origin "$GITHUB_REF" + exit 1 + } + + echo "Setting vars" + RELEASE_VERSION_NAME="${GITHUB_REF/refs\/tags\//}" + if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then + exit_on_error "The release version '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html." + fi + + APK_DIR_PATH="./app/build/outputs/apk/debug" + APK_VERSION_TAG="$RELEASE_VERSION_NAME+github.debug" + APK_BASENAME_PREFIX="termux-float-app_$APK_VERSION_TAG" + + echo "Building APK file for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag" + export TERMUX_FLOAT_APP__BUILD__APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle + if ! ./gradlew assembleDebug; then + exit_on_error "Build failed for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag." + fi + + echo "Validating APK file" + if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then + files_found="$(ls "$APK_DIR_PATH")" + exit_on_error "Failed to find built APK file at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found" + fi + + echo "Generating checksums-sha256.txt file" + if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > checksums-sha256.txt); then + exit_on_error "Generate checksums-sha256.txt file failed for '$RELEASE_VERSION_NAME' release." + fi + echo "checksums-sha256.txt:"$'\n```\n'"$(cat "$APK_DIR_PATH/checksums-sha256.txt")"$'\n```' + + echo "Uploading files to release" + if ! gh release upload "$RELEASE_VERSION_NAME" \ + "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk" \ + "$APK_DIR_PATH/checksums-sha256.txt" \ + ; then + exit_on_error "Upload files to release failed for '$RELEASE_VERSION_NAME' release." + fi diff --git a/README.md b/README.md index 10a77f1..469ae98 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ A [Termux] plugin app to show the terminal in a floating terminal window. ### Installation -Latest version is `v0.15.0`. +Latest version is `v0.17.0`. **Check [`termux-app` Installation](https://github.com/termux/termux-app#Installation) for details before reading forward.** @@ -31,19 +31,23 @@ Latest version is `v0.15.0`. You **do not** need to download the `F-Droid` app (via the `Download F-Droid` link) to install `Termux:Float`. You can download the `Termux:Float` APK directly from the site by clicking the `Download APK` link at the bottom of each version section. -It usually takes a few days (or even a week or more) for updates to be available on `F-Droid` once an update has been released on `Github`. The `F-Droid` releases are built and published by `F-Droid` once they [detect](https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/com.termux.yml) a new `Github` release. The Termux maintainers **do not** have any control over the building and publishing of the Termux apps on `F-Droid`. Moreover, the Termux maintainers also do not have access to the APK signing keys of `F-Droid` releases, so we cannot release an APK ourselves on `Github` that would be compatible with `F-Droid` releases. +It usually takes a few days (or even a week or more) for updates to be available on `F-Droid` once an update has been released on `Github`. The `F-Droid` releases are built and published by `F-Droid` once they [detect](https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/com.termux.window.yml) a new `Github` release. The Termux maintainers **do not** have any control over the building and publishing of the Termux apps on `F-Droid`. Moreover, the Termux maintainers also do not have access to the APK signing keys of `F-Droid` releases, so we cannot release an APK ourselves on `Github` that would be compatible with `F-Droid` releases. The `F-Droid` app often may not notify you of updates and you will manually have to do a pull down swipe action in the `Updates` tab of the app for it to check updates. Make sure battery optimizations are disabled for the app, check https://dontkillmyapp.com/ for details on how to do that. ### Github -`Termux:Float` application can be obtained on `Github` either from [`Github Releases`](https://github.com/termux/termux-float/releases) for version `>= 0.15.0` or from [`Github Build`](https://github.com/termux/termux-float/actions/workflows/debug_build.yml) action workflows. +`Termux:Float` application can be obtained on `Github` either from [`Github Releases`](https://github.com/termux/termux-float/releases) for version `>= 0.15.0` or from [`Github Actions`](https://github.com/termux/termux-float/actions/workflows/github_action_build.yml?query=branch%3Amaster+event%3Apush). -The APKs for `Github Releases` will be listed under `Assets` drop-down of a release. These are automatically attached when a new version is released. +The APKs for `Github Releases` will be listed under `Assets` drop-down of the release. These are automatically attached when a new version is released. -The APKs for `Github Build` action workflows will be listed under `Artifacts` section of a workflow run. These are created for each commit/push done to the repository and can be used by users who don't want to wait for releases and want to try out the latest features immediately or want to test their pull requests. Note that for action workflows, you need to be [**logged into a `Github` account**](https://github.com/login) for the `Artifacts` links to be enabled/clickable. If you are using the [`Github` app](https://github.com/mobile), then make sure to open workflow link in a browser like Chrome or Firefox that has your Github account logged in since the in-app browser may not be logged in. +The APKs for `Github Actions` will be listed under `Artifacts` section of the workflow run. These are created for each commit/push done to the repository and can be used by users who don't want to wait for releases and want to try out the latest features immediately or want to test their pull requests. Note that for action workflows, you need to be [**logged into a `Github` account**](https://github.com/login) for the `Artifacts` links to be enabled/clickable. If you are using the [`Github` app](https://github.com/mobile), then make sure to open workflow link in a browser like Chrome or Firefox that has your Github account logged in since the in-app browser may not be logged in. The APKs for both of these are [`debuggable`](https://developer.android.com/studio/debug) and are compatible with each other but they are not compatible with other sources. + +### Google Play Store **(Deprecated)** + +**Termux and its plugins are no longer updated on [Google Play Store](https://play.google.com/store/apps/details?id=com.termux.window) due to [android 10 issues](https://github.com/termux/termux-packages/wiki/Termux-and-Android-10) and have been deprecated. It is highly recommended to not install Termux apps from Play Store any more.** Check https://github.com/termux/termux-app#google-play-store-deprecated for details. ## @@ -67,7 +71,7 @@ nano ~/.termux/termux.float.properties You can help debug problems by setting appropriate `logcat` `Log Level` in `Termux` app settings -> `Termux:Float` -> `Debugging` -> `Log Level` (Requires `Termux` app version `>= 0.118.0`). The `Log Level` defaults to `Normal` and log level `Verbose` currently logs additional information. Its best to revert log level to `Normal` after you have finished debugging since private data may otherwise be passed to `logcat` during normal operation and moreover, additional logging increases execution time. -Once log levels have been set, you can run the `logcat` command in `Termux` or `Termux:Float` app terminal to view the logs in realtime (`Ctrl+c` to stop) or use `logcat -d` to take a dump of the log. You can also view the logs from a PC over `ADB`. For more information, check official android `logcat` guide [here](https://developer.android.com/studio/command-line/logcat). +Once log levels have been set, you can run the `logcat` command in `Termux` or `Termux:Float` app terminal to view the logs in realtime (`Ctrl+c` to stop) or use `logcat -d > logcat.txt` to take a dump of the log. You can also view the logs from a PC over `ADB`. For more information, check official android `logcat` guide [here](https://developer.android.com/studio/command-line/logcat). ##### Log Levels - `Off` - Log nothing @@ -92,4 +96,4 @@ Check [Forking](https://github.com/termux/termux-app#Forking) section of `termux -[Termux]: https://termux.com +[Termux]: https://termux.dev diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..479f15c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1 @@ +Check https://termux.dev/security for info on Termux security policies and how to report vulnerabilities. diff --git a/app/build.gradle b/app/build.gradle index e5ae623..82357ab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,18 @@ apply plugin: 'com.android.application' android { - compileSdkVersion project.properties.compileSdkVersion.toInteger() - def appVersionName = System.getenv("TERMUX_FLOAT_APP_VERSION_NAME") ?: "" - def apkVersionTag = System.getenv("TERMUX_FLOAT_APK_VERSION_TAG") ?: "" + namespace "com.termux.window" + + compileSdk project.properties.compileSdkVersion.toInteger() + def appVersionName = System.getenv("TERMUX_FLOAT_APP__BUILD__APP_VERSION_NAME") ?: "" + def apkVersionTag = System.getenv("TERMUX_FLOAT_APP__BUILD__APK_VERSION_TAG") ?: "" defaultConfig { applicationId "com.termux.window" - minSdkVersion project.properties.minSdkVersion.toInteger() - targetSdkVersion project.properties.targetSdkVersion.toInteger() - versionCode 15 - versionName "0.15.0" + minSdk project.properties.minSdkVersion.toInteger() + targetSdk project.properties.targetSdkVersion.toInteger() + versionCode 1001 + versionName "0.17.0" if (appVersionName) versionName = appVersionName validateVersionName(versionName) @@ -22,7 +24,7 @@ android { signingConfigs { debug { - storeFile file('dev_keystore.jks') + storeFile file('testkey_untrusted.jks') keyAlias 'alias' storePassword 'xrj45yWGLbsO7W0v' keyPassword 'xrj45yWGLbsO7W0v' @@ -43,34 +45,43 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + // Flag to enable support for the new language APIs + coreLibraryDesugaringEnabled true + + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } applicationVariants.all { variant -> variant.outputs.all { output -> - if (variant.buildType.name == "debug") { - outputFileName = new File("termux-float_" + (apkVersionTag ? apkVersionTag : "debug") + ".apk") - } else if (variant.buildType.name == "release") { - outputFileName = new File("termux-float_" + (apkVersionTag ? apkVersionTag : "release") + ".apk") - } + outputFileName = new File("termux-float-app_" + + (apkVersionTag ? apkVersionTag : "v" + versionName + "+" + variant.buildType.name) + ".apk") } } + + packagingOptions { + // Remove terminal-shared JNI libs added via termux-shared dependency + exclude "lib/*/liblocal-socket.so" + } } dependencies { - implementation 'androidx.annotation:annotation:1.3.0' + coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" + + testImplementation "junit:junit:4.13.2" + + implementation "androidx.annotation:annotation:1.9.1" - implementation 'com.termux.termux-app:termux-shared:fcc0d36258' - implementation 'com.termux.termux-app:terminal-view:fcc0d36258' + implementation "com.termux.termux-app:termux-shared:7bceab88e2" + implementation "com.termux.termux-app:terminal-view:7bceab88e2" // Use if below libraries are published locally by termux-app with `./gradlew publishReleasePublicationToMavenLocal` and used with `mavenLocal()`. // If updates are done, republish there and sync project with gradle files here // https://github.com/termux/termux-app/wiki/Termux-Libraries - //implementation 'com.termux:termux-shared:0.117' - //implementation 'com.termux:terminal-view:0.117' + //implementation "com.termux:termux-shared:0.118.0" + //implementation "com.termux:terminal-view:0.118.0" - testImplementation 'junit:junit:4.13.2' + implementation "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" } task versionName { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 50f8976..b3aed65 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,13 +1,12 @@ + - = Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0); // Build the notification Notification.Builder builder = NotificationUtils.geNotificationBuilder(this, @@ -158,7 +162,9 @@ private Notification buildNotification() { // Set Exit button action Intent exitIntent = new Intent(this, TermuxFloatService.class).setAction(TERMUX_FLOAT_SERVICE.ACTION_STOP_SERVICE); - builder.addAction(android.R.drawable.ic_delete, res.getString(R.string.notification_action_exit), PendingIntent.getService(this, 0, exitIntent, 0)); + builder.addAction(android.R.drawable.ic_delete, res.getString(R.string.notification_action_exit), + PendingIntent.getService(this, 0, exitIntent, + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0)); return builder.build(); } @@ -177,7 +183,7 @@ private boolean initializeFloatView() { mFloatingWindow.initFloatView(this); mSession = createTermuxSession( - new ExecutionCommand(0, null, null, null, mFloatingWindow.getProperties().getDefaultWorkingDirectory(), false, false), null); + new ExecutionCommand(0, null, null, null, mFloatingWindow.getProperties().getDefaultWorkingDirectory(), ExecutionCommand.Runner.TERMINAL_SESSION.getName(), false), null); if (mSession == null) return false; mFloatingWindow.getTerminalView().attachSession(mSession.getTerminalSession()); @@ -214,7 +220,7 @@ public synchronized TermuxSession createTermuxSession(ExecutionCommand execution Logger.logDebug(LOG_TAG, "Creating \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxSession"); - if (executionCommand.inBackground) { + if (ExecutionCommand.Runner.APP_SHELL.getName().equals(executionCommand.runner)) { Logger.logDebug(LOG_TAG, "Ignoring a background execution command passed to createTermuxSession()"); return null; } @@ -222,10 +228,11 @@ public synchronized TermuxSession createTermuxSession(ExecutionCommand execution if (Logger.getLogLevel() >= Logger.LOG_LEVEL_VERBOSE) Logger.logVerboseExtended(LOG_TAG, executionCommand.toString()); + executionCommand.shellName = sessionName; executionCommand.terminalTranscriptRows = mFloatingWindow.getProperties().getTerminalTranscriptRows(); TermuxSession newTermuxSession = TermuxSession.execute(this, executionCommand, - mFloatingWindow.getTermuxFloatSessionClient(), null, new TermuxShellEnvironmentClient(), - sessionName, executionCommand.isPluginExecutionCommand); + mFloatingWindow.getTermuxFloatSessionClient(), null, new TermuxShellEnvironment(), + null, executionCommand.isPluginExecutionCommand); if (newTermuxSession == null) { Logger.logError(LOG_TAG, "Failed to execute new TermuxSession command for:\n" + executionCommand.getCommandIdAndLabelLogString()); return null; @@ -237,8 +244,12 @@ public synchronized TermuxSession createTermuxSession(ExecutionCommand execution return newTermuxSession; } - public TermuxSession getSession() { + public TermuxSession getTermuxSession() { return mSession; } + public TerminalSession getCurrentSession() { + return mSession != null ? mSession.getTerminalSession() : null; + } + } diff --git a/app/src/main/java/com/termux/window/TermuxFloatSessionClient.java b/app/src/main/java/com/termux/window/TermuxFloatSessionClient.java index 6891a0a..135fc4f 100644 --- a/app/src/main/java/com/termux/window/TermuxFloatSessionClient.java +++ b/app/src/main/java/com/termux/window/TermuxFloatSessionClient.java @@ -9,10 +9,10 @@ import android.text.TextUtils; import com.termux.shared.logger.Logger; -import com.termux.shared.settings.properties.TermuxPropertyConstants; -import com.termux.shared.terminal.TermuxTerminalSessionClientBase; -import com.termux.shared.terminal.io.BellHandler; import com.termux.shared.termux.TermuxConstants; +import com.termux.shared.termux.settings.properties.TermuxPropertyConstants; +import com.termux.shared.termux.terminal.TermuxTerminalSessionClientBase; +import com.termux.shared.termux.terminal.io.BellHandler; import com.termux.terminal.TerminalColors; import com.termux.terminal.TerminalSession; import com.termux.terminal.TextStyle; @@ -45,7 +45,7 @@ public void onAttachedToWindow() { // Just initialize the mBellSoundPool and load the sound, otherwise bell might not run // the first time bell key is pressed and play() is called, since sound may not be loaded // quickly enough before the call to play(). https://stackoverflow.com/questions/35435625 - getBellSoundPool(); + loadBellSoundPool(); } /** @@ -102,16 +102,15 @@ public void onPasteTextFromClipboard(TerminalSession session) { public void onBell(TerminalSession session) { if (!mView.isVisible()) return; - switch (mView.getProperties().getBellBehaviour()) { - case TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_VIBRATE: - BellHandler.getInstance(mService).doBell(); - break; - case TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_BEEP: - getBellSoundPool().play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f); - break; - case TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_IGNORE: - // Ignore the bell character. - break; + int bellBehaviour = mView.getProperties().getBellBehaviour(); + if (bellBehaviour == TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_VIBRATE) { + BellHandler.getInstance(mService).doBell(); + } else if (bellBehaviour == TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_BEEP) { + loadBellSoundPool(); + if (mBellSoundPool != null) + mBellSoundPool.play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f); + } else if (bellBehaviour == TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_IGNORE) { + // Ignore the bell character. } } @@ -127,17 +126,20 @@ public Integer getTerminalCursorStyle() { } - /** Initialize and get mBellSoundPool */ - private synchronized SoundPool getBellSoundPool() { + /** Load mBellSoundPool */ + private synchronized void loadBellSoundPool() { if (mBellSoundPool == null) { mBellSoundPool = new SoundPool.Builder().setMaxStreams(1).setAudioAttributes( new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()).build(); - mBellSoundId = mBellSoundPool.load(mService, R.raw.bell, 1); + try { + mBellSoundId = mBellSoundPool.load(mService, com.termux.shared.R.raw.bell, 1); + } catch (Exception e){ + // Catch java.lang.RuntimeException: Unable to resume activity {com.termux/com.termux.app.TermuxActivity}: android.content.res.Resources$NotFoundException: File res/raw/bell.ogg from drawable resource ID + Logger.logStackTraceWithMessage(LOG_TAG, "Failed to load bell sound pool", e); + } } - - return mBellSoundPool; } /** Release mBellSoundPool resources */ @@ -163,10 +165,11 @@ public void checkForFontAndColors() { } TerminalColors.COLOR_SCHEME.updateWith(props); - TerminalSession session = mService.getSession().getTerminalSession(); + TerminalSession session = mService.getCurrentSession(); if (session != null && session.getEmulator() != null) { session.getEmulator().mColors.reset(); } + updateBackgroundColor(); final Typeface newTypeface = (fontFile.exists() && fontFile.length() > 0) ? Typeface.createFromFile(fontFile) : Typeface.MONOSPACE; @@ -178,7 +181,8 @@ public void checkForFontAndColors() { public void updateBackgroundColor() { //if (!mView.isVisible()) return; - TerminalSession session = mService.getSession().getTerminalSession(); + + TerminalSession session = mService.getCurrentSession(); if (session != null && session.getEmulator() != null) { mView.getTerminalView().setBackgroundColor(session.getEmulator().mColors.mCurrentColors[TextStyle.COLOR_INDEX_BACKGROUND]); } diff --git a/app/src/main/java/com/termux/window/TermuxFloatView.java b/app/src/main/java/com/termux/window/TermuxFloatView.java index 629c279..dff9e46 100644 --- a/app/src/main/java/com/termux/window/TermuxFloatView.java +++ b/app/src/main/java/com/termux/window/TermuxFloatView.java @@ -18,8 +18,8 @@ import android.widget.LinearLayout; import com.termux.shared.logger.Logger; -import com.termux.shared.settings.preferences.TermuxFloatAppSharedPreferences; import com.termux.shared.termux.TermuxConstants; +import com.termux.shared.termux.settings.preferences.TermuxFloatAppSharedPreferences; import com.termux.shared.view.KeyboardUtils; import com.termux.terminal.TerminalSession; import com.termux.terminal.TerminalSessionClient; diff --git a/app/src/main/java/com/termux/window/TermuxFloatViewClient.java b/app/src/main/java/com/termux/window/TermuxFloatViewClient.java index c52906b..ad814ed 100644 --- a/app/src/main/java/com/termux/window/TermuxFloatViewClient.java +++ b/app/src/main/java/com/termux/window/TermuxFloatViewClient.java @@ -6,7 +6,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; -import com.termux.shared.terminal.TermuxTerminalViewClientBase; +import com.termux.shared.termux.terminal.TermuxTerminalViewClientBase; import com.termux.shared.view.KeyboardUtils; import com.termux.terminal.KeyHandler; import com.termux.terminal.TerminalEmulator; diff --git a/app/src/main/java/com/termux/window/settings/properties/TermuxFloatAppSharedProperties.java b/app/src/main/java/com/termux/window/settings/properties/TermuxFloatAppSharedProperties.java index 2690c33..0986af8 100644 --- a/app/src/main/java/com/termux/window/settings/properties/TermuxFloatAppSharedProperties.java +++ b/app/src/main/java/com/termux/window/settings/properties/TermuxFloatAppSharedProperties.java @@ -4,25 +4,19 @@ import androidx.annotation.NonNull; -import com.termux.shared.settings.properties.TermuxPropertyConstants; -import com.termux.shared.settings.properties.TermuxSharedProperties; import com.termux.shared.termux.TermuxConstants; +import com.termux.shared.termux.settings.properties.TermuxPropertyConstants; +import com.termux.shared.termux.settings.properties.TermuxSharedProperties; public class TermuxFloatAppSharedProperties extends TermuxSharedProperties { private static final String LOG_TAG = "TermuxFloatAppSharedProperties"; public TermuxFloatAppSharedProperties(@NonNull Context context) { - super(context, TermuxConstants.TERMUX_FLOAT_APP_NAME, TermuxPropertyConstants.getTermuxFloatPropertiesFile(), - TermuxPropertyConstants.TERMUX_PROPERTIES_LIST, new SharedPropertiesParserClient()); - } - - /** - * Load the {@link TermuxPropertyConstants#KEY_TERMINAL_TRANSCRIPT_ROWS} value from termux properties file on disk. - */ - public static int getTerminalTranscriptRows(Context context) { - return (int) TermuxSharedProperties.getInternalPropertyValue(context, TermuxPropertyConstants.getTermuxFloatPropertiesFile(), - TermuxPropertyConstants.KEY_TERMINAL_TRANSCRIPT_ROWS, new SharedPropertiesParserClient()); + super(context, TermuxConstants.TERMUX_FLOAT_APP_NAME, + TermuxConstants.TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST, + TermuxPropertyConstants.TERMUX_APP_PROPERTIES_LIST, + new SharedPropertiesParserClient()); } } diff --git a/app/dev_keystore.jks b/app/testkey_untrusted.jks similarity index 100% rename from app/dev_keystore.jks rename to app/testkey_untrusted.jks diff --git a/build.gradle b/build.gradle index 565c865..2452b6d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath "com.android.tools.build:gradle:8.7.3" } } diff --git a/gradle.properties b/gradle.properties index 8618581..bff406b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,4 @@ android.useAndroidX=true minSdkVersion=24 targetSdkVersion=28 -compileSdkVersion=30 +compileSdkVersion=35 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a0f7639..2fa91c5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists