เพิ่มกฎการเก็บรักษา

ในระดับสูง กฎการเก็บจะระบุคลาส (หรือคลาสย่อยหรือการใช้งาน) จากนั้นก็ระบุสมาชิก ซึ่งได้แก่ เมธอด ตัวสร้าง หรือฟิลด์ภายในคลาสนั้นเพื่อเก็บไว้

ไวยากรณ์ทั่วไปสำหรับกฎการเก็บมีดังนี้ แต่ตัวเลือกการเก็บข้อมูลบางอย่างไม่ยอมรับ keep_option_modfier ที่ไม่บังคับ


-<keep_option>[,<keep_option_modifier_1>,<keep_option_modifier_2>,...] <class_specification>

ตัวอย่างต่อไปนี้คือกฎการเก็บที่ใช้ keepclassmembers เป็นตัวเลือกการเก็บ allowoptimization เป็นตัวแก้ไข และเก็บ someSpecificMethod() จาก com.example.MyClass

-keepclassmembers,allowoptimization class com.example.MyClass {
  void someSpecificMethod();
}

ตัวเลือกการเก็บ

ตัวเลือกการเก็บคือส่วนแรกของกฎการเก็บ โดยจะระบุลักษณะของคลาสที่จะเก็บไว้ โดยมีตัวเลือกการเก็บ 6 แบบ ได้แก่ keep, keepclassmembers, keepclasseswithmembers, keepnames, keepclassmembernames, keepclasseswithmembernames

ตารางต่อไปนี้จะอธิบายตัวเลือกการเก็บรักษาเหล่านี้

ตัวเลือก Keep คำอธิบาย
keepclassmembers เก็บเฉพาะสมาชิกที่ระบุไว้หากชั้นเรียนยังคงมีอยู่หลังจากการเพิ่มประสิทธิภาพ
keep คงคลาสและสมาชิก (ฟิลด์และเมธอด) ที่ระบุไว้ เพื่อป้องกันไม่ให้มีการเพิ่มประสิทธิภาพ

หมายเหตุ: โดยทั่วไปแล้ว keep ควรใช้กับตัวแก้ไขตัวเลือกการคงค่าเท่านั้น เนื่องจาก keep เพียงอย่างเดียวจะป้องกันไม่ให้มีการเพิ่มประสิทธิภาพใดๆ ในคลาสที่ตรงกัน
keepclasseswithmembers เก็บรักษาชั้นเรียนและสมาชิกที่ระบุไว้เฉพาะในกรณีที่ชั้นเรียนมีสมาชิกทั้งหมดตามที่ระบุไว้ในชั้นเรียน
keepclassmembernames ป้องกันไม่ให้เปลี่ยนชื่อสมาชิกในชั้นเรียนที่ระบุ แต่ไม่ได้ป้องกันไม่ให้นำชั้นเรียนหรือสมาชิกออก

หมายเหตุ: ผู้ใช้มักเข้าใจความหมายของตัวเลือกนี้ผิด ให้ลองใช้ -keepclassmembers,allowshrinking ที่เทียบเท่าแทน
keepnames ป้องกันการเปลี่ยนชื่อชั้นเรียนและสมาชิก แต่ไม่ได้ป้องกันไม่ให้ระบบนำชั้นเรียนและสมาชิกออกทั้งหมดหากเห็นว่าไม่ได้ใช้งาน

หมายเหตุ: ผู้ใช้มักเข้าใจความหมายของตัวเลือกนี้ผิด ให้ลองใช้ -keep,allowshrinking ที่เทียบเท่าแทน
keepclasseswithmembernames ป้องกันการเปลี่ยนชื่อชั้นเรียนและสมาชิกที่ระบุ แต่จะทำได้ก็ต่อเมื่อสมาชิกอยู่ในโค้ดสุดท้าย แต่ไม่ได้ป้องกันการนำโค้ดออก

หมายเหตุ: มักจะมีการเข้าใจความหมายของตัวเลือกนี้ผิด ให้ลองใช้ -keepclasseswithmembers,allowshrinking ที่เทียบเท่าแทน

เลือกตัวเลือกการเก็บที่เหมาะสม

การเลือกตัวเลือกการเก็บที่เหมาะสมเป็นสิ่งสำคัญในการกำหนดการเพิ่มประสิทธิภาพที่เหมาะสม สำหรับแอปของคุณ ตัวเลือกการเก็บบางอย่างจะลดขนาดโค้ด ซึ่งเป็นกระบวนการที่ โค้ดที่ไม่ได้อ้างอิงจะถูกนำออก ในขณะที่ตัวเลือกอื่นๆ จะทำให้โค้ดสับสนหรือเปลี่ยนชื่อโค้ด ตารางต่อไปนี้แสดงการดำเนินการของตัวเลือกการเก็บรักษาต่างๆ

ตัวเลือก Keep ลดขนาดคลาส ปิดบังคลาส ลดจำนวนสมาชิก ซ่อนสมาชิก
keep
keepclassmembers
keepclasseswithmembers
keepnames
keepclassmembernames
keepclasseswithmembernames

ตัวปรับแต่งตัวเลือก Keep

ตัวแก้ไขตัวเลือกการเก็บจะใช้เพื่อควบคุมขอบเขตและลักษณะการทำงานของกฎการเก็บ คุณสามารถเพิ่มตัวแก้ไขตัวเลือก keep 0 รายการขึ้นไปลงในกฎการเก็บรักษา

ค่าที่เป็นไปได้สำหรับตัวแก้ไขตัวเลือกการเก็บจะอธิบายไว้ในตารางต่อไปนี้

ค่านิยม คำอธิบาย
allowoptimization อนุญาตให้เพิ่มประสิทธิภาพองค์ประกอบที่ระบุ อย่างไรก็ตาม ระบบจะไม่เปลี่ยนชื่อหรือนำองค์ประกอบที่ระบุออก
allowobfucastion อนุญาตให้เปลี่ยนชื่อองค์ประกอบที่ระบุ อย่างไรก็ตาม จะไม่มีการนำองค์ประกอบออกหรือเพิ่มประสิทธิภาพองค์ประกอบ
allowshrinking อนุญาตให้นำองค์ประกอบที่ระบุออกได้หาก R8 ไม่พบการอ้างอิงถึงองค์ประกอบเหล่านั้น อย่างไรก็ตาม ระบบจะไม่เปลี่ยนชื่อหรือเพิ่มประสิทธิภาพองค์ประกอบ
includedescriptorclasses สั่งให้ R8 เก็บรักษาคลาสทั้งหมดที่ปรากฏในตัวอธิบายของเมธอด (ประเภทพารามิเตอร์และประเภทการคืนค่า) และฟิลด์ (ประเภทฟิลด์) ที่จะเก็บไว้
allowaccessmodification อนุญาตให้ R8 เปลี่ยน (โดยปกติคือขยาย) ตัวแก้ไขการเข้าถึง (public, private, protected) ของคลาส เมธอด และฟิลด์ในระหว่างกระบวนการเพิ่มประสิทธิภาพ
allowrepackage อนุญาตให้ R8 ย้ายคลาสไปยังแพ็กเกจต่างๆ รวมถึงแพ็กเกจเริ่มต้น (รูท)

ข้อกำหนดของชั้นเรียน

คุณต้องระบุคลาส คลาสแม่ หรืออินเทอร์เฟซที่ติดตั้งใช้งานเป็นส่วนหนึ่งของกฎ keep ต้องระบุคลาสทั้งหมด รวมถึงคลาสจากเนมสเปซ java.lang เช่น java.lang.String โดยใช้ชื่อ Java ที่สมบูรณ์ หากต้องการ ทำความเข้าใจชื่อที่ควรใช้ ให้ตรวจสอบไบต์โค้ดโดยใช้เครื่องมือ ที่อธิบายไว้ในรับชื่อ Java ที่สร้างขึ้น

ตัวอย่างต่อไปนี้แสดงวิธีระบุคลาส MaterialButton

  • ถูกต้อง: com.google.android.material.button.MaterialButton
  • ไม่ถูกต้อง: MaterialButton

นอกจากนี้ ข้อมูลจำเพาะของชั้นเรียนยังระบุสมาชิกในชั้นเรียนที่ ควรเก็บไว้ด้วย กฎต่อไปนี้จะเก็บคลาส MaterialButton และสมาชิกทั้งหมดไว้

-keep class com.google.android.material.button.MaterialButton { *; }

คลาสย่อยและการใช้งาน

หากต้องการกำหนดเป้าหมายไปยังคลาสย่อยหรือคลาสที่ใช้การติดตั้งใช้งานอินเทอร์เฟซ ให้ใช้ extend และ implements ตามลำดับ

ตัวอย่างเช่น หากคุณมีคลาส Bar ที่มีคลาสย่อย Foo ดังนี้

class Foo : Bar()

กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาสับคลาสทั้งหมดของ Bar โปรดทราบว่า กฎ keep ไม่รวมคลาสหลัก Bar เอง

-keep class * extends Bar

หากคุณมีคลาส Foo ที่ใช้ Bar ให้ทำดังนี้

class Foo : Bar

กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาคลาสทั้งหมดที่ใช้ Bar โปรดทราบว่า กฎการเก็บรักษาไม่ได้รวมอินเทอร์เฟซ Bar เอง

-keep class * implements Bar

ตัวแก้ไขการเข้าถึง

คุณระบุตัวแก้ไขการเข้าถึง เช่น public, private, static และ final เพื่อให้กฎการเก็บรักษาแม่นยำยิ่งขึ้นได้

ตัวอย่างเช่น กฎต่อไปนี้จะเก็บคลาส public ทั้งหมดไว้ในแพ็กเกจ api และแพ็กเกจย่อย รวมถึงสมาชิกแบบสาธารณะและแบบป้องกันทั้งหมดในคลาสเหล่านี้

-keep public class com.example.api.** { public protected *; }

นอกจากนี้ คุณยังใช้ตัวแก้ไขสำหรับสมาชิกในชั้นเรียนได้ด้วย ตัวอย่างเช่น กฎต่อไปนี้จะเก็บเฉพาะpublic staticเมธอดของคลาส Utils

-keep class com.example.Utils {
    public static void *(...);
}

ตัวแก้ไขเฉพาะ Kotlin

R8 ไม่รองรับตัวแก้ไขเฉพาะของ Kotlin เช่น internal และ suspend โปรดใช้หลักเกณฑ์ต่อไปนี้เพื่อเก็บช่องดังกล่าว

  • หากต้องการเก็บ internal คลาส เมธอด หรือฟิลด์ ให้ถือว่าเป็นแบบสาธารณะ ตัวอย่างเช่น ลองพิจารณาแหล่งที่มาของ Kotlin ต่อไปนี้

    package com.example
    internal class ImportantInternalClass {
      internal f: Int
      internal fun m() {}
    }
    

    คลาส เมธอด และฟิลด์ internal จะเป็น public ในไฟล์ที่คอมไพเลอร์ Kotlin สร้างขึ้น ดังนั้นคุณต้องใช้คีย์เวิร์ด public ตามที่แสดงในตัวอย่างต่อไปนี้ .class

    -keepclassmembers public class com.example.ImportantInternalClass {
      public int f;
      public void m();
    }
    
  • เมื่อรวบรวมsuspendสมาชิก ให้จับคู่ลายเซ็นที่รวบรวมไว้ใน กฎการเก็บรักษา

    เช่น หากคุณมีฟังก์ชัน fetchUser ที่กำหนดตามที่แสดงใน ข้อมูลโค้ดต่อไปนี้

    suspend fun fetchUser(id: String): User
    

    เมื่อคอมไพล์แล้ว ลายเซ็นในไบต์โค้ดจะมีลักษณะดังนี้

    public final Object fetchUser(String id, Continuation<? super User> continuation);
    

    หากต้องการเขียนกฎการเก็บรักษาสำหรับฟังก์ชันนี้ คุณต้องจับคู่ลายเซ็นที่คอมไพล์นี้ หรือใช้ ...

    ตัวอย่างการใช้ลายเซ็นที่คอมไพล์แล้วมีดังนี้

    -keepclassmembers class com.example.repository.UserRepository {
    public java.lang.Object fetchUser(java.lang.String,  kotlin.coroutines.Continuation);
    }
    

    ตัวอย่างการใช้ ... มีดังนี้

    -keepclassmembers class com.example.repository.UserRepository {
    public java.lang.Object fetchUser(...);
    }
    

ข้อกำหนดของสมาชิก

การระบุคลาสอาจรวมถึงสมาชิกของคลาสที่จะเก็บไว้ด้วย (ไม่บังคับ) หากคุณระบุสมาชิกอย่างน้อย 1 คนสำหรับชั้นเรียน กฎจะมีผลกับสมาชิกเหล่านั้นเท่านั้น

ตัวอย่างเช่น หากต้องการเก็บรักษาชั้นเรียนที่เฉพาะเจาะจงและสมาชิกทั้งหมด ให้ใช้คำสั่งต่อไปนี้

-keep class com.myapp.MyClass { *; }

หากต้องการเก็บรักษาเฉพาะชั้นเรียนและไม่รวมสมาชิก ให้ใช้คำสั่งต่อไปนี้

-keep class com.myapp.MyClass

โดยส่วนใหญ่แล้ว คุณจะต้องระบุสมาชิกบางราย ตัวอย่างเช่น ตัวอย่างต่อไปนี้จะเก็บฟิลด์สาธารณะ text และเมธอดสาธารณะ updateText() ไว้ในคลาส MyClass

-keep class com.myapp.MyClass {
    public java.lang.String text;
    public void updateText(java.lang.String);
}

หากต้องการเก็บฟิลด์และเมธอดสาธารณะทั้งหมดไว้ ให้ดูตัวอย่างต่อไปนี้

-keep public class com.example.api.ApiClient {
    public *;
}

วิธีการ

ไวยากรณ์สำหรับการระบุวิธีการในการระบุสมาชิกสำหรับกฎการเก็บมีดังนี้

[<access_modifier>] [<return_type>] <method_name>(<parameter_types>);

ตัวอย่างเช่น กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาวิธีการสาธารณะที่ชื่อ setLabel() ซึ่งแสดงผลเป็น void และรับ String

-keep class com.example.MyView {
    public void setLabel(java.lang.String);
}

คุณใช้ <methods> เป็นแป้นพิมพ์ลัดเพื่อจับคู่เมธอดทั้งหมดในคลาสได้ดังนี้

-keep class com.example.MyView {
    <methods>;
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีระบุประเภทสำหรับประเภทการคืนค่าและประเภทพารามิเตอร์ได้ที่ประเภท

ผู้ผลิต

หากต้องการระบุตัวสร้าง ให้ใช้ <init> ไวยากรณ์สำหรับการระบุตัวสร้าง ในข้อกำหนดของสมาชิกสำหรับกฎการเก็บมีดังนี้

[<access_modifier>] <init>(parameter_types);

ตัวอย่างเช่น กฎการเก็บรักษาต่อไปนี้จะเก็บตัวสร้าง View ที่กำหนดเองซึ่ง รับ Context และ AttributeSet

-keep class com.example.ui.MyCustomView {
    public <init>(android.content.Context, android.util.AttributeSet);
}

หากต้องการเก็บตัวสร้างสาธารณะทั้งหมด ให้ใช้ตัวอย่างต่อไปนี้เป็นข้อมูลอ้างอิง

-keep class com.example.ui.MyCustomView {
    public <init>(...);
}

ช่อง

ไวยากรณ์สำหรับการระบุฟิลด์ในข้อกำหนดของสมาชิกสำหรับกฎการเก็บมีลักษณะดังนี้

[<access_modifier>...] [<type>] <field_name>;

เช่น กฎ keep ต่อไปนี้จะเก็บฟิลด์สตริงส่วนตัวที่ชื่อ userId และฟิลด์จำนวนเต็มแบบคงที่สาธารณะที่ชื่อ STATUS_ACTIVE

-keep class com.example.models.User {
    private java.lang.String userId;
    public static int STATUS_ACTIVE;
}

คุณใช้ <fields> เป็นทางลัดเพื่อจับคู่ช่องทั้งหมดในชั้นเรียนได้ดังนี้

-keep class com.example.models.User {
    <fields>;
}

ฟังก์ชันระดับแพ็กเกจ

หากต้องการอ้างอิงฟังก์ชัน Kotlin ที่กำหนดไว้นอกคลาส (โดยทั่วไปเรียกว่าฟังก์ชันระดับบนสุด) ให้ตรวจสอบว่าได้ใช้ชื่อ Java ที่สร้างขึ้นสำหรับคลาสที่คอมไพเลอร์ Kotlin เพิ่มโดยนัย ชื่อคลาสคือชื่อไฟล์ Kotlin ที่ต่อท้ายด้วย Kt ตัวอย่างเช่น หากคุณมีไฟล์ Kotlin ชื่อ MyClass.kt ที่กำหนดไว้ดังนี้

package com.example.myapp.utils

// A top-level function not inside a class
fun isEmailValid(email: String): Boolean {
    return email.contains("@")
}

หากต้องการเขียนกฎการเก็บสำหรับฟังก์ชัน isEmailValid ข้อกำหนดของคลาส ต้องกำหนดเป้าหมายเป็นคลาส MyClassKt ที่สร้างขึ้น

-keep class com.example.myapp.utils.MyClassKt {
    public static boolean isEmailValid(java.lang.String);
}

ประเภท

ส่วนนี้จะอธิบายวิธีระบุประเภทการคืนค่า ประเภทพารามิเตอร์ และประเภทฟิลด์ในข้อกำหนดของสมาชิกกฎการเก็บรักษา อย่าลืมใช้ชื่อ Java ที่สร้างขึ้นเพื่อระบุ ประเภทหากแตกต่างจากซอร์สโค้ด Kotlin

ประเภทดั้งเดิม

หากต้องการระบุประเภทดั้งเดิม ให้ใช้คีย์เวิร์ด Java ของประเภทนั้น R8 จะรู้จักประเภทข้อมูลพื้นฐานต่อไปนี้ boolean, byte, short, char, int, long, float, double

ตัวอย่างกฎที่มีประเภทดั้งเดิมมีดังนี้

# Keeps a method that takes an int and a float as parameters.
-keepclassmembers class com.example.Calculator {
    public void setValues(int, float);
}

ประเภททั่วไป

ในระหว่างการคอมไพล์ คอมไพลเลอร์ Kotlin/Java จะลบข้อมูลประเภททั่วไป ดังนั้นเมื่อเขียนกฎ keep ที่เกี่ยวข้องกับประเภททั่วไป คุณต้องกำหนดเป้าหมายเป็นการแสดงที่คอมไพล์แล้วของโค้ด ไม่ใช่ซอร์สโค้ดเดิม ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเปลี่ยนประเภททั่วไปได้ที่การลบประเภท

ตัวอย่างเช่น หากคุณมีโค้ดต่อไปนี้ที่มีประเภททั่วไปแบบไม่จำกัด ซึ่งกำหนดไว้ใน Box.kt

package com.myapp.data

class Box<T>(val item: T) {
    fun getItem(): T {
        return item
    }
}

หลังจากลบประเภทแล้ว T จะถูกแทนที่ด้วย Object หากต้องการเก็บตัวสร้างและเมธอดของคลาส ไว้ กฎของคุณต้องใช้ java.lang.Object แทนT ทั่วไป

ตัวอย่างกฎการเก็บรักษาจะเป็นดังนี้

# Keep the constructor and methods of the Box class.
-keep class com.myapp.data.Box {
    public init(java.lang.Object);
    public java.lang.Object getItem();
}

หากคุณมีโค้ดต่อไปนี้ที่มีประเภททั่วไปที่จำกัดใน NumberBox.kt

package com.myapp.data

// T is constrained to be a subtype of Number
class NumberBox<T : Number>(val number: T)

ในกรณีนี้ การลบแบบพิมพ์จะแทนที่ T ด้วยขอบเขตของ java.lang.Number

ตัวอย่างกฎการเก็บรักษาจะเป็นดังนี้

-keep class com.myapp.data.NumberBox {
    public init(java.lang.Number);
}

เมื่อใช้ประเภททั่วไปเฉพาะแอปเป็นคลาสฐาน คุณจะต้อง รวมกฎการเก็บสำหรับคลาสฐานด้วย

เช่น สำหรับโค้ดต่อไปนี้

package com.myapp.data

data class UnpackOptions(val useHighPriority: Boolean)

// The generic Box class with UnpackOptions as the bounded type
class Box<T: UnpackOptions>(val item: T) {
}

คุณใช้กฎการเก็บรักษาด้วย includedescriptorclasses เพื่อเก็บรักษาทั้งคลาส UnpackOptions และเมธอดของคลาส Box ด้วยกฎเดียวได้ดังนี้

-keep,includedescriptorclasses class com.myapp.data.Box {
    public <init>(com.myapp.data.UnpackOptions);
}

หากต้องการเก็บฟังก์ชันที่เฉพาะเจาะจงซึ่งประมวลผลรายการออบเจ็กต์ คุณต้องเขียนกฎที่ตรงกับลายเซ็นของฟังก์ชันอย่างแม่นยำ โปรดทราบว่าเนื่องจากมีการลบประเภททั่วไป พารามิเตอร์อย่าง List<Product> จึงถือเป็น java.util.List

ตัวอย่างเช่น หากคุณมีคลาสยูทิลิตีที่มีฟังก์ชันที่ประมวลผลรายการ ของออบเจ็กต์ Product ดังนี้

package com.myapp.utils

import com.myapp.data.Product
import android.util.Log

class DataProcessor {
    // This is the function we want to keep
    fun processProducts(products: List<Product>) {
        Log.d("DataProcessor", "Processing ${products.size} products.")
        // Business logic ...
    }
}

// The data class used in the list (from the previous example)
package com.myapp.data
data class Product(val id: String, val name: String)

คุณสามารถใช้กฎการเก็บรักษาต่อไปนี้เพื่อปกป้องเฉพาะprocessProducts ฟังก์ชันได้

-keep class com.myapp.utils.DataProcessor {
    public void processProducts(java.util.List);
}

ประเภทอาร์เรย์

ระบุประเภทอาร์เรย์โดยต่อท้าย [] กับประเภทคอมโพเนนต์สำหรับแต่ละมิติข้อมูล ของอาร์เรย์ ซึ่งมีผลกับทั้งประเภทคลาสและประเภทดั้งเดิม

  • อาร์เรย์คลาสแบบมิติเดียว: java.lang.String[]
  • อาร์เรย์ดั้งเดิมแบบ 2 มิติ: int[][]

ตัวอย่างเช่น หากคุณมีโค้ดต่อไปนี้

package com.example.data

class ImageProcessor {
  fun process(): ByteArray {
    // process image to return a byte array
  }
}

คุณสามารถใช้กฎการเก็บรักษาต่อไปนี้

# Keeps a method that returns a byte array.
-keepclassmembers class com.example.data.ImageProcessor {
    public byte[] process();
}

ไวลด์การ์ด

ตารางต่อไปนี้แสดงวิธีใช้อักขระไวด์การ์ดเพื่อใช้กฎการเก็บกับคลาสหรือสมาชิกหลายรายการที่ตรงกับรูปแบบหนึ่งๆ

สัญลักษณ์แทน ใช้กับชั้นเรียนหรือสมาชิก คำอธิบาย
** ทั้งคู่ ใช้บ่อยที่สุด ตรงกับชื่อประเภทใดก็ได้ รวมถึงตัวคั่นแพ็กเกจจำนวนเท่าใดก็ได้ ซึ่งจะมีประโยชน์ในการจับคู่คลาสทั้งหมดภายในแพ็กเกจและแพ็กเกจย่อย
* ทั้งคู่ สำหรับข้อกำหนดของคลาส จะตรงกับส่วนใดก็ได้ของชื่อประเภทที่ไม่มีตัวคั่นแพ็กเกจ (.)
สำหรับข้อกำหนดของสมาชิก จะตรงกับชื่อเมธอดหรือฟิลด์ใดก็ได้ เมื่อใช้เพียงอย่างเดียว ก็จะเป็นชื่อแทนของ ** ด้วย
? ทั้งคู่ จับคู่อักขระเดียวในชื่อคลาสหรือชื่อสมาชิก
*** สมาชิก ตรงกับประเภทใดก็ได้ รวมถึงประเภทดั้งเดิม (เช่น int) ประเภทคลาส (เช่น java.lang.String) และประเภทอาร์เรย์ของมิติข้อมูลใดก็ได้ (เช่น byte[][])
... สมาชิก จับคู่รายการพารามิเตอร์ใดก็ได้สำหรับเมธอด
% สมาชิก ตรงกับประเภทดั้งเดิมใดก็ได้ (เช่น `int`, `float`, `boolean` หรืออื่นๆ)

ตัวอย่างวิธีใช้ไวลด์การ์ดพิเศษมีดังนี้

  • หากคุณมีหลายวิธีที่มีชื่อเดียวกันซึ่งใช้ประเภทดั้งเดิมที่แตกต่างกันเป็นอินพุต คุณสามารถใช้ % เพื่อเขียนกฎการเก็บที่จะเก็บทั้งหมดไว้ เช่น คลาส DataStore นี้มีเมธอด setValue หลายรายการ

    class DataStore {
        fun setValue(key: String, value: Int) { ... }
        fun setValue(key: String, value: Boolean) { ... }
        fun setValue(key: String, value: Float) { ... }
    }
    

    กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาวิธีการทั้งหมด

    -keep class com.example.DataStore {
        public void setValue(java.lang.String, %);
    }
    
  • หากคุณมีหลายชั้นเรียนที่มีชื่อต่างกันเพียง 1 อักขระ ให้ใช้ ? เพื่อเขียนกฎการเก็บที่เก็บชั้นเรียนทั้งหมดไว้ เช่น หากคุณมีคลาสต่อไปนี้

    com.example.models.UserV1 {...}
    com.example.models.UserV2 {...}
    com.example.models.UserV3 {...}
    

    กฎการเก็บรักษาต่อไปนี้จะเก็บรักษาชั้นเรียนทั้งหมด

    -keep class com.example.models.UserV?
    
  • หากต้องการจับคู่คลาส Example และ AnotherExample (หากเป็นคลาสระดับรูท) แต่ไม่จับคู่ com.foo.Example ให้ใช้กฎการเก็บรักษาต่อไปนี้

    -keep class *Example
    
  • หากคุณใช้ * เพียงอย่างเดียว ระบบจะถือว่าเครื่องหมายนี้เป็นชื่อแทนของ ** ตัวอย่างเช่น กฎการเก็บข้อมูลต่อไปนี้จะมีความหมายเหมือนกัน

    -keepclasseswithmembers class * { public static void main(java.lang.String[];) }
    
    -keepclasseswithmembers class ** { public static void main(java.lang.String[];) }
    

ตรวจสอบชื่อ Java ที่สร้างขึ้น

เมื่อเขียนกฎการเก็บรักษา คุณต้องระบุคลาสและประเภทอ้างอิงอื่นๆ โดยใช้ชื่อหลังจากที่คอมไพล์เป็น Java bytecode แล้ว (ดูตัวอย่างได้ในข้อกำหนดของคลาสและประเภท) หากต้องการตรวจสอบชื่อ Java ที่สร้างขึ้นสำหรับโค้ด ให้ใช้เครื่องมือใดเครื่องมือหนึ่งต่อไปนี้ใน Android Studio

  • ตัววิเคราะห์ APK
  • เมื่อเปิดไฟล์ต้นฉบับ Kotlin แล้ว ให้ตรวจสอบไบต์โค้ดโดยไปที่เครื่องมือ > Kotlin > แสดงไบต์โค้ด Kotlin > แยก