Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Key features of Ackpine:
- **Deferred**: Ackpine allows to defer user's intervention via customizable high-priority notification.
- **Progress and state updates**: it's easy to observe every session's state and progress updates.
- **Advanced features**: Ackpine allows to benefit from advanced features without juggling complex OS APIs (such as install pre-approval) introduced in later Android versions.
- **Elevated permissions**: Shizuku and root shell are supported as installer backends with advanced install flags.
- **Elevated permissions**: Shizuku, root shell and Dhizuku are supported as installer backends with advanced install flags.
- **100% Java and Kotlin-friendly**: while maintaining full Java compatibility, Ackpine was developed as a Kotlin-first library.
- **Compatibility**: Ackpine supports Android versions starting from API level 16.

Expand Down Expand Up @@ -69,6 +69,12 @@ ackpine-libsu = { module = "ru.solrudev.ackpine:ackpine-libsu", version.ref = "a
# optional - Kotlin extensions for libsu plugin
ackpine-libsu-ktx = { module = "ru.solrudev.ackpine:ackpine-libsu-ktx", version.ref = "ackpine" }

# optional - plugin enabling installs/uninstalls through Dhizuku
ackpine-dhizuku = { module = "ru.solrudev.ackpine:ackpine-dhizuku", version.ref = "ackpine" }

# optional - Kotlin extensions for Dhizuku plugin
ackpine-dhizuku-ktx = { module = "ru.solrudev.ackpine:ackpine-dhizuku-ktx", version.ref = "ackpine" }

# optional - testing utilities
ackpine-test = { module = "ru.solrudev.ackpine:ackpine-test", version.ref = "ackpine" }

Expand All @@ -82,7 +88,9 @@ ackpine = [
"ackpine-shizuku",
"ackpine-shizuku-ktx",
"ackpine-libsu",
"ackpine-libsu-ktx"
"ackpine-libsu-ktx",
"ackpine-dhizuku",
"ackpine-dhizuku-ktx"
]
```
</details>
Expand Down Expand Up @@ -119,6 +127,12 @@ dependencies {
// optional - Kotlin extensions for libsu plugin
implementation("ru.solrudev.ackpine:ackpine-libsu-ktx:$ackpineVersion")

// optional - plugin enabling installs/uninstalls through Dhizuku
implementation("ru.solrudev.ackpine:ackpine-dhizuku:$ackpineVersion")

// optional - Kotlin extensions for Dhizuku plugin
implementation("ru.solrudev.ackpine:ackpine-dhizuku-ktx:$ackpineVersion")

// optional - testing utilities
testImplementation("ru.solrudev.ackpine:ackpine-test:$ackpineVersion")
}
Expand Down
52 changes: 52 additions & 0 deletions ackpine-plugins/dhizuku-ktx/api/dhizuku-ktx.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
public abstract interface class ru/solrudev/ackpine/dhizuku/DhizukuInstallParametersDsl {
public abstract fun getRequestDowngrade ()Z
public abstract fun setRequestDowngrade (Z)V
}

public final class ru/solrudev/ackpine/dhizuku/DhizukuInstallParametersDslBuilder : ru/solrudev/ackpine/dhizuku/DhizukuInstallParametersDsl {
public fun <init> ()V
public final fun build ()Lru/solrudev/ackpine/dhizuku/DhizukuPlugin$InstallParameters;
public fun getRequestDowngrade ()Z
public fun setRequestDowngrade (Z)V
}

public final class ru/solrudev/ackpine/dhizuku/DhizukuInstallParametersKt {
public static final fun DhizukuInstallParameters (Lkotlin/jvm/functions/Function1;)Lru/solrudev/ackpine/dhizuku/DhizukuPlugin$InstallParameters;
public static synthetic fun DhizukuInstallParameters$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lru/solrudev/ackpine/dhizuku/DhizukuPlugin$InstallParameters;
}

public abstract interface class ru/solrudev/ackpine/dhizuku/DhizukuUninstallParametersDsl {
public abstract fun getAllUsers ()Z
public abstract fun getKeepData ()Z
public abstract fun getSystemApp ()Z
public abstract fun setAllUsers (Z)V
public abstract fun setKeepData (Z)V
public abstract fun setSystemApp (Z)V
}

public final class ru/solrudev/ackpine/dhizuku/DhizukuUninstallParametersDslBuilder : ru/solrudev/ackpine/dhizuku/DhizukuUninstallParametersDsl {
public fun <init> ()V
public final fun build ()Lru/solrudev/ackpine/dhizuku/DhizukuPlugin$UninstallParameters;
public fun getAllUsers ()Z
public fun getKeepData ()Z
public fun getSystemApp ()Z
public fun setAllUsers (Z)V
public fun setKeepData (Z)V
public fun setSystemApp (Z)V
}

public final class ru/solrudev/ackpine/dhizuku/DhizukuUninstallParametersKt {
public static final fun DhizukuUninstallParameters (Lkotlin/jvm/functions/Function1;)Lru/solrudev/ackpine/dhizuku/DhizukuPlugin$UninstallParameters;
public static synthetic fun DhizukuUninstallParameters$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lru/solrudev/ackpine/dhizuku/DhizukuPlugin$UninstallParameters;
}

public final class ru/solrudev/ackpine/dhizuku/InstallParametersDslKt {
public static final fun dhizuku (Lru/solrudev/ackpine/installer/parameters/InstallParametersDsl;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun dhizuku$default (Lru/solrudev/ackpine/installer/parameters/InstallParametersDsl;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}

public final class ru/solrudev/ackpine/dhizuku/UninstallParametersDslKt {
public static final fun dhizuku (Lru/solrudev/ackpine/uninstaller/parameters/UninstallParametersDsl;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun dhizuku$default (Lru/solrudev/ackpine/uninstaller/parameters/UninstallParametersDsl;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}

37 changes: 37 additions & 0 deletions ackpine-plugins/dhizuku-ktx/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

description = "Kotlin extensions for Ackpine Dhizuku plugin"

plugins {
id("ru.solrudev.ackpine.library")
id("ru.solrudev.ackpine.library-publish")
id("ru.solrudev.ackpine.dokka")
}

ackpine {
id = "dhizuku-ktx"
minSdk = 26
artifact {
name = "Ackpine Dhizuku Plugin KTX"
inceptionYear = "2026"
}
}

dependencies {
api(projects.ackpineKtx)
api(projects.ackpinePlugins.dhizuku)
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

package ru.solrudev.ackpine.dhizuku

/**
* Constructs a new instance of [DhizukuPlugin.InstallParameters].
*/
@Suppress("FunctionName")
public inline fun DhizukuInstallParameters(
configure: DhizukuInstallParametersDsl.() -> Unit = {}
): DhizukuPlugin.InstallParameters {
return DhizukuInstallParametersDslBuilder().apply(configure).build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

package ru.solrudev.ackpine.dhizuku

import ru.solrudev.ackpine.DelicateAckpineApi
import ru.solrudev.ackpine.session.parameters.SessionParametersDsl

/**
* DSL allowing to configure [install parameters for DhizukuPlugin][DhizukuPlugin.InstallParameters].
*/
@SessionParametersDsl
public interface DhizukuInstallParametersDsl {

/**
* Whether an upgrade to a lower version of a package than currently installed is requested.
*
* Ackpine sets downgrade-request flag which is honored for debuggable installed apps or debuggable OS builds, but
* does not add the unrestricted downgrade permission flag used by root, shell, or system identities.
* The device owner must still be authorized by Android to perform the downgrade, so setting this option does
* not guarantee that a downgrade will succeed.
*
* This is a **delicate** API. The outcome of using this flag depends on the app being installed, on a
* specific OS build, and on the permissions that the used device owner identity has.
*/
@set:DelicateAckpineApi
public var requestDowngrade: Boolean
}

@PublishedApi
internal class DhizukuInstallParametersDslBuilder : DhizukuInstallParametersDsl {

private val delegate = DhizukuPlugin.InstallParameters.Builder()

@set:DelicateAckpineApi
override var requestDowngrade: Boolean
get() = delegate.requestDowngrade
set(value) {
delegate.setRequestDowngrade(value)
}

fun build(): DhizukuPlugin.InstallParameters = delegate.build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

package ru.solrudev.ackpine.dhizuku

/**
* Constructs a new instance of [DhizukuPlugin.UninstallParameters].
*/
@Suppress("FunctionName")
public inline fun DhizukuUninstallParameters(
configure: DhizukuUninstallParametersDsl.() -> Unit = {}
): DhizukuPlugin.UninstallParameters {
return DhizukuUninstallParametersDslBuilder().apply(configure).build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

package ru.solrudev.ackpine.dhizuku

import ru.solrudev.ackpine.session.parameters.SessionParametersDsl

/**
* DSL allowing to configure [uninstall parameters for DhizukuPlugin][DhizukuPlugin.UninstallParameters].
*/
@SessionParametersDsl
public interface DhizukuUninstallParametersDsl {

/**
* Whether to retain the package's data directory.
*/
public var keepData: Boolean

/**
* Whether to delete the package for all users.
*/
public var allUsers: Boolean

/**
* Whether a system app should be marked as uninstalled for the current user.
*/
public var systemApp: Boolean
}

@PublishedApi
internal class DhizukuUninstallParametersDslBuilder : DhizukuUninstallParametersDsl {

private val delegate = DhizukuPlugin.UninstallParameters.Builder()

override var keepData: Boolean
get() = delegate.keepData
set(value) {
delegate.setKeepData(value)
}

override var allUsers: Boolean
get() = delegate.allUsers
set(value) {
delegate.setAllUsers(value)
}

override var systemApp: Boolean
get() = delegate.systemApp
set(value) {
delegate.setSystemApp(value)
}

fun build(): DhizukuPlugin.UninstallParameters = delegate.build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

package ru.solrudev.ackpine.dhizuku

import ru.solrudev.ackpine.installer.parameters.InstallParametersDsl

/**
* Registers [DhizukuPlugin] for the session.
*/
public inline fun InstallParametersDsl.dhizuku(
configure: DhizukuInstallParametersDsl.() -> Unit = {}
) {
plugin(DhizukuPlugin::class, DhizukuInstallParameters(configure))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2026 Ilya Fomichev
*
* 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
*
* http://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.
*/

package ru.solrudev.ackpine.dhizuku

import ru.solrudev.ackpine.uninstaller.parameters.UninstallParametersDsl

/**
* Registers [DhizukuPlugin] for the session.
*/
public inline fun UninstallParametersDsl.dhizuku(
configure: DhizukuUninstallParametersDsl.() -> Unit = {}
) {
plugin(DhizukuPlugin::class, DhizukuUninstallParameters(configure))
}
Loading