diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bcb7791a3a..08887b3dd7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -168,10 +168,18 @@ jobs: strategy: fail-fast: false matrix: - arch: [x64, x86, arm64, arm] + include: + - arch: x64 + abi: x86_64 + - arch: x86 + abi: x86 + - arch: arm64 + abi: arm64-v8a + - arch: arm + abi: armeabi-v7a env: EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}" target_os="android"' - BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }} + BUNDLE: naiveproxy-plugin-${{ github.event.release.tag_name || 'v1' }}-${{ matrix.abi }}.apk steps: - uses: actions/checkout@v4 - name: Cache toolchains (Linux, OpenWrt, Android) @@ -219,20 +227,31 @@ jobs: - run: ccache -s - run: ./get-android-sys.sh - run: ../tests/basic.sh out/Release/naive - - name: Pack naiveproxy assets + - name: Gradle cache + uses: actions/cache@v3 + with: + path: ~/.gradle + key: gradle-${{ hashFiles('**/*.gradle.kts') }} + - name: Create APK + working-directory: apk + env: + APK_ABI: ${{ matrix.abi }} + APK_VERSION_NAME: ${{ github.event.release.tag_name || 'v1' }} + KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} run: | - mkdir ${{ env.BUNDLE }} - cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} - tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - openssl sha256 out/Release/naive >sha256sum.txt + mkdir -p app/libs/$APK_ABI + cp ../src/out/Release/naive app/libs/$APK_ABI/libnaive.so + ./gradlew :app:assembleRelease + openssl sha256 app/build/outputs/apk/release/${{ env.BUNDLE }} >sha256sum.txt echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV - uses: actions/upload-artifact@v3 with: - name: ${{ env.BUNDLE }}.tar.xz naive executable sha256 ${{ env.SHA256SUM }} - path: src/sha256sum.txt + name: ${{ env.BUNDLE }} sha256 ${{ env.SHA256SUM }} + path: apk/sha256sum.txt - name: Upload naiveproxy assets if: ${{ github.event_name == 'release' }} - run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }}.tar.xz --clobber + working-directory: apk/app/build/outputs/apk/release + run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }} --clobber env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} win: @@ -394,108 +413,108 @@ jobs: matrix: include: - arch: x86_64 - openwrt: 'target=x86 subtarget=64' + openwrt: "target=x86 subtarget=64" target_cpu: x64 - arch: x86 - openwrt: 'target=x86 subtarget=generic' + openwrt: "target=x86 subtarget=generic" target_cpu: x86 - arch: aarch64_cortex-a53 - openwrt: 'target=sunxi subtarget=cortexa53' + openwrt: "target=sunxi subtarget=cortexa53" target_cpu: arm64 extra: 'arm_cpu="cortex-a53"' - arch: aarch64_cortex-a53-static - openwrt: 'target=sunxi subtarget=cortexa53' + openwrt: "target=sunxi subtarget=cortexa53" target_cpu: arm64 extra: 'arm_cpu="cortex-a53" build_static=true no_madvise_syscall=true' - arch: aarch64_cortex-a72 - openwrt: 'target=mvebu subtarget=cortexa72' + openwrt: "target=mvebu subtarget=cortexa72" target_cpu: arm64 extra: 'arm_cpu="cortex-a72"' - arch: aarch64_cortex-a72-static - openwrt: 'target=mvebu subtarget=cortexa72' + openwrt: "target=mvebu subtarget=cortexa72" target_cpu: arm64 extra: 'arm_cpu="cortex-a72" build_static=true no_madvise_syscall=true' - arch: aarch64_generic - openwrt: 'target=rockchip subtarget=armv8' + openwrt: "target=rockchip subtarget=armv8" target_cpu: arm64 - arch: aarch64_generic-static - openwrt: 'target=rockchip subtarget=armv8' + openwrt: "target=rockchip subtarget=armv8" target_cpu: arm64 - extra: 'build_static=true no_madvise_syscall=true' + extra: "build_static=true no_madvise_syscall=true" - arch: arm_arm1176jzf-s_vfp - openwrt: 'target=bcm27xx subtarget=bcm2708' + openwrt: "target=bcm27xx subtarget=bcm2708" target_cpu: arm extra: 'arm_version=0 arm_cpu="arm1176jzf-s" arm_fpu="vfp" arm_float_abi="hard" arm_use_neon=false arm_use_thumb=false' - arch: arm_arm926ej-s - openwrt: 'target=mxs subtarget=generic' + openwrt: "target=mxs subtarget=generic" target_cpu: arm extra: 'arm_version=0 arm_cpu="arm926ej-s" arm_float_abi="soft" arm_use_neon=false arm_use_thumb=false' - arch: arm_cortex-a15_neon-vfpv4 - openwrt: 'target=armsr subtarget=armv7' + openwrt: "target=armsr subtarget=armv7" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a15" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true' - arch: arm_cortex-a5_vfpv4 - openwrt: 'target=at91 subtarget=sama5' + openwrt: "target=at91 subtarget=sama5" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a5" arm_fpu="vfpv4" arm_float_abi="hard" arm_use_neon=false' - arch: arm_cortex-a7 - openwrt: 'target=mediatek subtarget=mt7629' + openwrt: "target=mediatek subtarget=mt7629" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a7" arm_float_abi="soft" arm_use_neon=false' - arch: arm_cortex-a7_neon-vfpv4 - openwrt: 'target=sunxi subtarget=cortexa7' + openwrt: "target=sunxi subtarget=cortexa7" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true' - arch: arm_cortex-a7_vfpv4 - openwrt: 'target=at91 subtarget=sama7' + openwrt: "target=at91 subtarget=sama7" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="vfpv4" arm_float_abi="hard" arm_use_neon=false' - arch: arm_cortex-a7_neon-vfpv4-static - openwrt: 'target=sunxi subtarget=cortexa7' + openwrt: "target=sunxi subtarget=cortexa7" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true build_static=true no_madvise_syscall=true' - arch: arm_cortex-a8_vfpv3 - openwrt: 'target=sunxi subtarget=cortexa8' + openwrt: "target=sunxi subtarget=cortexa8" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a8" arm_fpu="vfpv3" arm_float_abi="hard" arm_use_neon=false' - arch: arm_cortex-a9 - openwrt: 'target=bcm53xx subtarget=generic' + openwrt: "target=bcm53xx subtarget=generic" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a9" arm_float_abi="soft" arm_use_neon=false' - arch: arm_cortex-a9-static - openwrt: 'target=bcm53xx subtarget=generic' + openwrt: "target=bcm53xx subtarget=generic" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a9" arm_float_abi="soft" arm_use_neon=false build_static=true no_madvise_syscall=true' - arch: arm_cortex-a9_neon - openwrt: 'target=zynq subtarget=generic' + openwrt: "target=zynq subtarget=generic" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a9" arm_fpu="neon" arm_float_abi="hard" arm_use_neon=true' - arch: arm_cortex-a9_vfpv3-d16 - openwrt: 'target=tegra subtarget=generic' + openwrt: "target=tegra subtarget=generic" target_cpu: arm extra: 'arm_version=0 arm_cpu="cortex-a9" arm_fpu="vfpv3-d16" arm_float_abi="hard" arm_use_neon=false' - arch: arm_mpcore - openwrt: 'target=oxnas subtarget=ox820' + openwrt: "target=oxnas subtarget=ox820" target_cpu: arm extra: 'arm_version=0 arm_cpu="mpcore" arm_float_abi="soft" arm_use_neon=false arm_use_thumb=false' - arch: arm_xscale - openwrt: 'target=kirkwood subtarget=generic' + openwrt: "target=kirkwood subtarget=generic" target_cpu: arm extra: 'arm_version=0 arm_cpu="xscale" arm_float_abi="soft" arm_use_neon=false arm_use_thumb=false' - arch: mipsel_24kc - openwrt: 'target=ramips subtarget=rt305x' + openwrt: "target=ramips subtarget=rt305x" target_cpu: mipsel extra: 'mips_arch_variant="r2" mips_float_abi="soft"' - arch: mipsel_24kc-static - openwrt: 'target=ramips subtarget=rt305x' + openwrt: "target=ramips subtarget=rt305x" target_cpu: mipsel extra: 'mips_arch_variant="r2" mips_float_abi="soft" build_static=true no_madvise_syscall=true' - arch: mipsel_mips32 - openwrt: 'target=bcm47xx subtarget=generic' + openwrt: "target=bcm47xx subtarget=generic" target_cpu: mipsel extra: 'mips_arch_variant="r1" mips_float_abi="soft"' - arch: riscv64 - openwrt: 'target=sifiveu subtarget=generic' + openwrt: "target=sifiveu subtarget=generic" target_cpu: riscv64 env: EXTRA_FLAGS: target_cpu="${{ matrix.target_cpu }}" target_os="openwrt" ${{ matrix.extra }} diff --git a/apk/.gitignore b/apk/.gitignore new file mode 100644 index 0000000000..33e08ed755 --- /dev/null +++ b/apk/.gitignore @@ -0,0 +1,2 @@ +.gradle/ +app/build/ diff --git a/apk/app/build.gradle.kts b/apk/app/build.gradle.kts new file mode 100644 index 0000000000..00cd5ac030 --- /dev/null +++ b/apk/app/build.gradle.kts @@ -0,0 +1,75 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "moe.matsuri.exe.naive" + + signingConfigs { + create("release") { + storeFile = rootProject.file("release.keystore") + storePassword = System.getenv("KEYSTORE_PASS") + keyAlias = "release" + keyPassword = System.getenv("KEYSTORE_PASS") + } + } + + buildTypes { + getByName("release") { + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + file("proguard-rules.pro") + ) + isMinifyEnabled = true + signingConfig = signingConfigs.getByName("release") + } + } + + compileSdk = 33 + + defaultConfig { + minSdk = 21 + targetSdk = 33 + + applicationId = "moe.matsuri.exe.naive" + versionCode = System.getenv("APK_VERSION_NAME").removePrefix("v").split(".")[0].toInt() + versionName = System.getenv("APK_VERSION_NAME").removePrefix("v") + splits.abi { + isEnable = true + isUniversalApk = false + reset() + include(System.getenv("APK_ABI")) + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + } + + lint { + showAll = true + checkAllWarnings = true + checkReleaseBuilds = false + warningsAsErrors = true + } + + applicationVariants.all { + outputs.all { + this as com.android.build.gradle.internal.api.BaseVariantOutputImpl + outputFileName = + outputFileName.replace(project.name, "naiveproxy-plugin-v$versionName") + .replace("-release", "") + .replace("-oss", "") + } + } + + sourceSets.getByName("main") { + jniLibs.srcDir("libs") + } +} diff --git a/apk/app/src/main/AndroidManifest.xml b/apk/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..72f3c643dc --- /dev/null +++ b/apk/app/src/main/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/NativePluginProvider.kt b/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/NativePluginProvider.kt new file mode 100644 index 0000000000..ef37e2b3e3 --- /dev/null +++ b/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/NativePluginProvider.kt @@ -0,0 +1,98 @@ +/****************************************************************************** + * * + * Copyright (C) 2021 by nekohasekai * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +package io.nekohasekai.sagernet.plugin + +import android.content.ContentProvider +import android.content.ContentValues +import android.database.Cursor +import android.database.MatrixCursor +import android.net.Uri +import android.os.Bundle +import android.os.ParcelFileDescriptor + +abstract class NativePluginProvider : ContentProvider() { + override fun getType(uri: Uri): String? = "application/x-elf" + + override fun onCreate(): Boolean = true + + /** + * Provide all files needed for native plugin. + * + * @param provider A helper object to use to add files. + */ + protected abstract fun populateFiles(provider: PathProvider) + + override fun query( + uri: Uri, + projection: Array?, + selection: String?, + selectionArgs: Array?, + sortOrder: String?, + ): Cursor? { + check(selection == null && selectionArgs == null && sortOrder == null) + val result = MatrixCursor(projection) + populateFiles(PathProvider(uri, result)) + return result + } + + /** + * Returns executable entry absolute path. + * This is used for fast mode initialization where ss-local launches your native binary at the path given directly. + * In order for this to work, plugin app is encouraged to have the following in its AndroidManifest.xml: + * - android:installLocation="internalOnly" for + * - android:extractNativeLibs="true" for + * + * Default behavior is throwing UnsupportedOperationException. If you don't wish to use this feature, use the + * default behavior. + * + * @return Absolute path for executable entry. + */ + open fun getExecutable(): String = throw UnsupportedOperationException() + + abstract fun openFile(uri: Uri): ParcelFileDescriptor + override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor { + check(mode == "r") + return openFile(uri) + } + + override fun call(method: String, arg: String?, extras: Bundle?): Bundle? = when (method) { + PluginContract.METHOD_GET_EXECUTABLE -> { + Bundle().apply { + putString(PluginContract.EXTRA_ENTRY, getExecutable()) + } + } + else -> super.call(method, arg, extras) + } + + // Methods that should not be used + override fun insert(uri: Uri, values: ContentValues?): Uri? = + throw UnsupportedOperationException() + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array?, + ): Int = + throw UnsupportedOperationException() + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int = + throw UnsupportedOperationException() +} diff --git a/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/PathProvider.kt b/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/PathProvider.kt new file mode 100644 index 0000000000..8008e5a510 --- /dev/null +++ b/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/PathProvider.kt @@ -0,0 +1,53 @@ +/****************************************************************************** + * * + * Copyright (C) 2021 by nekohasekai * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +package io.nekohasekai.sagernet.plugin + +import android.database.MatrixCursor +import android.net.Uri +import java.io.File + +/** + * Helper class to provide relative paths of files to copy. + */ +class PathProvider internal constructor(baseUri: Uri, private val cursor: MatrixCursor) { + private val basePath = baseUri.path?.trim('/') ?: "" + + fun addPath(path: String, mode: Int = 0b110100100): PathProvider { + val trimmed = path.trim('/') + if (trimmed.startsWith(basePath)) cursor.newRow() + .add(PluginContract.COLUMN_PATH, trimmed) + .add(PluginContract.COLUMN_MODE, mode) + return this + } + fun addTo(file: File, to: String = "", mode: Int = 0b110100100): PathProvider { + var sub = to + file.name + if (basePath.startsWith(sub)) if (file.isDirectory) { + sub += '/' + file.listFiles()!!.forEach { addTo(it, sub, mode) } + } else addPath(sub, mode) + return this + } + fun addAt(file: File, at: String = "", mode: Int = 0b110100100): PathProvider { + if (basePath.startsWith(at)) { + if (file.isDirectory) file.listFiles()!!.forEach { addTo(it, at, mode) } else addPath(at, mode) + } + return this + } +} diff --git a/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/PluginContract.kt b/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/PluginContract.kt new file mode 100644 index 0000000000..2788533292 --- /dev/null +++ b/apk/app/src/main/java/io/nekohasekai/sagernet/plugin/PluginContract.kt @@ -0,0 +1,34 @@ +/****************************************************************************** + * * + * Copyright (C) 2021 by nekohasekai * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +package io.nekohasekai.sagernet.plugin + +object PluginContract { + + const val ACTION_NATIVE_PLUGIN = "io.nekohasekai.sagernet.plugin.ACTION_NATIVE_PLUGIN" + const val EXTRA_ENTRY = "io.nekohasekai.sagernet.plugin.EXTRA_ENTRY" + const val METADATA_KEY_ID = "io.nekohasekai.sagernet.plugin.id" + const val METADATA_KEY_EXECUTABLE_PATH = "io.nekohasekai.sagernet.plguin.executable_path" + const val METHOD_GET_EXECUTABLE = "sagernet:getExecutable" + + const val COLUMN_PATH = "path" + const val COLUMN_MODE = "mode" + const val SCHEME = "plugin" + const val AUTHORITY = "io.nekohasekai.sagernet" +} diff --git a/apk/app/src/main/java/moe/matsuri/exe/naive/BinaryProvider.kt b/apk/app/src/main/java/moe/matsuri/exe/naive/BinaryProvider.kt new file mode 100644 index 0000000000..2776e4cd00 --- /dev/null +++ b/apk/app/src/main/java/moe/matsuri/exe/naive/BinaryProvider.kt @@ -0,0 +1,42 @@ +/****************************************************************************** + * * + * Copyright (C) 2021 by nekohasekai * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +package moe.matsuri.exe.naive + +import android.net.Uri +import android.os.ParcelFileDescriptor +import io.nekohasekai.sagernet.plugin.NativePluginProvider +import io.nekohasekai.sagernet.plugin.PathProvider +import java.io.File +import java.io.FileNotFoundException + +class BinaryProvider : NativePluginProvider() { + override fun populateFiles(provider: PathProvider) { + provider.addPath("naive-plugin", 0b111101101) + } + + override fun getExecutable() = context!!.applicationInfo.nativeLibraryDir + "/libnaive.so" + override fun openFile(uri: Uri): ParcelFileDescriptor = when (uri.path) { + "/naive-plugin" -> ParcelFileDescriptor.open( + File(getExecutable()), + ParcelFileDescriptor.MODE_READ_ONLY + ) + else -> throw FileNotFoundException() + } +} diff --git a/apk/app/src/main/res/drawable/ic_launcher_foreground.xml b/apk/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000000..ef0ca55847 --- /dev/null +++ b/apk/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..7005cb8e14 --- /dev/null +++ b/apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..7005cb8e14 --- /dev/null +++ b/apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/apk/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apk/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..db5767033e Binary files /dev/null and b/apk/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/apk/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/apk/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000..11b071c7d4 Binary files /dev/null and b/apk/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/apk/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apk/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..7d028abe13 Binary files /dev/null and b/apk/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/apk/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/apk/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000..a6650975c7 Binary files /dev/null and b/apk/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/apk/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/apk/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..3ce8151d0b Binary files /dev/null and b/apk/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/apk/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/apk/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..da5b85b0d9 Binary files /dev/null and b/apk/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/apk/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apk/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000..5181adaae7 Binary files /dev/null and b/apk/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/apk/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/apk/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..4feac43c28 Binary files /dev/null and b/apk/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000..b535a085dc Binary files /dev/null and b/apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..4a1edea686 Binary files /dev/null and b/apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/apk/app/src/main/res/values/ic_launcher_background.xml b/apk/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000000..c58f6bcbaa --- /dev/null +++ b/apk/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #E91E63 + \ No newline at end of file diff --git a/apk/build.gradle b/apk/build.gradle new file mode 100644 index 0000000000..74752cee64 --- /dev/null +++ b/apk/build.gradle @@ -0,0 +1,18 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/apk/gradle.properties b/apk/gradle.properties new file mode 100644 index 0000000000..98bed167dc --- /dev/null +++ b/apk/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official \ No newline at end of file diff --git a/apk/gradle/wrapper/gradle-wrapper.jar b/apk/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..e708b1c023 Binary files /dev/null and b/apk/gradle/wrapper/gradle-wrapper.jar differ diff --git a/apk/gradle/wrapper/gradle-wrapper.properties b/apk/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..e89ca18b4d --- /dev/null +++ b/apk/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Jan 27 22:42:44 HKT 2022 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/apk/gradlew b/apk/gradlew new file mode 100755 index 0000000000..4f906e0c81 --- /dev/null +++ b/apk/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/apk/release.keystore b/apk/release.keystore new file mode 100644 index 0000000000..bb93a21024 Binary files /dev/null and b/apk/release.keystore differ diff --git a/apk/settings.gradle b/apk/settings.gradle new file mode 100644 index 0000000000..aa6d172eb0 --- /dev/null +++ b/apk/settings.gradle @@ -0,0 +1,10 @@ +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +rootProject.name = "Matsuri Plugins" + +include ':app'