Jetpack Keep memungkinkan Anda mendeklarasikan penggunaan refleksi dan Java Native Interface (JNI) dengan anotasi langsung dalam kode sumber Kotlin atau Java, bukan dalam file aturan keep terpisah. Plugin Jetpack Keep Gradle membaca anotasi ini pada waktu build dan membuat aturan keep yang diperlukan R8.
Jetpack Keep membantu pengoptimalan R8 tetap efektif seiring perubahan codebase Anda:
Aturan keep tetap berada di samping kode yang memerlukannya. Saat mengganti nama atau menghapus kode yang menggunakan refleksi, Anda mengupdate anotasi di tempat yang sama. Tidak ada file aturan terpisah yang perlu disinkronkan.
Aturan yang dihasilkan bersifat kondisional. R8 hanya mempertahankan target panggilan reflektif jika juga mempertahankan kode yang melakukan panggilan. Jika kode panggilan tidak digunakan dan R8 menghapusnya (sering terjadi pada fitur library opsional), R8 juga dapat menghapus target, sehingga aturan dari fitur yang tidak digunakan tidak akan menambah beban.
Lint menemukan refleksi untuk Anda. Library ini menyertakan pemeriksaan lint yang menandai panggilan reflektif yang tidak dianotasi, dan dapat menambahkan banyak anotasi secara otomatis.
Cara kerja Jetpack Keep
Pertimbangkan fungsi yang membuat instance class berdasarkan nama. Jika R8 tidak dapat mengetahui bahwa kode Anda menggunakan class, R8 akan menghapus konstruktor class, dan aplikasi akan error saat runtime. Untuk mencegah error, Anda dapat menambahkan aturan seperti berikut ke file aturan keep:
# Unconditional: R8 keeps this constructor even if it removes the reflection that invokes it.
-keep class com.example.ResourceLocatorImpl {
<init>();
}
Dengan Jetpack Keep, Anda menganotasi fungsi yang melakukan refleksi:
// ResourceLocatorImpl isn't on this module's compile classpath, so both the
// annotation and the code refer to it by name.
@UsesReflectionToConstruct(
className = "com.example.ResourceLocatorImpl",
// Omitting parameterTypes keeps every constructor. An empty array keeps
// only the no-argument constructor, which the code calls.
parameterTypes = [],
)
fun loadResourceLocator(): ResourceLocator {
val implClass = Class.forName("com.example.ResourceLocatorImpl")
return implClass.getDeclaredConstructor().newInstance() as ResourceLocator
}
Pada waktu build, plugin Gradle akan membuat aturan keep untuk konstruktor.
Tidak seperti aturan yang ditulis secara manual sebelumnya, aturan yang dihasilkan bersifat kondisional:
R8 hanya mempertahankan konstruktor jika loadResourceLocator tetap ada di
aplikasi yang dioptimalkan.
Persyaratan
Untuk menggunakan Jetpack Keep, project Anda memerlukan Plugin Android Gradle (AGP) 8.7 atau yang lebih baru.
Plugin Gradle mendukung jenis modul berikut:
| Jenis modul | Plugin yang diterapkan modul | Penyiapan tambahan |
|---|---|---|
| Aplikasi Android | com.android.application |
Tidak ada |
| Library Android | com.android.library |
Tidak ada |
| Library Multiplatform Kotlin dengan target Android | com.android.kotlin.multiplatform.library |
Tidak ada |
| Library JVM (Java atau Kotlin) | java-library atau org.jetbrains.kotlin.jvm |
Mendaftarkan transformasi JAR |
Menyiapkan Jetpack Keep
Untuk menggunakan Jetpack Keep, tambahkan library dan plugin Gradle ke setiap modul yang menggunakan refleksi atau JNI. Library menyediakan anotasi dan pemeriksaan lint, dan plugin mengubah anotasi menjadi aturan keep.
Dalam file
libs.versions.toml, tambahkan library dan plugin. Library dan plugin memiliki versi yang sama:[versions] # The library and the plugin ship together. Use one version for both so # that they stay in sync when you upgrade. annotationKeep = "1.0.0-alpha01" [libraries] androidx-annotation-keep = { group = "androidx.annotation.keep", name = "keep", version.ref = "annotationKeep" } [plugins] androidx-annotation-keep = { id = "androidx.annotation.keep", version.ref = "annotationKeep" }Gradle mendownload plugin dari repositori Maven Google, jadi pastikan repositori
pluginManagementdalam filesettings.gradle.ktsAnda menyertakangoogle().Dalam file
build.gradle.ktsroot, deklarasikan plugin bersama AGP tanpa menerapkannya:plugins { alias(libs.plugins.android.application) apply false // Other plugins. // The plugin relies on AGP classes that it doesn't bundle, so declare // it next to AGP. Declaring it here also gives every module the same // plugin version. alias(libs.plugins.androidx.annotation.keep) apply false }Dalam file
build.gradle.ktssetiap modul yang menggunakan refleksi atau JNI, terapkan plugin dan tambahkan dependensi library:plugins { alias(libs.plugins.android.application) // The plugin reads annotations only from this module's own code, so // apply it in every module that uses Jetpack Keep. alias(libs.plugins.androidx.annotation.keep) } dependencies { implementation(libs.androidx.annotation.keep) }Sinkronkan project Anda dengan file Gradle.
Untuk setiap varian build modul aplikasi Android, plugin mendaftarkan tugas
<variant>ExtractKeepRules, seperti releaseExtractKeepRules, dan meneruskan
aturan yang dihasilkan ke R8 untuk varian tersebut. Untuk modul library, plugin
memaketkan aturan yang dihasilkan sebagai aturan keep konsumen dalam output library.
Modul library JVM memerlukan penyiapan tambahan.
Menemukan refleksi dengan lint
Jetpack Keep menyertakan pemeriksaan lint berikut:
ReflectionWithoutKeepAnnotations- Menandai panggilan reflektif, seperti
Class.forName,getDeclaredConstructor,getDeclaredMethod, dangetDeclaredField, yang tidak memiliki anotasi keep yang cocok. MissingKeepAnnotationPlugin- Menandai modul yang bergantung pada
androidx.annotation.keep:keep, tetapi tidak menerapkan plugin Gradleandroidx.annotation.keep. Tanpa plugin, build Anda tidak akan membuat aturan keep dari anotasi.
Untuk menggunakan lint guna menganotasi modul Android, ikuti langkah-langkah berikut:
Jalankan lint pada modul untuk menemukan panggilan reflektif yang memerlukan anotasi:
./gradlew :app:lintTerapkan perbaikan yang dapat dilakukan lint secara otomatis:
./gradlew :app:lintFixLint dapat menambahkan anotasi secara otomatis saat dapat menentukan class dan anggota yang direfleksikan oleh kode.
Tinjau setiap anotasi yang ditambahkan untuk mengonfirmasi bahwa anotasi tersebut cocok dengan fungsi kode Anda. Misalnya, pastikan jenis parameter cocok dengan konstruktor atau metode yang dipanggil kode Anda.
Selesaikan temuan yang tersisa di Android Studio. Jika lint tidak dapat menentukan class target, perbaikan cepat akan menyisipkan anotasi dengan placeholder
TODOuntuk Anda selesaikan. Anda juga dapat menambahkan anotasi secara manual.Misalnya, fungsi berikut menerima nama class sebagai parameter, sehingga lint tidak dapat menentukan class mana yang dibuatnya. Perbaikan cepat menambahkan anotasi dengan placeholder:
@UsesReflectionToConstruct( className = TODO(), parameterTypes = [] ) fun createInstance(className: String): Any = Class.forName(className).getDeclaredConstructor().newInstance()Ganti placeholder dengan class yang dibuat oleh kode Anda. Jika class tersedia pada waktu kompilasi, gunakan
classConstant, bukanclassName. Di Kotlin, kode Anda tidak akan dikompilasi sampai Anda menggantiTODO().Periksa aturan keep yang dihasilkan plugin dari anotasi Anda sebelum menghapus aturan yang ada. Untuk modul aplikasi, jalankan tugas ekstraksi untuk varian rilis:
./gradlew :app:releaseExtractKeepRulesPlugin menulis aturan ke
app/build/generated/release/androidx.annotation.keep.rules.pro. Untuk modul library, lihat Memverifikasi aturan yang dihasilkan.Hapus aturan keep yang digantikan oleh anotasi baru dari file aturan keep Anda. Aturan juga dapat mencakup refleksi yang tidak ditandai oleh lint, seperti refleksi dalam modul lain atau dalam library, jadi periksa setiap aturan sebelum Anda menghapusnya:
- Untuk aturan seluruh paket, seperti
-keep class com.example.** { *; }, pastikan anotasi atau aturan lainnya mencakup semua refleksi pada class paket. - Untuk aturan yang mempertahankan class atau anggota tertentu, pastikan aturan tersebut sangat cocok dengan salah satu aturan yang dihasilkan, atau tidak ada refleksi lain yang bergantung padanya.
- Untuk aturan seluruh paket, seperti
Uji build rilis Anda.
Memberi anotasi pada kode Anda
Tambahkan anotasi Jetpack Keep ke kode yang melakukan refleksi: fungsi, konstruktor, kolom, atau class yang berisi panggilan reflektif. Anotasi menjelaskan target refleksi, dan aturan yang dihasilkan hanya mempertahankan target tersebut jika R8 mempertahankan kode yang dianotasi.
Pilih anotasi berdasarkan fungsi kode Anda:
| Annotation | Gunakan saat kode Anda |
|---|---|
@UsesReflectionToConstruct |
Memanggil konstruktor melalui refleksi, misalnya dengan
getDeclaredConstructor().newInstance(). |
@UsesReflectionToAccessMethod |
Memanggil metode melalui refleksi, misalnya dengan
getMethod atau getDeclaredMethod. |
@UsesReflectionToAccessField |
Membaca atau menulis kolom melalui refleksi, misalnya dengan
getField atau getDeclaredField. |
@UnconditionallyKeep |
Dipanggil dari luar kode Kotlin atau Java aplikasi Anda, misalnya
dari kode native melalui JNI. Gunakan anotasi ini hanya jika Anda tidak dapat
menggunakan anotasi @UsesReflection*, yang menghasilkan
aturan bersyarat. |
Semua anotasi @UsesReflection* mengikuti konvensi berikut:
- Identifikasi class target dengan
classConstantatauclassName. Jika class tersedia pada waktu kompilasi, gunakanclassConstant. Compiler memeriksa referensi, dan pemfaktoran ulang IDE seperti penggantian nama akan memperbaruinya. GunakanclassNamehanya jika class tidak tersedia pada waktu kompilasi, seperti class dalam dependensi opsional. Kedua parameter ini saling terpisah. - Targetkan class yang paling spesifik. Aturan yang dihasilkan akan mempertahankan anggota yang cocok di class yang Anda tentukan dan di subclass atau implementasi antarmukanya. Makin umum class, makin banyak kode yang dipertahankan R8.
- Tentukan jenis parameter untuk mempertahankan satu overload. Jika Anda tidak menetapkan
parameterTypesatauparameterTypeNames, aturan akan mempertahankan semua konstruktor atau semua overload metode. Untuk hanya mempertahankan konstruktor atau metode tanpa argumen, teruskan array kosong. - Ulangi anotasi untuk beberapa target. Jika satu fungsi merefleksikan lebih dari satu class atau anggota, tambahkan satu anotasi untuk setiap target.
Membuat objek dengan refleksi
Gunakan @UsesReflectionToConstruct saat kode Anda membuat instance class melalui
refleksi. Dalam contoh berikut, runner tugas membuat instance
implementasi antarmuka StartupTask berdasarkan nama. Karena anotasi
menentukan antarmuka, aturan yang dihasilkan akan mempertahankan konstruktor tanpa argumen
dari setiap implementasi StartupTask, selama R8 mempertahankan execute:
interface StartupTask {
fun run()
}
object TaskRunner {
// The task class is known only at runtime, so target the interface that
// every task implements.
@UsesReflectionToConstruct(classConstant = StartupTask::class, parameterTypes = [])
fun execute(className: String) {
val task = Class.forName(className)
.getDeclaredConstructor()
.newInstance() as StartupTask
task.run()
}
}
Memanggil metode dengan refleksi
Gunakan @UsesReflectionToAccessMethod saat kode Anda memanggil metode melalui
refleksi. Tetapkan methodName ke nama metode. Dalam contoh berikut, kode memanggil metode statis dalam dependensi opsional. Class
ini tidak tersedia pada waktu kompilasi, sehingga anotasi menggunakan className, bukan
classConstant:
object CrashReporting {
@UsesReflectionToAccessMethod(
className = "com.example.crashlib.CrashReporter",
methodName = "log",
// Omitting parameterTypes keeps every log overload. Keep only the one
// that the code calls.
parameterTypes = [String::class],
)
fun log(message: String) {
val reporterClass = try {
Class.forName("com.example.crashlib.CrashReporter")
} catch (e: ClassNotFoundException) {
// Crash reporting is optional, so skip it instead of failing.
return
}
reporterClass.getMethod("log", String::class.java).invoke(null, message)
}
}
Mengakses kolom dengan refleksi
Gunakan @UsesReflectionToAccessField saat kode Anda membaca atau menulis kolom
melalui refleksi. Tetapkan fieldName ke nama kolom:
class UserProfileFetcher {
// User doesn't expose internalId, so reading it requires reflection.
@UsesReflectionToAccessField(classConstant = User::class, fieldName = "internalId")
fun readInternalId(user: User): Any? {
val field = User::class.java.getDeclaredField("internalId")
field.isAccessible = true
return field.get(user)
}
}
Mempertahankan kode yang dipanggil dari luar aplikasi Anda
Gunakan @UnconditionallyKeep untuk kode yang dipanggil dari luar kode Kotlin atau Java aplikasi Anda, seperti metode yang dipanggil kode native melalui JNI. Beri anotasi pada
elemen yang dipanggil, bukan kode yang memanggilnya:
class NativeBridge {
// Only native code calls this method, through a JNI lookup by name that
// R8 can't see. Keep the method and its name unconditionally.
@UnconditionallyKeep
fun onNativeEvent(message: String) {
Log.d("NativeBridge", "Received from native code: $message")
}
// The default proguard-android-optimize.txt file already keeps native
// method names, so this method doesn't need an annotation.
external fun startNativeProcess()
}
Aturan yang dihasilkan akan mempertahankan metode yang dianotasi dan class yang memuatnya, dengan nama aslinya. Aturan ini tidak mempertahankan class lain yang dirujuk oleh tanda tangan metode. Jika kode native bergantung pada class tersebut, anotasikan juga, atau tambahkan aturan keep untuk class tersebut. Untuk mengetahui informasi selengkapnya tentang JNI dan R8, lihat Interaksi dengan kode native melalui JNI.
Secara default, @UnconditionallyKeep mempertahankan nama elemen. Jika
pemanggil eksternal tidak bergantung pada nama, tetapkan shouldPreserveName = false agar
R8 dapat mengganti nama elemen.
Memverifikasi aturan yang dibuat
Bagian ini menjelaskan cara memeriksa aturan yang dihasilkan untuk setiap jenis modul. Untuk modul aplikasi, plugin meneruskan aturan langsung ke R8. Untuk modul library, plugin mengemas aturan sebagai aturan keep konsumen dalam output library. Aplikasi yang bergantung pada library Anda akan menerapkan aturan ini secara otomatis saat menjalankan R8, meskipun aplikasi tersebut tidak menggunakan Jetpack Keep. Untuk informasi selengkapnya tentang aturan keep konsumen, lihat Pengoptimalan untuk penulis library.
Aplikasi Android
Untuk memeriksa aturan keep yang dihasilkan plugin untuk modul aplikasi, jalankan tugas ekstraksi untuk varian build:
./gradlew :app:releaseExtractKeepRules
Plugin menulis aturan untuk setiap varian ke
app/build/generated/<variant>/androidx.annotation.keep.rules.pro. Komentar
# context: sebelum setiap aturan mengidentifikasi kode yang dianotasi yang
menghasilkannya.
Untuk memeriksa pengaruh aturan yang dihasilkan terhadap pengoptimalan bersama dengan aturan keep lainnya, gunakan R8 Configuration Analyzer.
Library Android
Modul library Android tidak memerlukan penyiapan tambahan. Saat Anda mem-build
AAR, plugin akan menambahkan aturan yang dihasilkan ke file proguard.txt AAR, setelah
aturan keep konsumen yang sudah ada di AAR. Plugin mendaftarkan tugas <variant>KeepRulesTransformAar untuk setiap varian build guna melakukan hal ini.
Untuk memverifikasi aturan, build AAR, misalnya dengan ./gradlew
:mylibrary:assembleRelease, dan buka proguard.txt di AAR yang dihasilkan. Aturan yang dihasilkan akan muncul di bagian dengan header berikut:
#################################################################
# Rules generated from androidx.annotation.keep annotations #
#################################################################
Di macOS dan Linux, Anda juga dapat mencetak aturan dari command line:
unzip -p mylibrary/build/intermediates/aar/release/releaseKeepRulesTransformAar/mylibrary-release.aar proguard.txt
Library Multiplatform Kotlin
Modul library Multiplatform Kotlin dengan target Android juga tidak memerlukan
penyiapan tambahan. Saat Anda mem-build AAR untuk target Android, plugin akan menambahkan aturan yang dihasilkan ke file proguard.txt AAR dengan cara yang sama seperti untuk library Android. Plugin mendaftarkan tugas
androidMainKeepRulesTransformAar untuk melakukannya.
Untuk memverifikasi aturan, jalankan tugas tersebut dan buka proguard.txt di AAR yang
dibuatnya. Di macOS dan Linux, Anda dapat mencetak aturan dari command line:
./gradlew :mylibrary:androidMainKeepRulesTransformAar
unzip -p mylibrary/build/intermediates/aar/androidMain/androidMainKeepRulesTransformAar/mylibrary.aar proguard.txt
Library JVM
Sebelum Anda dapat memverifikasi aturan untuk modul library JVM, konfigurasikan
modul agar plugin menambahkan aturan yang dihasilkan ke salinan
JAR-nya. Kemudian, jalankan tugas transformasi yang Anda daftarkan dan periksa file aturan
dalam JAR yang dibuatnya. Misalnya, jika Anda menamai tugas
keepRulesJar, Anda dapat mencetak aturan di macOS dan Linux dengan perintah
berikut:
./gradlew :mylibrary:keepRulesJar
unzip -p mylibrary/build/intermediates/annotation-keep/keepRulesJar/mylibrary-keep-rules.jar \
"META-INF/com.android.tools/*" "META-INF/proguard/*"
Mengonfigurasi library JVM
Untuk modul library JVM yang menghasilkan JAR, plugin tidak mengubah JAR secara otomatis. Sebagai gantinya, gunakan fungsi annotationKeep.registerJavaArchiveTransform
untuk mendaftarkan tugas yang membuat salinan JAR dengan aturan yang
dibuat, lalu publikasikan JAR tersebut. Tambahkan kode berikut ke file build.gradle.kts modul library:
plugins {
id("java-library")
alias(libs.plugins.jetbrains.kotlin.jvm)
alias(libs.plugins.androidx.annotation.keep)
}
val jarTask = tasks.named<Jar>("jar")
// Apps run R8 on this library's code, so the generated rules must be inside
// the JAR. The plugin handles this automatically only for Android modules.
val keepRulesJarTask = annotationKeep.registerJavaArchiveTransform(
taskName = "keepRulesJar",
input = jarTask.flatMap { it.archiveFile },
fileName = jarTask.flatMap { it.archiveFileName }.map { it.replace(".jar", "-keep-rules.jar") },
)
// Consumers of this library resolve apiElements and runtimeElements, so add
// the JAR that contains the generated rules to them.
configurations.configureEach {
if (name == "apiElements" || name == "runtimeElements") {
outgoing.artifact(keepRulesJarTask.flatMap { it.outputJar })
}
}
dependencies {
implementation(libs.androidx.annotation.keep)
}
Transformasi menambahkan aturan yang dihasilkan ke lokasi aturan R8 yang ditargetkan JAR,
META-INF/com.android.tools/r8/proguard.txt. Jika JAR sudah berisi aturan
di META-INF/com.android.tools/ atau META-INF/proguard/, transformasi akan menambahkan
aturan yang dihasilkan ke file aturan yang ada. Untuk informasi selengkapnya
tentang lokasi ini, lihat Mendukung berbagai versi R8.
Setelah mendaftarkan transformasi, verifikasi aturan di JAR.
Contoh: Memuat library add-on opsional
Library sering menggunakan refleksi untuk memuat add-on opsional. Misalnya, SDK analisis mungkin mengirimkan library inti dan add-on video. Add-on bergantung pada library inti, sehingga library inti tidak dapat merujuk ke class add-on secara langsung. Sebagai gantinya, library inti akan mencari class add-on berdasarkan nama saat runtime dan mengaktifkan analisis video hanya jika class tersebut ditemukan.
Karena library inti menggunakan class add-on hanya melalui refleksi, R8 dapat menghapus class atau konstruktornya dari build rilis aplikasi, yang membuat pencarian gagal. Kegagalan hanya terjadi di build rilis aplikasi yang menyertakan add-on, sehingga sulit dideteksi dalam pengujian.
Tanpa Jetpack Keep, add-on akan mengirimkan aturan keep konsumen untuk class-nya, seperti yang ditunjukkan dalam Refleksi untuk mendukung dependensi opsional:
# In the add-on's consumer keep rules file.
-keep class com.example.analytics.video.VideoEventTracker {
<init>();
}
Aturan ini berada di library yang berbeda dengan pencarian yang memerlukannya, sehingga keduanya bisa tidak sinkron. Dengan Jetpack Keep, Anda dapat menganotasi pencarian di library inti:
// In the core library.
interface AnalyticsPlugin {
fun start()
}
object AnalyticsManager {
// The annotation and the lookup share this constant so that they can't
// refer to different classes.
private const val VIDEO_TRACKER_CLASS =
"com.example.analytics.video.VideoEventTracker"
@UsesReflectionToConstruct(
className = VIDEO_TRACKER_CLASS,
parameterTypes = [],
)
fun initialize() {
val tracker = try {
Class.forName(VIDEO_TRACKER_CLASS)
.getDeclaredConstructor()
.newInstance() as AnalyticsPlugin
} catch (e: ClassNotFoundException) {
// Apps that don't play video leave out the add-on, so a missing
// class isn't an error.
return
}
// This is an ordinary interface call, not a reflective one, so R8
// keeps start() without an annotation.
tracker.start()
}
}
Anotasi mengikuti panduan berikut:
- Beri anotasi pada kode yang melakukan refleksi. Anotasi ada di
initialize, yang memanggilClass.forName, bukan di class add-on. - Pilih anotasi berdasarkan fungsi kode. Pencarian akan membuat
instance class, sehingga kode menggunakan
@UsesReflectionToConstruct. - Gunakan
classNameuntuk class yang tidak dapat Anda referensikan. Class add-on tidak ada di classpath kompilasi library inti, sehingga anotasi tidak dapat menggunakanclassConstant. - Hanya pertahankan konstruktor yang dipanggil oleh kode. Pencarian memanggil konstruktor tanpa argumen, sehingga
parameterTypesadalah array kosong.
Saat Anda mem-build AAR library inti, plugin akan menambahkan aturan yang mempertahankan
VideoEventTracker dan konstruktor tanpa argumennya setiap kali R8 mempertahankan
initialize. Aplikasi yang menggunakan SDK menerapkan aturan ini secara otomatis, meskipun tidak menggunakan Jetpack Keep, sehingga add-on tidak memerlukan aturannya sendiri.
Dibandingkan dengan aturan add-on, pendekatan ini memiliki keuntungan berikut:
- Aturan tetap berada di samping pencarian. Library inti memiliki pencarian dan aturan, sehingga Anda dapat memperbaruinya bersama-sama, bukan mengoordinasikan perubahan di dua library.
- R8 masih dapat menghapus kode yang tidak digunakan. Jika aplikasi menyertakan add-on, tetapi
tidak pernah memanggil
initialize, aturan yang dihasilkan tidak akan berlaku, dan R8 dapat menghapusVideoEventTracker. Aturan add-on akan mempertahankannya di setiap aplikasi yang menyertakan add-on. - Lint menangkap pencarian yang tidak dianotasi. Jika library inti nantinya menambahkan pencarian reflektif lain tanpa anotasi, lint akan menandainya, sehingga Anda dapat memperbaikinya sebelum merilis library.
Untuk mengonfirmasi hasilnya, pastikan aturan yang dihasilkan muncul di file proguard.txt AAR, seperti yang dijelaskan dalam Library Android. Kemudian,
uji build rilis aplikasi yang menyertakan add-on, karena di situlah
aturan yang tidak ada akan merusak analisis video.
Batasan
Jetpack Keep belum mendeteksi refleksi yang menemukan class dan anggota berdasarkan anotasinya, atau membuat aturan keep untuknya. Fitur ini sedang direncanakan.
Sebelum itu, gunakan aturan keep untuk jenis refleksi ini. Misalnya, aturan
berikut mempertahankan setiap anggota yang dianotasi dengan @SomeAnnotation di
class yang dipertahankan R8:
-keepclassmembers class * {
@com.example.annotation.SomeAnnotation <methods>;
@com.example.annotation.SomeAnnotation <fields>;
}
Jika Jetpack Keep tidak berfungsi untuk kasus penggunaan Anda, atau jika Anda memiliki masukan lain, laporkan masalah.
Referensi lainnya
- Contoh Jetpack Keep: Project Android Studio yang menggunakan Jetpack Keep di aplikasi, library Android, library Kotlin Multiplatform, dan library JVM.
- Kasus penggunaan dan contoh aturan keep: Aturan keep untuk skenario refleksi dan JNI umum.
- Mengikuti praktik terbaik: Panduan dalam menulis aturan keep dengan cakupan yang sempit.