mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-04 01:35:39 +08:00
The `AmSocketServer` now handles the entire logic for processing of am commands sent by clients and its results. This can be used by other apps as well to run their own am servers. The server started by `termux-app` will be managed by `TermuxAmSocketServer`. Read their javadocs for details. The extended implementation `TermuxAmSocketServerClient` of `AmSocketServer.AmSocketServerClient`/`ILocalSocketManager` will also send a plugin error notification for all errors to the user instead of just logging to logcat since users are not very good at checking those, this should save dev time debugging problems. We may need to ignore notifications for some errors like broken pipe, based on their `Error` objects if they are normally expected, this requires further investigation. The `TERMUX_APP_AM_SOCKET_SERVER_ENABLED` env variable will also be exported for all shell sessions and tasks for whether the server was successfully started on app startup. The user can disable the server by adding "run-termux-am-socket-server=false" to the "~/.termux/termux.properties" as implemented in5f8a9222
. The env variable will be checked by `$PREFIX/bin/termux-am` before attempting to connect. The new path for the server socket is `/data/data/com.termux/files/apps/termux-app/termux-am/am.sock` as per `TERMUX_APP.APPS_DIR_PATH` added inbcd8f4c4
.
212 lines
8.1 KiB
Groovy
212 lines
8.1 KiB
Groovy
plugins {
|
|
id "com.android.application"
|
|
}
|
|
|
|
android {
|
|
compileSdkVersion project.properties.compileSdkVersion.toInteger()
|
|
ndkVersion = System.getenv("JITPACK_NDK_VERSION") ?: project.properties.ndkVersion
|
|
def appVersionName = System.getenv("TERMUX_APP_VERSION_NAME") ?: ""
|
|
def apkVersionTag = System.getenv("TERMUX_APK_VERSION_TAG") ?: ""
|
|
def splitAPKsForDebugBuilds = System.getenv("TERMUX_SPLIT_APKS_FOR_DEBUG_BUILDS") ?: "1"
|
|
def splitAPKsForReleaseBuilds = System.getenv("TERMUX_SPLIT_APKS_FOR_RELEASE_BUILDS") ?: "0" // F-Droid does not support split APKs #1904
|
|
|
|
dependencies {
|
|
implementation "androidx.annotation:annotation:1.3.0"
|
|
implementation "androidx.core:core:1.6.0"
|
|
implementation "androidx.drawerlayout:drawerlayout:1.1.1"
|
|
implementation "androidx.preference:preference:1.1.1"
|
|
implementation "androidx.viewpager:viewpager:1.0.0"
|
|
implementation "com.google.android.material:material:1.4.0"
|
|
implementation "com.google.guava:guava:24.1-jre"
|
|
implementation "io.noties.markwon:core:$markwonVersion"
|
|
implementation "io.noties.markwon:ext-strikethrough:$markwonVersion"
|
|
implementation "io.noties.markwon:linkify:$markwonVersion"
|
|
implementation "io.noties.markwon:recycler:$markwonVersion"
|
|
|
|
implementation project(":terminal-view")
|
|
implementation project(":termux-shared")
|
|
}
|
|
|
|
defaultConfig {
|
|
applicationId "com.termux"
|
|
minSdkVersion project.properties.minSdkVersion.toInteger()
|
|
targetSdkVersion project.properties.targetSdkVersion.toInteger()
|
|
versionCode 118
|
|
versionName "0.118.0"
|
|
|
|
if (appVersionName) versionName = appVersionName
|
|
validateVersionName(versionName)
|
|
|
|
manifestPlaceholders.TERMUX_PACKAGE_NAME = "com.termux"
|
|
manifestPlaceholders.TERMUX_APP_NAME = "Termux"
|
|
manifestPlaceholders.TERMUX_API_APP_NAME = "Termux:API"
|
|
manifestPlaceholders.TERMUX_BOOT_APP_NAME = "Termux:Boot"
|
|
manifestPlaceholders.TERMUX_FLOAT_APP_NAME = "Termux:Float"
|
|
manifestPlaceholders.TERMUX_STYLING_APP_NAME = "Termux:Styling"
|
|
manifestPlaceholders.TERMUX_TASKER_APP_NAME = "Termux:Tasker"
|
|
manifestPlaceholders.TERMUX_WIDGET_APP_NAME = "Termux:Widget"
|
|
|
|
externalNativeBuild {
|
|
ndkBuild {
|
|
cFlags "-std=c11", "-Wall", "-Wextra", "-Werror", "-Os", "-fno-stack-protector", "-Wl,--gc-sections"
|
|
}
|
|
}
|
|
|
|
splits {
|
|
abi {
|
|
enable ((gradle.startParameter.taskNames.any { it.contains("Debug") } && splitAPKsForDebugBuilds == "1") ||
|
|
(gradle.startParameter.taskNames.any { it.contains("Release") } && splitAPKsForReleaseBuilds == "1"))
|
|
reset ()
|
|
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
|
universalApk true
|
|
}
|
|
}
|
|
}
|
|
|
|
signingConfigs {
|
|
debug {
|
|
storeFile file('dev_keystore.jks')
|
|
keyAlias 'alias'
|
|
storePassword 'xrj45yWGLbsO7W0v'
|
|
keyPassword 'xrj45yWGLbsO7W0v'
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
minifyEnabled true
|
|
shrinkResources false // Reproducible builds
|
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
}
|
|
|
|
debug {
|
|
signingConfig signingConfigs.debug
|
|
}
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility JavaVersion.VERSION_1_8
|
|
targetCompatibility JavaVersion.VERSION_1_8
|
|
}
|
|
|
|
externalNativeBuild {
|
|
ndkBuild {
|
|
path "src/main/cpp/Android.mk"
|
|
}
|
|
}
|
|
|
|
lintOptions {
|
|
disable 'ProtectedPermissions'
|
|
}
|
|
|
|
testOptions {
|
|
unitTests {
|
|
includeAndroidResources = true
|
|
}
|
|
}
|
|
|
|
packagingOptions {
|
|
jniLibs {
|
|
useLegacyPackaging true
|
|
}
|
|
}
|
|
|
|
applicationVariants.all { variant ->
|
|
variant.outputs.all { output ->
|
|
if (variant.buildType.name == "debug") {
|
|
def abi = output.getFilter(com.android.build.OutputFile.ABI)
|
|
outputFileName = new File("termux-app_" + (apkVersionTag ? apkVersionTag : "debug") + "_" + (abi ? abi : "universal") + ".apk")
|
|
} else if (variant.buildType.name == "release") {
|
|
def abi = output.getFilter(com.android.build.OutputFile.ABI)
|
|
outputFileName = new File("termux-app_" + (apkVersionTag ? apkVersionTag : "release") + "_" + (abi ? abi : "universal") + ".apk")
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
dependencies {
|
|
testImplementation "junit:junit:4.13.2"
|
|
testImplementation "org.robolectric:robolectric:4.4"
|
|
}
|
|
|
|
task versionName {
|
|
doLast {
|
|
print android.defaultConfig.versionName
|
|
}
|
|
}
|
|
|
|
def validateVersionName(String versionName) {
|
|
// https://semver.org/spec/v2.0.0.html#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
|
// ^(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-]+)*))?$
|
|
if (!java.util.regex.Pattern.matches("^(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-]+)*))?\$", versionName))
|
|
throw new GradleException("The versionName '" + versionName + "' 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.")
|
|
}
|
|
|
|
def downloadBootstrap(String arch, String expectedChecksum, String version) {
|
|
def digest = java.security.MessageDigest.getInstance("SHA-256")
|
|
|
|
def localUrl = "src/main/cpp/bootstrap-" + arch + ".zip"
|
|
def file = new File(projectDir, localUrl)
|
|
if (file.exists()) {
|
|
def buffer = new byte[8192]
|
|
def input = new FileInputStream(file)
|
|
while (true) {
|
|
def readBytes = input.read(buffer)
|
|
if (readBytes < 0) break
|
|
digest.update(buffer, 0, readBytes)
|
|
}
|
|
def checksum = new BigInteger(1, digest.digest()).toString(16)
|
|
while (checksum.length() < 64) { checksum = "0" + checksum }
|
|
if (checksum == expectedChecksum) {
|
|
return
|
|
} else {
|
|
logger.quiet("Deleting old local file with wrong hash: " + localUrl)
|
|
file.delete()
|
|
}
|
|
}
|
|
|
|
def remoteUrl = "https://github.com/termux/termux-packages/releases/download/bootstrap-" + version + "/bootstrap-" + arch + ".zip"
|
|
logger.quiet("Downloading " + remoteUrl + " ...")
|
|
|
|
file.parentFile.mkdirs()
|
|
def out = new BufferedOutputStream(new FileOutputStream(file))
|
|
|
|
def connection = new URL(remoteUrl).openConnection()
|
|
connection.setInstanceFollowRedirects(true)
|
|
def digestStream = new java.security.DigestInputStream(connection.inputStream, digest)
|
|
out << digestStream
|
|
out.close()
|
|
|
|
def checksum = new BigInteger(1, digest.digest()).toString(16)
|
|
while (checksum.length() < 64) { checksum = "0" + checksum }
|
|
if (checksum != expectedChecksum) {
|
|
file.delete()
|
|
throw new GradleException("Wrong checksum for " + remoteUrl + ": expected: " + expectedChecksum + ", actual: " + checksum)
|
|
}
|
|
}
|
|
|
|
clean {
|
|
doLast {
|
|
def tree = fileTree(new File(projectDir, 'src/main/cpp'))
|
|
tree.include 'bootstrap-*.zip'
|
|
tree.each { it.delete() }
|
|
}
|
|
}
|
|
|
|
task downloadBootstraps() {
|
|
doLast {
|
|
def version = "2022.04.21-r1"
|
|
downloadBootstrap("aarch64", "6ef5d51ebcc98cabec178de58b3846d192e3c47f1575f6319c0d55b4b2550ee8", version)
|
|
downloadBootstrap("arm", "39f371b9b0892a5e263993eab8fc8d1f58020a7df78372d134184e8da3d5d18e", version)
|
|
downloadBootstrap("i686", "2355c44da98c3990bce1fc527e36b9f9f913bb8d814d73601811fc62bb86d864", version)
|
|
downloadBootstrap("x86_64", "21ced5aacde882999306a46f913191bbea134af38532fb85ef958f6822a8730c", version)
|
|
}
|
|
}
|
|
|
|
afterEvaluate {
|
|
android.applicationVariants.all { variant ->
|
|
variant.javaCompileProvider.get().dependsOn(downloadBootstraps)
|
|
}
|
|
}
|