রানটাইম রিসোর্স ওভারলে (RROs)

রানটাইম রিসোর্স ওভারলে (RRO) হল একটি প্যাকেজ যা রানটাইমে লক্ষ্য প্যাকেজের রিসোর্স মান পরিবর্তন করে। উদাহরণস্বরূপ, সিস্টেম ইমেজে ইনস্টল করা একটি অ্যাপ একটি সম্পদের মূল্যের উপর ভিত্তি করে তার আচরণ পরিবর্তন করতে পারে। বিল্ড টাইমে রিসোর্স ভ্যালু হার্ডকোড করার পরিবর্তে, একটি ভিন্ন পার্টিশনে ইনস্টল করা একটি RRO রানটাইমে অ্যাপের রিসোর্সের মান পরিবর্তন করতে পারে।

RROs সক্ষম বা নিষ্ক্রিয় করা যেতে পারে। সম্পদের মান পরিবর্তন করার জন্য RRO-এর ক্ষমতা টগল করার জন্য আপনি প্রোগ্রামেটিকভাবে সক্ষম/অক্ষম অবস্থা সেট করতে পারেন। RROs ডিফল্টরূপে নিষ্ক্রিয় করা হয় (তবে, স্ট্যাটিক RROs ডিফল্টরূপে সক্রিয় করা হয়)।

ওভারলেইং রিসোর্স

ওভারলেগুলি লক্ষ্য প্যাকেজে সংজ্ঞায়িত সংস্থানগুলির সাথে ওভারলে প্যাকেজে সংজ্ঞায়িত সংস্থানগুলি ম্যাপ করে কাজ করে৷ যখন একটি অ্যাপ লক্ষ্য প্যাকেজে একটি সম্পদের মান সমাধান করার চেষ্টা করে, তখন লক্ষ্য সম্পদটি ম্যাপ করা ওভারলে রিসোর্সের মান পরিবর্তে ফেরত দেওয়া হয়।

ম্যানিফেস্ট সেট আপ করা হচ্ছে

একটি প্যাকেজ একটি RRO প্যাকেজ হিসাবে বিবেচিত হয় যদি এতে <manifest> ট্যাগের একটি চাইল্ড হিসাবে একটি <overlay> ট্যাগ থাকে।

  • প্রয়োজনীয় android:targetPackage অ্যাট্রিবিউটের মান RRO যে প্যাকেজটি ওভারলে করতে চায় তার নাম নির্দিষ্ট করে৷

  • ঐচ্ছিক android:targetName অ্যাট্রিবিউটের মান RRO ওভারলে করতে চায় এমন টার্গেট প্যাকেজের রিসোর্সের ওভারলেয়েবল উপসেটের নাম নির্দিষ্ট করে। টার্গেট যদি ওভারলেয়েবল রিসোর্সের সেটকে সংজ্ঞায়িত না করে, তাহলে এই অ্যাট্রিবিউটটি উপস্থিত থাকা উচিত নয়।

নিম্নলিখিত কোডটি AndroidManifest.xml ওভারলে একটি উদাহরণ দেখায়।

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlay">
    <application android:hasCode="false" />
    <overlay android:targetPackage="com.example.target"
                   android:targetName="OverlayableResources"/>
</manifest>

ওভারলে কোড ওভারলে করতে পারে না, তাই তাদের কাছে DEX ফাইল থাকতে পারে না। উপরন্তু, ম্যানিফেস্টে <application > ট্যাগের android:hasCode অ্যাট্রিবিউট অবশ্যই false সেট করতে হবে।

সম্পদ মানচিত্র সংজ্ঞায়িত

অ্যান্ড্রয়েড 11 বা উচ্চতর সংস্করণে, ওভারলে রিসোর্স ম্যাপ সংজ্ঞায়িত করার জন্য প্রস্তাবিত পদ্ধতি হল ওভারলে প্যাকেজের res/xml ডিরেক্টরিতে একটি ফাইল তৈরি করা, ওভারলে করা উচিত এমন টার্গেট রিসোর্স এবং তাদের প্রতিস্থাপনের মানগুলি গণনা করা, তারপরে এর মান সেট করা। android:resourcesMap বৈশিষ্ট্য <overlay> ম্যানিফেস্ট ট্যাগের রিসোর্স ম্যাপিং ফাইলের একটি রেফারেন্সে।

নিম্নলিখিত কোডটি res/xml/overlays.xml ফাইলের একটি উদাহরণ দেখায়।

<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- Overlays string/config1 and string/config2 with the same resource. -->
    <item target="string/config1" value="@string/overlay1" />
    <item target="string/config2" value="@string/overlay1" />

    <!-- Overlays string/config3 with the string "yes". -->
    <item target="string/config3" value="@android:string/yes" />

    <!-- Overlays string/config4 with the string "Hardcoded string". -->
    <item target="string/config4" value="Hardcoded string" />

    <!-- Overlays integer/config5 with the integer "42". -->
    <item target="integer/config5" value="42" />
</overlay>

নিম্নলিখিত কোড একটি উদাহরণ ওভারলে ম্যানিফেস্ট দেখায়.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlay">
    <application android:hasCode="false" />
    <overlay android:targetPackage="com.example.target"
                   android:targetName="OverlayableResources"
                   android:resourcesMap="@xml/overlays"/>
</manifest>

প্যাকেজ নির্মাণ

অ্যান্ড্রয়েড 11 বা উচ্চতর ওভারলেগুলির জন্য একটি Soong বিল্ড নিয়ম সমর্থন করে যা Android অ্যাসেট প্যাকেজিং টুল 2 (AAPT2) কে একই মান ( --no-resource-deduping ) সহ সংস্থানগুলির কনফিগারেশন ডিডিউপ করার চেষ্টা থেকে এবং ডিফল্ট কনফিগারেশন ছাড়াই সংস্থানগুলি সরানো থেকে বাধা দেয় ( --no-resource-removal )। নিম্নলিখিত কোড একটি উদাহরণ Android.bp ফাইল দেখায়.

runtime_resource_overlay {
    name: "ExampleOverlay",
    sdk_version: "current",
}

সম্পদ সমাধান

যদি একটি টার্গেট রিসোর্স বা ওভারলে রিসোর্সে একাধিক কনফিগারেশন থাকে যে রিসোর্সকে জিজ্ঞাসা করা হচ্ছে, রিসোর্স রানটাইম কনফিগারেশনের মান প্রদান করে যা ডিভাইস কনফিগারেশনের কনফিগারেশনের সাথে সবচেয়ে ভালো মেলে। কোন কনফিগারেশনটি সবচেয়ে ভালো ম্যাচিং কনফিগারেশন তা নির্ধারণ করতে, ওভারলে রিসোর্স কনফিগারেশনের সেটটিকে টার্গেট রিসোর্স কনফিগারেশনের সেটে মার্জ করুন এবং তারপরে নিয়মিত রিসোর্স রেজোলিউশন ফ্লো অনুসরণ করুন (বিস্তারিত জানার জন্য, Android কীভাবে সেরা-ম্যাচিং রিসোর্স খুঁজে পায় তা দেখুন)।

উদাহরণস্বরূপ, যদি একটি ওভারলে drawable-en -এন-পোর্টের জন্য একটি মান সংজ্ঞায়িত করে এবং লক্ষ্য drawable-en-port জন্য একটি মান সংজ্ঞায়িত করে, তবে drawable-en-port সাথে আরও ভাল মিল রয়েছে তাই লক্ষ্য কনফিগারেশন drawable-en-port মান রানটাইমে নির্বাচিত। সমস্ত drawable-en কনফিগারেশনগুলিকে ওভারলে করতে, ওভারলেকে লক্ষ্য নির্ধারণ করা প্রতিটি drawable-en কনফিগারেশনের জন্য একটি মান নির্ধারণ করতে হবে।

অ্যান্ড্রয়েড রিলিজের মধ্যে ভিন্ন আচরণ সহ ওভারলেগুলি তাদের নিজস্ব সংস্থানগুলি উল্লেখ করতে পারে।

  • অ্যান্ড্রয়েড 11 বা উচ্চতর সংস্করণে, প্রতিটি ওভারলে এর নিজস্ব সংরক্ষিত রিসোর্স আইডি স্পেস থাকে যা টার্গেট রিসোর্স আইডি স্পেস বা অন্যান্য ওভারলে রিসোর্স আইডি স্পেসকে ওভারল্যাপ করে না, তাই ওভারলে তাদের নিজস্ব রিসোর্স উল্লেখ করে প্রত্যাশিতভাবে কাজ করে।

  • অ্যান্ড্রয়েড 10 বা তার কম সময়ে, ওভারলে এবং টার্গেট প্যাকেজ একই রিসোর্স আইডি স্পেস শেয়ার করে, যা তাদের নিজস্ব রিসোর্সকে @type/name সিনট্যাক্স ব্যবহার করে উল্লেখ করার চেষ্টা করার সময় সংঘর্ষ এবং অপ্রত্যাশিত আচরণের কারণ হতে পারে।

ওভারলে সক্রিয়/অক্ষম করা হচ্ছে

পরিবর্তনযোগ্য ওভারলে সক্ষম এবং নিষ্ক্রিয় করতে OverlayManager API ব্যবহার করুন ( Context#getSystemService(Context.OVERLAY_SERVICE) ব্যবহার করে API ইন্টারফেস পুনরুদ্ধার করুন)। একটি ওভারলে শুধুমাত্র প্যাকেজ দ্বারা টার্গেট করে বা android.permission.CHANGE_OVERLAY_PACKAGES অনুমতি সহ একটি প্যাকেজ দ্বারা সক্ষম করা যেতে পারে৷ যখন একটি ওভারলে সক্ষম বা অক্ষম করা হয়, তখন কনফিগারেশন পরিবর্তন ইভেন্টগুলি লক্ষ্য প্যাকেজে প্রচারিত হয় এবং লক্ষ্য ক্রিয়াকলাপগুলি পুনরায় চালু হয়।

overlayable সম্পদ সীমাবদ্ধ

Android 10 বা উচ্চতর সংস্করণে, <overlayable> XML ট্যাগ রিসোর্সের একটি সেট প্রকাশ করে যা RRO-কে ওভারলে করার অনুমতি দেওয়া হয়। নিম্নলিখিত উদাহরণে res/values/overlayable.xml ফাইল, string/foo এবং integer/bar হল ডিভাইসের চেহারা থিম করার জন্য ব্যবহৃত সম্পদ; এই সংস্থানগুলিকে ওভারলে করার জন্য, একটি ওভারলেকে স্পষ্টভাবে নাম অনুসারে ওভারলেযোগ্য সংস্থানগুলির সংগ্রহকে লক্ষ্য করতে হবে।

<!-- The collection of resources for theming the appearance of the device -->
<overlayable name="ThemeResources">
       <policy type="public">
               <item type="string" name="foo/" />
               <item type="integer" name="bar/" />
       </policy>
       ...
</overlayable>

একটি APK একাধিক <overlayable> ট্যাগ সংজ্ঞায়িত করতে পারে, তবে প্রতিটি ট্যাগের প্যাকেজের মধ্যে একটি অনন্য নাম থাকতে হবে। উদাহরণস্বরূপ, এটি হল:

  • <overlayable name="foo"> উভয়কে সংজ্ঞায়িত করতে দুটি ভিন্ন প্যাকেজের জন্য ঠিক আছে।

  • একটি একক APK-এর জন্য দুটি <overlayable name="foo"> ব্লক থাকা ঠিক নয়৷

নিম্নলিখিত কোডটি AndroidManifest.xml ফাইলে একটি ওভারলের একটি উদাহরণ দেখায়৷

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.my.theme.overlay">
       <application android:hasCode="false" />
       <!-- This overlay will override the ThemeResources resources -->
       <overlay android:targetPackage="android" android:targetName="ThemeResources">
</manifest>

যখন একটি অ্যাপ একটি <overlayable> ট্যাগ সংজ্ঞায়িত করে, সেই অ্যাপটিকে লক্ষ্য করে ওভারলে করে:

  • targetName অবশ্যই উল্লেখ করতে হবে।

  • শুধুমাত্র <overlayable> ট্যাগের মধ্যে তালিকাভুক্ত সম্পদগুলিকে ওভারলে করতে পারে।

  • শুধুমাত্র একটি <overlayable> নাম টার্গেট করতে পারে।

আপনি একটি প্যাকেজকে লক্ষ্য করে একটি ওভারলে সক্ষম করতে পারবেন না যা ওভারলেয়েবল রিসোর্স প্রকাশ করে কিন্তু একটি নির্দিষ্ট <overlayable> ট্যাগ টার্গেট করতে android:targetName ব্যবহার করে না।

সীমাবদ্ধ নীতি

ওভারলেয়েবল রিসোর্সে সীমাবদ্ধতা প্রয়োগ করতে <policy> ট্যাগ ব্যবহার করুন। type অ্যাট্রিবিউট উল্লেখ করে যে কোন ওভারলে অন্তর্ভুক্ত রিসোর্স ওভাররাইড করার জন্য কোন নীতিগুলি পূরণ করতে হবে। সমর্থিত ধরনের নিম্নলিখিত অন্তর্ভুক্ত.

  • public যেকোন ওভারলে সম্পদ ওভাররাইড করতে পারে।
  • system সিস্টেম পার্টিশনের যেকোনো ওভারলে সম্পদগুলিকে ওভাররাইড করতে পারে।
  • vendor বিক্রেতা পার্টিশনে যেকোন ওভারলে সম্পদগুলিকে ওভাররাইড করতে পারে।
  • product প্রোডাক্ট পার্টিশনের যেকোন ওভারলে রিসোর্স ওভাররাইড করতে পারে।
  • signature লক্ষ্য APK এর মতো একই স্বাক্ষর সহ স্বাক্ষরিত যেকোন ওভারলে সংস্থানগুলিকে ওভাররাইড করতে পারে৷

নিম্নলিখিত কোডটি res/values/overlayable.xml ফাইলে একটি উদাহরণ <policy> ট্যাগ দেখায়।

<overlayable name="ThemeResources">
   <policy type="vendor" >
       <item type="string" name="foo" />
   </policy>
   <policy type="product|signature"  >
       <item type="string" name="bar" />
       <item type="string" name="baz" />
   </policy>
</overlayable>

একাধিক নীতি নির্দিষ্ট করতে, বিভাজক অক্ষর হিসাবে উল্লম্ব বার (|) ব্যবহার করুন। যখন একাধিক নীতি নির্দিষ্ট করা হয়, একটি ওভারলেকে <policy> ট্যাগের মধ্যে তালিকাভুক্ত সংস্থানগুলিকে ওভাররাইড করতে শুধুমাত্র একটি নীতি পূরণ করতে হবে।

ওভারলে কনফিগার করা হচ্ছে

Android রিলিজ সংস্করণের উপর নির্ভর করে পরিবর্তনশীলতা, ডিফল্ট অবস্থা এবং ওভারলেগুলির অগ্রাধিকার কনফিগার করার জন্য বিভিন্ন প্রক্রিয়া সমর্থন করে।

  • অ্যান্ড্রয়েড 11 বা উচ্চতর সংস্করণে চলমান ডিভাইসগুলি ম্যানিফেস্ট বৈশিষ্ট্যগুলির পরিবর্তে একটি OverlayConfig ফাইল ( config.xml ) ব্যবহার করতে পারে৷ ওভারলে ফাইল ব্যবহার করা ওভারলেগুলির জন্য প্রস্তাবিত পদ্ধতি।

  • স্ট্যাটিক RRO কনফিগার করতে সমস্ত ডিভাইস ম্যানিফেস্ট অ্যাট্রিবিউট ( android:isStatic এবং android:priority ) ব্যবহার করতে পারে।

OverlayConfig ব্যবহার করে

Android 11 বা উচ্চতর সংস্করণে, আপনি পরিবর্তনযোগ্যতা, ডিফল্ট অবস্থা এবং ওভারলেগুলির অগ্রাধিকার কনফিগার করতে OverlayConfig ব্যবহার করতে পারেন। একটি ওভারলে কনফিগার করতে, partition/overlay/config/config.xml এ অবস্থিত ফাইলটি তৈরি বা পরিবর্তন করুন, যেখানে partition হল ওভারলেটির পার্টিশন যা কনফিগার করা হবে। কনফিগার করার জন্য, একটি ওভারলে অবশ্যই পার্টিশনের overlay/ ডিরেক্টরিতে থাকবে যেখানে ওভারলে কনফিগার করা হয়েছে। নিম্নলিখিত কোড একটি উদাহরণ product/overlay/config/config.xml

<config>
    <merge path="OEM-common-rros-config.xml" />
    <overlay package="com.oem.overlay.device" mutable="false" enabled="true" />
    <overlay package="com.oem.green.theme" enabled="true" />
</config>"

<overlay> ট্যাগের জন্য একটি package অ্যাট্রিবিউট প্রয়োজন যা নির্দেশ করে কোন ওভারলে প্যাকেজটি কনফিগার করা হচ্ছে। ঐচ্ছিক enabled বৈশিষ্ট্য নিয়ন্ত্রণ করে ডিফল্টরূপে ওভারলে সক্ষম কিনা (ডিফল্ট false )। ঐচ্ছিক mutable অ্যাট্রিবিউট ওভারলে পরিবর্তনযোগ্য কিনা তা নিয়ন্ত্রণ করে এবং রানটাইমে এটির সক্রিয় অবস্থা প্রোগ্রামেটিকভাবে পরিবর্তিত হতে পারে (ডিফল্ট true )। কনফিগারেশন ফাইলের মধ্যে তালিকাভুক্ত নয় এমন ওভারলেগুলি পরিবর্তনযোগ্য এবং ডিফল্টরূপে অক্ষম করা হয়।

ওভারলে অগ্রাধিকার

যখন একাধিক ওভারলে একই সংস্থানগুলিকে ওভাররাইড করে, তখন ওভারলেগুলির ক্রম গুরুত্বপূর্ণ। একটি ওভারলে এর নিজস্ব কনফিগারেশনের পূর্ববর্তী কনফিগারেশন সহ ওভারলেগুলির চেয়ে বেশি অগ্রাধিকার রয়েছে। বিভিন্ন পার্টিশনে ওভারলেগুলির অগ্রাধিকার ক্রম (অন্তত থেকে সর্বাধিক অগ্রাধিকার পর্যন্ত) নিম্নরূপ।

  • system
  • vendor
  • oem
  • odm
  • product
  • system_ext

ফাইল মার্জিং

<merge> ট্যাগ ব্যবহার করে অন্যান্য কনফিগারেশন ফাইলগুলিকে নির্দিষ্ট অবস্থানে কনফিগারেশন ফাইলে মার্জ করার অনুমতি দেয়। ট্যাগের path অ্যাট্রিবিউট ওভারলে কনফিগারেশন ফাইল ধারণকারী ডিরেক্টরির সাপেক্ষে মার্জ করার জন্য ফাইলের পাথ উপস্থাপন করে।

ম্যানিফেস্ট অ্যাট্রিবিউট ব্যবহার করা (স্ট্যাটিক RROs)

অ্যান্ড্রয়েড 10 বা তার কম সময়ে, ওভারলে অপরিবর্তনীয়তা এবং অগ্রাধিকার নিম্নলিখিত ম্যানিফেস্ট বৈশিষ্ট্যগুলি ব্যবহার করে কনফিগার করা হয়েছে।

  • android:isStatic । যখন এই বুলিয়ান অ্যাট্রিবিউটের মান true তে সেট করা হয়, ওভারলে ডিফল্টরূপে সক্রিয় থাকে এবং অপরিবর্তনীয়, যা ওভারলেকে নিষ্ক্রিয় হতে বাধা দেয়।

  • android:priority । এই সাংখ্যিক বৈশিষ্ট্যের মান (যা শুধুমাত্র স্ট্যাটিক ওভারলেকে প্রভাবিত করে) ওভারলে-এর অগ্রাধিকার কনফিগার করে যখন একাধিক স্ট্যাটিক ওভারলে একই সম্পদের মানকে লক্ষ্য করে। একটি উচ্চ সংখ্যা একটি উচ্চ অগ্রাধিকার নির্দেশ করে.

নিম্নলিখিত কোডটি AndroidManifest.xml এর একটি উদাহরণ দেখায়।

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlay">
    <application android:hasCode="false" />
    <overlay android:targetPackage="com.example.target"
                   android:isStatic="true"
                   android:priority="5"/>
</manifest>

Android 11 এ পরিবর্তন

Android 11 বা উচ্চতর সংস্করণে, যদি একটি কনফিগারেশন ফাইল partition/overlay/config/config.xml এ অবস্থিত থাকে, ওভারলেগুলি সেই ফাইলটি ব্যবহার করে কনফিগার করা হয় এবং android:isStatic এবং android:priority পার্টিশনে অবস্থিত ওভারলেগুলিতে কোনও প্রভাব ফেলে না। যে কোনো পার্টিশনে একটি ওভারলে কনফিগারেশন ফাইল সংজ্ঞায়িত করা ওভারলে পার্টিশন অগ্রাধিকার প্রয়োগ করে।

এছাড়াও, Android 11 বা উচ্চতর প্যাকেজ ইনস্টলেশনের সময় রিসোর্সের মানগুলিকে প্রভাবিত করতে স্ট্যাটিক ওভারলে ব্যবহার করার ক্ষমতা সরিয়ে দেয়। বুলিয়ানের মান পরিবর্তন করার জন্য স্ট্যাটিক ওভারলে ব্যবহার করার ক্ষেত্রে সাধারণ ব্যবহারের ক্ষেত্রে, যা কম্পোনেন্ট-এনাবল স্টেট কনফিগার করে, <component-override> SystemConfig ট্যাগ ব্যবহার করুন (Android 11-এ নতুন)।

ডিবাগিং ওভারলে

ওভারলে ম্যানুয়ালি সক্ষম, নিষ্ক্রিয় এবং ডাম্প করতে, নিম্নলিখিত ওভারলে ম্যানেজার শেল কমান্ড ব্যবহার করুন।

adb shell cmd overlay

OverlayManagerService টার্গেট প্যাকেজে রিসোর্স আইডি ম্যাপ করতে ওভারলে প্যাকেজে রিসোর্স idmap2 ব্যবহার করে। উত্পন্ন আইডি ম্যাপিংগুলি /data/resource-cache/ এ সংরক্ষণ করা হয়। যদি আপনার ওভারলে সঠিকভাবে কাজ না করে, তাহলে /data/resource-cache/ এ আপনার ওভারলের জন্য সংশ্লিষ্ট idmap ফাইলটি খুঁজুন, তারপর নিম্নলিখিত কমান্ডটি চালান।

adb shell idmap2 dump --idmap-path [file]

এই কমান্ডটি নীচে দেখানো হিসাবে সম্পদের ম্যাপিং প্রিন্ট করে।

[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType