1## Deprecation and removal 2 3While SemVer's binary compatibility guarantees restrict the types of changes 4that may be made within a library revision and make it difficult to remove an 5API, there are many other ways to influence how developers interact with your 6library. 7 8### Deprecation (`@Deprecated`) 9 10Deprecation lets a developer know that they should stop using an API or class. 11All deprecations must be marked with a `@Deprecated` code annotation as well as 12a `@deprecated <explanation>` docs annotation (for Java) or 13[`@Deprecated(message = <explanation>)`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-deprecated/) 14(for Kotlin) explaining the rationale and how the developer should migrate away 15from the API. 16 17Deprecations in Kotlin are encouraged to provide an automatic migration by 18specifying the 19[`replaceWith = ReplaceWith(<replacement>)`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-replace-with/) 20parameter to `@Deprecated` in cases where the migration is a straightforward 21replacement and *may* specify 22[`level = DeprecationLevel.ERROR`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-deprecation-level/) 23(source-breaking) in cases where the API on track to be fully removed. 24 25Deprecation is an non-breaking API change that must occur in a **major** or 26**minor** release. 27 28APIs that are added during a pre-release cycle and marked as `@Deprecated` 29within the same cycle, e.g. added in `alpha01` and deprecated in `alpha06`, 30[must be removed](/docs/versioning.md#beta-checklist) before 31moving to `beta01`. 32 33NOTE While some APIs can safely be removed without a deprecation cycle, a full 34cycle of deprecate (with replacement) and release prior to removal is *strongly 35recommended* for APIs that are likely to have clients, including APIs referenced 36by the Android platform build and `@RequiresOptIn` APIs that have shipped 37in a public beta. 38 39### Soft removal (`@removed` or `DeprecationLevel.HIDDEN`) 40 41Soft removal preserves binary compatibility while preventing source code from 42compiling against an API. It is a *source-breaking change* and not recommended. 43 44Soft removals **must** do the following: 45 461. Mark the API as deprecated for at least one stable release prior to removal, 47 following language conventions for documenting why the API is being removed. 481. In a subsequent release: 49 * In Java sources, mark the API as `@RestrictTo(LIBRARY_GROUP_PREFIX)`. 50 This will remove the API from `current.txt` but retain it in 51 `restricted_current.txt` for compatibility checking. 52 * In Kotlin sources, mark the API as `@Deprecated(message = <reason>, 53 level = DeprecationLevel.HIDDEN)`. This will retain the API in 54 `current.txt` for compatibility checking. 551. For all future releases: 56 * Maintain binary compatibility, as the API may still be called by 57 existing dependent libraries. 58 * Maintain behavioral compatibility and existing tests. 59 60This is a disruptive change and should be avoided when possible. 61 62Soft removal is a source-breaking API change that must occur in a **major** or 63**minor** release. 64 65### Hard removal 66 67Hard removal entails removing the entire implementation of an API that was 68exposed in a public release. Prior to removal, an API must be marked as 69`@deprecated` for a full **minor** version (`alpha`->`beta`->`rc`->stable), 70prior to being hard removed. 71 72This is a disruptive change and should be avoided when possible. 73 74Hard removal is a binary-breaking API change that must occur in a **major** 75release. 76 77### For entire artifacts 78 79We do not typically deprecate or remove entire artifacts; however, it may be 80useful in cases where we want to halt development and focus elsewhere or 81strongly discourage developers from using a library. 82 83Halting development, either because of staffing or prioritization issues, leaves 84the door open for future bug fixes or continued development. This quite simply 85means we stop releasing updates but retain the source in our tree. 86 87Deprecating an artifact provides developers with a migration path and strongly 88encourages them -- through Lint warnings -- to migrate elsewhere. This is 89accomplished by adding a `@Deprecated` and `@deprecated` (with migration 90comment) annotation pair to *every* class and interface in the artifact. 91 92To deprecate an entire artifact: 93 941. Mark every top-level API (class, interface, extension function, etc.) in the 95 artifact as `@Deprecated` and update the API files 96 ([example CL](https://android-review.googlesource.com/c/platform/frameworks/support/+/1938773)) 971. Schedule a release of the artifact as a new minor version. When you populate 98 the release notes, explain that the entire artifact has been deprecated and 99 will no longer receive new features or bug fixes. Include the reason for 100 deprecation and the migration strategy. 1011. After the artifact has been released, remove the artifact from the source 102 tree, versions file, and tip-of-tree docs configuration 103 ([example CL](https://android-review.googlesource.com/c/platform/frameworks/support/+/2061731/)) 104 105The fully-deprecated artifact will be released as a deprecation release -- it 106will ship normally with accompanying release notes indicating the reason for 107deprecation and migration strategy, and it will be the last version of the 108artifact that ships. It will ship as a new minor stable release. For example, if 109`1.0.0` was the last stable release, then the deprecation release will be 110`1.1.0`. This is so Android Studio users will get a suggestion to update to a 111new stable version, which will contain the `@deprecated` annotations. 112 113After an artifact has been released as fully-deprecated, it can be removed from 114the source tree. 115 116#### Long-term support 117 118Artifacts which have been fully deprecated and removed are not required to fix 119any bugs -- including security issues -- which are reported after the library 120has been removed from source control; however, library owners *may* utilize 121release branches to provide long-term support. 122 123When working on long-term support in a release branch, you may encounter the 124following issues: 125 126- Release metadata produced by the build system is not compatible with the 127 release scheduling tool 128- Build targets associated with the release branch do not match targets used 129 by the snapped build ID 130- Delta between last snapped build ID and proposed snap build ID is too large 131 and cannot be processed by the release branch management tool 132 133### Discouraging usage in Play Store 134 135[Google Play SDK Console](https://play.google.com/sdk-console/) allows library 136owners to annotate specific library versions with notes, which are shown to app 137developers in the Play Store Console, or permanently mark them as outdated, 138which shows a warning in Play Store Console asking app developers to upgrade. 139 140In both cases, library owners have the option to prevent app developers from 141releasing apps to Play Store that have been built against specific library 142versions. 143 144Generally, Jetpack discourages the use of either notes or marking versions as 145outdated. There are few cases that warrant pushing notifications to app 146developers, and it is easy to abuse notes as advertising to drive adoption. As a 147rule, upgrades to Jetpack libraries should be driven by the needs of app 148developers. 149 150Cases where notes may be used include: 151 1521. The library is used directly, rather than transitively, and contains `P0` or 153 `P1` (ship-blocking, from the app's perspective) issues 154 - Transitively-included libraries should instead urge their dependent 155 libraries to bump their pinned dependency versions 1561. The library contains ship-blocking security issues. In this case, we 157 recommend preventing app releases since developers may be less aware of 158 security issues. 1591. The library was built against a pre-release SDK which has been superseded by 160 a finalized SDK. In this case, we recommend preventing app releases since 161 the library may crash or show unexpected behavior. 162 163Cases where marking a version as outdated maybe used: 164 1651. The library has security implications and the version is no longer receiving 166 security updates, e.g. the release branch has moved to the next version. 167 168In all cases, there must be a newer stable or bugfix release of the library that 169app developers can use to replace the outdated version. 170