From 2aa975ab5a440cd07056fbf911f67e0d979b1fe5 Mon Sep 17 00:00:00 2001 From: Ax333l Date: Sat, 11 Jan 2025 22:29:24 +0100 Subject: [PATCH] feat: Update to account for API changes --- .gitignore | 6 +- README.md | 19 ++++-- build.gradle.kts | 21 +----- gradle.properties | 2 + gradle/libs.versions.toml | 19 ++---- gradlew | 0 src/main/AndroidManifest.xml | 12 ++-- .../downloader/example/ExampleDownloader.kt | 61 ----------------- .../downloader/example/InteractionActivity.kt | 65 ------------------- .../downloader/example/ExampleDownloader.kt | 42 ++++++++++++ 10 files changed, 76 insertions(+), 171 deletions(-) mode change 100644 => 100755 gradlew delete mode 100644 src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt delete mode 100644 src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt create mode 100644 src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt diff --git a/.gitignore b/.gitignore index 58b769c..390ce08 100644 --- a/.gitignore +++ b/.gitignore @@ -123,4 +123,8 @@ gradle-app.setting node_modules/ # Ignore IDEA files -.idea/ \ No newline at end of file +.idea/ + +.kotlin/ + +local.properties diff --git a/README.md b/README.md index b332277..e8bf5f7 100644 --- a/README.md +++ b/README.md @@ -63,13 +63,11 @@ ![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/ReVanced/revanced-manager-downloader-template/release.yml) ![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg) -Template repository for ReVanced Manager downloader. +Template repository for ReVanced Manager downloader plugins. ## ❓ About -This is a template to create a new ReVanced Manager downloader repository. - -For an example repository, see [TODO](https://github.com/revanced/revanced-manager). +This is a template to create a new ReVanced Manager downloader repository. An example implementation is included. ## 🚀 Get started @@ -108,7 +106,7 @@ To develop and release ReVanced Manager downloader using this template, some thi - Commits on the `dev` branch and `main` branch are automatically released via the [release.yml](.github/workflows/release.yml) workflow, which is also responsible for generating the changelog and updating the version of ReVanced Manager downloader. It is triggered by pushing to the `dev` or `main` branch. -The workflow uses the `publish` task to publish the release of ReVanced Patches +The workflow uses the `publish` task to publish the release. - The `publish` task depends on the `assembleRelease` task, so it will be run automatically when publishing a release. ## 📚 Everything else @@ -126,6 +124,17 @@ Follow the steps below to build ReVanced Manager downloader template: 1. Run `git clone git@github.com:ReVanced/revanced-manager-downloader-template.git` to clone the repository 2. Run `gradlew assembleRelease` to build the project +> [!NOTE] +> If the build fails due to authentication, you may need to authenticate to GitHub Packages. +> Create a PAT with the scope `read:packages` [here](https://github.com/settings/tokens/new?scopes=read:packages&description=ReVanced) and add your token to ~/.gradle/gradle.properties. +> +> Example `gradle.properties` file: +> +> ```properties +> gpr.user = user +> gpr.key = key +> ``` + ## 📜 Licence ReVanced Manager downloader template is licensed under the GPLv3 licence. diff --git a/build.gradle.kts b/build.gradle.kts index 9b68ef8..4f47d5d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,36 +1,26 @@ plugins { alias(libs.plugins.android.application) - alias(libs.plugins.compose.compiler) alias(libs.plugins.kotlin.android) - alias(libs.plugins.kotlin.parcelize) publishing signing } dependencies { - implementation(libs.compose.activity) - implementation(platform(libs.compose.bom)) - implementation(libs.compose.material3) - implementation(libs.compose.ui) - implementation(libs.compose.ui.tooling) - - compileOnly(project(":downloader-plugin")) + compileOnly(libs.plugin.api) } android { val packageName = "app.revanced.manager.plugin.downloader.example" namespace = packageName - compileSdk = 34 + compileSdk = 35 defaultConfig { applicationId = packageName minSdk = 26 - targetSdk = 34 + targetSdk = 35 versionName = version.toString() versionCode = versionName!!.filter { it.isDigit() }.toInt() - - buildConfigField("String", "PLUGIN_PACKAGE_NAME", "\"$packageName\"") } buildTypes { @@ -64,11 +54,6 @@ android { jvmTarget = "17" } - buildFeatures { - compose = true - buildConfig = true - } - applicationVariants.all { outputs.all { this as com.android.build.gradle.internal.api.ApkVariantOutputImpl diff --git a/gradle.properties b/gradle.properties index bab8b10..c6ebaca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,3 +4,5 @@ android.nonFinalResIds=false kotlin.code.style = official org.gradle.parallel = true org.gradle.caching = true + +version = 1.0.0 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index abd6cad..fefb0d6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,20 +1,11 @@ [versions] -android = "8.5.2" -compose-activity = "1.9.1" -compose-bom = "2024.08.00" -kotlin = "2.0.20" -material3 = "1.3.0-rc01" -ui-tooling = "1.6.8" +plugin-api = "1.0.0" +android-gradle-plugin = "8.7.3" +kotlin = "2.1.0" [libraries] -compose-activity = { group = "androidx.activity", name = "activity-compose", version.ref = "compose-activity" } -compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } -compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3"} -compose-ui = { group = "androidx.compose.ui", name = "ui" } -compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "ui-tooling" } +plugin-api = { group = "app.revanced", name = "revanced-manager-downloader-api", version.ref = "plugin-api" } [plugins] -android-application = { id = "com.android.application", version.ref = "android" } -compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index b89570b..fdee611 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -7,14 +7,12 @@ - - + tools:targetApi="35"> + diff --git a/src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt b/src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt deleted file mode 100644 index 32724f7..0000000 --- a/src/main/java/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt +++ /dev/null @@ -1,61 +0,0 @@ -@file:Suppress("Unused") - -package app.revanced.manager.plugin.downloader.example - -import android.content.Intent -import android.content.pm.PackageManager -import app.revanced.manager.plugin.downloader.App -import app.revanced.manager.plugin.downloader.example.BuildConfig.PLUGIN_PACKAGE_NAME -import app.revanced.manager.plugin.downloader.DownloaderContext -import app.revanced.manager.plugin.downloader.downloader -import kotlinx.coroutines.delay -import kotlinx.parcelize.Parcelize -import java.nio.file.Files -import java.nio.file.StandardCopyOption -import kotlin.io.path.Path - -// TODO: document API, change dispatcher. - -@Parcelize -class InstalledApp( - override val packageName: String, - override val version: String, - internal val apkPath: String -) : App(packageName, version) - -fun installedAppDownloader(context: DownloaderContext) = downloader { - val pm = context.androidContext.packageManager - - get { packageName, version -> - val packageInfo = try { - pm.getPackageInfo(packageName, 0) - } catch (_: PackageManager.NameNotFoundException) { - return@get null - } - - requestUserInteraction().launch(Intent().apply { - setClassName( - PLUGIN_PACKAGE_NAME, - InteractionActivity::class.java.canonicalName!! - ) - }) - - InstalledApp( - packageName, - packageInfo.versionName, - packageInfo.applicationInfo.sourceDir - ).takeIf { version == null || it.version == version } - } - - download { - // Simulate download progress - for (i in 0..5) { - reportProgress(i.megaBytes, 5.megaBytes) - delay(1000L) - } - - Files.copy(Path(it.apkPath), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING) - } -} - -private val Int.megaBytes get() = times(1_000_000).toLong() \ No newline at end of file diff --git a/src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt b/src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt deleted file mode 100644 index 0390f3b..0000000 --- a/src/main/java/app/revanced/manager/plugin/downloader/example/InteractionActivity.kt +++ /dev/null @@ -1,65 +0,0 @@ -package app.revanced.manager.plugin.downloader.example - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.ui.Modifier - -class InteractionActivity : ComponentActivity() { - @OptIn(ExperimentalMaterial3Api::class) - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - val isDarkTheme = isSystemInDarkTheme() - - val colorScheme = if (isDarkTheme) darkColorScheme() else lightColorScheme() - - MaterialTheme(colorScheme) { - Scaffold( - topBar = { - TopAppBar( - title = { Text("User interaction example") } - ) - } - ) { paddingValues -> - Column(modifier = Modifier.padding(paddingValues)) { - Text("This is an example interaction.") - Row { - TextButton( - onClick = { - setResult(RESULT_CANCELED) - finish() - } - ) { - Text("Cancel") - } - - TextButton( - onClick = { - setResult(RESULT_OK) - finish() - } - ) { - Text("Continue") - } - } - } - } - } - - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt b/src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt new file mode 100644 index 0000000..e177694 --- /dev/null +++ b/src/main/kotlin/app/revanced/manager/plugin/downloader/example/ExampleDownloader.kt @@ -0,0 +1,42 @@ +@file:Suppress("Unused") + +package app.revanced.manager.plugin.downloader.example + +import android.annotation.SuppressLint +import android.app.Application +import android.content.Intent +import android.content.res.AssetFileDescriptor +import app.revanced.manager.plugin.downloader.* + +// This file contains an example downloader implementation using the system file picker. +// Remember to update the Android manifest if you move the definition file. + +val exampleDownloader = Downloader { + get { packageName, version -> + // Use the requestStartActivity API to open the system file picker and get the resulting content URI. + val uri = requestStartActivity( + Intent(Intent.ACTION_GET_CONTENT) + .addCategory(Intent.CATEGORY_OPENABLE) + .setType("application/vnd.android.package-archive") + )?.data ?: return@get null + + println("Package name: $packageName, version: $version") + + // We assume the user has selected the correct version, but this might not be the case. + // Real plugins should verify the version and package name if possible. + uri to version + } + + // Get an Android context. This is only used for reading the file that the user selected. + // This hack should not be necessary in a real plugin. + @SuppressLint("PrivateApi") + val application = with(Class.forName("android.app.ActivityThread")) { + val activityThread = getMethod("currentActivityThread")(null) + getMethod("getApplication")(activityThread) as Application + } + download { uri -> + // Open the file and return an InputStream to it along with the size. + val fd = application.contentResolver.openAssetFileDescriptor(uri, "r")!! + AssetFileDescriptor.AutoCloseInputStream(fd) to fd.length.takeIf { it > 0L } + } +} \ No newline at end of file