ปลั๊กอิน Android Gradle 9.0 เป็นรุ่นหลักที่มาพร้อมการเปลี่ยนแปลง API และลักษณะการทำงาน
หากต้องการอัปเดตเป็นปลั๊กอิน Android Gradle 9.0.1 ให้ใช้ผู้ช่วยอัปเกรดปลั๊กอิน Android Gradle ผู้ช่วยอัปเกรด AGP จะช่วยคงลักษณะการทำงานที่มีอยู่ไว้เมื่ออัปเกรดโปรเจ็กต์เมื่อเหมาะสม คุณจึงอัปเกรดโปรเจ็กต์เพื่อใช้ AGP 9.0 ได้แม้ว่าจะยังไม่พร้อมใช้ค่าเริ่มต้นใหม่ทั้งหมดใน AGP 9.0 ก็ตาม
นอกจากนี้ยังมีทักษะของ Agent 2 รายการที่ช่วยให้กระบวนการอัปเกรดง่ายขึ้น สำหรับแอปที่ไม่ใช่ KMP ให้ลองใช้ทักษะการอัปเกรด AGP 9 จากที่เก็บทักษะ Android สำหรับแอป KMP ให้ลองใช้ทักษะการอัปเกรด AGP 9 จาก JetBrains ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ทักษะใน Android Studio ได้ที่ขยายโหมด Agent ด้วยทักษะ
ความเข้ากันได้
ระดับ API สูงสุดที่ปลั๊กอิน Android Gradle 9.0 รองรับคือระดับ API 36.1 ข้อมูลอื่นๆ เกี่ยวกับความเข้ากันได้มีดังนี้
| เวอร์ชันขั้นต่ำ | เวอร์ชันเริ่มต้น | หมายเหตุ | |
|---|---|---|---|
| Gradle | 9.1.0 | 9.1.0 | ดูข้อมูลเพิ่มเติมได้ที่การอัปเดต Gradle |
| เครื่องมือสร้าง SDK | 36.0.0 | 36.0.0 | ติดตั้งหรือกำหนดค่าเครื่องมือสร้าง SDK |
| NDK | ไม่มี | 28.2.13676358 | ติดตั้งหรือกำหนดค่า NDK เวอร์ชันอื่น |
| JDK | 17 | 17 | ดูข้อมูลเพิ่มเติมได้ที่การตั้งค่าเวอร์ชัน JDK |
| ปลั๊กอิน Kotlin Gradle (KGP) | 2.2.10 | 2.2.10 | ดูข้อมูลเพิ่มเติมได้ที่ทรัพยากร Dependency ของรันไทม์ในปลั๊กอิน Kotlin Gradle |
ตอนนี้คลาส DSL ของ android จะใช้อินเทอร์เฟซสาธารณะใหม่เท่านั้น
ในช่วงหลายปีที่ผ่านมา เราได้เปิดตัวอินเทอร์เฟซใหม่สำหรับ DSL และ API เพื่อควบคุม API ที่เป็นสาธารณะได้ดียิ่งขึ้น AGP เวอร์ชัน 7.x และ 8.x ยังคงใช้ DSL ประเภทเก่า (เช่น BaseExtension) ซึ่งใช้อินเทอร์เฟซสาธารณะใหม่ด้วย เพื่อรักษาความเข้ากันได้ขณะที่การทำงานในอินเทอร์เฟซดำเนินไป
AGP 9.0 ใช้อินเทอร์เฟซ DSL ใหม่ของเราโดยเฉพาะ และการติดตั้งใช้งานได้เปลี่ยนไปเป็นประเภทใหม่ที่ซ่อนไว้อย่างสมบูรณ์ นโยบายนี้ยังนำสิทธิ์เข้าถึง Variant API เก่าที่เลิกใช้งานแล้วออกด้วย
หากต้องการอัปเดตเป็น AGP 9.0 คุณอาจต้องทำดังนี้
- ตรวจสอบว่าโปรเจ็กต์เข้ากันได้กับ Kotlin ในตัว: ปลั๊กอิน
org.jetbrains.kotlin.androidไม่เข้ากันได้กับ DSL ใหม่ เปลี่ยนโปรเจ็กต์ KMP เป็นปลั๊กอินไลบรารี Android Gradle สำหรับ KMP: การใช้ปลั๊กอิน
org.jetbrains.kotlin.multiplatformในโปรเจ็กต์ย่อย Gradle เดียวกันกับปลั๊กอินcom.android.libraryและcom.android.applicationไม่เข้ากันกับ DSL ใหม่อัปเดตไฟล์บิลด์: แม้ว่าการเปลี่ยนแปลงอินเทอร์เฟซมีไว้เพื่อรักษา DSL ให้คล้ายกันมากที่สุด แต่อาจมีการเปลี่ยนแปลงเล็กน้อย
อัปเดตตรรกะบิลด์ที่กำหนดเองเพื่ออ้างอิง DSL และ API ใหม่: แทนที่การอ้างอิง DSL ภายในด้วยอินเทอร์เฟซ DSL สาธารณะ ในกรณีส่วนใหญ่ การดำเนินการนี้จะเป็นการแทนที่แบบ 1 ต่อ 1 แทนที่การใช้
applicationVariantsและ API ที่คล้ายกันด้วยandroidComponentsAPI ใหม่ ซึ่งอาจซับซ้อนกว่า เนื่องจาก API ของandroidComponentsได้รับการออกแบบมาให้มีความเสถียรมากขึ้นเพื่อให้ปลั๊กอินใช้งานร่วมกันได้นานขึ้น ดูตัวอย่างได้ที่สูตร Gradleอัปเดตปลั๊กอินของบุคคลที่สาม: ปลั๊กอินของบุคคลที่สามบางรายการอาจยังคงขึ้นอยู่กับอินเทอร์เฟซหรือ API ที่ไม่มีการแสดงอีกต่อไป ย้ายไปใช้ปลั๊กอินเวอร์ชันที่เข้ากันได้กับ AGP 9.0
การเปลี่ยนไปใช้อินเทอร์เฟซ DSL ใหม่จะป้องกันไม่ให้ปลั๊กอินและสคริปต์บิลด์ Gradle ใช้ API ที่เลิกใช้งานแล้วต่างๆ ซึ่งรวมถึง API ต่อไปนี้
API ที่เลิกใช้งานแล้วในบล็อก android |
ฟังก์ชัน | การแทนที่ |
|---|---|---|
applicationVariants,libraryVariants,testVariants และunitTestVariants
|
จุดส่วนขยายสำหรับปลั๊กอินเพื่อเพิ่มฟังก์ชันการทำงานใหม่ให้กับ AGP |
แทนที่ด้วย API androidComponents.onVariants เช่น
androidComponents { onVariants() { variant -> variant.signingConfig .enableV1Signing.set(false) } } |
variantFilter
|
อนุญาตให้ปิดใช้ตัวแปรที่เลือก |
แทนที่ด้วย API androidComponents.beforeVariants เช่น
androidComponents { beforeVariants( selector() .withBuildType("debug") .withFlavor("color", "blue") ) { variantBuilder -> variantBuilder.enable = false } } |
deviceProvider และtestServer
|
การลงทะเบียนสภาพแวดล้อมการทดสอบที่กำหนดเองสำหรับการทดสอบกับอุปกรณ์ Android และโปรแกรมจำลอง | เปลี่ยนไปใช้อุปกรณ์ที่มีการจัดการจาก Gradle |
sdkDirectory,ndkDirectory,bootClasspath,adbExecutable และadbExe
|
การใช้คอมโพเนนต์ต่างๆ ของ Android SDK สำหรับงานที่กำหนดเอง |
เปลี่ยนเป็น androidComponents.sdkComponents
|
registerArtifactTyperegisterBuildTypeSourceProviderregisterProductFlavorSourceProviderregisterJavaArtifactregisterMultiFlavorSourceProvider และwrapJavaSourceSet |
ฟังก์ชันการทำงานที่ล้าสมัยซึ่งส่วนใหญ่เกี่ยวข้องกับการจัดการแหล่งที่มาที่สร้างขึ้นใน Android Studio ซึ่งหยุดทำงานใน AGP 7.2.0 | ไม่มี API ใดที่จะมาแทนที่ API เหล่านี้โดยตรง |
dexOptions
|
การตั้งค่าที่ล้าสมัยซึ่งเกี่ยวข้องกับเครื่องมือ dx ซึ่งถูกแทนที่ด้วย d8 การตั้งค่าทั้งหมดไม่มีผลตั้งแต่ปลั๊กอิน Android Gradle 7.0
|
ไม่มีการแทนที่โดยตรง |
generatePureSplits
|
สร้างการแยกการกำหนดค่าสำหรับ Instant App | ตอนนี้ความสามารถในการจัดส่งการแยกการกำหนดค่ามีอยู่ใน Android App Bundle แล้ว |
aidlPackagedList
|
ไฟล์ AIDL ที่จะแพ็กเกจใน AAR เพื่อแสดงเป็น API สำหรับไลบรารีและแอปที่ขึ้นอยู่กับไลบรารีนี้ |
ซึ่งยังคงแสดงใน LibraryExtension แต่ไม่แสดงในส่วนขยายประเภทอื่นๆ
|
หากคุณอัปเดตเป็น AGP 9.0 และเห็นข้อความแสดงข้อผิดพลาดต่อไปนี้ แสดงว่าโปรเจ็กต์ยังคงอ้างอิงประเภทเก่าบางประเภทอยู่
java.lang.ClassCastException: class com.android.build.gradle.internal.dsl.ApplicationExtensionImpl$AgpDecorated_Decorated
cannot be cast to class com.android.build.gradle.BaseExtension
หากถูกบล็อกโดยปลั๊กอินของบุคคลที่สามที่เข้ากันไม่ได้ คุณสามารถเลือกไม่ใช้และกลับไปใช้การติดตั้งใช้งานแบบเก่าสำหรับ DSL รวมถึง Variant API แบบเก่าได้
ในระหว่างนี้ อินเทอร์เฟซใหม่ก็พร้อมใช้งานด้วย และคุณยังคงอัปเดตตรรกะการสร้างของคุณเองเป็น API ใหม่ได้ หากต้องการเลือกไม่ใช้ ให้ใส่บรรทัดนี้ในไฟล์ gradle.properties
android.newDsl=false
หรือหากต้องการย้ายข้อมูลแบบค่อยเป็นค่อยไป AGP 9.4 จะช่วยให้คุณเลือกไม่ใช้โมดูลแต่ละรายการได้ ดูวิธีได้ที่การเลือกไม่ใช้โมดูล Variant API
คลาสก่อนหน้าจะถูกทำเครื่องหมายว่าเลิกใช้งานแล้วใน AGP 9.0 ซึ่งหมายความว่าโปรเจ็กต์ที่เลือกไม่ใช้แฟล็ก newDsl จะเห็นคำเตือนการเลิกใช้งาน รวมถึงในบล็อก android เองด้วย
นอกจากนี้ คุณยังเริ่มอัปเกรดเป็น API ใหม่ก่อนอัปเกรดเป็น AGP 9.0 ได้ด้วย อินเทอร์เฟซใหม่มีอยู่ใน AGP หลายเวอร์ชัน คุณจึงสามารถใช้ทั้งอินเทอร์เฟซใหม่และเก่าผสมกันได้ เอกสารอ้างอิง AGP API แสดงแพลตฟอร์ม API สำหรับ AGP แต่ละเวอร์ชัน และเวลาที่เพิ่มคลาส เมธอด และฟิลด์แต่ละรายการ
เรากำลังติดต่อผู้เขียนปลั๊กอินที่ใช้กันโดยทั่วไปเพื่อช่วยปรับเปลี่ยนและเผยแพร่ปลั๊กอินที่เข้ากันได้อย่างสมบูรณ์กับโหมดใหม่ และจะปรับปรุง AGP Upgrade Assistant ใน Android Studio ต่อไปเพื่อแนะนำคุณตลอดการย้ายข้อมูล
หากพบว่า DSL หรือ Variant API ใหม่ไม่มีความสามารถหรือฟีเจอร์ โปรดแจ้งปัญหาโดยเร็วที่สุด
Kotlin ในตัว
ปลั๊กอิน Android Gradle 9.0 เปิดตัวการรองรับ Kotlin ในตัวและเปิดใช้โดยค่าเริ่มต้น ซึ่งหมายความว่าคุณไม่จำเป็นต้องใช้ปลั๊กอิน org.jetbrains.kotlin.android (หรือ kotlin-android) ในไฟล์บิลด์เพื่อคอมไพล์ไฟล์ซอร์สโค้ด Kotlin อีกต่อไป
ซึ่งจะช่วยลดความซับซ้อนของการผสานรวม Kotlin กับ AGP, หลีกเลี่ยงการใช้ API ที่เลิกใช้งานแล้ว และปรับปรุงประสิทธิภาพในบางกรณี
ดังนั้นเมื่ออัปเกรดโปรเจ็กต์เป็น AGP 9.0 คุณจะต้องย้ายข้อมูลไปยัง Kotlin ในตัวหรือเลือกไม่ใช้ด้วย
นอกจากนี้ คุณยังเลือกปิดใช้การรองรับ Kotlin ในตัวสำหรับโปรเจ็กต์ย่อย Gradle ที่ไม่มีแหล่งที่มา Kotlin ได้ด้วย
ทรัพยากร Dependency ของรันไทม์ในปลั๊กอิน Kotlin สำหรับ Gradle
ปลั๊กอิน Android Gradle 9.0 มีทรัพยากร Dependency รันไทม์ในปลั๊กอิน Kotlin Gradle (KGP) 2.2.10 เพื่อรองรับ Kotlin ในตัว ซึ่งหมายความว่าคุณไม่จำเป็นต้องประกาศเวอร์ชัน KGP อีกต่อไป และหากคุณใช้เวอร์ชัน KGP ที่ต่ำกว่า 2.2.10 Gradle จะอัปเกรดเวอร์ชัน KGP เป็น 2.2.10 โดยอัตโนมัติ ในทำนองเดียวกัน หากคุณใช้ KSP เวอร์ชันต่ำกว่า 2.2.10-2.0.2 AGP จะอัปเกรดเป็น 2.2.10-2.0.2 เพื่อให้ตรงกับเวอร์ชัน KGP
อัปเกรดเป็น KGP เวอร์ชันที่สูงขึ้น
หากต้องการใช้ KGP หรือ KSP เวอร์ชันที่สูงกว่า ให้เพิ่มโค้ดต่อไปนี้ลงในไฟล์บิลด์ระดับบนสุด
buildscript {
dependencies {
// For KGP
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:KGP_VERSION")
// For KSP
classpath("com.google.devtools.ksp:symbol-processing-gradle-plugin:KSP_VERSION")
}
}
ดาวน์เกรดเป็น KGP เวอร์ชันที่ต่ำกว่า
คุณจะดาวน์เกรดเวอร์ชัน KGP ได้ก็ต่อเมื่อเลือกไม่ใช้ Kotlin ในตัว เนื่องจาก AGP 9.0 เปิดใช้ Kotlin ในตัวโดยค่าเริ่มต้น และ Kotlin ในตัวต้องใช้ KGP 2.2.10 ขึ้นไป
หากต้องการใช้ KGP หรือ KSP เวอร์ชันต่ำกว่า ให้ประกาศเวอร์ชันนั้นในไฟล์บิลด์ระดับบนสุดโดยใช้การประกาศเวอร์ชันที่เข้มงวด ดังนี้
buildscript {
dependencies {
// For KGP
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") {
version { strictly("KGP_VERSION") }
}
// For KSP
classpath("com.google.devtools.ksp:symbol-processing-gradle-plugin") {
version { strictly("KSP_VERSION") }
}
}
}
โปรดทราบว่าเวอร์ชัน KGP ขั้นต่ำที่คุณดาวน์เกรดได้คือ 2.0.0
การรองรับ IDE สำหรับฟิกซ์เจอร์ทดสอบ
AGP 9.0 รองรับ IDE ของ Android Studio อย่างเต็มรูปแบบสำหรับฟิกซ์เจอร์ทดสอบ
ปลั๊กอิน Fused Library
ปลั๊กอินไลบรารีแบบรวม (เวอร์ชันตัวอย่าง) ช่วยให้คุณเผยแพร่ไลบรารีหลายรายการเป็น Android Library AAR รายการเดียวได้ ซึ่งจะช่วยให้ผู้ใช้พึ่งพาอาร์ติแฟกต์ที่เผยแพร่ได้ง่ายขึ้น
ดูข้อมูลเกี่ยวกับการเริ่มต้นใช้งานได้ที่เผยแพร่ไลบรารี Android หลายรายการเป็นไลบรารีเดียวด้วย Fused Library
การเปลี่ยนแปลงพฤติกรรม
ปลั๊กอิน Android Gradle 9.0 มีลักษณะการทำงานใหม่ดังต่อไปนี้
| ลักษณะการทำงาน | คำแนะนำ |
|---|---|
ปลั๊กอิน Android Gradle 9.0 ใช้ NDK เวอร์ชัน r28c โดยค่าเริ่มต้น
|
พิจารณาระบุเวอร์ชัน NDK ที่ต้องการใช้อย่างชัดเจน |
| โดยค่าเริ่มต้น ปลั๊กอิน Android Gradle 9.0 กำหนดให้ผู้ใช้ไลบรารีต้องใช้ SDK เวอร์ชันเดียวกันหรือสูงกว่าในการคอมไพล์ |
ใช้ SDK คอมไพล์เดียวกันหรือสูงกว่าเมื่อใช้ไลบรารี
หากเป็นไปไม่ได้ หรือคุณต้องการให้ผู้ใช้ไลบรารีที่คุณเผยแพร่มีเวลาเปลี่ยนมากขึ้น ให้ตั้งค่า AarMetadata.minCompileSdk อย่างชัดเจน
|
AGP 9.0 มีการอัปเดตค่าเริ่มต้นของพร็อพเพอร์ตี้ Gradle ต่อไปนี้ ซึ่งจะช่วยให้คุณเลือกคงลักษณะการทำงานของ AGP 8.13 ไว้ได้เมื่ออัปเกรด โดยทำดังนี้
| พร็อพเพอร์ตี้ | ฟังก์ชัน | การเปลี่ยนแปลงจาก AGP 8.13 เป็น AGP 9.0 | คำแนะนำ |
|---|---|---|---|
android. |
ใช้อินเทอร์เฟซ DSL ใหม่โดยไม่แสดงการใช้งานเดิมของบล็อก androidซึ่งหมายความว่า API ตัวแปรเดิม เช่น android.applicationVariants
จะเข้าถึงไม่ได้อีกต่อไป
|
false → true |
คุณเลือกไม่ใช้ได้โดยตั้งค่า android.newDsl=falseเมื่อปลั๊กอินและตรรกะบิลด์ทั้งหมดที่โปรเจ็กต์ใช้เข้ากันได้แล้ว ให้นำการเลือกไม่ใช้ออก |
android. |
เปิดใช้ Kotlin ในตัว | false → true |
ย้ายข้อมูลไปยัง Kotlin ในตัวหากทำได้ หรือเลือกไม่ใช้ |
android. |
บังคับให้แต่ละไลบรารีมีชื่อแพ็กเกจที่แตกต่างกัน | false → true |
ระบุชื่อแพ็กเกจที่ไม่ซ้ำกันสำหรับไลบรารีทั้งหมดภายในโปรเจ็กต์ หากทำไม่ได้ คุณสามารถปิดใช้แฟล็กนี้ขณะย้ายข้อมูล |
android. |
ใช้ทรัพยากร Dependency ของ androidx โดยค่าเริ่มต้น
|
false → true |
ใช้ทรัพยากร Dependency ของ androidx
|
android. |
เรียกใช้การทดสอบในอุปกรณ์ด้วยคลาส androidx.test.runner.AndroidJUnitRunner โดยค่าเริ่มต้น ซึ่งจะแทนที่ค่าเริ่มต้นของ InstrumentationTestRunner ที่เลิกใช้งานแล้วสำหรับ
android {
defaultConfig {
testInstrumentationRunner = "..."
}
} |
false → true |
ใช้ AndroidJUnitRunner หรือระบุ testInstrumentationRunner ที่กำหนดเองอย่างชัดเจน
|
android. |
ควบคุมการใช้ข้อจำกัดการขึ้นต่อกันระหว่างการกำหนดค่า ค่าเริ่มต้นใน AGP 9.0 คือ false ซึ่งใช้ข้อจำกัดในการทดสอบอุปกรณ์แอปพลิเคชัน (AndroidTest) เท่านั้น
การตั้งค่านี้เป็น true จะเปลี่ยนกลับไปใช้ลักษณะการทำงานของเวอร์ชัน 8.13
|
true → false |
อย่าใช้ข้อจำกัดของทรัพยากร Dependency ทุกที่ เว้นแต่คุณจะต้องการใช้ การยอมรับค่าเริ่มต้นใหม่ของแฟล็กนี้ยังเปิดใช้การเพิ่มประสิทธิภาพในกระบวนการนำเข้าโปรเจ็กต์ด้วย ซึ่งจะช่วยลดเวลานำเข้าสำหรับบิลด์ที่มีโปรเจ็กต์ย่อยของไลบรารี Android จำนวนมาก |
android. |
คอมไพล์โค้ดในแอปพลิเคชันกับคลาส R ที่ไม่ใช่คลาสสุดท้าย ซึ่งจะทำให้การคอมไพล์แอปพลิเคชันสอดคล้องกับการคอมไพล์ไลบรารี ซึ่งจะช่วยปรับปรุงการเพิ่มขึ้นและปูทางให้กับการเพิ่มประสิทธิภาพในอนาคตสำหรับขั้นตอนการประมวลผลทรัพยากร |
false → true |
หลายโปรเจ็กต์สามารถใช้ลักษณะการทำงานใหม่ได้โดยไม่ต้องเปลี่ยนแหล่งที่มา หากมีการใช้ฟิลด์คลาส R ในตำแหน่งที่ต้องใช้ค่าคงที่ เช่น เคสสวิตช์ ให้เปลี่ยนโครงสร้างภายในโค้ดเพื่อใช้คำสั่ง if แบบต่อกัน |
android. |
ใช้เวอร์ชัน SDK ที่คอมไพล์เป็นค่าเริ่มต้นสำหรับเวอร์ชัน SDK เป้าหมายในแอปและการทดสอบ ก่อนการเปลี่ยนแปลงนี้ เวอร์ชัน SDK เป้าหมายจะใช้เวอร์ชัน SDK ขั้นต่ำเป็นค่าเริ่มต้น |
false → true |
ระบุเวอร์ชัน SDK เป้าหมายอย่างชัดเจนสำหรับแอปและการทดสอบ |
android. |
สร้างคอมโพเนนต์ Unit Test สำหรับประเภทบิลด์ที่ทดสอบเท่านั้น ในโปรเจ็กต์เริ่มต้น การดำเนินการนี้จะส่งผลให้เกิด Unit Test รายการเดียวสำหรับการแก้ไขข้อบกพร่อง โดยลักษณะการทำงานก่อนหน้านี้คือการเรียกใช้ Unit Test สำหรับการแก้ไขข้อบกพร่องหรือการเผยแพร่ |
false → true |
หากโปรเจ็กต์ไม่จำเป็นต้องทำการทดสอบทั้งสำหรับการแก้ไขข้อบกพร่องและการเผยแพร่ ก็ไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ |
android. |
ทำให้บิลด์ไม่สำเร็จพร้อมข้อผิดพลาดหากไฟล์ที่เก็บไว้ซึ่งระบุไว้ใน AGP DSL ไม่มีอยู่ในดิสก์ ก่อนการเปลี่ยนแปลงนี้ การพิมพ์ชื่อไฟล์ผิดจะส่งผลให้ระบบละเว้นไฟล์โดยไม่แจ้งให้ทราบ | false → true |
นำการประกาศไฟล์ ProGuard ที่ไม่ถูกต้องออก |
android. |
อนุญาตให้ R8 เก็บรักษาทรัพยากร Android น้อยลงโดยพิจารณาคลาสและทรัพยากร Android ร่วมกัน | false → true |
หากกฎการเก็บรักษาของโปรเจ็กต์เสร็จสมบูรณ์แล้ว คุณก็ไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ |
android. |
อนุญาตให้ R8 เก็บข้อมูลน้อยลงโดยไม่เก็บคอนสตรัคเตอร์เริ่มต้นโดยนัยเมื่อมีการเก็บคลาสไว้
กล่าวคือ -keep class A ไม่ได้หมายถึง -keep class A { <init>(); } อีกต่อไป |
false → true |
หากกฎการเก็บรักษาของโปรเจ็กต์สมบูรณ์แล้ว คุณก็ไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ
แทนที่ -keep class A
ด้วย
-keep class A { <init>(); }
ในกฎการเก็บรักษาของโปรเจ็กต์ในกรณีที่คุณต้องการเก็บคอนสตรัคเตอร์เริ่มต้นไว้
|
android. |
เปิดใช้
resValues
ในโปรเจ็กต์ย่อยทั้งหมด
|
true → false |
เปิดใช้ resValues เฉพาะในโปรเจ็กต์ย่อยที่ต้องการโดยตั้งค่าต่อไปนี้ในไฟล์บิลด์ Gradle ของโปรเจ็กต์เหล่านั้น
android {
buildFeatures {
resValues = true
}
} |
android. |
เปิดใช้การคอมไพล์ตัวปรับเฉดสีในโปรเจ็กต์ย่อยทั้งหมด | true → false |
เปิดใช้การคอมไพล์ตัวปรับเฉดสีเฉพาะในโปรเจ็กต์ย่อยที่มีตัวปรับเฉดสีที่จะคอมไพล์โดยตั้งค่าต่อไปนี้ในไฟล์บิลด์ Gradle ของโปรเจ็กต์เหล่านั้น
android {
buildFeatures {
shaders = true
}
} |
android. |
ใน AGP 9.0 getDefaultProguardFile() จะรองรับเฉพาะ proguard-android-optimize.txt แทน proguard-android.txt ทั้งนี้เพื่อป้องกันการใช้แฟล็ก dontoptimize โดยไม่ตั้งใจ ซึ่งรวมอยู่ใน proguard-android.txt
|
false → true |
คุณสามารถระบุ dontoptimize อย่างชัดเจนใน proguardFile ที่กำหนดเองได้หากต้องการหลีกเลี่ยงการเพิ่มประสิทธิภาพ ควบคู่ไปกับการใช้ proguard-android-optimize.txt อย่าลืมนำแฟล็ก dontoptimize ออกจากไฟล์นี้หากเป็นไปได้ เนื่องจากจะลดประโยชน์ของการเพิ่มประสิทธิภาพ R8 หากไม่ต้องการ ให้เลือกไม่ใช้โดยตั้งค่า android.r8.globalOptionsInConsumerRules.disallowed=false
|
android. |
ตั้งแต่ AGP 9.0 เป็นต้นไป การเผยแพร่ไลบรารี Android และโมดูลฟีเจอร์จะดำเนินการไม่สำเร็จหากไฟล์ Keep ของผู้ใช้มีการกำหนดค่า Proguard ที่เป็นปัญหา ไฟล์ Keep ของผู้ใช้ที่มีตัวเลือกส่วนกลาง เช่น dontoptimize หรือ dontobfuscate ควรใช้ในโมดูลแอปพลิเคชันเท่านั้น และอาจลดประโยชน์ของการเพิ่มประสิทธิภาพสำหรับผู้ใช้ไลบรารี การคอมไพล์โมดูลแอป Android จะละเว้นตัวเลือกส่วนกลางดังกล่าวโดยไม่แจ้งให้ทราบหากฝังอยู่ในทรัพยากร Dependency ที่คอมไพล์ไว้ล่วงหน้า (JAR หรือ AAR) คุณสามารถดูได้ว่าเหตุการณ์นี้เกิดขึ้นเมื่อใดโดยตรวจสอบ configuration.txt (โดยปกติจะอยู่ในเส้นทางอย่าง <app_module>/build/outputs/mapping/<build_variant>/configuration.txt) เพื่อหาความคิดเห็น เช่น # REMOVED CONSUMER RULE: dontoptimize
|
false → true |
ไลบรารีที่เผยแพร่ควรนำกฎที่ใช้ร่วมกันไม่ได้ออก ไลบรารีภายในควรย้ายกฎที่เข้ากันไม่ได้แต่จำเป็นไปยัง proguardFile ในโมดูลแอปแทน เลือกไม่ใช้โดยตั้งค่า android.r8.globalOptionsInConsumerRules.disallowed=false เมื่อไฟล์ Keep ของผู้บริโภคทั้งหมดเข้ากันได้แล้ว ให้นำการเลือกไม่ใช้ออก
|
android. |
ไม่อนุญาตให้ส่งผู้ให้บริการสำหรับแหล่งที่มาที่สร้างขึ้นโดยใช้ DSL AndroidSourceSet
|
false → true |
ใช้ API Sources ใน androidComponents เพื่อลงทะเบียนแหล่งที่มาที่สร้างขึ้น
|
android. |
ต้องตั้งค่าเส้นทางคอมไพเลอร์เฉดสีอย่างชัดเจนใน local.properties หากเปิดใช้การคอมไพล์เฉดสี
|
false → true |
เพิ่ม glslc.dir=/path/to/shader-tools ลงใน local.properties ของโปรเจ็กต์
|
ฟีเจอร์ที่นำออก
ปลั๊กอิน Android Gradle 9.0 จะนำฟังก์ชันการทำงานต่อไปนี้ออก
- การรองรับแอป Wear OS แบบฝัง
AGP 9.0 จะนำการรองรับการฝังแอป Wear OS ออก ซึ่ง Play ไม่รองรับอีกต่อไป ซึ่งรวมถึงการนำการกำหนดค่าwearAppและ DSLAndroidSourceSet.wearAppConfigurationNameออก ดูวิธีเผยแพร่แอปไปยัง Wear OS ได้ที่เผยแพร่ไปยัง Wear OS - งานรายงาน
androidDependenciesและsourceSets - การรองรับ APK แยกตามความหนาแน่น
AGP 9.0 จะนำการรองรับการสร้าง APK แยกตามความหนาแน่นของหน้าจอออก ระบบได้นำฟังก์ชันการทำงานและ API ที่เกี่ยวข้องออกแล้ว หากต้องการแยก APK ตามความหนาแน่นของหน้าจอโดยใช้ AGP 9.0 ขึ้นไป ให้ใช้ App Bundle
DSL ที่เปลี่ยนแปลง
ปลั๊กอิน Android Gradle 9.0 มีการเปลี่ยนแปลง DSL ที่ส่งผลกับส่วนอื่นดังต่อไปนี้
นำการกำหนดพารามิเตอร์ของ
CommonExtensionออกแล้วการเปลี่ยนแปลงนี้เป็นการเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบระดับแหล่งที่มาเท่านั้นเพื่อช่วยหลีกเลี่ยงการเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบระดับแหล่งที่มาในอนาคต แต่ก็หมายความว่าเมธอดบล็อกจะต้องย้ายจาก
CommonExtensionไปยังApplicationExtension,LibraryExtension,DynamicFeatureExtensionและTestExtensionด้วยเมื่ออัปเกรดโปรเจ็กต์เป็น AGP 9.0 ให้เปลี่ยนโครงสร้างภายในโค้ดปลั๊กอิน Gradle ซึ่งใช้พารามิเตอร์หรือเมธอดบล็อกเหล่านั้น ตัวอย่างเช่น ปลั๊กอินต่อไปนี้ได้รับการอัปเดตเพื่อนำพารามิเตอร์ประเภทออก และไม่ใช้เมธอดบล็อกที่นำออก
AGP 8.13
val commonExtension: CommonExtension<*, *, *, *, *, *> = extensions.getByType(CommonExtension::class) commonExtension.apply { defaultConfig { minSdk { version = release(28) } } }AGP 9.0
val commonExtension: CommonExtension = extensions.getByType(CommonExtension::class) commonExtension.apply { defaultConfig.apply { minSdk { version = release(28) } } }สำหรับปลั๊กอินที่กำหนดเป้าหมายเป็น AGP เวอร์ชันต่างๆ การใช้ Getter โดยตรงจะเข้ากันได้กับไบนารีของ AGP เวอร์ชันต่ำกว่า 9.0
นำ DSL ออกแล้ว
ปลั๊กอิน Android Gradle 9.0 จะนำสิ่งต่อไปนี้ออก
AndroidSourceSet.jniเนื่องจากใช้งานไม่ได้AndroidSourceSet.wearAppConfigurationNameเนื่องจากเกี่ยวข้องกับการนำการรองรับแอป Wear OS ที่ฝังไว้ออกBuildType.isRenderscriptDebuggableเนื่องจากใช้งานไม่ได้DependencyVariantSelectionโดยจะแทนที่ด้วยDependencySelectionซึ่งแสดงเป็นkotlin.android.localDependencySelectionInstallation.installOptions(String)โดยจะแทนที่ด้วยพร็อพเพอร์ตี้ที่เปลี่ยนแปลงได้ของInstallation.installOptionsบล็อก
PostProcessingที่อยู่ระหว่างการทดสอบแต่ยังไม่เสถียรProductFlavor.setDimensionซึ่งแทนที่ด้วยพร็อพเพอร์ตี้dimensionLanguageSplitOptionsซึ่งมีประโยชน์สำหรับ Google Play Instant เท่านั้น และเลิกใช้งานแล้วDensitySplitเนื่องจากระบบไม่รองรับฟีเจอร์นี้อีกต่อไป โดยจะแทนที่ด้วย App Bundle
API ที่นำออก
ปลั๊กอิน Android Gradle 9.0 จะนำสิ่งต่อไปนี้ออก
AndroidComponentsExtension.finalizeDSlโดยจะแทนที่ด้วยfinalizeDslComponent.transformClassesWithโดยจะแทนที่ด้วยInstrumentation.transformClassesWithComponent.setAsmFramesComputationModeโดยจะแทนที่ด้วยInstrumentation.setAsmFramesComputationModeComponentBuilder.enabledโดยจะแทนที่ด้วยComponentBuilder.enableDependenciesInfoBuilder.includedInApkโดยจะแทนที่ด้วยincludeInApkDependenciesInfoBuilder.includedInBundleโดยจะแทนที่ด้วยincludeInBundleGeneratesApk.targetSdkVersionโดยจะแทนที่ด้วยtargetSdkVariant.minSdkVersionโดยจะแทนที่ด้วยminSdkVariant.maxSdkVersionโดยจะแทนที่ด้วยmaxSdkVariant.targetSdkVersionโดยจะแทนที่ด้วยtargetSdkVariant.unitTestเนื่องจากไม่เกี่ยวข้องกับปลั๊กอินcom.android.testunitTestพร้อมใช้งานในประเภทย่อยVariantBuilderที่ขยายHasUnitTestVariantBuilder.targetSdkและtargetSdkPreviewเนื่องจากไม่มีความหมายในไลบรารี โปรดใช้GeneratesApkBuilder.targetSdkหรือGeneratesApkBuilder.targetSdkPreviewแทนVariantBuilder.enableUnitTestเนื่องจากไม่เกี่ยวข้องกับปลั๊กอินcom.android.testenableUnitTestพร้อมใช้งานในประเภทย่อยVariantBuilderที่ขยายHasUnitTestBuilderVariantBuilder.unitTestEnabledถูกนำออกเพื่อใช้enableUnitTestที่มีชื่อสอดคล้องกันมากกว่าในประเภทย่อยVariantBuilderที่ขยายHasUnitTestBuilderVariantOutput.enableโดยจะแทนที่ด้วยenabledFeaturePluginและFeatureExtensionที่เลิกใช้งานและปิดใช้แล้วAPI
BaseExtension.registerTransformที่เลิกใช้งานและปิดใช้แล้ว ซึ่งยังคงอยู่เพื่อให้คอมไพล์กับ AGP เวอร์ชันล่าสุดได้เท่านั้น ขณะที่กำหนดเป้าหมายการทำงานใน AGP 4.2 หรือต่ำกว่า
พร็อพเพอร์ตี้ Gradle ที่นำออก
เริ่มแรกมีการเพิ่มพร็อพเพอร์ตี้ Gradle ต่อไปนี้เพื่อเป็นวิธีปิดใช้ฟีเจอร์ที่เปิดใช้โดยค่าเริ่มต้นทั่วโลก
ฟีเจอร์เหล่านี้ถูกปิดใช้โดยค่าเริ่มต้นตั้งแต่ AGP 8.0 หรือต่ำกว่า เปิดใช้ฟีเจอร์เหล่านี้เฉพาะในโปรเจ็กต์ย่อยที่ใช้ฟีเจอร์ดังกล่าวเพื่อให้บิลด์มีประสิทธิภาพมากขึ้น
| พร็อพเพอร์ตี้ | ฟังก์ชัน | การแทนที่ |
|---|---|---|
android. |
เปิดใช้การคอมไพล์ AIDL ในโปรเจ็กต์ย่อยทั้งหมด |
เปิดใช้การคอมไพล์ AIDL เฉพาะในโปรเจ็กต์ย่อยที่มีแหล่งที่มา AIDL โดยตั้งค่าพร็อพเพอร์ตี้ต่อไปนี้ในไฟล์บิลด์ Gradle ของโปรเจ็กต์เหล่านั้น
android {
buildFeatures {
aidl = true
}
} |
android. |
เปิดใช้ การคอมไพล์ RenderScript ในโปรเจ็กต์ย่อยทั้งหมด |
เปิดใช้การคอมไพล์ Renderscript เฉพาะในโปรเจ็กต์ย่อยที่มีแหล่งที่มาของ Renderscript โดยตั้งค่าพร็อพเพอร์ตี้ต่อไปนี้ในไฟล์บิลด์ Gradle ของโปรเจ็กต์เหล่านั้น
android {
buildFeatures {
renderScript = true
}
} |
พร็อพเพอร์ตี้ Gradle ที่บังคับใช้
AGP 9.0 จะแสดงข้อผิดพลาดหากคุณตั้งค่าพร็อพเพอร์ตี้ Gradle ต่อไปนี้
ผู้ช่วยอัปเกรดปลั๊กอิน Android Gradle จะไม่อัปเกรดโปรเจ็กต์เป็น AGP 9.0 ที่ใช้พร็อพเพอร์ตี้เหล่านี้
| พร็อพเพอร์ตี้ | ฟังก์ชัน |
|---|---|
android. |
ตอนนี้การลดขนาดทรัพยากรจะทำงานเป็นส่วนหนึ่งของ R8 เสมอ โดยระบบได้นำการใช้งานก่อนหน้านี้ออกแล้ว |
android. |
ตอนนี้การลดขนาดทรัพยากรจะใช้การลดขนาดทรัพยากรที่แม่นยำเสมอ ซึ่งช่วยให้นำทรัพยากรออกได้มากขึ้น |
การเปลี่ยนแปลง R8
การเปลี่ยนแปลง R8 ต่อไปนี้รวมอยู่ใน AGP 9.0.0
ตัวเลือกการกำหนดค่าใหม่ -processkotlinnullchecks
เราได้เพิ่มตัวเลือก R8 ใหม่ -processkotlinnullchecks เพื่อกำหนดค่า R8 สำหรับการประมวลผลการตรวจสอบค่า Null ของ Kotlin ตัวเลือกนี้ใช้อาร์กิวเมนต์ที่จำเป็นซึ่งต้องเป็นค่าใดค่าหนึ่งใน 3 ค่าต่อไปนี้ ได้แก่ keep, remove_message และ remove
ตัวเลือกนี้จะประมวลผลการตรวจสอบค่า Null ต่อไปนี้ที่เพิ่มโดยคอมไพเลอร์ Kotlin
class kotlin.jvm.internal.Intrinsics {
void checkNotNull(java.lang.Object);
void checkNotNull(java.lang.Object, java.lang.String);
void checkExpressionValueIsNotNull(
java.lang.Object, java.lang.String);
void checkNotNullExpressionValue(
java.lang.Object, java.lang.String);
void checkReturnedValueIsNotNull(
java.lang.Object, java.lang.String);
void checkReturnedValueIsNotNull(
java.lang.Object, java.lang.String, java.lang.String);
void checkFieldIsNotNull(java.lang.Object, java.lang.String);
void checkFieldIsNotNull(
java.lang.Object, java.lang.String, java.lang.String);
void checkParameterIsNotNull(java.lang.Object, java.lang.String);
void checkNotNullParameter(java.lang.Object, java.lang.String);
}
ค่าตัวเลือกที่เรียงลำดับจากอ่อนที่สุดไปจนถึงเข้มงวดที่สุดจะมีผลดังนี้
keepไม่ได้เปลี่ยนแปลงการตรวจสอบremove_messageจะเขียนการเรียกใช้เมธอดการตรวจสอบแต่ละรายการใหม่เป็นการเรียกใช้getClass()ในอาร์กิวเมนต์แรกของการเรียกใช้ (ซึ่งจะคงการตรวจสอบค่า Null ไว้ได้อย่างมีประสิทธิภาพ แต่ไม่มีข้อความใดๆ)removeจะนำการตรวจสอบออกโดยสมบูรณ์
โดยค่าเริ่มต้น R8 จะใช้ remove_message ข้อกำหนดใดๆ ของ -processkotlinnullchecks จะลบล้างการตั้งค่านั้น หากระบุหลายครั้ง ระบบจะใช้ค่าที่เข้มงวดที่สุด
หยุดเผยแพร่ข้อมูล Keep ไปยังเมธอดที่ใช้ร่วมกัน
เมื่อกฎการเก็บรักษาตรงกับเมธอดอินเทอร์เฟซที่ต้องผ่านกระบวนการ Desugaring ก่อนหน้านี้ R8 จะโอนบิตไม่อนุญาตการเพิ่มประสิทธิภาพและไม่อนุญาตการลดขนาดภายในไปยังเมธอดที่ใช้ร่วมกันที่สังเคราะห์ขึ้น
ตั้งแต่ AGP 9.0 เป็นต้นไป กฎ Keep จะไม่มีผลกับเมธอด Companion อีกต่อไป ซึ่งสอดคล้องกับข้อเท็จจริงที่ว่ากฎการเก็บรักษาใช้ไม่ได้กับฟิลด์/เมธอด/คลาสอื่นๆ ที่คอมไพเลอร์สังเคราะห์ขึ้น
ก่อนหน้านี้ระบบรองรับ Use Case ต่อไปนี้โดยการโอนบิตไม่อนุญาตการเพิ่มประสิทธิภาพและไม่อนุญาตการลดขนาดไปยังเมธอดที่ใช้ร่วมกัน
- คอมไพล์ไลบรารีที่มีเมธอดอินเทอร์เฟซ
default/static/privateไปยัง DEX ที่มีminSdk< 24 และกฎที่เก็บเมธอดอินเทอร์เฟซไว้ - คอมไพล์แอปด้วยไลบรารีใน classpath และ
-applymapping - ผสานรวมแอปและไลบรารี
โปรดทราบว่าวิธีนี้ใช้ได้กับ -applymapping เท่านั้น เนื่องจากบิต disallow
obfuscation ไม่ได้โอนไปยังเมธอดที่ใช้ร่วมกัน กล่าวคือ คลาสที่ใช้ร่วมกันที่สร้างจากขั้นตอนที่ 1 จะมีชื่อเมธอดที่สร้างความสับสน
นับจากนี้ไป ระบบจะไม่รองรับกรณีการใช้งานนี้สำหรับ minSdk เวอร์ชันต่ำกว่า 24 วิธีแก้ปัญหาชั่วคราวคือทำดังนี้
- Desugar ไลบรารีด้วยเมธอดอินเทอร์เฟซ
default/static/privateไปยังไฟล์คลาสที่มีminSdk< 24 - คอมไพล์อาร์ติแฟกต์ที่ผ่านกระบวนการ Desugaring โดยใช้ R8 และกฎที่เก็บเมธอดอินเทอร์เฟซไว้ในคลาสที่ใช้ร่วมกัน
- คอมไพล์แอปด้วยไลบรารีใน classpath
- รวมแอปและอาร์ติแฟกต์ที่ผ่านกระบวนการ Desugaring
ผลข้างเคียงอีกประการหนึ่งคือไม่สามารถเก็บแอตทริบิวต์คลาสภายในและเมธอดที่ล้อมรอบสำหรับคลาสที่ไม่ระบุชื่อและคลาสโลคัลภายในเมธอด Companion ของอินเทอร์เฟซได้อีกต่อไป
เปลี่ยนไฟล์ต้นฉบับที่ปล่อยออกมาเริ่มต้นเป็น r8-map-id-<MAP_ID>
การเปลี่ยนแปลงนี้อยู่ใน AGP ตั้งแต่เวอร์ชัน 8.12.0 เป็นต้นไป
แอตทริบิวต์ไฟล์ต้นฉบับที่ปล่อยออกมาเริ่มต้นสำหรับคลาสจะเปลี่ยนจาก SourceFile เป็น r8-map-id-<MAP_ID> เมื่อจำเป็นต้องมีการติดตามย้อนกลับ (นั่นคือเมื่อเปิดใช้การสร้างความสับสนหรือการเพิ่มประสิทธิภาพ)
เมื่อมีสแต็กเทรซที่สร้างความสับสน แอตทริบิวต์ไฟล์ต้นฉบับใหม่จะช่วยให้สามารถดึงรหัสของไฟล์การแมปที่จำเป็นสำหรับการติดตามย้อนกลับ ซึ่งสามารถใช้เพื่อรองรับการติดตามย้อนกลับสแต็กเทรซแบบอัตโนมัติใน Logcat
หากใช้แอตทริบิวต์ไฟล์ต้นฉบับที่กำหนดเอง (-renamesourcefileattribute) แอตทริบิวต์ไฟล์ต้นฉบับที่กำหนดเองนี้จะยังคงมีผลเหนือกว่า
ในโหมดความเข้ากันได้ของ ProGuard (เมื่อ gradle.properties มี android.enableR8.fullMode=false) การปล่อยแอตทริบิวต์ไฟล์ต้นฉบับของ r8-map-id-<MAP_ID> จะมีผลก็ต่อเมื่อไม่ได้เก็บแอตทริบิวต์ SourceFile ไว้ แอปที่ใช้โหมดความเข้ากันได้ของ ProGuard และต้องการรวมรหัสไฟล์การแมปไว้ในสแต็กเทรซควรนำ -keepattributes SourceFile ออก (หรือย้ายข้อมูลไปยังโหมดเต็มรูปแบบของ R8)
รหัสแผนที่ที่ใช้ใน r8-map-id-<MAP_ID> คือแฮชแผนที่แบบเต็ม ไม่ใช่คำนำหน้า 7 อักขระของแฮชแผนที่ที่ใช้ก่อนหน้านี้
เปิดใช้ชื่อสังเคราะห์ที่ลดขนาดในการ Desugaring ของ L8
โดยปกติแล้ว ชื่อของคลาสสังเคราะห์ที่สร้างโดย D8 จะมีสตริงย่อย $$ExternalSynthetic ซึ่งบอกให้คุณทราบว่านี่เป็นคลาสสังเคราะห์ที่สร้างโดย D8
นอกจากนี้ ชื่อของ Synthetic ยังเข้ารหัสประเภท Synthetic ด้วย (เช่น Backport, Lambda) ซึ่งส่งผลเสียต่อขนาด DEX ที่ได้ เนื่องจากชื่อคลาสใช้พื้นที่ในพูลสตริงมากกว่า
AGP 9.0 กำหนดค่า L8 (กระบวนการ Desugaring ของไลบรารีหลัก) เพื่อให้ไฟล์ DEX ที่มีคลาส j$ ทั้งหมดใช้รูปแบบชื่อคลาสแบบย่อใหม่สำหรับคลาสสังเคราะห์ ชื่อคลาสใหม่จะใช้รหัสที่เป็นตัวเลข (เช่น $1)
นำการสนับสนุนสำหรับ -addconfigurationdebugging ออก
AGP 9.0 หยุดรองรับ -addconfigurationdebugging แล้ว ตอนนี้คอมไพเลอร์จะรายงานคำเตือนหากมีการใช้แฟล็ก
นำการรองรับการสร้างกฎ L8 ออกจาก D8/R8
การเปลี่ยนแปลงนี้เกี่ยวข้องกับนักพัฒนาแอปที่ใช้บรรทัดคำสั่งหรือ API ของ D8/R8 โดยตรงเท่านั้น
R8 9.0 ยกเลิกการรองรับการสร้างกฎการเก็บรักษาสำหรับ L8 จาก D8 และ R8
คุณควรใช้ TraceReferences เพื่อวัตถุประสงค์นี้แทน
กล่าวอย่างเจาะจงคือ ระบบจะนำเมธอด D8Command.builder.setDesugaredLibraryKeepRuleConsumer และ R8Command.Builder.setDesugaredLibraryKeepRuleConsumer ออก และนำการรองรับ --desugared-lib-pg-conf-output ออกจากตัวเลือกบรรทัดคำสั่งของ D8 และ R8
ปัญหาที่แก้ไขแล้ว
ปลั๊กอิน Android Gradle 9.0.0
| ปัญหาที่แก้ไขแล้ว | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ปลั๊กอิน Android Gradle |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| เครื่องมือวิเคราะห์ซอร์สโค้ด |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| การผสานรวมเครื่องมือวิเคราะห์ซอร์สโค้ด |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Shrinker (R8) |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||