রাখার নিয়ম যোগ করুন

উচ্চ স্তরে, একটি কিপ নিয়ম একটি শ্রেণী (অথবা উপশ্রেণী বা বাস্তবায়ন) নির্দিষ্ট করে, এবং তারপর সদস্যদের - পদ্ধতি, কনস্ট্রাক্টর, বা ক্ষেত্র - সেই শ্রেণীর মধ্যে সংরক্ষণের জন্য।

কিপ রুলের সাধারণ বাক্য গঠন নিম্নরূপ:


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

নিচে একটি keep নিয়মের উদাহরণ দেওয়া হল যা keep অপশন হিসেবে keepclassmembers ব্যবহার করে, modifier হিসেবে allowoptimization ব্যবহার করে এবং com.example.MyClass থেকে someSpecificMethod() ব্যবহার করে:

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

রাখার বিকল্প

keep অপশনটি হল আপনার keep রুলের প্রথম অংশ। এটি নির্দিষ্ট করে যে একটি ক্লাসের কোন দিকগুলি সংরক্ষণ করতে হবে। keep এর ছয়টি ভিন্ন অপশন রয়েছে, যথা keep , keepclassmembers , keepclasseswithmembers , keepnames , keepclassmembernames , keepclasseswithmembernames

নিম্নলিখিত টেবিলে এই কিপ অপশনগুলি বর্ণনা করা হয়েছে:

রাখার বিকল্প বিবরণ
keepclassmembers অপ্টিমাইজেশনের পরে যদি ক্লাসটি বিদ্যমান থাকে তবেই নির্দিষ্ট সদস্যদের সংরক্ষণ করে।
keep নির্দিষ্ট ক্লাস এবং নির্দিষ্ট সদস্যদের (ক্ষেত্র এবং পদ্ধতি) সংরক্ষণ করে, তাদের অপ্টিমাইজ করা থেকে বিরত রাখে।

দ্রষ্টব্য : keep সাধারণত শুধুমাত্র keep অপশন মডিফায়ারের সাথে ব্যবহার করা উচিত কারণ keep নিজেই মিলে যাওয়া ক্লাসগুলিতে যেকোনো ধরণের অপ্টিমাইজেশন ঘটতে বাধা দেয়।
keepclasseswithmembers একটি ক্লাস এবং তার নির্দিষ্ট সদস্যদের সংরক্ষণ করে শুধুমাত্র যদি ক্লাসে ক্লাস স্পেসিফিকেশনের সমস্ত সদস্য থাকে।
keepclassmembernames নির্দিষ্ট শ্রেণীর সদস্যদের নাম পরিবর্তন করা রোধ করে, কিন্তু শ্রেণী বা এর সদস্যদের অপসারণ থেকে রোধ করে না।

দ্রষ্টব্য: এই বিকল্পটির অর্থ প্রায়শই ভুল বোঝাবুঝি হয়; এর পরিবর্তে -keepclassmembers,allowshrinking সমতুল্য ব্যবহার করার কথা বিবেচনা করুন।
keepnames ক্লাস এবং তাদের সদস্যদের নাম পরিবর্তন করা রোধ করে, কিন্তু যদি সেগুলি অব্যবহৃত বলে মনে করা হয় তবে এটি সম্পূর্ণরূপে অপসারণ করা থেকে বিরত রাখে না।

দ্রষ্টব্য: এই বিকল্পটির অর্থ প্রায়শই ভুল বোঝাবুঝি হয়; এর পরিবর্তে -keep,allowshrinking সমতুল্য ব্যবহার করার কথা বিবেচনা করুন।
keepclasseswithmembernames ক্লাস এবং তাদের নির্দিষ্ট সদস্যদের নাম পরিবর্তন করা রোধ করে, তবে শুধুমাত্র যদি সদস্যরা চূড়ান্ত কোডে বিদ্যমান থাকে। এটি কোড অপসারণকে বাধা দেয় না।

দ্রষ্টব্য: এই বিকল্পটির অর্থ প্রায়শই ভুল বোঝাবুঝি হয়; এর পরিবর্তে সমতুল্য -keepclasseswithmembers,allowshrinking ব্যবহার করার কথা বিবেচনা করুন।

সঠিক কিপ অপশনটি বেছে নিন

আপনার অ্যাপের জন্য সঠিক অপ্টিমাইজেশন নির্ধারণের জন্য সঠিক কিপ অপশনটি নির্বাচন করা অত্যন্ত গুরুত্বপূর্ণ। কিছু কিপ অপশন কোড সঙ্কুচিত করে, একটি প্রক্রিয়া যার মাধ্যমে অ-রেফারেন্সড কোড সরানো হয়, অন্যরা কোডকে অস্পষ্ট করে, বা পুনঃনামকরণ করে। নিম্নলিখিত টেবিলটি বিভিন্ন কিপ অপশনের ক্রিয়াগুলি নির্দেশ করে:

রাখার বিকল্প শ্রেণী সঙ্কুচিত করে ক্লাসগুলিকে অস্পষ্ট করে সদস্যদের সঙ্কুচিত করে সদস্যদের অস্পষ্ট করে তোলে
keep
keepclassmembers
keepclasseswithmembers
keepnames
keepclassmembernames
keepclasseswithmembernames

অপশন মডিফায়ার রাখুন

একটি কিপ রুলের সুযোগ এবং আচরণ নিয়ন্ত্রণ করতে একটি কিপ অপশন মডিফায়ার ব্যবহার করা হয়। আপনি আপনার কিপ রুলে 0 বা তার বেশি কিপ অপশন মডিফায়ার যোগ করতে পারেন।

একটি কিপ অপশন মডিফায়ারের সম্ভাব্য মানগুলি নিম্নলিখিত টেবিলে বর্ণনা করা হয়েছে:

মূল্য বিবরণ
allowoptimization নির্দিষ্ট উপাদানগুলির অপ্টিমাইজেশনের অনুমতি দেয়। তবে, নির্দিষ্ট উপাদানগুলির নাম পরিবর্তন বা সরানো হয় না।
allowobfucastion নির্দিষ্ট উপাদানগুলির নাম পরিবর্তন করার অনুমতি দেয়। তবে, উপাদানগুলি সরানো বা অন্যথায় অপ্টিমাইজ করা হয় না।
allowshrinking R8 যদি নির্দিষ্ট উপাদানগুলির কোনও উল্লেখ না পায় তবে সেগুলি অপসারণের অনুমতি দেয়। তবে, উপাদানগুলির নাম পরিবর্তন করা হয় না বা অন্যথায় অপ্টিমাইজ করা হয় না।
includedescriptorclasses R8 কে নির্দেশ দেয় যে পদ্ধতিগুলির বর্ণনাকারীতে প্রদর্শিত সমস্ত ক্লাস (প্যারামিটার প্রকার এবং রিটার্ন প্রকার) এবং ক্ষেত্রগুলি (ক্ষেত্রের প্রকার) রাখা হচ্ছে।
allowaccessmodification অপ্টিমাইজেশন প্রক্রিয়ার সময় R8 কে ক্লাস, পদ্ধতি এবং ক্ষেত্রের অ্যাক্সেস মডিফায়ার ( public , private , protected ) পরিবর্তন (সাধারণত প্রশস্ত) করার অনুমতি দেয়।
allowrepackage R8 কে ডিফল্ট (রুট) প্যাকেজ সহ বিভিন্ন প্যাকেজে ক্লাস স্থানান্তর করার অনুমতি দেয়।

ক্লাস স্পেসিফিকেশন

প্রতিটি কিপ রুলে আপনাকে অবশ্যই একটি ক্লাস (ইন্টারফেস, এনাম এবং অ্যানোটেশন ক্লাস সহ) নির্দিষ্ট করতে হবে। আপনি ঐচ্ছিকভাবে টীকাগুলির উপর ভিত্তি করে নিয়মটি সীমাবদ্ধ করতে পারেন, অথবা একটি সুপারক্লাস বা বাস্তবায়িত ইন্টারফেস নির্দিষ্ট করে। java.lang নেমস্পেস থেকে ক্লাস সহ সমস্ত ক্লাস, যেমন java.lang.String , তাদের সম্পূর্ণরূপে যোগ্য জাভা নাম ব্যবহার করে নির্দিষ্ট করতে হবে। কোন নামগুলি ব্যবহার করা উচিত তা বুঝতে, Inspect generated Java names -এ বর্ণিত টুলগুলি ব্যবহার করে বাইটকোডটি পরীক্ষা করুন।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে আপনার MaterialButton ক্লাস নির্দিষ্ট করা উচিত:

  • সঠিক: com.google.android.material.button.MaterialButton
  • ভুল: MaterialButton

ক্লাস স্পেসিফিকেশনগুলি একটি ক্লাসের মধ্যে থাকা সদস্যদেরও নির্দিষ্ট করে যা রাখা উচিত। নিম্নলিখিত নিয়মটি MaterialButton ক্লাস এবং এর সমস্ত সদস্যকে ধরে রাখে:

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

টীকাগুলির উপর ভিত্তি করে ক্লাস নির্দিষ্ট করুন

টীকাগুলির উপর ভিত্তি করে ক্লাস নির্দিষ্ট করতে, টীকাটির সম্পূর্ণরূপে যোগ্য জাভা নামের পূর্বে @ চিহ্ন যুক্ত করুন। উদাহরণস্বরূপ:

-keep class @com.example.MyAnnotation com.example.MyClass

যদি একটি keep নিয়মে একাধিক টীকা থাকে, তাহলে এটি এমন ক্লাসগুলিকে রাখে যেখানে তালিকাভুক্ত সমস্ত টীকা থাকে। আপনি একাধিক টীকা তালিকাভুক্ত করতে পারেন, তবে নিয়মটি কেবল তখনই প্রযোজ্য যদি ক্লাসটিতে প্রতিটি তালিকাভুক্ত টীকা থাকে। উদাহরণস্বরূপ, নিম্নলিখিত নিয়মটি সমস্ত ক্লাসকে টীকাযুক্ত রাখে Annotation1 এবং Annotation2 উভয় দ্বারা।

-keep class @com.example.Annotation1 @com.example.Annotation2 *

সাবক্লাস এবং বাস্তবায়ন নির্দিষ্ট করুন

একটি সাবক্লাস, অথবা একটি ইন্টারফেস বাস্তবায়নকারী ক্লাসকে লক্ষ্য করতে, যথাক্রমে extend এবং implements ব্যবহার করুন।

উদাহরণস্বরূপ, যদি আপনার ক্লাস Bar থাকে এবং সাবক্লাস Foo থাকে তাহলে নিম্নরূপ:

class Foo : Bar()

নিম্নলিখিত keep নিয়মটি Bar এর সকল উপশ্রেণী সংরক্ষণ করে। মনে রাখবেন যে keep নিয়মে সুপারক্লাস Bar অন্তর্ভুক্ত নয়।

-keep class * extends Bar

যদি আপনার Foo ক্লাস থাকে যা ইন্টারফেস Bar প্রয়োগ করে:

class Foo : Bar

নিম্নলিখিত keep নিয়মটি Bar বাস্তবায়নকারী সকল ক্লাস সংরক্ষণ করে। মনে রাখবেন যে keep নিয়মে ইন্টারফেস Bar অন্তর্ভুক্ত নয়।

-keep class * implements Bar

অ্যাক্সেস মডিফায়ার

আপনার কিপ রুলসকে আরও সুনির্দিষ্ট করার জন্য আপনি অ্যাক্সেস মডিফায়ার যেমন public , private , static , এবং final নির্দিষ্ট করতে পারেন।

উদাহরণস্বরূপ, নিম্নলিখিত নিয়মটি api প্যাকেজ এবং এর সাব-প্যাকেজগুলির মধ্যে সমস্ত public ক্লাস এবং এই ক্লাসগুলির সমস্ত পাবলিক এবং সুরক্ষিত সদস্যদের রাখে।

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

আপনি একটি ক্লাসের সদস্যদের জন্য মডিফায়ারও ব্যবহার করতে পারেন। উদাহরণস্বরূপ, নিম্নলিখিত নিয়মটি শুধুমাত্র একটি Utils ক্লাসের public static পদ্ধতিগুলিকে ধরে রাখে:

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

কোটলিন-নির্দিষ্ট সংশোধক

R8 কোটলিন-নির্দিষ্ট মডিফায়ার যেমন internal এবং suspend সমর্থন করে না। এই ধরনের ক্ষেত্রগুলি রাখার জন্য নিম্নলিখিত নির্দেশিকাগুলি ব্যবহার করুন।

  • একটি internal ক্লাস, পদ্ধতি বা ক্ষেত্র রাখতে, এটিকে সর্বজনীন হিসাবে বিবেচনা করুন। উদাহরণস্বরূপ, নিম্নলিখিত কোটলিন উৎসটি বিবেচনা করুন:

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

    কোটলিন কম্পাইলার দ্বারা তৈরি .class ফাইলগুলিতে internal ক্লাস, পদ্ধতি এবং ক্ষেত্রগুলি public , তাই আপনাকে নিম্নলিখিত উদাহরণে দেখানো হিসাবে public কীওয়ার্ড ব্যবহার করতে হবে:

    -keepclassmembers public class com.example.ImportantInternalClass {
      public int f;
      public void m();
    }
    
  • যখন একটি suspend সদস্য কম্পাইল করা হয়, তখন তার কম্পাইল করা স্বাক্ষরটি Keep নিয়মের সাথে মিলিয়ে নিন।

    উদাহরণস্বরূপ, যদি আপনার ফাংশন 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(...);
    }
    

সদস্যের স্পেসিফিকেশন

ক্লাস স্পেসিফিকেশনে ঐচ্ছিকভাবে সংরক্ষিত ক্লাস সদস্যদের অন্তর্ভুক্ত করা হয়। যদি আপনি একটি ক্লাসের জন্য এক বা একাধিক সদস্য নির্দিষ্ট করেন, তাহলে নিয়মটি শুধুমাত্র সেই সদস্যদের জন্য প্রযোজ্য।

আপনি সদস্যদের তাদের টীকা অনুসারে নির্দিষ্ট করতে পারেন। ক্লাসের মতো, আপনি টীকাটির সম্পূর্ণরূপে যোগ্য জাভা নামের সাথে @ ব্যবহার করেন। এটি আপনাকে কেবলমাত্র সেই সদস্যদের ক্লাসের মধ্যে রাখতে দেয় যারা নির্দিষ্ট টীকা দিয়ে চিহ্নিত। উদাহরণস্বরূপ, পদ্ধতি এবং ক্ষেত্রগুলিকে @com.example.MyAnnotation দিয়ে টীকাযুক্ত রাখতে:

-keep class com.example.MyClass {
  @com.example.MyAnnotation <methods>;
  @com.example.MyAnnotation <fields>;
}

শক্তিশালী, লক্ষ্যবস্তুযুক্ত নিয়মের জন্য আপনি এটিকে ক্লাস-স্তরের অ্যানোটেশন ম্যাচিংয়ের সাথে একত্রিত করতে পারেন:

-keep class @com.example.ClassAnnotation * {
  @com.example.MethodAnnotation <methods>;
  @com.example.FieldAnnotation <fields>;
}

এটি @ClassAnnotation দিয়ে ক্লাসগুলিকে টীকাবদ্ধ রাখে, এবং সেই ক্লাসগুলিতে, এটি @MethodAnnotation দিয়ে পদ্ধতিগুলিকে টীকাবদ্ধ রাখে এবং @FieldAnnotation দিয়ে ক্ষেত্রগুলিকে টীকাবদ্ধ রাখে।

সম্ভব হলে অ্যানোটেশন-ভিত্তিক কিপ রুলস ব্যবহার করার কথা বিবেচনা করুন। এই পদ্ধতিটি আপনার কোড এবং আপনার কিপ রুলসের মধ্যে একটি স্পষ্ট লিঙ্ক প্রদান করে এবং প্রায়শই আরও শক্তিশালী কনফিগারেশনের দিকে পরিচালিত করে। উদাহরণস্বরূপ, androidx.annotation লাইব্রেরি এই প্রক্রিয়াটি ব্যবহার করে।

উদাহরণ

উদাহরণস্বরূপ, একটি নির্দিষ্ট শ্রেণী এবং এর সকল সদস্য সংরক্ষণ করতে, নিম্নলিখিতগুলি ব্যবহার করুন:

-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>);

উদাহরণস্বরূপ, নিম্নলিখিত keep নিয়মটি setLabel() নামক একটি পাবলিক পদ্ধতি রাখে যা void ফেরত দেয় এবং একটি String নেয়।

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

একটি ক্লাসের সকল পদ্ধতি মেলানোর জন্য আপনি <methods> কে শর্টকাট হিসেবে ব্যবহার করতে পারেন:

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

রিটার্ন টাইপ এবং প্যারামিটার টাইপের জন্য টাইপ কীভাবে নির্দিষ্ট করতে হয় সে সম্পর্কে আরও জানতে, টাইপ দেখুন।

নির্মাতারা

একটি কনস্ট্রাক্টর নির্দিষ্ট করতে, <init> ব্যবহার করুন। একটি keep রুলের জন্য সদস্য স্পেসিফিকেশনে একটি কনস্ট্রাক্টর নির্দিষ্ট করার সিনট্যাক্স নিম্নরূপ:

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

উদাহরণস্বরূপ, নিম্নলিখিত keep নিয়মটি একটি কাস্টম 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 ফাংশন (সাধারণত টপ লেভেল ফাংশন বলা হয়) উল্লেখ করতে, Kotlin কম্পাইলার দ্বারা অন্তর্নিহিতভাবে যোগ করা ক্লাসের জন্য জেনারেট করা জাভা নামটি ব্যবহার করতে ভুলবেন না। ক্লাসের নাম হল Kt যুক্ত Ktলিন ফাইলের নাম। উদাহরণস্বরূপ, যদি আপনার MyClass.kt নামক একটি Kotlin ফাইল নিম্নরূপ সংজ্ঞায়িত করা থাকে:

package com.example.myapp.utils

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

isEmailValid ফাংশনের জন্য একটি keep নিয়ম লিখতে, ক্লাস স্পেসিফিকেশনটি তৈরি হওয়া ক্লাস MyClassKt লক্ষ্য করে তৈরি করতে হবে:

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

প্রকারভেদ

এই বিভাগটি বর্ণনা করে কিভাবে রিটার্ন টাইপ, প্যারামিটার টাইপ এবং ফিল্ড টাইপ Keep রুল মেম্বার স্পেসিফিকেশনে নির্দিষ্ট করতে হয়। যদি টাইপগুলি Kotlin সোর্স কোড থেকে আলাদা হয় তবে সেগুলি নির্দিষ্ট করার জন্য জেনারেট করা জাভা নামগুলি ব্যবহার করতে ভুলবেন না।

আদিম প্রকারভেদ

একটি আদিম টাইপ নির্দিষ্ট করতে, এর জাভা কীওয়ার্ড ব্যবহার করুন। 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 নিয়ম লেখেন তখন আপনাকে অবশ্যই আপনার কোডের কম্পাইল করা উপস্থাপনা লক্ষ্য করতে হবে, মূল সোর্স কোড নয়। জেনেরিক টাইপ কীভাবে পরিবর্তন করা হয় সে সম্পর্কে আরও জানতে, Type erasure দেখুন।

উদাহরণস্বরূপ, যদি আপনার Box.kt এ সংজ্ঞায়িত একটি আনবাউন্ডেড জেনেরিক টাইপ সহ নিম্নলিখিত কোড থাকে:

package com.myapp.data

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

টাইপ ইরেজারের পরে, T এর পরিবর্তে Object ব্যবহার করা হয়। ক্লাস কনস্ট্রাক্টর এবং পদ্ধতি বজায় রাখতে, আপনার নিয়মে জেনেরিক T এর পরিবর্তে java.lang.Object ব্যবহার করতে হবে।

রাখার নিয়মের একটি উদাহরণ নিম্নরূপ হবে:

# 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)

এই ক্ষেত্রে, টাইপ erasure T তার বাউন্ড, java.lang.Number দিয়ে প্রতিস্থাপন করে।

রাখার নিয়মের একটি উদাহরণ নিম্নরূপ হবে:

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

বেস ক্লাস হিসেবে অ্যাপ-নির্দিষ্ট জেনেরিক টাইপ ব্যবহার করার সময়, বেস ক্লাসের জন্যও Keep নিয়ম অন্তর্ভুক্ত করা প্রয়োজন।

উদাহরণস্বরূপ, নিম্নলিখিত কোডের জন্য:

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 সহ একটি keep নিয়ম ব্যবহার করে 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 নিয়মটি ব্যবহার করতে পারেন:

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

অ্যারের ধরণ

অ্যারের প্রতিটি মাত্রার জন্য কম্পোনেন্ট টাইপের সাথে [] যোগ করে একটি অ্যারের টাইপ নির্দিষ্ট করুন। এটি ক্লাস টাইপ এবং প্রিমিটিভ টাইপ উভয়ের ক্ষেত্রেই প্রযোজ্য।

  • এক-মাত্রিক ক্লাস অ্যারে: java.lang.String[]
  • দ্বি-মাত্রিক আদিম অ্যারে: int[][]

উদাহরণস্বরূপ, যদি আপনার নিম্নলিখিত কোড থাকে:

package com.example.data

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

আপনি নিম্নলিখিত keep নিয়মটি ব্যবহার করতে পারেন:

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

ওয়াইল্ডকার্ড

নিম্নলিখিত টেবিলে দেখানো হয়েছে কিভাবে ওয়াইল্ডকার্ড ব্যবহার করে একাধিক ক্লাস বা সদস্যদের জন্য Keep নিয়ম প্রয়োগ করতে হয় যা একটি নির্দিষ্ট প্যাটার্নের সাথে মেলে।

ওয়াইল্ডকার্ড ক্লাস বা সদস্যদের ক্ষেত্রে প্রযোজ্য বিবরণ
** উভয়ই সর্বাধিক ব্যবহৃত। যেকোনো ধরণের নামের সাথে মিল করে, যেকোনো সংখ্যক প্যাকেজ বিভাজক সহ। এটি একটি প্যাকেজের মধ্যে সমস্ত ক্লাস এবং এর সাব-প্যাকেজগুলির সাথে মিল করার জন্য কার্যকর।
* উভয়ই ক্লাস স্পেসিফিকেশনের জন্য, এমন কোনও টাইপ নামের অংশের সাথে মেলে যেখানে প্যাকেজ বিভাজক ( . ) থাকে না।
সদস্যের স্পেসিফিকেশনের জন্য, যেকোনো পদ্ধতি বা ক্ষেত্রের নামের সাথে মেলে। যখন এটি নিজে ব্যবহার করা হয়, তখন এটি ** এর একটি উপনামও।
? উভয়ই একটি ক্লাস বা সদস্যের নামের যেকোনো একক অক্ষরের সাথে মেলে।
*** সদস্যরা যেকোনো ধরণের সাথে মেলে, যার মধ্যে রয়েছে আদিম প্রকার (যেমন int ), শ্রেণীর প্রকার (যেমন java.lang.String ), এবং যেকোনো মাত্রার অ্যারে প্রকার (যেমন byte[][] )।
... সদস্যরা একটি পদ্ধতির জন্য যেকোনো প্যারামিটারের তালিকার সাথে মেলে।
% সদস্যরা যেকোনো আদিম প্রকারের সাথে মিলিত হয় (যেমন `int`, `float`, `boolean`, অথবা অন্যান্য)।

বিশেষ ওয়াইল্ডকার্ডগুলি কীভাবে ব্যবহার করবেন তার কিছু উদাহরণ এখানে দেওয়া হল:

  • যদি আপনার একই নামের একাধিক পদ্ধতি থাকে এবং বিভিন্ন আদিম প্রকারের ইনপুট গ্রহণ করে, তাহলে আপনি % ব্যবহার করে একটি keep নিয়ম লিখতে পারেন যা তাদের সকলকে ধরে রাখে। উদাহরণস্বরূপ, এই 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, %);
    }
    
  • যদি আপনার একাধিক ক্লাস থাকে যার নাম এক অক্ষরের উপর নির্ভর করে পরিবর্তিত হয়, তাহলে ? ব্যবহার করে একটি keep নিয়ম লিখুন যা তাদের সকলকে ধরে রাখে। উদাহরণস্বরূপ, যদি আপনার নিম্নলিখিত ক্লাস থাকে:

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

    নিম্নলিখিত কিপ নিয়মটি সমস্ত ক্লাস ধরে রাখে:

    -keep class com.example.models.UserV?
    
  • Example এবং AnotherExample ক্লাসগুলি মেলাতে (যদি সেগুলি রুট-লেভেল ক্লাস হয়), কিন্তু com.foo.Example না হয়, তাহলে নিম্নলিখিত keep নিয়মটি ব্যবহার করুন:

    -keep class *Example
    
  • যদি আপনি নিজে থেকে * ব্যবহার করেন, তাহলে এটি ** এর একটি উপনাম হিসেবে কাজ করে। উদাহরণস্বরূপ, নিম্নলিখিত keep নিয়মগুলি সমতুল্য:

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

জেনারেটেড জাভা নামগুলি পরীক্ষা করুন

Keep নিয়ম লেখার সময়, জাভা বাইটকোডে কম্পাইল করার পরে আপনাকে অবশ্যই ক্লাস এবং অন্যান্য রেফারেন্স টাইপের নাম উল্লেখ করতে হবে (উদাহরণস্বরূপ ক্লাস স্পেসিফিকেশন এবং টাইপ দেখুন)। আপনার কোডের জন্য জেনারেট করা জাভা নামগুলি পরীক্ষা করতে, Android Studio-তে নিম্নলিখিত টুলগুলির যেকোনো একটি ব্যবহার করুন:

  • APK বিশ্লেষক
  • কোটলিন সোর্স ফাইল খোলা থাকা অবস্থায়, টুলস > কোটলিন > কোটলিন বাইটকোড দেখান > ডিকম্পাইল এ গিয়ে বাইটকোডটি পরীক্ষা করুন।