├── ackpine-api
├── build.gradle.kts
├── api-stubs
│ ├── src
│ │ └── main
│ │ │ └── kotlin
│ │ │ ├── android
│ │ │ └── content
│ │ │ │ └── Context.kt
│ │ │ └── ru
│ │ │ └── solrudev
│ │ │ └── ackpine
│ │ │ ├── installer
│ │ │ └── PackageInstaller.kt
│ │ │ ├── uninstaller
│ │ │ └── PackageUninstaller.kt
│ │ │ ├── SdkInt.kt
│ │ │ └── impl
│ │ │ ├── installer
│ │ │ └── PackageInstallerImpl.kt
│ │ │ └── uninstaller
│ │ │ └── PackageUninstallerImpl.kt
│ └── build.gradle.kts
└── api-main
│ ├── consumer-rules.pro
│ ├── src
│ └── main
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ ├── session
│ │ ├── Progress.kt
│ │ ├── Failure.kt
│ │ └── parameters
│ │ │ └── ConfirmationAware.kt
│ │ ├── exceptions
│ │ └── Exceptions.kt
│ │ ├── SdkIntWrapper.kt
│ │ ├── PackageInstallerApiCheck.kt
│ │ ├── Annotations.kt
│ │ └── plugability
│ │ └── AckpinePluginRegistry.kt
│ └── build.gradle.kts
├── ackpine-assets
├── consumer-rules.pro
├── build.gradle.kts
└── src
│ └── main
│ └── AndroidManifest.xml
├── ackpine-core
├── consumer-rules.pro
├── api
│ └── ackpine-core.api
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── public.xml
│ │ │ ├── styles.xml
│ │ │ └── themes.xml
│ │ ├── values-af-rZA
│ │ │ └── strings.xml
│ │ ├── anim
│ │ │ └── ackpine_fade_out.xml
│ │ ├── values-v19
│ │ │ └── themes.xml
│ │ ├── values-v29
│ │ │ └── themes.xml
│ │ ├── layout
│ │ │ └── ackpine_activity_session_commit.xml
│ │ ├── values-v21
│ │ │ └── themes.xml
│ │ ├── values-vi
│ │ │ └── strings.xml
│ │ └── values-ru
│ │ │ └── strings.xml
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ ├── SdkInt.kt
│ │ ├── impl
│ │ ├── database
│ │ │ ├── dao
│ │ │ │ ├── SessionFailureDao.kt
│ │ │ │ ├── SessionNameDao.kt
│ │ │ │ ├── InstallPreapprovalDao.kt
│ │ │ │ ├── NotificationIdDao.kt
│ │ │ │ ├── ConfirmationLaunchDao.kt
│ │ │ │ ├── InstallConstraintsDao.kt
│ │ │ │ └── NativeSessionIdDao.kt
│ │ │ └── model
│ │ │ │ ├── InstallUriEntity.kt
│ │ │ │ ├── SessionNameEntity.kt
│ │ │ │ ├── PackageNameEntity.kt
│ │ │ │ ├── NotificationIdEntity.kt
│ │ │ │ ├── UpdateOwnershipEntity.kt
│ │ │ │ ├── NativeSessionIdEntity.kt
│ │ │ │ ├── LastUpdateTimestampEntity.kt
│ │ │ │ ├── ConfirmationLaunchEntity.kt
│ │ │ │ └── InstallFailureEntity.kt
│ │ ├── plugability
│ │ │ └── AckpineService.kt
│ │ ├── helpers
│ │ │ └── concurrent
│ │ │ │ └── BinarySemaphore.kt
│ │ └── uninstaller
│ │ │ └── helpers
│ │ │ └── PackageManagerHelpers.kt
│ │ ├── exceptions
│ │ └── Exceptions.kt
│ │ └── AckpineInitializer.kt
└── build.gradle.kts
├── ackpine-ktx
├── consumer-rules.pro
├── src
│ └── main
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ ├── session
│ │ └── parameters
│ │ │ ├── SessionParametersDsl.kt
│ │ │ ├── NotificationData.kt
│ │ │ └── ConfirmationDsl.kt
│ │ ├── DisposableSubscriptionContainer.kt
│ │ ├── uninstaller
│ │ └── parameters
│ │ │ └── UninstallParameters.kt
│ │ └── installer
│ │ └── parameters
│ │ ├── InstallConstraints.kt
│ │ ├── ApkList.kt
│ │ └── InstallParameters.kt
└── build.gradle.kts
├── ackpine-plugins
├── build.gradle.kts
├── shizuku-ktx
│ ├── consumer-rules.pro
│ ├── src
│ │ └── main
│ │ │ └── kotlin
│ │ │ └── ru
│ │ │ └── solrudev
│ │ │ └── ackpine
│ │ │ └── shizuku
│ │ │ ├── ShizukuPluginParameters.kt
│ │ │ ├── InstallParametersDsl.kt
│ │ │ ├── ShizukuUninstallPluginParameters.kt
│ │ │ └── UninstallParametersDsl.kt
│ └── build.gradle.kts
├── shizuku-stubs
│ ├── consumer-rules.pro
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── java
│ │ └── android
│ │ └── content
│ │ └── pm
│ │ ├── IPackageInstallerSession.java
│ │ ├── IPackageManager.java
│ │ └── IPackageInstaller.java
└── shizuku
│ ├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── ru.solrudev.ackpine.impl.plugability.AckpineServiceProvider
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ └── shizuku
│ │ ├── DeleteFlags.kt
│ │ └── InstallFlags.kt
│ └── consumer-rules.pro
├── ackpine-splits
├── build.gradle.kts
├── splits-ktx
│ ├── consumer-rules.pro
│ ├── api
│ │ └── splits-ktx.api
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ └── splits
│ │ └── SplitPackageProvider.kt
├── splits-main
│ ├── consumer-rules.pro
│ ├── src
│ │ └── main
│ │ │ ├── kotlin
│ │ │ └── ru
│ │ │ │ └── solrudev
│ │ │ │ └── ackpine
│ │ │ │ ├── io
│ │ │ │ ├── NonClosingInputStream.kt
│ │ │ │ └── ToByteBuffer.kt
│ │ │ │ ├── helpers
│ │ │ │ └── ZipHelpers.kt
│ │ │ │ └── splits
│ │ │ │ └── helpers
│ │ │ │ ├── SplitTypePart.kt
│ │ │ │ ├── IsApk.kt
│ │ │ │ ├── UriHelpers.kt
│ │ │ │ └── LocaleHelpers.kt
│ │ │ └── AndroidManifest.xml
│ └── build.gradle.kts
└── compress-android
│ ├── consumer-rules.pro
│ └── src
│ └── main
│ └── java
│ └── ru
│ └── solrudev
│ └── ackpine
│ └── compress
│ └── compressors
│ └── deflate64
│ └── HuffmanState.java
├── dokka-plugins
├── build.gradle.kts
└── suppress-annotated-api
│ ├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── org.jetbrains.dokka.plugability.DokkaPlugin
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ └── documentation
│ │ └── SuppressAnnotatedApiConfig.kt
│ └── build.gradle.kts
├── sample-api34
├── proguard-rules.pro
├── src
│ └── main
│ │ ├── assets
│ │ └── ackpine_icon.webp
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── values-vi
│ │ │ └── strings.xml
│ │ ├── values-af-rZA
│ │ │ └── strings.xml
│ │ ├── values
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── dimens.xml
│ │ │ ├── styles.xml
│ │ │ └── strings.xml
│ │ ├── values-v29
│ │ │ └── themes.xml
│ │ ├── values-ru
│ │ │ └── strings.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ └── drawable
│ │ │ └── ic_launcher_foreground.xml
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ └── sample
│ │ └── updater
│ │ └── UpdaterUiState.kt
└── build.gradle.kts
├── sample-java
├── proguard-rules.pro
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── values
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── styles.xml
│ │ │ └── dimens.xml
│ │ ├── values-v29
│ │ │ └── themes.xml
│ │ ├── drawable
│ │ │ ├── ic_install.xml
│ │ │ ├── ic_uninstall.xml
│ │ │ ├── ic_launcher_foreground.xml
│ │ │ └── ic_install_filled.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── values-af-rZA
│ │ │ └── strings.xml
│ │ ├── values-vi
│ │ │ └── strings.xml
│ │ ├── menu
│ │ │ └── bottom_nav_menu.xml
│ │ └── navigation
│ │ │ └── ackpine_navigation_graph.xml
│ │ └── java
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ └── sample
│ │ └── install
│ │ ├── SessionData.java
│ │ ├── SessionProgress.java
│ │ └── SessionDataRepository.java
└── build.gradle.kts
├── sample-ktx
├── proguard-rules.pro
└── src
│ └── main
│ ├── res
│ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ ├── values
│ │ ├── ic_launcher_background.xml
│ │ ├── styles.xml
│ │ └── dimens.xml
│ ├── values-v29
│ │ └── themes.xml
│ ├── drawable
│ │ ├── ic_install.xml
│ │ ├── ic_uninstall.xml
│ │ ├── ic_launcher_foreground.xml
│ │ └── ic_install_filled.xml
│ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ ├── values-af-rZA
│ │ └── strings.xml
│ ├── menu
│ │ └── bottom_nav_menu.xml
│ ├── values-vi
│ │ └── strings.xml
│ └── navigation
│ │ └── ackpine_navigation_graph.xml
│ └── kotlin
│ └── ru
│ └── solrudev
│ └── ackpine
│ └── sample
│ ├── uninstall
│ ├── ApplicationData.kt
│ └── UninstallUiState.kt
│ ├── util
│ ├── FragmentExt.kt
│ └── PackageManagerExt.kt
│ └── install
│ ├── InstallUiState.kt
│ ├── SessionData.kt
│ ├── SessionProgress.kt
│ └── SessionDataRepository.kt
├── ackpine-runtime
├── consumer-rules.pro
├── api
│ └── ackpine-runtime.api
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ └── public.xml
│ │ └── xml
│ │ │ └── ackpine_file_provider_paths.xml
│ │ ├── AndroidManifest.xml
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ ├── AckpineFileProvider.kt
│ │ └── AckpineThreadPool.kt
└── build.gradle.kts
├── docs
├── .meta.yml
├── css
│ ├── logo-styles.css
│ └── docs.css
├── images
│ ├── logo-white.svg
│ └── logo-icon.svg
├── samples.md
├── permissions.md
└── architecture.md
├── version.properties
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── kotlinx.versions.toml
└── settings
│ ├── settings.gradle.kts
│ ├── src
│ └── main
│ │ └── kotlin
│ │ └── ru
│ │ └── solrudev
│ │ └── ackpine
│ │ └── gradle
│ │ └── ConfigureRepositories.kt
│ └── build.gradle.kts
├── ackpine-resources
├── consumer-rules.pro
├── build.gradle.kts
└── api
│ └── ackpine-resources.api
├── gradle.properties
├── .github
├── ci-gradle.properties
├── workflows
│ └── release-tag.yml
└── actions
│ └── setup-gradle-environment-action
│ └── action.yml
├── settings.gradle.kts
└── api-documentation
└── build.gradle.kts
/ackpine-api/build.gradle.kts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-assets/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-core/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-ktx/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-plugins/build.gradle.kts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-splits/build.gradle.kts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dokka-plugins/build.gradle.kts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sample-api34/proguard-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sample-java/proguard-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sample-ktx/proguard-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-runtime/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/.meta.yml:
--------------------------------------------------------------------------------
1 | hide:
2 | - navigation
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-ktx/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-stubs/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-ktx/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/version.properties:
--------------------------------------------------------------------------------
1 | MAJOR_VERSION=0
2 | MINOR_VERSION=18
3 | PATCH_VERSION=4
4 | SUFFIX=
5 | SNAPSHOT=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/sample-api34/src/main/assets/ackpine_icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/assets/ackpine_icon.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku/src/main/resources/META-INF/services/ru.solrudev.ackpine.impl.plugability.AckpineServiceProvider:
--------------------------------------------------------------------------------
1 | ru.solrudev.ackpine.shizuku.ShizukuServiceProvider
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/docs/css/logo-styles.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --dokka-logo-image-url: url('../../images/logo-white.svg');
3 | --dokka-logo-height: 50px;
4 | --dokka-logo-width: 50px;
5 | }
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-api34/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-java/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/solrudev/Ackpine/HEAD/sample-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/ackpine-runtime/api/ackpine-runtime.api:
--------------------------------------------------------------------------------
1 | public final class ru/solrudev/ackpine/AckpineFileProvider$Companion {
2 | public final fun getAuthority ()Ljava/lang/String;
3 | }
4 |
5 |
--------------------------------------------------------------------------------
/dokka-plugins/suppress-annotated-api/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin:
--------------------------------------------------------------------------------
1 | ru.solrudev.ackpine.documentation.SuppressAnnotatedApiDokkaPlugin
--------------------------------------------------------------------------------
/gradle/kotlinx.versions.toml:
--------------------------------------------------------------------------------
1 | [libraries]
2 | coroutines-core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2"
3 | serialization-json = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
--------------------------------------------------------------------------------
/ackpine-splits/compress-android/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -dontwarn com.github.luben.zstd.ZstdInputStream
2 | -dontwarn org.tukaani.xz.MemoryLimitException
3 | -dontwarn org.tukaani.xz.SingleXZInputStream
4 | -dontwarn org.tukaani.xz.XZInputStream
--------------------------------------------------------------------------------
/ackpine-splits/splits-ktx/api/splits-ktx.api:
--------------------------------------------------------------------------------
1 | public final class ru/solrudev/ackpine/splits/SplitPackageProviderKt {
2 | public static final fun get (Lru/solrudev/ackpine/splits/SplitPackage$Provider;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
3 | }
4 |
5 |
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Cài đặt
4 | Cài đặt
5 | Huỷ
6 | Có lỗi
7 | Lỗi: %s
8 |
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -dontwarn android.content.pm.IPackageInstaller$Stub
2 | -dontwarn android.content.pm.IPackageInstaller
3 | -dontwarn android.content.pm.IPackageInstallerSession$Stub
4 | -dontwarn android.content.pm.IPackageInstallerSession
5 | -dontwarn android.content.pm.IPackageManager$Stub
6 | -dontwarn android.content.pm.IPackageManager
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values-af-rZA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Installeer
4 | Installeer
5 | Kanselleer
6 | Fout
7 | Fout: %s
8 |
--------------------------------------------------------------------------------
/ackpine-resources/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | # Serializable
2 | -keep class ru.solrudev.ackpine.resources.ResolvableString { *; }
3 | -keep class ru.solrudev.ackpine.resources.ResolvableString$* { *; }
4 | -keep class * extends ru.solrudev.ackpine.resources.ResolvableString$Resource { *; }
5 | -keep class ru.solrudev.ackpine.resources.Empty { *; }
6 | -keep class ru.solrudev.ackpine.resources.Raw { *; }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
5 | networkTimeout=10000
6 | validateDistributionUrl=true
7 | zipStoreBase=GRADLE_USER_HOME
8 | zipStorePath=wrapper/dists
9 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=1g
2 | org.gradle.daemon=true
3 | org.gradle.parallel=true
4 | org.gradle.configuration-cache=true
5 | org.gradle.configuration-cache.parallel=true
6 | org.gradle.configureondemand=true
7 | android.useAndroidX=true
8 | kotlin.code.style=official
9 | android.r8.maxWorkers=2
10 | android.lint.useK2Uast=true
--------------------------------------------------------------------------------
/.github/ci-gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=1g
2 | org.gradle.daemon=false
3 | org.gradle.caching=true
4 | org.gradle.parallel=true
5 | org.gradle.configuration-cache=true
6 | org.gradle.configuration-cache.parallel=true
7 | org.gradle.configureondemand=true
8 | android.useAndroidX=true
9 | kotlin.code.style=official
10 | android.r8.maxWorkers=2
11 | android.lint.useK2Uast=true
--------------------------------------------------------------------------------
/docs/images/logo-white.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/ackpine-core/api/ackpine-core.api:
--------------------------------------------------------------------------------
1 | public final class ru/solrudev/ackpine/Ackpine {
2 | public static final field INSTANCE Lru/solrudev/ackpine/Ackpine;
3 | public static final fun deleteNotificationChannel (Landroid/content/Context;)V
4 | }
5 |
6 | public final class ru/solrudev/ackpine/AckpineInitializer : androidx/startup/Initializer {
7 | public fun ()V
8 | public synthetic fun create (Landroid/content/Context;)Ljava/lang/Object;
9 | public fun create (Landroid/content/Context;)Lru/solrudev/ackpine/Ackpine;
10 | public fun dependencies ()Ljava/util/List;
11 | }
12 |
13 | public final class ru/solrudev/ackpine/exceptions/AckpineReinitializeException : java/lang/Exception {
14 | public fun ()V
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values/public.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ackpine-runtime/src/main/res/values/public.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/src/main/kotlin/android/content/Context.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.content
18 |
19 | /**
20 | * Stub for `android.content.Context`.
21 | */
22 | public abstract class Context
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | #FFFFFF
19 |
--------------------------------------------------------------------------------
/sample-java/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | #FFFFFF
19 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | #FFFFFF
19 |
--------------------------------------------------------------------------------
/docs/images/logo-icon.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/ackpine-api/api-main/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | # Serializable
2 | -keep interface ru.solrudev.ackpine.session.parameters.DrawableId { *; }
3 | -keep class * implements ru.solrudev.ackpine.session.parameters.DrawableId { *; }
4 | -keep class ru.solrudev.ackpine.installer.InstallFailure { *; }
5 | -keep class * extends ru.solrudev.ackpine.installer.InstallFailure { *; }
6 | -keep interface ru.solrudev.ackpine.uninstaller.UninstallFailure { *; }
7 | -keep class * implements ru.solrudev.ackpine.uninstaller.UninstallFailure { *; }
8 | -keep interface ru.solrudev.ackpine.installer.parameters.InstallConstraints$TimeoutStrategy { *; }
9 | -keep class * implements ru.solrudev.ackpine.installer.parameters.InstallConstraints$TimeoutStrategy { *; }
10 |
11 | # Plugins
12 | -keep interface ru.solrudev.ackpine.plugability.AckpinePlugin { *; }
13 | -keep class * implements ru.solrudev.ackpine.plugability.AckpinePlugin { *; }
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/src/main/kotlin/ru/solrudev/ackpine/installer/PackageInstaller.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.installer
18 |
19 | /**
20 | * Stub for `PackageInstaller` from `ackpine-api`.
21 | */
22 | public interface PackageInstaller
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values-af-rZA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Bevestig asseblief installasie.
4 | Bevestig asseblief installasie van %s.
5 | Installasie
6 | Bevestig asseblief verwydering van %s.
7 | Verwydering
8 | As u dit afskakel, word pakket installerings funksionaliteit verbreek
9 | Installeer en verwyder
10 | Bevestig asseblief verwydering.
11 |
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/src/main/kotlin/ru/solrudev/ackpine/uninstaller/PackageUninstaller.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.uninstaller
18 |
19 | /**
20 | * Stub for `PackageUninstaller` from `ackpine-api`.
21 | */
22 | public interface PackageUninstaller
--------------------------------------------------------------------------------
/gradle/settings/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
19 | }
20 |
21 | dependencyResolutionManagement {
22 | repositories {
23 | mavenCentral()
24 | gradlePluginPortal()
25 | }
26 | }
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import ru.solrudev.ackpine.gradle.Constants
18 |
19 | description = "Ackpine API stubs"
20 |
21 | plugins {
22 | kotlin("jvm")
23 | }
24 |
25 | kotlin {
26 | jvmToolchain(Constants.JDK_VERSION)
27 | explicitApi()
28 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku/src/main/kotlin/ru/solrudev/ackpine/shizuku/DeleteFlags.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.shizuku
18 |
19 | @JvmSynthetic
20 | internal const val DELETE_KEEP_DATA = 0x00000001
21 |
22 | @JvmSynthetic
23 | internal const val DELETE_ALL_USERS = 0x00000002
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/SdkInt.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | import android.os.Build
20 |
21 | @Suppress("Unused")
22 | internal object SdkInt {
23 | @JvmSynthetic
24 | @JvmName("get")
25 | internal fun get() = Build.VERSION.SDK_INT
26 | }
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/src/main/kotlin/ru/solrudev/ackpine/SdkInt.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | /**
20 | * A replaceable stub for getting current SDK version.
21 | */
22 | public object SdkInt {
23 | public fun get(): Int {
24 | throw NotImplementedError()
25 | }
26 | }
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/uninstall/ApplicationData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.uninstall
18 |
19 | import android.graphics.drawable.Drawable
20 |
21 | data class ApplicationData(
22 | val name: String,
23 | val packageName: String,
24 | val icon: Drawable
25 | )
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/session/Progress.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.session
18 |
19 | /**
20 | * Represents progress data.
21 | */
22 | public data class Progress @JvmOverloads public constructor(
23 | public val progress: Int = 0,
24 | public val max: Int = 100
25 | )
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/uninstall/UninstallUiState.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.uninstall
18 |
19 | data class UninstallUiState(
20 | val isLoading: Boolean = false,
21 | val applications: List = emptyList(),
22 | val failure: String? = null
23 | )
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/anim/ackpine_fade_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/io/NonClosingInputStream.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.io
18 |
19 | import ru.solrudev.ackpine.compress.utils.CloseShieldInputStream
20 | import java.io.InputStream
21 |
22 | @JvmSynthetic
23 | internal fun InputStream.nonClosing() = CloseShieldInputStream.wrap(this)
24 |
--------------------------------------------------------------------------------
/docs/samples.md:
--------------------------------------------------------------------------------
1 | Samples
2 | =======
3 |
4 | Sample app showcasing the usage of Ackpine can be found in the [GitHub repository](https://github.com/solrudev/Ackpine).
5 |
6 | It utilizes `ackpine-splits` functionality and allows to install zipped split packages as well as monolithic APKs and uninstall an application from the list of installed user applications. The sample app correctly handles process death, so install sessions aren't going to waste if Android decides to kill the app.
7 |
8 | [`sample-java`](https://github.com/solrudev/Ackpine/tree/master/sample-java) is fully written in Java, while [`sample-ktx`](https://github.com/solrudev/Ackpine/tree/master/sample-ktx) is leveraging the `ackpine-ktx` artifact.
9 |
10 | [`sample-api34`](https://github.com/solrudev/Ackpine/tree/master/sample-api34) showcases usage of features supported on API level 34 and higher, such as [install pre-commit preapproval](configuration.md#preapproval) and [installation constraints](configuration.md#constraints).
--------------------------------------------------------------------------------
/.github/workflows/release-tag.yml:
--------------------------------------------------------------------------------
1 | name: release-tag
2 |
3 | on:
4 | pull_request:
5 | types:
6 | - closed
7 | branches:
8 | - master
9 |
10 | permissions:
11 | contents: read
12 |
13 | jobs:
14 | push-tag:
15 | runs-on: ubuntu-latest
16 | if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release')
17 |
18 | steps:
19 | - name: Checkout
20 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
21 | with:
22 | ref: ${{ github.event.pull_request.merge_commit_sha }}
23 | fetch-depth: '0'
24 | persist-credentials: false
25 |
26 | - name: Push tag
27 | uses: anothrNick/github-tag-action@4ed44965e0db8dab2b466a16da04aec3cc312fd8 # 1.75.0
28 | env:
29 | GITHUB_TOKEN: ${{ secrets.PAT_AUTOTAG }}
30 | CUSTOM_TAG: ${{ github.event.pull_request.title }}
31 | WITH_V: false
32 | PRERELEASE: false
--------------------------------------------------------------------------------
/sample-java/src/main/res/values-v29/themes.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/values-v29/themes.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values-v29/themes.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/session/Failure.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.session
18 |
19 | /**
20 | * Represents a session's failure
21 | */
22 | public interface Failure {
23 |
24 | /**
25 | * Failure occurred due to an [exception].
26 | */
27 | public interface Exceptional {
28 | public val exception: Exception
29 | }
30 | }
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/session/parameters/SessionParametersDsl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.session.parameters
18 |
19 | import androidx.annotation.RestrictTo
20 |
21 | /**
22 | * DSL marker for Ackpine session parameters.
23 | */
24 | @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
25 | @DslMarker
26 | public annotation class SessionParametersDsl
--------------------------------------------------------------------------------
/sample-java/src/main/res/drawable/ic_install.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/drawable/ic_install.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/drawable/ic_uninstall.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | rootProject.name = "Ackpine"
18 |
19 | pluginManagement {
20 | includeBuild("build-logic")
21 | includeBuild("gradle/settings")
22 | }
23 |
24 | plugins {
25 | id("ru.solrudev.ackpine.settings")
26 | }
27 |
28 | ackpine {
29 | configurePluginRepositories()
30 | includeSubprojects()
31 | versionCatalog("androidx")
32 | versionCatalog("kotlinx")
33 | }
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/session/parameters/NotificationData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.session.parameters
18 |
19 | /**
20 | * Constructs a new instance of [NotificationData].
21 | */
22 | public inline fun NotificationData(configure: NotificationDataDsl.() -> Unit): NotificationData {
23 | return NotificationDataDslBuilder().apply(configure).build()
24 | }
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | Установка
20 | Установить
21 | Отмена
22 | Ошибка
23 | Ошибка: %s
24 |
--------------------------------------------------------------------------------
/sample-java/src/main/res/drawable/ic_uninstall.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-stubs/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "API stubs for ackpine-shizuku"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library.base")
21 | }
22 |
23 | ackpine {
24 | id = "shizuku-stubs"
25 | }
26 |
27 | dependencies {
28 | annotationProcessor(libs.hiddenApiRefine.processor)
29 | compileOnly(libs.hiddenApiRefine.annotation)
30 | api(androidx.annotation)
31 | }
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/DisposableSubscriptionContainer.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | /**
20 | * Adds the specified [subscription] to this [DisposableSubscriptionContainer].
21 | */
22 | @Suppress("NOTHING_TO_INLINE")
23 | public inline operator fun DisposableSubscriptionContainer.plusAssign(subscription: DisposableSubscription) {
24 | add(subscription)
25 | }
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/util/FragmentExt.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.util
18 |
19 | import androidx.fragment.app.Fragment
20 | import com.google.android.material.appbar.AppBarLayout
21 | import ru.solrudev.ackpine.sample.R
22 |
23 | fun Fragment.findAppBarLayout(): AppBarLayout {
24 | return requireActivity().findViewById(R.id.appBarLayout_nav_host)
25 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/install/InstallUiState.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install
18 |
19 | import ru.solrudev.ackpine.resources.ResolvableString
20 |
21 | data class InstallUiState(
22 | val error: ResolvableString = ResolvableString.empty(),
23 | val sessions: List = emptyList(),
24 | val sessionsProgress: List = emptyList()
25 | )
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/SessionFailureDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import ru.solrudev.ackpine.session.Failure
21 |
22 | @RestrictTo(RestrictTo.Scope.LIBRARY)
23 | internal interface SessionFailureDao {
24 | fun getFailure(id: String): F?
25 | fun setFailure(id: String, failure: F)
26 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/exceptions/Exceptions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.exceptions
18 |
19 | /**
20 | * Thrown if Ackpine initialization is attempted more than once.
21 | */
22 | public class AckpineReinitializeException : Exception(
23 | "Attempt of Ackpine re-initialization. Make sure you're not initializing Ackpine manually without disabling " +
24 | "automatic initialization."
25 | )
--------------------------------------------------------------------------------
/ackpine-runtime/src/main/res/xml/ackpine_file_provider_paths.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
21 |
24 |
27 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/io/ToByteBuffer.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.io
18 |
19 | import java.io.ByteArrayOutputStream
20 | import java.io.InputStream
21 | import java.nio.ByteBuffer
22 |
23 | @JvmSynthetic
24 | internal fun InputStream.toByteBuffer(): ByteBuffer {
25 | val buffer = ByteArrayOutputStream()
26 | copyTo(buffer)
27 | return ByteBuffer.wrap(buffer.toByteArray())
28 | }
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample-api34/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample-java/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/helpers/ZipHelpers.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.helpers
18 |
19 | import java.util.zip.ZipInputStream
20 |
21 | /**
22 | * The returned sequence is constrained to be iterated only once.
23 | */
24 | @JvmSynthetic
25 | internal fun ZipInputStream.entries() = sequence {
26 | while (true) {
27 | val entry = nextEntry ?: break
28 | yield(entry)
29 | }
30 | }.constrainOnce()
--------------------------------------------------------------------------------
/ackpine-assets/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Provides support of asset files inside of application's package for Ackpine"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "assets"
27 | artifact {
28 | name = "Ackpine Assets"
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation(projects.ackpineRuntime)
34 | }
--------------------------------------------------------------------------------
/ackpine-assets/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
26 |
27 |
--------------------------------------------------------------------------------
/docs/permissions.md:
--------------------------------------------------------------------------------
1 | Permissions
2 | ===========
3 |
4 | Ackpine adds the following permissions to `AndroidManifest.xml`:
5 |
6 | - `WRITE_EXTERNAL_STORAGE` — used by `INTENT_BASED` package installer to create temporary APK copy;
7 | - `REQUEST_INSTALL_PACKAGES` and `REQUEST_DELETE_PACKAGES` — self-explanatory;
8 | - `VIBRATE` — to be able to set heads-up notifications' vibration when using `DEFERRED` confirmation;
9 | - `POST_NOTIFICATIONS` — for posting notifications when using `DEFERRED` confirmation;
10 | - `UPDATE_PACKAGES_WITHOUT_USER_ACTION` — to be able to leverage `requireUserAction` feature on API >= 31;
11 | - `ENFORCE_UPDATE_OWNERSHIP` — to be able to leverage update ownership enforcement feature on API >= 34.
12 |
13 | If you don't need some of the features listed above and don't want to have unneeded permissions in your app, you can remove them from the resulting merged `AndroidManifest.xml`, but do so carefully to not break the library functionality you use:
14 |
15 | ```xml
16 |
19 | ```
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/uninstaller/parameters/UninstallParameters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.uninstaller.parameters
18 |
19 | /**
20 | * Constructs a new instance of [UninstallParameters].
21 | */
22 | public inline fun UninstallParameters(
23 | packageName: String,
24 | configure: UninstallParametersDsl.() -> Unit
25 | ): UninstallParameters {
26 | return UninstallParametersDslBuilder(packageName).apply(configure).build()
27 | }
--------------------------------------------------------------------------------
/ackpine-resources/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Abstractions for resolvable and persistable Android resources"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "resources"
27 | artifact {
28 | name = "Ackpine Resources"
29 | inceptionYear = "2024"
30 | }
31 | }
32 |
33 | dependencies {
34 | api(androidx.annotation)
35 | }
--------------------------------------------------------------------------------
/gradle/settings/src/main/kotlin/ru/solrudev/ackpine/gradle/ConfigureRepositories.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.gradle
18 |
19 | import org.gradle.api.artifacts.dsl.RepositoryHandler
20 |
21 | internal fun RepositoryHandler.configureRepositories() {
22 | google {
23 | content {
24 | includeGroupAndSubgroups("androidx")
25 | includeGroupAndSubgroups("com.android")
26 | includeGroupAndSubgroups("com.google")
27 | }
28 | }
29 | mavenCentral()
30 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-ktx/src/main/kotlin/ru/solrudev/ackpine/shizuku/ShizukuPluginParameters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.shizuku
18 |
19 | /**
20 | * Constructs a new instance of [ShizukuPlugin.Parameters].
21 | */
22 | @Suppress("FunctionName")
23 | public inline fun ShizukuPluginParameters(
24 | configure: ShizukuPluginParametersDsl.() -> Unit = {}
25 | ): ShizukuPlugin.Parameters {
26 | return ShizukuPluginParametersDslBuilder().apply(configure).build()
27 | }
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/splits/helpers/SplitTypePart.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.splits.helpers
18 |
19 | private const val CONFIG_PART = "config."
20 |
21 | @JvmSynthetic
22 | internal fun splitTypePart(name: String): String? {
23 | if (!name.contains(CONFIG_PART, ignoreCase = true) && !name.contains(".$CONFIG_PART", ignoreCase = true)) {
24 | return null
25 | }
26 | return name.substringAfter(CONFIG_PART).lowercase()
27 | }
--------------------------------------------------------------------------------
/ackpine-splits/compress-android/src/main/java/ru/solrudev/ackpine/compress/compressors/deflate64/HuffmanState.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * https://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package ru.solrudev.ackpine.compress.compressors.deflate64;
20 |
21 | enum HuffmanState {
22 | INITIAL, STORED, DYNAMIC_CODES, FIXED_CODES
23 | }
24 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-ktx/src/main/kotlin/ru/solrudev/ackpine/shizuku/InstallParametersDsl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.shizuku
18 |
19 | import ru.solrudev.ackpine.installer.parameters.InstallParametersDsl
20 |
21 | /**
22 | * Applies [ShizukuPlugin] to the session.
23 | */
24 | public inline fun InstallParametersDsl.useShizuku(
25 | configure: ShizukuPluginParametersDsl.() -> Unit = {}
26 | ) {
27 | usePlugin(ShizukuPlugin::class, ShizukuPluginParameters(configure))
28 | }
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/exceptions/Exceptions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.exceptions
18 |
19 | import ru.solrudev.ackpine.SdkIntWrapper
20 |
21 | /**
22 | * Thrown if installation of split packages is not supported when creating session with split package is attempted.
23 | */
24 | public class SplitPackagesNotSupportedException : IllegalStateException(
25 | "Split packages are not supported on current Android API level: ${SdkIntWrapper.get()}"
26 | )
--------------------------------------------------------------------------------
/sample-java/src/main/res/values-af-rZA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Installeer
4 | Verwyder
5 | Kanselleer
6 | Installeer
7 | Verwyder
8 | Fout
9 | Fout: %s
10 | Geen installasie sessies nie
11 | Geen geïnstalleerde toepassings nie
12 | Geen basis APK gevind nie
13 | Meer as een basis APK gevind
14 | Botesende gesplete naam: %s
15 | Botesende pakket naam. Verwag: %1$s, gevind: %2$s, naam: %3$s
16 | Botesende weergawe kode. Verwag: %1$s, gevind: %2$s, naam: %3$s
17 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/values-af-rZA/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Installeer
4 | Verwyder
5 | Kanselleer
6 | Installeer
7 | Verwyder
8 | Fout
9 | Fout: %s
10 | Geen installasie sessies nie
11 | Geen geïnstalleerde toepassings nie
12 | Geen basis APK gevind nie
13 | Meer as een basis APK gevind
14 | Botesende gesplete naam: %s
15 | Botesende pakket naam. Verwag: %1$s, gevind: %2$s, naam: %3$s
16 | Botesende weergawe kode. Verwag: %1$s, gevind: %2$s, naam: %3$s
17 |
--------------------------------------------------------------------------------
/ackpine-ktx/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Kotlin extensions for Ackpine"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "ktx"
27 | artifact {
28 | name = "Ackpine Kotlin Extensions"
29 | }
30 | }
31 |
32 | dependencies {
33 | api(projects.ackpineApi.apiMain)
34 | api(kotlinx.coroutines.core)
35 | implementation(androidx.concurrent.futures.ktx)
36 | }
--------------------------------------------------------------------------------
/ackpine-runtime/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Ackpine Runtime dependency"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | }
23 |
24 | ackpine {
25 | id = "runtime"
26 | artifact {
27 | name = "Ackpine Runtime"
28 | }
29 | }
30 |
31 | dependencies {
32 | api(androidx.annotation)
33 | compileOnly(libs.listenableFuture)
34 | implementation(androidx.core.ktx)
35 | implementation(androidx.concurrent.futures.core)
36 | }
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/install/SessionData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install
18 |
19 | import android.os.Parcelable
20 | import kotlinx.parcelize.Parcelize
21 | import ru.solrudev.ackpine.resources.ResolvableString
22 | import java.util.UUID
23 |
24 | @Parcelize
25 | data class SessionData(
26 | val id: UUID,
27 | val name: String,
28 | val error: ResolvableString = ResolvableString.empty(),
29 | val isCancellable: Boolean = true
30 | ) : Parcelable
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/SessionNameDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.Dao
21 | import androidx.room.Query
22 |
23 | @RestrictTo(RestrictTo.Scope.LIBRARY)
24 | @Dao
25 | internal interface SessionNameDao {
26 |
27 | @Query("INSERT OR REPLACE INTO sessions_names(session_id, name) VALUES (:sessionId, :name)")
28 | fun setSessionName(sessionId: String, name: String)
29 | }
--------------------------------------------------------------------------------
/sample-java/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Cài đặt
4 | Gỡ cài đặt
5 | Huỷ
6 | Cài đặt
7 | Gỡ cài đặt
8 | Lỗi
9 | Lỗi: %s
10 | Không có quá trình cài đặt nào
11 | Chưa có ứng dụng nào được cài đặt
12 | Không tìm thấy tệp APK gốc (base.apk)
13 | Có nhiều hơn một tệp APK gốc (base.apk)
14 | Tên split bị trùng: %s
15 | Xung đột tên gói. Mong đợi: %1$s, nhưng tìm thấy: %2$s (tên: %3$s)
16 | Mã phiên bản bị xung đột. Mong đợi: %1$s, nhưng tìm thấy: %2$s (tên: %3$s)
17 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/menu/bottom_nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Cài đặt
4 | Gỡ cài đặt
5 | Huỷ
6 | Cài đặt
7 | Gỡ cài đặt
8 | Lỗi
9 | Lỗi: %s
10 | Không có quá trình cài đặt nào
11 | Chưa có ứng dụng nào được cài đặt
12 | Không tìm thấy tệp APK gốc (base.apk)
13 | Có nhiều hơn một tệp APK gốc (base.apk)
14 | Tên split bị trùng: %s
15 | Xung đột tên gói. Mong đợi: %1$s, nhưng tìm thấy: %2$s (tên: %3$s)
16 | Mã phiên bản bị xung đột. Mong đợi: %1$s, nhưng tìm thấy: %2$s (tên: %3$s)
17 |
--------------------------------------------------------------------------------
/sample-java/src/main/res/menu/bottom_nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 6dp
20 | 50dp
21 | 8dp
22 | 100dp
23 | 16dp
24 | 16dp
25 | 16dp
26 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/InstallPreapprovalDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.Dao
21 | import androidx.room.Query
22 |
23 | @RestrictTo(RestrictTo.Scope.LIBRARY)
24 | @Dao
25 | internal interface InstallPreapprovalDao {
26 |
27 | @Query("UPDATE OR IGNORE sessions_install_preapproval SET is_preapproved = 1 WHERE session_id = :sessionId")
28 | fun setPreapproved(sessionId: String)
29 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values-v19/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values-v29/themes.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-ktx/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Kotlin extensions for Ackpine Shizuku plugin"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "shizuku-ktx"
27 | minSdk = 24
28 | artifact {
29 | name = "Ackpine Shizuku Plugin KTX"
30 | inceptionYear = "2025"
31 | }
32 | }
33 |
34 | dependencies {
35 | api(projects.ackpineKtx)
36 | api(projects.ackpinePlugins.shizuku)
37 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-ktx/src/main/kotlin/ru/solrudev/ackpine/shizuku/ShizukuUninstallPluginParameters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.shizuku
18 |
19 | /**
20 | * Constructs a new instance of [ShizukuUninstallPlugin.Parameters].
21 | */
22 | @Suppress("FunctionName")
23 | public inline fun ShizukuUninstallPluginParameters(
24 | configure: ShizukuUninstallPluginParametersDsl.() -> Unit = {}
25 | ): ShizukuUninstallPlugin.Parameters {
26 | return ShizukuUninstallPluginParametersDslBuilder().apply(configure).build()
27 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-ktx/src/main/kotlin/ru/solrudev/ackpine/shizuku/UninstallParametersDsl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.shizuku
18 |
19 | import ru.solrudev.ackpine.uninstaller.parameters.UninstallParametersDsl
20 |
21 | /**
22 | * Applies [ShizukuUninstallPlugin] to the session.
23 | */
24 | public inline fun UninstallParametersDsl.useShizuku(
25 | configure: ShizukuUninstallPluginParametersDsl.() -> Unit = {}
26 | ) {
27 | usePlugin(ShizukuUninstallPlugin::class, ShizukuUninstallPluginParameters(configure))
28 | }
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/SdkIntWrapper.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | import androidx.annotation.RestrictTo
20 |
21 | @RestrictTo(RestrictTo.Scope.LIBRARY)
22 | internal object SdkIntWrapper {
23 | @JvmSynthetic
24 | fun get() = try {
25 | SdkInt.get()
26 | } catch (_: NoClassDefFoundError) {
27 | throw NoClassDefFoundError(
28 | "Class ru.solrudev.ackpine.SdkInt was not found. " +
29 | "Make sure you have configured a dependency on ackpine-core module."
30 | )
31 | }
32 | }
--------------------------------------------------------------------------------
/ackpine-api/api-main/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "API definitions for Ackpine"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "api"
27 | artifact {
28 | name = "Ackpine API"
29 | inceptionYear = "2025"
30 | }
31 | }
32 |
33 | dependencies {
34 | api(libs.listenableFuture)
35 | api(androidx.annotation)
36 | api(projects.ackpineResources)
37 | compileOnly(projects.ackpineApi.apiStubs)
38 | }
--------------------------------------------------------------------------------
/docs/css/docs.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --md-hue: 148deg;
3 | --md-primary-fg-color: hsla(var(--md-hue), 65%, 25%, 1);
4 | --md-primary-fg-color--light: hsla(var(--md-hue), 65%, 40%, 1);
5 | --md-primary-fg-color--dark: hsla(var(--md-hue), 65%, 20%, 1);
6 | --md-accent-fg-color: hsla(var(--md-hue), 80%, 38%, 1);
7 | --md-accent-fg-color--transparent: hsla(var(--md-hue), 80%, 38%, 0.1);
8 | }
9 |
10 | [data-md-color-scheme="slate"] {
11 | --md-hue: 148deg;
12 | --md-accent-fg-color: hsla(var(--md-hue), 80%, 42%, 1);
13 | --md-accent-fg-color--transparent: hsla(var(--md-hue), 80%, 42%, 0.1);
14 | --md-default-bg-color: hsla(var(--md-hue), 15%, 12%, 1);
15 | --md-typeset-a-color: var(--md-primary-fg-color--light);
16 | --md-footer-bg-color: hsla(var(--md-hue), 15%, 15%, 0.87);
17 | --md-footer-bg-color--dark: hsla(var(--md-hue), 15%, 8%, 1);
18 | }
19 |
20 | .md-typeset h1, .md-typeset h2, .md-typeset h3, .md-typeset h4 {
21 | font-weight: bold;
22 | color: var(--md-default-fg-color);
23 | }
--------------------------------------------------------------------------------
/gradle/settings/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | `kotlin-dsl`
19 | }
20 |
21 | kotlin {
22 | jvmToolchain(21)
23 | explicitApi()
24 | }
25 |
26 | gradlePlugin {
27 | plugins {
28 | register("ackpine-settings") {
29 | id = "ru.solrudev.ackpine.settings"
30 | implementationClass = "ru.solrudev.ackpine.gradle.AckpineSettingsPlugin"
31 | }
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation("org.gradle.toolchains.foojay-resolver-convention:org.gradle.toolchains.foojay-resolver-convention.gradle.plugin:1.0.0")
37 | }
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/src/main/kotlin/ru/solrudev/ackpine/impl/installer/PackageInstallerImpl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.installer
18 |
19 | import android.content.Context
20 | import ru.solrudev.ackpine.installer.PackageInstaller
21 |
22 | /**
23 | * Stub for `PackageInstallerImpl` from `ackpine-core`.
24 | */
25 | public class PackageInstallerImpl : PackageInstaller {
26 | public companion object {
27 | public fun getInstance(context: Context): PackageInstallerImpl {
28 | throw NotImplementedError()
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/NotificationIdDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.Dao
21 | import androidx.room.Query
22 |
23 | @RestrictTo(RestrictTo.Scope.LIBRARY)
24 | @Dao
25 | internal interface NotificationIdDao {
26 |
27 | @Query("INSERT INTO sessions_notification_ids(session_id, notification_id) VALUES (:sessionId, :notificationId)")
28 | fun initNotificationId(sessionId: String, notificationId: Int)
29 | }
--------------------------------------------------------------------------------
/sample-java/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
25 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
25 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/AckpineInitializer.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | import android.content.Context
20 | import androidx.startup.Initializer
21 |
22 | /**
23 | * Initializes [Ackpine] using `androidx.startup`.
24 | */
25 | public class AckpineInitializer : Initializer {
26 |
27 | override fun create(context: Context): Ackpine {
28 | Ackpine.init(context)
29 | return Ackpine
30 | }
31 |
32 | override fun dependencies(): List>> {
33 | return emptyList()
34 | }
35 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/layout/ackpine_activity_session_commit.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
21 |
22 |
28 |
--------------------------------------------------------------------------------
/dokka-plugins/suppress-annotated-api/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import ru.solrudev.ackpine.gradle.Constants
18 |
19 | description = "Dokka plugin allowing to hide declarations marked with provided annotations from API documentation"
20 |
21 | plugins {
22 | kotlin("jvm")
23 | alias(libs.plugins.kotlin.serialization)
24 | }
25 |
26 | kotlin {
27 | jvmToolchain(Constants.JDK_VERSION)
28 | explicitApi()
29 | }
30 |
31 | dependencies {
32 | compileOnly(libs.dokka.core)
33 | implementation(libs.dokka.base)
34 | implementation(kotlinx.serialization.json)
35 | }
--------------------------------------------------------------------------------
/sample-api34/src/main/kotlin/ru/solrudev/ackpine/sample/updater/UpdaterUiState.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.updater
18 |
19 | import ru.solrudev.ackpine.resources.ResolvableString
20 | import ru.solrudev.ackpine.session.Progress
21 |
22 | data class UpdaterUiState(
23 | val isInstalling: Boolean = false,
24 | val progress: Progress = Progress(),
25 | val error: ResolvableString = ResolvableString.empty(),
26 | val isCancellable: Boolean = true,
27 | val buttonText: ResolvableString = ResolvableString.transientResource(R.string.install)
28 | )
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 6dp
20 | 8dp
21 | 80dp
22 | 16dp
23 | 50dp
24 | 16dp
25 | 16dp
26 | 16dp
27 |
--------------------------------------------------------------------------------
/ackpine-api/api-stubs/src/main/kotlin/ru/solrudev/ackpine/impl/uninstaller/PackageUninstallerImpl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.uninstaller
18 |
19 | import android.content.Context
20 | import ru.solrudev.ackpine.uninstaller.PackageUninstaller
21 |
22 | /**
23 | * Stub for `PackageUninstallerImpl` from `ackpine-core`.
24 | */
25 | public interface PackageUninstallerImpl : PackageUninstaller {
26 | public companion object {
27 | public fun getInstance(context: Context): PackageUninstallerImpl {
28 | throw NotImplementedError()
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/sample-java/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | 6dp
20 | 8dp
21 | 80dp
22 | 16dp
23 | 50dp
24 | 16dp
25 | 16dp
26 | 16dp
27 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/ConfirmationLaunchDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.Dao
21 | import androidx.room.Query
22 |
23 | @RestrictTo(RestrictTo.Scope.LIBRARY)
24 | @Dao
25 | internal interface ConfirmationLaunchDao {
26 |
27 | @Query(
28 | "INSERT OR IGNORE INTO sessions_confirmation_launches(session_id, was_confirmation_launched) " +
29 | "VALUES (:sessionId, 1)"
30 | )
31 | fun setConfirmationLaunched(sessionId: String)
32 | }
--------------------------------------------------------------------------------
/ackpine-splits/splits-ktx/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Kotlin extensions for Ackpine Splits"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "splits-ktx"
27 | minSdk = 21
28 | artifact {
29 | name = "Ackpine Splits Kotlin Extensions"
30 | inceptionYear = "2025"
31 | }
32 | }
33 |
34 | dependencies {
35 | api(projects.ackpineSplits.splitsMain)
36 | api(kotlinx.coroutines.core)
37 | implementation(androidx.concurrent.futures.ktx)
38 | }
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/installer/parameters/InstallConstraints.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.installer.parameters
18 |
19 | import kotlin.time.Duration
20 |
21 | /**
22 | * Constructs a new instance of [InstallConstraints].
23 | * @param timeout the maximum time to wait, in milliseconds until the constraints are satisfied.
24 | */
25 | public inline fun InstallConstraints(
26 | timeout: Duration,
27 | configure: InstallConstraintsDsl.() -> Unit = {}
28 | ): InstallConstraints {
29 | return InstallConstraintsDslBuilder(timeout).apply(configure).build()
30 | }
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/util/PackageManagerExt.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.util
18 |
19 | import android.content.pm.ApplicationInfo
20 | import android.content.pm.PackageManager
21 | import android.os.Build
22 |
23 | @Suppress("DEPRECATION")
24 | fun PackageManager.getInstalledApplicationsCompat(flags: Int): List {
25 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
26 | getInstalledApplications(PackageManager.ApplicationInfoFlags.of(flags.toLong()))
27 | } else {
28 | getInstalledApplications(flags)
29 | }
30 | }
--------------------------------------------------------------------------------
/dokka-plugins/suppress-annotated-api/src/main/kotlin/ru/solrudev/ackpine/documentation/SuppressAnnotatedApiConfig.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.documentation
18 |
19 | import kotlinx.serialization.Serializable
20 |
21 | /**
22 | * Configuration for [SuppressAnnotatedApiDokkaPlugin].
23 | */
24 | @Serializable
25 | public data class SuppressAnnotatedApiConfig(
26 |
27 | /**
28 | * Fully qualified names of annotation classes.
29 | *
30 | * Every declaration marked with any of these annotations will be hidden from resulting documentation.
31 | */
32 | val annotatedWith: Set
33 | )
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
26 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/InstallConstraintsDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.Dao
21 | import androidx.room.Query
22 |
23 | @RestrictTo(RestrictTo.Scope.LIBRARY)
24 | @Dao
25 | internal interface InstallConstraintsDao {
26 |
27 | @Query(
28 | "UPDATE OR IGNORE sessions_install_constraints SET commit_attempts_count = :commitAttemptsCount " +
29 | "WHERE session_id = :sessionId"
30 | )
31 | fun setCommitAttemptsCount(sessionId: String, commitAttemptsCount: Int)
32 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-stubs/src/main/java/android/content/pm/IPackageInstallerSession.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.content.pm;
18 |
19 | import android.os.Binder;
20 | import android.os.IBinder;
21 | import android.os.IInterface;
22 |
23 | /**
24 | * Stub for {@code android.content.pm.IPackageInstallerSession}.
25 | */
26 | public interface IPackageInstallerSession extends IInterface {
27 | abstract class Stub extends Binder implements IPackageInstallerSession {
28 | public static IPackageInstallerSession asInterface(IBinder binder) {
29 | throw new UnsupportedOperationException();
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-stubs/src/main/java/android/content/pm/IPackageManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.content.pm;
18 |
19 | import android.os.Binder;
20 | import android.os.IBinder;
21 | import android.os.IInterface;
22 |
23 | /**
24 | * Stub for {@code android.content.pm.IPackageManager}.
25 | */
26 | public interface IPackageManager extends IInterface {
27 | IPackageInstaller getPackageInstaller();
28 | abstract class Stub extends Binder implements IPackageManager {
29 | public static IPackageManager asInterface(IBinder obj) {
30 | throw new UnsupportedOperationException();
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/PackageInstallerApiCheck.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | import android.os.Build
20 | import androidx.annotation.ChecksSdkIntAtLeast
21 |
22 | @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.LOLLIPOP)
23 | @JvmSynthetic
24 | internal fun isPackageInstallerApiAvailable(): Boolean = isPackageInstallerAvailable
25 |
26 | // To avoid referencing Build.VERSION.SDK_INT
27 | private val isPackageInstallerAvailable = try {
28 | Class.forName("android.content.pm.PackageInstaller")
29 | true
30 | } catch (_: ClassNotFoundException) {
31 | false
32 | }
--------------------------------------------------------------------------------
/ackpine-runtime/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/install/SessionProgress.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install
18 |
19 | import android.os.Parcelable
20 | import kotlinx.parcelize.Parcelize
21 | import ru.solrudev.ackpine.session.Progress
22 | import java.util.UUID
23 |
24 | @Parcelize
25 | data class SessionProgress(
26 | val id: UUID,
27 | val currentProgress: Int,
28 | val progressMax: Int
29 | ) : Parcelable {
30 |
31 | constructor(id: UUID, progress: Progress) : this(id, progress.progress, progress.max)
32 |
33 | val progress: Progress
34 | get() = Progress(currentProgress, progressMax)
35 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/plugability/AckpineService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.plugability
18 |
19 | import androidx.annotation.RestrictTo
20 | import ru.solrudev.ackpine.plugability.AckpinePlugin
21 | import java.util.UUID
22 |
23 | /**
24 | * A service provided by an [AckpinePlugin] via [AckpineServiceProvider].
25 | */
26 | @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
27 | public interface AckpineService {
28 |
29 | /**
30 | * Applies [parameters] of an [AckpinePlugin] to a session with ID equal to [sessionId].
31 | */
32 | public fun applyParameters(sessionId: UUID, parameters: AckpinePlugin.Parameters)
33 | }
--------------------------------------------------------------------------------
/sample-api34/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | Ackpine Updater
20 | Ackpine
21 | 0%
22 | %d%%
23 | Install
24 | Install
25 | Cancel
26 | Error
27 | Error: %s
28 |
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku-stubs/src/main/java/android/content/pm/IPackageInstaller.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.content.pm;
18 |
19 | import android.os.Binder;
20 | import android.os.IBinder;
21 | import android.os.IInterface;
22 |
23 | /**
24 | * Stub for {@code android.content.pm.IPackageInstaller}.
25 | */
26 | public interface IPackageInstaller extends IInterface {
27 | void abandonSession(int sessionId);
28 | IPackageInstallerSession openSession(int sessionId);
29 | abstract class Stub extends Binder implements IPackageInstaller {
30 | public static IPackageInstaller asInterface(IBinder binder) {
31 | throw new UnsupportedOperationException();
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/session/parameters/ConfirmationDsl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.session.parameters
18 |
19 | import ru.solrudev.ackpine.session.Session
20 |
21 | /**
22 | * DSL allowing to configure user-facing confirmation for the [Session].
23 | */
24 | public interface ConfirmationDsl : ConfirmationAware {
25 | override var confirmation: Confirmation
26 | override var notificationData: NotificationData
27 | }
28 |
29 | /**
30 | * Configures [notification DSL][NotificationDataDsl].
31 | */
32 | public inline fun ConfirmationDsl.notification(configure: NotificationDataDsl.() -> Unit) {
33 | this.notificationData = NotificationData(configure)
34 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023-2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Utilities for working with split APKs"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | ackpine {
26 | id = "splits"
27 | minSdk = 21
28 | artifact {
29 | name = "Ackpine Splits"
30 | }
31 | }
32 |
33 | dependencies {
34 | api(androidx.annotation)
35 | api(libs.listenableFuture)
36 | implementation(projects.ackpineRuntime)
37 | implementation(projects.ackpineSplits.compressAndroid)
38 | implementation(androidx.core.ktx)
39 | implementation(androidx.concurrent.futures.core)
40 | implementation(libs.apksig)
41 | }
--------------------------------------------------------------------------------
/ackpine-splits/splits-ktx/src/main/kotlin/ru/solrudev/ackpine/splits/SplitPackageProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.splits
18 |
19 | import androidx.concurrent.futures.await
20 | import kotlinx.coroutines.CancellationException
21 | import kotlinx.coroutines.Job
22 |
23 | /**
24 | * A suspending variant of [getAsync][SplitPackage.Provider.getAsync].
25 | *
26 | * This suspending function is cancellable.
27 | * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this
28 | * function immediately resumes with [CancellationException].
29 | */
30 | public suspend fun SplitPackage.Provider.get(): SplitPackage {
31 | return getAsync().await()
32 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/dao/NativeSessionIdDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.dao
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.Dao
21 | import androidx.room.Query
22 |
23 | @RestrictTo(RestrictTo.Scope.LIBRARY)
24 | @Dao
25 | internal interface NativeSessionIdDao {
26 |
27 | @Query("INSERT OR REPLACE INTO sessions_native_session_ids(session_id, native_session_id) " +
28 | "VALUES (:sessionId, :nativeSessionId)")
29 | fun setNativeSessionId(sessionId: String, nativeSessionId: Int)
30 |
31 | @Query("DELETE FROM sessions_native_session_ids WHERE session_id = :sessionId")
32 | fun removeNativeSessionId(sessionId: String)
33 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/helpers/concurrent/BinarySemaphore.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024-2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | @file:Suppress("ConstPropertyName", "Unused")
18 |
19 | package ru.solrudev.ackpine.impl.helpers.concurrent
20 |
21 | import androidx.annotation.RestrictTo
22 | import java.util.concurrent.Semaphore
23 |
24 | @RestrictTo(RestrictTo.Scope.LIBRARY)
25 | internal class BinarySemaphore : Semaphore(1) {
26 | private companion object {
27 | private const val serialVersionUID: Long = -1496811586616841420L
28 | }
29 | }
30 |
31 | @JvmSynthetic
32 | internal inline fun BinarySemaphore.withPermit(action: () -> T): T {
33 | acquire()
34 | try {
35 | return action()
36 | } finally {
37 | release()
38 | }
39 | }
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/splits/helpers/IsApk.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.splits.helpers
18 |
19 | import android.content.Context
20 | import android.net.Uri
21 | import java.io.File
22 | import java.util.zip.ZipEntry
23 |
24 | @get:JvmSynthetic
25 | internal val ZipEntry.isApk: Boolean
26 | get() = name.endsWith(".apk", ignoreCase = true) && !isDirectory
27 |
28 | @get:JvmSynthetic
29 | internal val File.isApk: Boolean
30 | get() = name.endsWith(".apk", ignoreCase = true) && !isDirectory
31 |
32 | @JvmSynthetic
33 | internal fun Uri.isApk(context: Context): Boolean {
34 | return context.contentResolver.getType(this) == "application/vnd.android.package-archive"
35 | }
--------------------------------------------------------------------------------
/ackpine-plugins/shizuku/src/main/kotlin/ru/solrudev/ackpine/shizuku/InstallFlags.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.shizuku
18 |
19 | @JvmSynthetic
20 | internal const val INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK = 0x01000000
21 |
22 | @JvmSynthetic
23 | internal const val INSTALL_ALLOW_TEST = 0x00000004
24 |
25 | @JvmSynthetic
26 | internal const val INSTALL_REPLACE_EXISTING = 0x00000002
27 |
28 | @JvmSynthetic
29 | internal const val INSTALL_REQUEST_DOWNGRADE = 0x00000080
30 |
31 | @JvmSynthetic
32 | internal const val INSTALL_ALLOW_DOWNGRADE = 0x00100000
33 |
34 | @JvmSynthetic
35 | internal const val INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS = 0x00000100
36 |
37 | @JvmSynthetic
38 | internal const val INSTALL_ALL_USERS = 0x00000040
--------------------------------------------------------------------------------
/ackpine-runtime/src/main/kotlin/ru/solrudev/ackpine/AckpineFileProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | import android.content.Context
20 | import android.content.pm.ProviderInfo
21 | import androidx.annotation.RestrictTo
22 | import androidx.core.content.FileProvider
23 | import ru.solrudev.ackpine.runtime.R
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
26 | public class AckpineFileProvider : FileProvider(R.xml.ackpine_file_provider_paths) {
27 |
28 | override fun attachInfo(context: Context, info: ProviderInfo) {
29 | super.attachInfo(context, info)
30 | authority = info.authority
31 | }
32 |
33 | public companion object {
34 | public lateinit var authority: String
35 | private set
36 | }
37 | }
--------------------------------------------------------------------------------
/sample-ktx/src/main/kotlin/ru/solrudev/ackpine/sample/install/SessionDataRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install
18 |
19 | import kotlinx.coroutines.flow.StateFlow
20 | import ru.solrudev.ackpine.resources.ResolvableString
21 | import ru.solrudev.ackpine.session.Progress
22 | import java.util.UUID
23 |
24 | interface SessionDataRepository {
25 | val sessions: StateFlow>
26 | val sessionsProgress: StateFlow>
27 | fun addSessionData(sessionData: SessionData)
28 | fun removeSessionData(id: UUID)
29 | fun updateSessionProgress(id: UUID, progress: Progress)
30 | fun updateSessionIsCancellable(id: UUID, isCancellable: Boolean)
31 | fun setError(id: UUID, error: ResolvableString)
32 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values-v21/themes.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/sample-java/src/main/java/ru/solrudev/ackpine/sample/install/SessionData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install;
18 |
19 | import androidx.annotation.NonNull;
20 |
21 | import java.io.Serial;
22 | import java.io.Serializable;
23 | import java.util.UUID;
24 |
25 | import ru.solrudev.ackpine.resources.ResolvableString;
26 |
27 | public record SessionData(@NonNull UUID id,
28 | @NonNull String name,
29 | @NonNull ResolvableString error,
30 | boolean isCancellable) implements Serializable {
31 |
32 | @Serial
33 | private static final long serialVersionUID = -7412725679599146483L;
34 |
35 | public SessionData(@NonNull UUID id, @NonNull String name) {
36 | this(id, name, ResolvableString.empty(), true);
37 | }
38 | }
--------------------------------------------------------------------------------
/.github/actions/setup-gradle-environment-action/action.yml:
--------------------------------------------------------------------------------
1 | name: Setup Gradle environment
2 | description: Sets up JDK and Gradle with caching
3 |
4 | inputs:
5 | gradle-encryption-key:
6 | description: Gradle configuration cache encryption key.
7 | required: true
8 |
9 | runs:
10 | using: composite
11 |
12 | steps:
13 | - name: Copy gradle.properties
14 | shell: bash
15 | run: |
16 | mkdir -p ~/.gradle
17 | cp .github/ci-gradle.properties ~/.gradle/gradle.properties
18 |
19 | - name: Set up JDK
20 | uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # 5.0.0
21 | with:
22 | distribution: adopt
23 | java-version: 21
24 |
25 | - name: Setup Gradle
26 | uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # 5.0.0
27 | with:
28 | cache-encryption-key: ${{ inputs.gradle-encryption-key }}
29 |
30 | - name: Cache build logic
31 | uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # 4.3.0
32 | with:
33 | path: |
34 | build-logic/build
35 | gradle/settings/build
36 | key: ${{ runner.os }}-build-logic-${{ hashFiles('build-logic/*.gradle*', 'build-logic/src/**', 'gradle/settings/*.gradle*', 'gradle/settings/src/**', 'gradle/*.versions.toml', '**/gradle-wrapper.properties') }}
37 | restore-keys: |
38 | ${{ runner.os }}-build-logic-
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/splits/helpers/UriHelpers.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.splits.helpers
18 |
19 | import android.content.Context
20 | import android.net.Uri
21 | import android.os.CancellationSignal
22 | import android.provider.OpenableColumns
23 |
24 | @JvmSynthetic
25 | internal fun Uri.displayNameAndSize(context: Context, signal: CancellationSignal? = null): Pair {
26 | context.contentResolver.query(
27 | this,
28 | arrayOf(OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE),
29 | null, null, null, signal
30 | ).use { cursor ->
31 | cursor ?: return "" to -1L
32 | if (!cursor.moveToFirst()) {
33 | return "" to -1L
34 | }
35 | return cursor.getString(0).orEmpty() to cursor.getLong(1)
36 | }
37 | }
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/installer/parameters/ApkList.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.installer.parameters
18 |
19 | import android.net.Uri
20 | import android.os.Build
21 | import androidx.annotation.RequiresApi
22 |
23 | /**
24 | * Adds the specified [apk] to this [MutableApkList].
25 | */
26 | @Suppress("NOTHING_TO_INLINE")
27 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
28 | public inline operator fun MutableApkList.plusAssign(apk: Uri) {
29 | add(apk)
30 | }
31 |
32 | /**
33 | * Adds all elements of the given [apks] collection to this [MutableApkList].
34 | */
35 | @Suppress("NOTHING_TO_INLINE")
36 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
37 | public inline operator fun MutableApkList.plusAssign(apks: Iterable) {
38 | addAll(apks)
39 | }
--------------------------------------------------------------------------------
/sample-api34/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
27 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/sample-java/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
27 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
27 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/session/parameters/ConfirmationAware.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.session.parameters
18 |
19 | /**
20 | * Denotes that object contains session confirmation configuration.
21 | */
22 | public interface ConfirmationAware {
23 |
24 | /**
25 | * A strategy for handling user's confirmation of installation or uninstallation.
26 | *
27 | * Default strategy is [Confirmation.DEFERRED].
28 | */
29 | public val confirmation: Confirmation
30 |
31 | /**
32 | * Data for a high-priority notification which launches confirmation activity.
33 | *
34 | * Default value is [NotificationData.DEFAULT].
35 | *
36 | * Ignored when [confirmation] is [Confirmation.IMMEDIATE].
37 | */
38 | public val notificationData: NotificationData
39 | }
--------------------------------------------------------------------------------
/sample-java/src/main/java/ru/solrudev/ackpine/sample/install/SessionProgress.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install;
18 |
19 | import androidx.annotation.NonNull;
20 |
21 | import java.io.Serial;
22 | import java.io.Serializable;
23 | import java.util.UUID;
24 |
25 | import ru.solrudev.ackpine.session.Progress;
26 |
27 | public record SessionProgress(@NonNull UUID id, int progress, int progressMax) implements Serializable {
28 |
29 | @Serial
30 | private static final long serialVersionUID = -1923187412469582409L;
31 |
32 | public SessionProgress(@NonNull UUID id, @NonNull Progress progress) {
33 | this(id, progress.getProgress(), progress.getMax());
34 | }
35 |
36 | @NonNull
37 | public Progress toProgress() {
38 | return new Progress(progress, progressMax);
39 | }
40 | }
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/Annotations.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | /**
20 | * Marks declarations that are **delicate** — they should be used with care.
21 | * Any use of a delicate declaration has to be carefully reviewed to make sure it doesn't have problems for any
22 | * particular use case.
23 | * Carefully read documentation of any declaration marked as `DelicateAckpineApi`.
24 | */
25 | @MustBeDocumented
26 | @Retention(value = AnnotationRetention.BINARY)
27 | @RequiresOptIn(
28 | level = RequiresOptIn.Level.WARNING,
29 | message = "This is a delicate API and its use requires care. " +
30 | "Make sure you read and understand documentation of the declaration that is marked as a delicate API."
31 | )
32 | public annotation class DelicateAckpineApi
--------------------------------------------------------------------------------
/ackpine-resources/api/ackpine-resources.api:
--------------------------------------------------------------------------------
1 | public abstract interface class ru/solrudev/ackpine/resources/ResolvableString : java/io/Serializable {
2 | public static final field Companion Lru/solrudev/ackpine/resources/ResolvableString$Companion;
3 | public static fun empty ()Lru/solrudev/ackpine/resources/ResolvableString;
4 | public fun isEmpty ()Z
5 | public fun isRaw ()Z
6 | public fun isResource ()Z
7 | public static fun raw (Ljava/lang/String;)Lru/solrudev/ackpine/resources/ResolvableString;
8 | public abstract fun resolve (Landroid/content/Context;)Ljava/lang/String;
9 | public static fun transientResource (I[Ljava/io/Serializable;)Lru/solrudev/ackpine/resources/ResolvableString;
10 | }
11 |
12 | public final class ru/solrudev/ackpine/resources/ResolvableString$Companion {
13 | public final fun empty ()Lru/solrudev/ackpine/resources/ResolvableString;
14 | public final fun raw (Ljava/lang/String;)Lru/solrudev/ackpine/resources/ResolvableString;
15 | public final fun transientResource (I[Ljava/io/Serializable;)Lru/solrudev/ackpine/resources/ResolvableString;
16 | }
17 |
18 | public abstract class ru/solrudev/ackpine/resources/ResolvableString$Resource : ru/solrudev/ackpine/resources/ResolvableString {
19 | public fun ([Ljava/io/Serializable;)V
20 | public final fun equals (Ljava/lang/Object;)Z
21 | public final fun hashCode ()I
22 | public final fun resolve (Landroid/content/Context;)Ljava/lang/String;
23 | protected abstract fun stringId ()I
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values-vi/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | Vui lòng xác nhận cài đặt.
20 | Xác nhận cài đặt từ tệp %s.
21 | Cài đặt
22 | Vui lòng xác nhận gỡ cài đặt.
23 | Xác nhận gỡ cài đặt ứng dụng %s.
24 | Gỡ cài đặt
25 | Tắt tùy chọn này sẽ làm hỏng chức năng cài đặt gói.
26 | Cài đặt và gỡ bỏ
27 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/InstallUriEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.*
21 |
22 | @RestrictTo(RestrictTo.Scope.LIBRARY)
23 | @Entity(
24 | tableName = "sessions_install_uris",
25 | foreignKeys = [ForeignKey(
26 | entity = SessionEntity::class,
27 | parentColumns = ["id"],
28 | childColumns = ["session_id"],
29 | onDelete = ForeignKey.CASCADE,
30 | onUpdate = ForeignKey.CASCADE
31 | )]
32 | )
33 | internal class InstallUriEntity internal constructor(
34 | @JvmField
35 | @PrimaryKey(autoGenerate = true)
36 | @ColumnInfo(name = "id")
37 | val id: Int = 0,
38 | @JvmField
39 | @ColumnInfo(name = "session_id", index = true)
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "uri")
43 | val uri: String
44 | )
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/SessionNameEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | @Entity(
27 | tableName = "sessions_names",
28 | foreignKeys = [ForeignKey(
29 | entity = SessionEntity::class,
30 | parentColumns = ["id"],
31 | childColumns = ["session_id"],
32 | onDelete = ForeignKey.CASCADE,
33 | onUpdate = ForeignKey.CASCADE
34 | )]
35 | )
36 | internal class SessionNameEntity internal constructor(
37 | @JvmField
38 | @PrimaryKey
39 | @ColumnInfo(name = "session_id")
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "name")
43 | val name: String
44 | )
--------------------------------------------------------------------------------
/docs/architecture.md:
--------------------------------------------------------------------------------
1 | Architecture
2 | ============
3 |
4 | Ackpine library has a concept of `Session`. `Session` manages the flow of installation or uninstallation process.
5 |
6 | One can launch multiple different sessions at once, but can't create them directly. To create a session, one needs to use `PackageInstaller` or `PackageUninstaller`.
7 |
8 | In essence, `PackageInstaller` is a _repository_ of `ProgressSessions`, and `PackageUninstaller` is a _repository_ of `Sessions`. They track and persist every session launched.
9 |
10 | Session by itself is passive, it doesn't do anything until client code says so. One can say that session is a finite-state machine which transfers from one state to another, but for this to be possible client needs to react to state changes and call necessary methods on the session. This is done to make sessions persistable and suspendable.
11 |
12 | If any of the steps while the session is active is interrupted (e.g. with process death), it can be re-executed later by examining last session's state and executing the steps which weren't finished. The library provides ready-to-use implementations of such listeners in the form of `Session.TerminalStateListener` and `Session.await()`. They can be safely re-attached after interruption.
13 |
14 | `Uri` is chosen as a sole input type of APKs. It makes them persistable and allows to plug in any APK source via `ContentProvider`. The library leverages this in `ackpine-splits` and `ackpine-assets` modules to read APKs from zipped files and app's asset files respectively.
--------------------------------------------------------------------------------
/ackpine-ktx/src/main/kotlin/ru/solrudev/ackpine/installer/parameters/InstallParameters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.installer.parameters
18 |
19 | import android.net.Uri
20 | import android.os.Build
21 | import androidx.annotation.RequiresApi
22 |
23 | /**
24 | * Constructs a new instance of [InstallParameters].
25 | */
26 | public inline fun InstallParameters(
27 | baseApk: Uri,
28 | configure: InstallParametersDsl.() -> Unit
29 | ): InstallParameters {
30 | return InstallParametersDslBuilder(baseApk).apply(configure).build()
31 | }
32 |
33 | /**
34 | * Constructs a new instance of [InstallParameters].
35 | */
36 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
37 | public inline fun InstallParameters(
38 | apks: Iterable,
39 | configure: InstallParametersDsl.() -> Unit
40 | ): InstallParameters {
41 | return InstallParametersDslBuilder(apks).apply(configure).build()
42 | }
--------------------------------------------------------------------------------
/api-documentation/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import ru.solrudev.ackpine.gradle.docsDirectory
18 |
19 | description = "Aggregates and generates API documentation for library projects"
20 |
21 | plugins {
22 | id("ru.solrudev.ackpine.dokka")
23 | }
24 |
25 | val apiDocsDir = layout.docsDirectory.dir("api")
26 |
27 | dokka {
28 | moduleName = isolated.rootProject.name
29 | dokkaPublications.html {
30 | outputDirectory = apiDocsDir
31 | }
32 | }
33 |
34 | dependencies {
35 | dokka(projects.ackpineApi.apiMain)
36 | dokka(projects.ackpineCore)
37 | dokka(projects.ackpineKtx)
38 | dokka(projects.ackpineSplits.splitsMain)
39 | dokka(projects.ackpineSplits.splitsKtx)
40 | dokka(projects.ackpineAssets)
41 | dokka(projects.ackpineResources)
42 | dokka(projects.ackpinePlugins.shizuku)
43 | dokka(projects.ackpinePlugins.shizukuKtx)
44 | }
45 |
46 | tasks.clean {
47 | delete(apiDocsDir)
48 | }
--------------------------------------------------------------------------------
/sample-api34/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Sample application showcasing usage of features supported on API level 34 and higher"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.sample.kotlin")
21 | id("ru.solrudev.ackpine.app-release")
22 | }
23 |
24 | ackpine {
25 | id = "updater"
26 | minSdk = 24
27 | }
28 |
29 | dependencies {
30 | implementation(projects.ackpineCore)
31 | implementation(projects.ackpineKtx)
32 | implementation(projects.ackpineAssets)
33 | implementation(projects.ackpineResources)
34 | implementation(androidx.activity)
35 | implementation(androidx.appCompat)
36 | implementation(androidx.constraintLayout)
37 | implementation(androidx.coordinatorLayout)
38 | implementation(androidx.lifecycle.viewModel)
39 | implementation(libs.materialComponents)
40 | implementation(libs.okHttp)
41 | implementation(libs.vbpd)
42 | implementation(libs.insetter)
43 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/PackageNameEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.*
21 |
22 | @RestrictTo(RestrictTo.Scope.LIBRARY)
23 | @Entity(
24 | tableName = "sessions_package_names",
25 | foreignKeys = [ForeignKey(
26 | entity = SessionEntity::class,
27 | parentColumns = ["id"],
28 | childColumns = ["session_id"],
29 | onDelete = ForeignKey.CASCADE,
30 | onUpdate = ForeignKey.CASCADE
31 | )]
32 | )
33 | internal class PackageNameEntity internal constructor(
34 | @JvmField
35 | @PrimaryKey(autoGenerate = true)
36 | @ColumnInfo(name = "id")
37 | val id: Int = 0,
38 | @JvmField
39 | @ColumnInfo(name = "session_id", index = true)
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "package_name")
43 | val packageName: String
44 | )
--------------------------------------------------------------------------------
/sample-java/src/main/res/navigation/ackpine_navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
29 |
30 |
35 |
36 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/navigation/ackpine_navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
29 |
30 |
35 |
36 |
--------------------------------------------------------------------------------
/ackpine-runtime/src/main/kotlin/ru/solrudev/ackpine/AckpineThreadPool.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine
18 |
19 | import androidx.annotation.RestrictTo
20 | import java.util.concurrent.ExecutorService
21 | import java.util.concurrent.Executors
22 | import java.util.concurrent.ThreadFactory
23 | import java.util.concurrent.atomic.AtomicInteger
24 | import kotlin.math.roundToInt
25 |
26 | /**
27 | * A thread pool shared between all Ackpine modules.
28 | */
29 | @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
30 | public object AckpineThreadPool : ExecutorService by Executors.newFixedThreadPool(
31 | (Runtime.getRuntime().availableProcessors() * 1.8).roundToInt(),
32 | object : ThreadFactory {
33 | private val threadCount = AtomicInteger(0)
34 |
35 | override fun newThread(runnable: Runnable?): Thread {
36 | return Thread(runnable, "ackpine.pool-${threadCount.incrementAndGet()}")
37 | }
38 | }
39 | )
--------------------------------------------------------------------------------
/ackpine-core/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "A library providing consistent APIs for installing and uninstalling apps on an Android device"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.library")
21 | id("ru.solrudev.ackpine.library-publish")
22 | id("ru.solrudev.ackpine.dokka")
23 | alias(libs.plugins.kotlin.ksp)
24 | alias(androidx.plugins.room)
25 | }
26 |
27 | ackpine {
28 | id = "core"
29 | artifact {
30 | name = "Ackpine Core"
31 | }
32 | internalPackages("ru.solrudev.ackpine.impl")
33 | }
34 |
35 | room {
36 | schemaDirectory(layout.projectDirectory.dir("schemas"))
37 | }
38 |
39 | dependencies {
40 | ksp(androidx.room.compiler)
41 | api(androidx.startup)
42 | api(projects.ackpineApi.apiMain)
43 | implementation(projects.ackpineRuntime)
44 | implementation(androidx.concurrent.futures.core)
45 | implementation(androidx.core.ktx)
46 | implementation(androidx.room.runtime)
47 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | Пожалуйста, подтвердите установку.
20 | Пожалуйста, подтвердите установку %s.
21 | Установка
22 | Пожалуйста, подтвердите деинсталляцию.
23 | Пожалуйста, подтвердите деинсталляцию %s.
24 | Деинсталляция
25 | При отключении нарушает функциональность установки пакетов
26 | Установка и деинсталляция
27 |
--------------------------------------------------------------------------------
/sample-java/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | description = "Sample application in Java showcasing Ackpine usage"
18 |
19 | plugins {
20 | id("ru.solrudev.ackpine.sample.base")
21 | id("ru.solrudev.ackpine.app-release")
22 | }
23 |
24 | dependencies {
25 | implementation(projects.ackpineCore)
26 | implementation(projects.ackpineSplits.splitsMain)
27 | implementation(projects.ackpineResources)
28 | implementation(androidx.activity)
29 | implementation(androidx.appCompat)
30 | implementation(androidx.documentFile)
31 | implementation(androidx.recyclerView)
32 | implementation(androidx.constraintLayout)
33 | implementation(androidx.coordinatorLayout)
34 | implementation(androidx.bundles.lifecycle)
35 | implementation(androidx.bundles.navigation)
36 | implementation(androidx.swipeRefreshLayout)
37 | implementation(libs.materialComponents)
38 | implementation(libs.guava)
39 | implementation(libs.insetter)
40 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/NotificationIdEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | @Entity(
27 | tableName = "sessions_notification_ids",
28 | foreignKeys = [ForeignKey(
29 | entity = SessionEntity::class,
30 | parentColumns = ["id"],
31 | childColumns = ["session_id"],
32 | onDelete = ForeignKey.CASCADE,
33 | onUpdate = ForeignKey.CASCADE
34 | )]
35 | )
36 | internal class NotificationIdEntity internal constructor(
37 | @JvmField
38 | @PrimaryKey
39 | @ColumnInfo(name = "session_id")
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "notification_id")
43 | val notificationId: Int
44 | )
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/UpdateOwnershipEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | @Entity(
27 | tableName = "sessions_update_ownership",
28 | foreignKeys = [ForeignKey(
29 | entity = SessionEntity::class,
30 | parentColumns = ["id"],
31 | childColumns = ["session_id"],
32 | onDelete = ForeignKey.CASCADE,
33 | onUpdate = ForeignKey.CASCADE
34 | )]
35 | )
36 | internal class UpdateOwnershipEntity(
37 | @JvmField
38 | @PrimaryKey
39 | @ColumnInfo(name = "session_id")
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "request_update_ownership")
43 | val requestUpdateOwnership: Boolean
44 | )
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/uninstaller/helpers/PackageManagerHelpers.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.uninstaller.helpers
18 |
19 | import android.content.pm.ApplicationInfo
20 | import android.content.pm.PackageManager
21 | import android.os.Build
22 |
23 | @JvmSynthetic
24 | internal fun PackageManager.getApplicationLabel(packageName: String) = try {
25 | getApplicationInfoCompat(packageName, PackageManager.GET_META_DATA).loadLabel(this)
26 | } catch (_: PackageManager.NameNotFoundException) {
27 | null
28 | }
29 |
30 | @Suppress("DEPRECATION")
31 | private fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): ApplicationInfo {
32 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
33 | getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(flags.toLong()))
34 | } else {
35 | getApplicationInfo(packageName, flags)
36 | }
37 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/NativeSessionIdEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | @Entity(
27 | tableName = "sessions_native_session_ids",
28 | foreignKeys = [ForeignKey(
29 | entity = SessionEntity::class,
30 | parentColumns = ["id"],
31 | childColumns = ["session_id"],
32 | onDelete = ForeignKey.CASCADE,
33 | onUpdate = ForeignKey.CASCADE
34 | )]
35 | )
36 | internal class NativeSessionIdEntity internal constructor(
37 | @JvmField
38 | @PrimaryKey
39 | @ColumnInfo(name = "session_id")
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "native_session_id")
43 | val nativeSessionId: Int
44 | )
--------------------------------------------------------------------------------
/ackpine-api/api-main/src/main/kotlin/ru/solrudev/ackpine/plugability/AckpinePluginRegistry.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.plugability
18 |
19 | /**
20 | * A registry allowing to add plugins to a session.
21 | */
22 | public interface AckpinePluginRegistry> {
23 |
24 | /**
25 | * Applies a [plugin] to a session.
26 | * @param plugin Java class of an applied plugin, implementing [AckpinePlugin].
27 | * @param parameters parameters of the applied plugin for the session being configured.
28 | */
29 | public fun usePlugin(
30 | plugin: Class>,
31 | parameters: Params
32 | ): Self
33 |
34 | /**
35 | * Applies a [plugin] to a session.
36 | * @param plugin Java class of an applied plugin, implementing [AckpinePlugin].
37 | */
38 | public fun usePlugin(plugin: Class>): Self
39 | }
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/LastUpdateTimestampEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2024 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | @Entity(
27 | tableName = "sessions_last_install_timestamps",
28 | foreignKeys = [ForeignKey(
29 | entity = SessionEntity::class,
30 | parentColumns = ["id"],
31 | childColumns = ["session_id"],
32 | onDelete = ForeignKey.CASCADE,
33 | onUpdate = ForeignKey.CASCADE
34 | )]
35 | )
36 | internal class LastUpdateTimestampEntity internal constructor(
37 | @JvmField
38 | @PrimaryKey
39 | @ColumnInfo(name = "session_id")
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "last_update_timestamp")
43 | val lastUpdateTimestamp: Long
44 | )
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/ConfirmationLaunchEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2025 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 |
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | @Entity(
27 | tableName = "sessions_confirmation_launches",
28 | foreignKeys = [ForeignKey(
29 | entity = SessionEntity::class,
30 | parentColumns = ["id"],
31 | childColumns = ["session_id"],
32 | onDelete = ForeignKey.CASCADE,
33 | onUpdate = ForeignKey.CASCADE
34 | )]
35 | )
36 | internal class ConfirmationLaunchEntity internal constructor(
37 | @JvmField
38 | @PrimaryKey
39 | @ColumnInfo(name = "session_id")
40 | val sessionId: String,
41 | @JvmField
42 | @ColumnInfo(name = "was_confirmation_launched")
43 | val wasConfirmationLaunched: Boolean
44 | )
--------------------------------------------------------------------------------
/ackpine-splits/splits-main/src/main/kotlin/ru/solrudev/ackpine/splits/helpers/LocaleHelpers.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.splits.helpers
18 |
19 | import android.content.Context
20 | import androidx.core.os.ConfigurationCompat
21 | import java.util.IllformedLocaleException
22 | import java.util.Locale
23 |
24 | @JvmSynthetic
25 | internal fun deviceLocales(context: Context): List {
26 | val locales = ConfigurationCompat.getLocales(context.resources.configuration)
27 | return buildList {
28 | for (index in 0..
2 |
17 |
18 |
24 |
27 |
--------------------------------------------------------------------------------
/sample-ktx/src/main/res/drawable/ic_install_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
27 |
--------------------------------------------------------------------------------
/sample-java/src/main/java/ru/solrudev/ackpine/sample/install/SessionDataRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.sample.install;
18 |
19 | import androidx.annotation.NonNull;
20 | import androidx.lifecycle.LiveData;
21 |
22 | import java.util.List;
23 | import java.util.UUID;
24 |
25 | import ru.solrudev.ackpine.resources.ResolvableString;
26 | import ru.solrudev.ackpine.session.Progress;
27 |
28 | public interface SessionDataRepository {
29 |
30 | @NonNull
31 | LiveData> getSessions();
32 |
33 | @NonNull
34 | LiveData> getSessionsProgress();
35 |
36 | void addSessionData(@NonNull SessionData sessionData);
37 |
38 | void removeSessionData(@NonNull UUID id);
39 |
40 | void updateSessionProgress(@NonNull UUID id, @NonNull Progress progress);
41 |
42 | void updateSessionIsCancellable(@NonNull UUID id, boolean isCancellable);
43 |
44 | void setError(@NonNull UUID id, @NonNull ResolvableString error);
45 | }
46 |
--------------------------------------------------------------------------------
/ackpine-core/src/main/kotlin/ru/solrudev/ackpine/impl/database/model/InstallFailureEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 Ilya Fomichev
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package ru.solrudev.ackpine.impl.database.model
18 |
19 | import androidx.annotation.RestrictTo
20 | import androidx.room.ColumnInfo
21 | import androidx.room.Entity
22 | import androidx.room.ForeignKey
23 | import androidx.room.PrimaryKey
24 | import ru.solrudev.ackpine.installer.InstallFailure
25 |
26 | @RestrictTo(RestrictTo.Scope.LIBRARY)
27 | @Entity(
28 | tableName = "sessions_install_failures",
29 | foreignKeys = [ForeignKey(
30 | entity = SessionEntity::class,
31 | parentColumns = ["id"],
32 | childColumns = ["session_id"],
33 | onDelete = ForeignKey.CASCADE,
34 | onUpdate = ForeignKey.CASCADE
35 | )]
36 | )
37 | internal class InstallFailureEntity internal constructor(
38 | @JvmField
39 | @PrimaryKey
40 | @ColumnInfo(name = "session_id")
41 | val sessionId: String,
42 | @JvmField
43 | @ColumnInfo(name = "failure")
44 | val failure: InstallFailure
45 | )
--------------------------------------------------------------------------------