Kitaplık yazarı olarak, uygulama geliştiricilerin kitaplığınızı uygulamalarına kolayca dahil edebilmesini ve aynı zamanda yüksek kaliteli bir son kullanıcı deneyimi sunabilmesini sağlamanız gerekir. Bu nedenle, kitaplığınızın geliştiriciden ek kurulum gerektirmeden Android optimizasyonu (R8) ile uyumlu olması veya kitaplığın Android'de kullanıma uygun olmayabileceğini belirten bir doküman sağlaması gerekir. Android'de kullanılmak üzere tasarlanan kitaplıkların önemli uygulama optimizasyonlarını engellememesi ve ek optimizasyon şartlarına uyması çok önemlidir.
Bu doküman, yayınlanmış kitaplıkların geliştiricilerine yöneliktir ancak büyük ve modüler bir uygulamadaki dahili kitaplık modüllerinin geliştiricileri için de faydalı olabilir.
Uygulama geliştiriciyseniz ve Android uygulamanızı optimize etme hakkında bilgi edinmek istiyorsanız Uygulama optimizasyonunu etkinleştirme başlıklı makaleyi inceleyin. Hangi kitaplıkların kullanıma uygun olduğu hakkında bilgi edinmek için Kitaplıkları akıllıca seçme başlıklı makaleyi inceleyin.
Saklama kuralı türlerini anlama
Kitaplıklarda kullanabileceğiniz iki farklı saklama kuralı türü vardır:
- Tüketici saklama kuralları, kitaplığın yansıttığı her şeyi saklayan kuralları belirtmelidir. Bir kitaplık, kodunu veya bir istemci uygulaması tarafından tanımlanan kodu çağırmak için yansıtma ya da JNI kullanıyorsa bu kurallarda hangi kodun saklanması gerektiği açıklanmalıdır. Kitaplıklar, uygulama saklama kurallarıyla aynı biçimi kullanan tüketici saklama kurallarını paketlemelidir. Bu kurallar, kitaplık yapılarına (AAR veya JAR) paketlenir ve kitaplık kullanıldığında Android uygulaması optimizasyonu sırasında otomatik olarak tüketilir. Bu kurallar,
build.gradle.kts(veyabuild.gradle) dosyanızdaconsumerProguardFilesözelliğiyle belirtilen dosyada tutulur. Daha fazla bilgi için Tüketici saklama kuralları yazma başlıklı makaleyi inceleyin. - Kitaplığınız oluşturulurken kitaplık oluşturma saklama kuralları uygulanır. Bu seçimler yalnızca kitaplığınızı derleme zamanında kısmen optimize etmeye karar verirseniz gereklidir. Kitaplığın herkese açık API'sinin kaldırılmasını önlemeleri gerekir. Aksi takdirde, herkese açık API kitaplık dağıtımında yer almaz ve uygulama geliştiriciler kitaplığı kullanamaz. Bu kurallar,
build.gradle.kts(veyabuild.gradle) dosyanızdaproguardFilesözelliğiyle belirtilen dosyada tutulur. Daha fazla bilgi edinmek için AAR kitaplığı derlemesini optimize etme başlıklı makaleyi inceleyin.
Optimizasyon koşulları ve yönergeleri
Kitaplıklardaki R8 yapılandırması, nihai ikili boyutu ve performansı tüketen uygulama üzerinde genel bir etkiye sahiptir. Kitaplık yazarları, genel saklama kuralı en iyi uygulamalarının yanı sıra belirli şartlara uymalı ve ek yönergeleri dikkate almalıdır.
Optimizasyon koşullarına uyma
Kitaplıklardaki verimsizlik, uygulama şişkinliğine, boşa harcanan belleğe, yavaş başlatmalara ve ANR'lere (uygulama yanıt vermiyor hataları) büyük ölçüde katkıda bulunur. Kitaplıklar, uygulama kalitesini ve kullanıcı deneyimini önemli ölçüde düşürmemek için aşağıdaki şartları ihlal etmemelidir.
Geniş kapsamlı veya paket genelinde saklama kuralları olmamalıdır: Kitaplığınız, kitaplığınızdaki veya başka bir kitaplıktaki kodun büyük bir kısmını saklayan geniş kapsamlı saklama kuralları içermemelidir. Kapsamlı saklama kuralları kısa vadede çökmeleri çözebilir ancak kitaplığınızı kullanan tüm uygulamaların uygulama boyutunu şişirir.
Kitaplığınızdaki veya referans verilen diğer kitaplıklardaki paketler için paket genelinde saklama kuralları (ör.
-keep class com.mylibrary.** {*; }) eklemeyin. Bu tür kurallar, kitaplığınızı kullanan tüm uygulamalarda bu paketlerin optimizasyonunu sınırlar.Uygunsuz genel kurallar yok:
-dontobfuscateveya-allowaccessmodificationgibi genel seçenekleri asla kullanmayın.Mümkün olduğunda yansıtma yerine kod oluşturma kullanın: Mümkün olduğunda yansıtma yerine kod oluşturma (codegen) kullanın. Codegen ve yansıtma, programlama sırasında standart koddan kaçınmak için kullanılan yaygın yaklaşımlardır. Ancak codegen, R8 gibi bir uygulama optimize ediciyle daha uyumludur.
Kod oluşturma ile kod, derleme işlemi sırasında analiz edilir ve değiştirilir. Derleme zamanından sonra büyük değişiklikler yapılmadığından, optimize edici hangi kodun nihai olarak gerekli olduğunu ve hangisinin güvenli bir şekilde kaldırılabileceğini bilir.
Yansıtma ile kod, çalışma zamanında analiz edilir ve üzerinde değişiklik yapılır. Kod yürütülene kadar gerçekten sonlandırılmadığından optimize edici, hangi kodun güvenli bir şekilde kaldırılabileceğini bilmez. Bu işlem, çalışma zamanında yansıtma yoluyla dinamik olarak kullanılan kodu kaldırdığı için kullanıcılar uygulamada kilitlenme sorunu yaşayabilir.
Birçok modern kitaplık, yansıtma yerine kod oluşturma kullanır. Room, Dagger2 ve diğer birçok kitaplık tarafından kullanılan ortak bir giriş noktası için KSP'ye bakın.
R8 tam modu desteklenmelidir: R8 tam modu etkinleştirildiğinde kitaplığınız kilitlenmemelidir. R8'in tam modu, R8'i kullanmak için önerilen moddur ve 2023'te kararlı hale getirilen AGP 8.0'dan beri varsayılan moddur. Kitaplığınız R8 altında kilitleniyorsa çözüm, belirli yansıtma veya JNI giriş noktasını belirleyip hedefli bir kural eklemektir. Tüm paketi tutmak çözüm değildir.
Ek öneriler
Optimizasyon koşullarının yanı sıra aşağıdaki ek önerileri de dikkate alabilirsiniz.
- Kitaplığınızın tüketici saklama kuralları dosyasında
-repackageclasseskullanmayın. Ancak kitaplık derlemenizi optimize etmek için kitaplığınızın derleme kurallarını koruma dosyasında-repackageclassesgibi dahili bir paket adıyla<your.library.package>.internalkullanabilirsiniz. Bu, kitaplığınızın optimize edilmemiş uygulamalardaki verimliliğini artırabilir. Ancak uygulamalar da optimize edilmesi gerektiğinden bu genellikle gerekli değildir. - Kitaplığınızın çalışması için gereken tüm özellikleri,
proguard-android-optimize.txtiçinde tanımlanan özelliklerle çakışma olsa bile kitaplığınızın saklama kuralları dosyalarında bildirin. - Kitaplığınızın dağıtımında aşağıdaki özelliklerin bulunmasını zorunlu kılıyorsanız bunları kitaplığınızın derleme koruma kuralları dosyasında tutun ve kitaplığınızın tüketici koruma kuralları dosyasında tutmayın:
AnnotationDefaultEnclosingMethodExceptionsInnerClassesRuntimeInvisibleAnnotationsRuntimeInvisibleParameterAnnotationsRuntimeInvisibleTypeAnnotationsRuntimeVisibleAnnotationsRuntimeVisibleParameterAnnotationsRuntimeVisibleTypeAnnotationsSignature
- Kitaplık yazarları, çalışma zamanında ek açıklamalar kullanılıyorsa tüketici saklama kurallarında
RuntimeVisibleAnnotationsözelliğini tutmalıdır. - Kitaplık yazarları, tüketici saklama kurallarında aşağıdaki genel seçenekleri kullanmamalıdır:
-include-basedirectory-injars-outjars-libraryjars-repackageclasses-flattenpackagehierarchy-allowaccessmodification-renamesourcefileattribute-ignorewarnings-addconfigurationdebugging-printconfiguration-printmapping-printusage-printseeds-applymapping-obfuscationdictionary-classobfuscationdictionary-packageobfuscationdictionary
Ne zaman yansıtma yapılabilir?
Yansıtma kullanmanız gerekiyorsa yalnızca aşağıdakilerden birine yansıtma yapmalısınız:
- Belirli hedeflenen türler (belirli arayüz uygulayıcıları veya alt sınıflar)
- Belirli bir çalışma zamanı ek açıklaması kullanan kod
Yansıtmayı bu şekilde kullanmak, çalışma zamanı maliyetini sınırlar ve hedefli tüketici saklama kuralları yazmaya olanak tanır.
Bu özel ve hedeflenmiş yansıtma biçimi, hem Android çerçevesinde (ör. etkinlikler, görünümler ve çizilebilir öğeler genişletilirken) hem de AndroidX kitaplıklarında (ör. WorkManager
ListenableWorkers veya RoomDatabases oluşturulurken) görebileceğiniz bir kalıptır. Buna karşılık, Gson'un açık uçlu yansıtması Android uygulamalarında kullanıma uygun değildir.
Yaygın yanlış kanılar
Birkaç yaygın yanlış kanı, R8'i yanlış yapılandırmanıza neden olabilir. Bu politikalara şunlar dahildir:
R8'in optimizasyonlarının yanlış anlaşılması: Yaygın kanının aksine, R8'in optimizasyonları yalnızca karartma ile sınırlı değildir. Aynı zamanda yöntem içi yerleştirme ve sınıf birleştirme teknikleriyle kod küçültme ve mantıksal optimizasyonları da içerir. Daha fazla bilgi için R8 optimizasyonuna genel bakış başlıklı makaleyi inceleyin.
Karartılmış kitaplıkların optimizasyonunu atlama: Kitaplık, AAR (Android Arşivi) veya JAR (Java Arşivi) olarak derlenirken optimize edildiği ya da karartıldığı için optimizasyondan çıkarılması yaygın bir hatadır. Kitaplık oluşturma süresindeki optimizasyonlar sınırlıdır ve uygulamanız, kitaplığı bir koruma kuralına dahil ederek kitaplığın optimizasyonunu devre dışı bırakmamalıdır. Daha fazla bilgi için AAR kitaplığı derlemesini optimize etme başlıklı makaleyi inceleyin.
-keepseçeneğinin yanlış anlaşılması-keepkuralı, R8'in optimizasyon geçişlerinden herhangi birini çalıştırmasını engeller. Daha fazla bilgi için Doğru saklama seçeneğini belirleme başlıklı makaleyi inceleyin.
Kural paketlemeyi yapılandırma
Tüketici saklama kurallarınızın doğru şekilde uygulanması için bunları kitaplık biçiminize bağlı olarak uygun şekilde paketlemeniz gerekir.
AAR kitaplıkları
AAR kitaplığı için tüketici kuralları eklemek üzere Android kitaplığı modülünün derleme komut dosyasında consumerProguardFiles seçeneğini kullanın. Daha fazla bilgi için kitaplık modülü oluşturma rehberimize göz atın.
Kotlin
android {
defaultConfig {
consumerProguardFiles("consumer-proguard-rules.pro")
}
...
}
Groovy
android {
defaultConfig {
consumerProguardFiles 'consumer-proguard-rules.pro'
}
...
}
JAR kitaplıkları
Kuralları, JAR olarak gönderilen Kotlin veya Java kitaplığınızla birlikte paketlemek için kurallar dosyanızı nihai JAR'ın META-INF/proguard/ dizinine herhangi bir dosya adıyla yerleştirin.
Örneğin, kodunuz <libraryroot>/src/main/kotlin ise <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro konumuna bir tüketici kuralları dosyası yerleştirin. Kurallar, çıkış JAR'ınızda doğru konuma yerleştirilir.
Kuralların META-INF/proguard dizininde olduğunu kontrol ederek nihai JAR paketlerinin kuralları doğru şekilde paketlediğini doğrulayın.
AAR kitaplığı derlemesini optimize etme (gelişmiş)
Genel olarak, kitaplık oluşturma sırasında olası optimizasyonlar çok sınırlı olduğundan kitaplık derlemesini doğrudan optimize etmeniz gerekmez. Kitaplık geliştiricisi olarak, kitaplığı optimize etmeden önce optimizasyonun birden fazla aşamasını göz önünde bulundurmanız ve kitaplık ile uygulama derleme zamanında davranışları korumanız gerekir.
Kitaplığınızı derleme sırasında optimize etmek istiyorsanız bu işlem Android Gradle eklentisi tarafından desteklenir.
Kotlin
android {
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
configureEach {
consumerProguardFiles("consumer-rules.pro")
}
}
}
Groovy
android {
buildTypes {
release {
minifyEnabled true
proguardFiles
getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
configureEach {
consumerProguardFiles "consumer-rules.pro"
}
}
}
proguardFiles davranışının consumerProguardFiles davranışından çok farklı olduğunu unutmayın:
proguardFiles, kitaplık oluşturma sırasında genelliklegetDefaultProguardFile("proguard-android-optimize.txt")ile birlikte kullanılarak kitaplığınızın hangi bölümünün kitaplık oluşturma sırasında korunacağını tanımlar. En azından bu, herkese açık API'nizdir.consumerProguardFilesise kitaplığınızı kullanan bir uygulamanın derlenmesi sırasında daha sonra gerçekleşecek optimizasyonları etkilemek için kitaplığa paketlenir.
Örneğin, kitaplığınız dahili sınıfları oluşturmak için yansıtma kullanıyorsa hem proguardFiles hem de consumerProguardFiles içinde koruma kurallarını tanımlamanız gerekebilir.
Kitaplığınızın derlemesinde -repackageclasses kullanıyorsanız sınıfları kitaplığınızın paketinin içinde bir alt pakete yeniden paketleyin. Örneğin, -repackageclasses 'internal' yerine -repackageclasses
'com.example.mylibrary.internal' kullanın.
Farklı R8 sürümlerini destekleme (gelişmiş)
Kuralları, R8'in belirli sürümlerini hedefleyecek şekilde uyarlayabilirsiniz. Bu sayede, kitaplığınız daha yeni R8 sürümlerinin kullanıldığı projelerde optimum şekilde çalışırken mevcut kurallar, daha eski R8 sürümlerinin kullanıldığı projelerde de kullanılmaya devam edebilir.
Hedeflenen R8 kurallarını belirtmek için bunları AAR'nin classes.jar içindeki META-INF/com.android.tools dizinine veya JAR'ın META-INF/com.android.tools dizinine eklemeniz gerekir.
In an AAR library:
proguard.txt (legacy location, the file name must be "proguard.txt")
classes.jar
└── META-INF
└── com.android.tools (location of targeted R8 rules)
├── r8-from-<X>-upto-<Y>/<R8-rule-files>
└── ... (more directories with the same name format)
In a JAR library:
META-INF
├── proguard/<ProGuard-rule-files> (legacy location)
└── com.android.tools (location of targeted R8 rules)
├── r8-from-<X>-upto-<Y>/<R8-rule-files>
└── ... (more directories with the same name format)
META-INF/com.android.tools dizininde, kuralların hangi R8 sürümleri için yazıldığını belirtmek üzere r8-from-<X>-upto-<Y> biçiminde adlara sahip birden fazla alt dizin olabilir. Her alt dizinde, R8 kurallarını içeren bir veya daha fazla dosya olabilir. Dosya adları ve uzantıları herhangi bir şekilde olabilir.
-from-<X> ve -upto-<Y> bölümlerinin isteğe bağlı olduğunu, <Y> sürümünün özel olduğunu ve sürüm aralıklarının genellikle kesintisiz olduğunu ancak çakışabileceğini unutmayın.
Örneğin, r8, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 ve r8-from-8.2.0, hedeflenen bir R8 kuralı grubunu temsil eden dizin adlarıdır. r8 dizinindeki kurallar, tüm R8 sürümleri tarafından kullanılabilir. r8-from-8.0.0-upto-8.2.0 dizinindeki kurallar, 8.0.0 sürümünden 8.2.0 sürümüne kadar (8.2.0 dahil değil) R8 tarafından kullanılabilir.
Android Gradle eklentisi, mevcut R8 sürümü tarafından kullanılabilecek tüm kuralları seçmek için bu bilgileri kullanır. Bir kitaplık, hedeflenen R8 kurallarını belirtmezse Android Gradle eklentisi, kuralları eski konumlardan (AAR için proguard.txt veya JAR için META-INF/proguard/<ProGuard-rule-files>) seçer.