একটি উচ্চ স্তরে, একটি রাখা নিয়ম একটি শ্রেণী (বা সাবক্লাস বা বাস্তবায়ন) নির্দিষ্ট করে এবং তারপরে সদস্য-পদ্ধতি, কনস্ট্রাক্টর বা ক্ষেত্রগুলি-কে সংরক্ষণ করার জন্য সেই শ্রেণীর মধ্যে।
একটি রাখার নিয়মের জন্য সাধারণ সিনট্যাক্স নিম্নরূপ:
-<keep_option>[,<keep_option_modifier_1>,<keep_option_modifier_2>,...] <class_specification>
নিম্নলিখিত একটি Keep নিয়মের উদাহরণ যা keepclassmembers Keep বিকল্প হিসেবে ব্যবহার করে, অপ্টিমাইজেশনকে মডিফায়ার হিসেবে allowoptimization এবং com.example.MyClass থেকে someSpecificMethod() রাখে:
-keepclassmembers,allowoptimization class com.example.MyClass {
void someSpecificMethod();
}
বিকল্প রাখুন
কিপ অপশনটি আপনার রাখার নিয়মের প্রথম অংশ। এটি একটি শ্রেণির কোন দিকগুলি সংরক্ষণ করতে হবে তা নির্দিষ্ট করে। এখানে ছয়টি আলাদা রাখার বিকল্প রয়েছে, যেমন 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 |
অপশন মডিফায়ার রাখুন
একটি Keep বিকল্প মডিফায়ার একটি Keep নিয়মের সুযোগ এবং আচরণ নিয়ন্ত্রণ করতে ব্যবহৃত হয়। আপনি আপনার Keep নিয়মে 0 বা তার বেশি Keep অপশন মডিফায়ার যোগ করতে পারেন।
একটি Keep অপশন মডিফায়ারের সম্ভাব্য মানগুলি নিম্নলিখিত টেবিলে বর্ণনা করা হয়েছে:
| মান | বর্ণনা |
|---|---|
allowoptimization | নির্দিষ্ট উপাদান অপ্টিমাইজেশান অনুমতি দেয়. যাইহোক, নির্দিষ্ট উপাদানের নাম পরিবর্তন বা সরানো হয় না। |
allowobfucastion | নির্দিষ্ট উপাদানের পুনঃনামকরণের অনুমতি দেয়। যাইহোক, উপাদানগুলি সরানো বা অন্যথায় অপ্টিমাইজ করা হয় না। |
allowshrinking | R8 তাদের কোনো রেফারেন্স খুঁজে না পেলে নির্দিষ্ট উপাদান অপসারণের অনুমতি দেয়। যাইহোক, উপাদানগুলির নাম পরিবর্তন করা হয় না বা অন্যথায় অপ্টিমাইজ করা হয় না। |
includedescriptorclasses | R8-কে নির্দেশ দেয় যে সমস্ত শ্রেণীগুলি (প্যারামিটারের ধরন এবং রিটার্নের ধরন) এবং ক্ষেত্রগুলি (ক্ষেত্রের ধরন) রাখা হচ্ছে তার বর্ণনাকারীতে প্রদর্শিত। |
allowaccessmodification | R8 কে অপ্টিমাইজেশন প্রক্রিয়া চলাকালীন ক্লাস, পদ্ধতি এবং ক্ষেত্রগুলির অ্যাক্সেস মডিফায়ারগুলি ( public , private , protected ) পরিবর্তন করতে (সাধারণত প্রশস্ত) করার অনুমতি দেয়। |
allowrepackage | R8 কে ডিফল্ট (রুট) প্যাকেজ সহ বিভিন্ন প্যাকেজে ক্লাস সরানোর অনুমতি দেয়। |
ক্লাস স্পেসিফিকেশন
রাখা নিয়মের অংশ হিসেবে আপনাকে অবশ্যই একটি ক্লাস, সুপারক্লাস বা বাস্তবায়িত ইন্টারফেস নির্দিষ্ট করতে হবে। java.lang.String মতো java.lang নামস্থান থেকে ক্লাস সহ সমস্ত ক্লাস, তাদের সম্পূর্ণ যোগ্য জাভা নাম ব্যবহার করে নির্দিষ্ট করতে হবে। যে নামগুলি ব্যবহার করা উচিত তা বোঝার জন্য, Get 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
যদি একটি রাখার নিয়মে একাধিক টীকা থাকে, তবে এটি এমন ক্লাসগুলিকে রাখে যাতে সমস্ত তালিকাভুক্ত টীকা থাকে৷ আপনি একাধিক টীকা তালিকাভুক্ত করতে পারেন, তবে নিয়মটি শুধুমাত্র তখনই প্রযোজ্য হয় যদি ক্লাসে প্রতিটি তালিকাভুক্ত টীকা থাকে। উদাহরণস্বরূপ, নিম্নলিখিত নিয়মটি সমস্ত শ্রেণীকে Annotation1 এবং Annotation2 উভয় দ্বারা টীকাযুক্ত রাখে।
-keep class @com.example.Annotation1 @com.example.Annotation2 *
উপশ্রেণী এবং বাস্তবায়ন
একটি সাবক্লাস বা শ্রেণী লক্ষ্য করতে যা একটি ইন্টারফেস প্রয়োগ করে, যথাক্রমে extend এবং implements ব্যবহার করুন।
উদাহরণস্বরূপ, আপনার যদি নিম্নরূপ সাবক্লাস Foo সহ ক্লাস Bar থাকে:
class Foo : Bar()
নিম্নলিখিত রাখা নিয়মটি Bar সমস্ত উপশ্রেণী সংরক্ষণ করে। মনে রাখবেন যে রাখা নিয়মটি সুপারক্লাস Bar অন্তর্ভুক্ত করে না।
-keep class * extends Bar
আপনার যদি ক্লাস Foo থাকে যা Bar প্রয়োগ করে:
class Foo : Bar
নিম্নলিখিত Keep নিয়মটি Bar প্রয়োগ করে এমন সমস্ত ক্লাস সংরক্ষণ করে। মনে রাখবেন যে রাখার নিয়মটি ইন্টারফেস 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() {} }internalক্লাস, পদ্ধতি এবং ক্ষেত্রগুলি Kotlin কম্পাইলার দ্বারা উত্পাদিত.classফাইলগুলিতেpublic, তাই আপনাকে অবশ্যইpublicকীওয়ার্ডটি ব্যবহার করতে হবে যা নিম্নলিখিত উদাহরণে দেখানো হয়েছে:-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);এই ফাংশনের জন্য একটি Keep নিয়ম লিখতে, আপনাকে অবশ্যই এই সংকলিত স্বাক্ষরের সাথে মেলে বা ব্যবহার করতে হবে
...সংকলিত স্বাক্ষর ব্যবহার করার একটি উদাহরণ নিম্নরূপ:
-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
বেশিরভাগ সময়, আপনি কিছু সদস্য নির্দিষ্ট করতে চাইবেন। উদাহরণস্বরূপ, নিম্নলিখিত উদাহরণটি MyClass ক্লাসের মধ্যে পাবলিক ফিল্ড text এবং পাবলিক মেথড updateText() রাখে।
-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> ব্যবহার করুন। একটি রাখা নিয়মের জন্য সদস্য স্পেসিফিকেশনে একটি কনস্ট্রাক্টর নির্দিষ্ট করার জন্য সিনট্যাক্স নিম্নরূপ:
[<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 ফাইলের নাম 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);
}
প্রকারভেদ
এই বিভাগে কীভাবে রিটার্নের ধরন, প্যারামিটারের ধরন এবং ক্ষেত্রটির ধরনগুলি নিয়ম মেম্বার স্পেসিফিকেশন বজায় রাখতে হয় তা বর্ণনা করা হয়েছে। কোটলিন সোর্স কোড থেকে ভিন্ন হলে প্রকারগুলি নির্দিষ্ট করতে জেনারেট করা জাভা নামগুলি ব্যবহার করতে ভুলবেন না৷
আদিম প্রকার
একটি আদিম প্রকার নির্দিষ্ট করতে, এর জাভা কীওয়ার্ড ব্যবহার করুন। 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 কম্পাইলার জেনেরিক ধরনের তথ্য মুছে ফেলে, তাই যখন আপনি লিখবেন এমন নিয়মগুলি রাখুন যাতে জেনেরিক প্রকার জড়িত থাকে আপনাকে অবশ্যই আপনার কোডের সংকলিত উপস্থাপনাকে লক্ষ্য করতে হবে , মূল সোর্স কোড নয়। জেনেরিক প্রকারগুলি কীভাবে পরিবর্তিত হয় সে সম্পর্কে আরও জানতে, টাইপ ইরেজার দেখুন।
উদাহরণস্বরূপ, যদি আপনার কাছে 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)
এই ক্ষেত্রে, টাইপ ইরেজার 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) {
}
UnpackOptions ক্লাস এবং Box ক্লাস পদ্ধতি উভয়ই একটি একক নিয়মের সাথে সংরক্ষণ করার জন্য আপনি includedescriptorclasses সহ একটি Keep নিয়ম ব্যবহার করতে পারেন:
-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
}
}
আপনি নিম্নলিখিত রাখার নিয়ম ব্যবহার করতে পারেন:
# Keeps a method that returns a byte array.
-keepclassmembers class com.example.data.ImageProcessor {
public byte[] process();
}
ওয়াইল্ডকার্ড
নিম্নলিখিত সারণীটি দেখায় যে কীভাবে ওয়াইল্ডকার্ড ব্যবহার করতে হয় একাধিক ক্লাস বা সদস্যদের জন্য নিয়মগুলি প্রয়োগ করতে যা একটি নির্দিষ্ট প্যাটার্নের সাথে মেলে।
| ওয়াইল্ডকার্ড | ক্লাস বা সদস্যদের জন্য প্রযোজ্য | বর্ণনা |
|---|---|---|
| ** | উভয় | সবচেয়ে বেশি ব্যবহৃত হয়। প্যাকেজ বিভাজক যেকোন সংখ্যক সহ যেকোন প্রকারের নামের সাথে মিলে যায়। এটি একটি প্যাকেজ এবং এর সাব-প্যাকেজের মধ্যে সমস্ত ক্লাস মেলানোর জন্য দরকারী। |
| * | উভয় | ক্লাস স্পেসিফিকেশনের জন্য, প্যাকেজ বিভাজক ( . ) ধারণ করে না এমন একটি টাইপ নামের যেকোনো অংশের সাথে মেলেসদস্য স্পেসিফিকেশনের জন্য, যেকোনো পদ্ধতি বা ক্ষেত্রের নামের সাথে মেলে। যখন নিজে ব্যবহার করা হয়, তখন এটি ** এর একটি উপনামও হয়। |
| ? | উভয় | শ্রেণী বা সদস্যের নামের যেকোনো একক অক্ষর মেলে। |
| *** | সদস্যরা | আদিম প্রকার (যেমন int ), ক্লাসের ধরন (যেমন java.lang.String ), এবং যেকোনো মাত্রার অ্যারের প্রকার (যেমন byte[][] ) সহ যেকোনো প্রকারের সাথে মেলে। |
| ... | সদস্যরা | একটি পদ্ধতির জন্য প্যারামিটারের যেকোনো তালিকার সাথে মেলে। |
| % | সদস্যরা | যেকোন আদিম প্রকারের সাথে মেলে (যেমন `int`, `float`, `বুলিয়ান`, বা অন্যান্য)। |
এখানে বিশেষ ওয়াইল্ডকার্ডগুলি কীভাবে ব্যবহার করবেন তার কয়েকটি উদাহরণ রয়েছে:
আপনার যদি একই নামের একাধিক পদ্ধতি থাকে যা ইনপুট হিসাবে বিভিন্ন আদিম ধরন গ্রহণ করে, আপনি একটি 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, %); }যদি আপনার একাধিক শ্রেণী থাকে যার নাম এক অক্ষর দ্বারা পরিবর্তিত হয়, ব্যবহার করুন
?একটি রাখা নিয়ম লিখতে যা তাদের সব রাখে। উদাহরণস্বরূপ, যদি আপনার নিম্নলিখিত ক্লাস থাকে: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[];) }
উত্পন্ন জাভা নাম পরিদর্শন করুন
রাখার নিয়ম লেখার সময়, আপনাকে অবশ্যই জাভা বাইটকোডে কম্পাইল করার পরে তাদের নাম ব্যবহার করে ক্লাস এবং অন্যান্য রেফারেন্স প্রকারগুলি নির্দিষ্ট করতে হবে (উদাহরণগুলির জন্য ক্লাস স্পেসিফিকেশন এবং প্রকারগুলি দেখুন)। আপনার কোডের জন্য জেনারেট করা জাভা নামগুলি কী তা পরীক্ষা করতে, অ্যান্ড্রয়েড স্টুডিওতে নিম্নলিখিত যে কোনও একটি টুল ব্যবহার করুন:
- APK বিশ্লেষক
- Kotlin সোর্স ফাইল খোলার সাথে, Tools > Kotlin > Show Kotlin Bytecode > Decompile- এ গিয়ে বাইটকোড পরিদর্শন করুন।