অ্যাক্টিভিটি এমবেডিং

অ্যাক্টিভিটি এম্বেডিং দুটি অ্যাক্টিভিটি বা একই অ্যাক্টিভিটির দুটি দৃষ্টান্তের মধ্যে একটি অ্যাপ্লিকেশানের টাস্ক উইন্ডোকে বিভক্ত করে বড় স্ক্রীন ডিভাইসে অ্যাপগুলিকে অপ্টিমাইজ করে৷

চিত্র 1. পাশাপাশি অ্যাক্টিভিটি সহ সেটিংস অ্যাপ।

আপনার অ্যাপ্লিকেশান একাধিক কার্যকলাপ নিয়ে গঠিত হলে, অ্যাক্টিভিটি এমবেডিং আপনাকে ট্যাবলেট, ফোল্ডেবল এবং ChromeOS ডিভাইসগুলিতে একটি উন্নত ব্যবহারকারীর অভিজ্ঞতা প্রদান করতে সক্ষম করে৷

অ্যাক্টিভিটি এম্বেডিংয়ের জন্য কোনো কোড রিফ্যাক্টরিংয়ের প্রয়োজন নেই। একটি XML কনফিগারেশন ফাইল তৈরি করে বা Jetpack WindowManager API কল করে আপনার অ্যাপ কীভাবে তার ক্রিয়াকলাপগুলি-পাশাপাশি বা স্তূপাকারভাবে প্রদর্শন করে তা আপনি নির্ধারণ করেন।

ছোট পর্দার জন্য সমর্থন স্বয়ংক্রিয়ভাবে বজায় রাখা হয়. যখন আপনার অ্যাপটি একটি ছোট স্ক্রীন সহ একটি ডিভাইসে থাকে, তখন ক্রিয়াকলাপগুলি একে অপরের উপরে স্ট্যাক করা হয়। বড় পর্দায়, কার্যকলাপ পাশাপাশি প্রদর্শিত হয়. সিস্টেম আপনার তৈরি করা কনফিগারেশনের উপর ভিত্তি করে উপস্থাপনা নির্ধারণ করে—কোন শাখার যুক্তির প্রয়োজন নেই।

অ্যাক্টিভিটি এম্বেডিং ডিভাইসের অভিযোজন পরিবর্তনগুলিকে মিটমাট করে এবং ভাঁজযোগ্য ডিভাইসে নির্বিঘ্নে কাজ করে, ডিভাইসটি ভাঁজ এবং উন্মোচিত হওয়ার সাথে সাথে স্ট্যাকিং এবং আনস্ট্যাকিং কার্যক্রম।

অ্যাক্টিভিটি এম্বেডিং অ্যান্ড্রয়েড 12L (API লেভেল 32) এবং উচ্চতর চলমান বেশিরভাগ বড় স্ক্রীন ডিভাইসে সমর্থিত।

স্প্লিট টাস্ক উইন্ডো

অ্যাক্টিভিটি এম্বেডিং অ্যাপ টাস্ক উইন্ডোটিকে দুটি পাত্রে বিভক্ত করে: প্রাথমিক এবং মাধ্যমিক৷ কন্টেইনারগুলি মূল ক্রিয়াকলাপ থেকে বা ইতিমধ্যে কন্টেইনারে থাকা অন্যান্য ক্রিয়াকলাপগুলি থেকে শুরু করা ক্রিয়াকলাপগুলিকে ধরে রাখে৷

অ্যাক্টিভিটিগুলি চালু হওয়ার সাথে সাথে সেকেন্ডারি কন্টেইনারে স্ট্যাক করা হয় এবং সেকেন্ডারি কন্টেইনারটি ছোট স্ক্রিনে প্রাথমিক কন্টেইনারের উপরে স্ট্যাক করা হয়, তাই অ্যাক্টিভিটি স্ট্যাকিং এবং ব্যাক নেভিগেশন আপনার অ্যাপে ইতিমধ্যে তৈরি করা অ্যাক্টিভিটিগুলির ক্রমানুসারে সামঞ্জস্যপূর্ণ।

কার্যকলাপ এম্বেডিং আপনাকে বিভিন্ন উপায়ে কার্যকলাপ প্রদর্শন করতে সক্ষম করে। আপনার অ্যাপ একই সাথে দুটি ক্রিয়াকলাপ পাশাপাশি চালু করে টাস্ক উইন্ডোকে বিভক্ত করতে পারে:

চিত্র 2. পাশাপাশি দুটি ক্রিয়াকলাপ।

অথবা, একটি ক্রিয়াকলাপ যা পুরো টাস্ক উইন্ডোটি দখল করে আছে পাশাপাশি একটি নতুন কার্যকলাপ চালু করে একটি বিভক্ত তৈরি করতে পারে:

চিত্র 3. A কার্যকলাপ B পাশ থেকে শুরু করে।

যে ক্রিয়াকলাপগুলি ইতিমধ্যে একটি বিভক্ত অবস্থায় রয়েছে এবং একটি টাস্ক উইন্ডো ভাগ করে নেওয়া হয়েছে সেগুলি নিম্নলিখিত উপায়ে অন্যান্য ক্রিয়াকলাপ চালু করতে পারে:

  • অন্য কার্যকলাপের উপরে পাশে:

    চিত্র 4. A কার্যকলাপ C শুরু করে B কার্যকলাপের পাশ দিয়ে।
  • পাশের দিকে, এবং পূর্ববর্তী প্রাথমিক কার্যকলাপ গোপন করে, বিভক্তটি পাশে স্থানান্তর করুন:

    চিত্র 5. অ্যাক্টিভিটি B অ্যাক্টিভিটি C-কে পাশে শুরু করে এবং বিভক্তটিকে পাশে সরিয়ে দেয়।
  • উপরে জায়গায় একটি কার্যকলাপ চালু করুন; যে, একই কার্যকলাপ স্ট্যাকে:

    চিত্র 6. কার্যকলাপ B কোনো অতিরিক্ত অভিপ্রায় ফ্ল্যাগ ছাড়াই C কার্যকলাপ শুরু করে।
  • একই টাস্কে একটি অ্যাক্টিভিটি পূর্ণ উইন্ডো চালু করুন:

    চিত্র 7. কার্যকলাপ A বা কার্যকলাপ B কার্যকলাপ C শুরু করে যা টাস্ক উইন্ডোটি পূরণ করে।

পিছনে নেভিগেশন

ক্রিয়াকলাপগুলির মধ্যে নির্ভরতা বা ব্যবহারকারীরা কীভাবে ব্যাক ইভেন্টটি ট্রিগার করে তার উপর নির্ভর করে বিভিন্ন ধরণের অ্যাপ্লিকেশনগুলির একটি বিভক্ত টাস্ক উইন্ডো অবস্থায় বিভিন্ন ব্যাক নেভিগেশন নিয়ম থাকতে পারে, উদাহরণস্বরূপ:

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

বোতাম নেভিগেশন ব্যবহার করার সময় পিছনের ইভেন্টটি শেষ ফোকাস করা কার্যকলাপে পাঠানো হয়।

অঙ্গভঙ্গি-ভিত্তিক নেভিগেশনের জন্য:

  • অ্যান্ড্রয়েড 14 (এপিআই স্তর 34) এবং নীচের — পিছনের ইভেন্টটি সেই কার্যকলাপে পাঠানো হয় যেখানে অঙ্গভঙ্গিটি ঘটেছে। যখন ব্যবহারকারীরা স্ক্রিনের বাম দিক থেকে সোয়াইপ করেন, তখন পিছনের ইভেন্টটি স্প্লিট উইন্ডোর বাম দিকের ফলকে কার্যকলাপে পাঠানো হয়। যখন ব্যবহারকারীরা স্ক্রিনের ডান দিক থেকে সোয়াইপ করেন, তখন পিছনের ইভেন্টটি ডানদিকের ফলকে কার্যকলাপে পাঠানো হয়।

  • Android 15 (API স্তর 35) এবং উচ্চতর

    • একই অ্যাপ থেকে একাধিক ক্রিয়াকলাপ নিয়ে কাজ করার সময়, অঙ্গভঙ্গিটি সোয়াইপ দিক নির্বিশেষে শীর্ষ ক্রিয়াকলাপ শেষ করে, আরও একীভূত অভিজ্ঞতা প্রদান করে।

    • বিভিন্ন অ্যাপ্লিকেশান (ওভারলে) থেকে দুটি ক্রিয়াকলাপ জড়িত পরিস্থিতিতে, পিছনের ইভেন্টটি বোতাম নেভিগেশনের আচরণের সাথে সারিবদ্ধ করে ফোকাসের শেষ কার্যকলাপের দিকে পরিচালিত হয়।

মাল্টি-প্যান লেআউট

Jetpack WindowManager আপনাকে Android 12L (API লেভেল 32) বা উচ্চতর এবং পূর্ববর্তী প্ল্যাটফর্ম সংস্করণ সহ কিছু ডিভাইসে বড় স্ক্রীনের ডিভাইসে মাল্টি-পেন লেআউট এম্বেড করার একটি অ্যাক্টিভিটি তৈরি করতে সক্ষম করে। বিদ্যমান অ্যাপ্লিকেশানগুলি যেগুলি খণ্ড বা ভিউ-ভিত্তিক লেআউটগুলির পরিবর্তে একাধিক ক্রিয়াকলাপের উপর ভিত্তি করে যেমন SlidingPaneLayout সোর্স কোড রিফ্যাক্টরিং ছাড়াই একটি উন্নত বড় স্ক্রীন ব্যবহারকারীর অভিজ্ঞতা প্রদান করতে পারে৷

একটি সাধারণ উদাহরণ হল একটি তালিকা-বিশদ বিভাজন। একটি উচ্চ-মানের উপস্থাপনা নিশ্চিত করতে, সিস্টেমটি তালিকা কার্যকলাপ শুরু করে এবং তারপরে অ্যাপ্লিকেশনটি অবিলম্বে বিস্তারিত কার্যকলাপ শুরু করে। উভয় ক্রিয়াকলাপ আঁকা না হওয়া পর্যন্ত ট্রানজিশন সিস্টেম অপেক্ষা করে, তারপর সেগুলি একসাথে প্রদর্শন করে। ব্যবহারকারীর কাছে, দুটি ক্রিয়াকলাপ এক হিসাবে চালু হয়।

চিত্র 8. একটি মাল্টি-পেন লেআউটে দুটি কার্যক্রম একই সাথে শুরু হয়েছে।

বিভক্ত বৈশিষ্ট্য

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

একটি XML কনফিগারেশন ফাইলে সংজ্ঞায়িত নিয়মগুলির জন্য, নিম্নলিখিত বৈশিষ্ট্যগুলি সেট করুন:

  • splitRatio : ধারক অনুপাত সেট করে। মানটি খোলা ব্যবধানে একটি ফ্লোটিং পয়েন্ট সংখ্যা (0.0, 1.0)।
  • splitLayoutDirection : বিভক্ত পাত্রগুলি একে অপরের সাপেক্ষে কীভাবে সাজানো হয় তা নির্দিষ্ট করে। মান অন্তর্ভুক্ত:
    • ltr : বাম থেকে ডানে
    • rtl : ডান থেকে বাম
    • locale : ltr বা rtl হয় লোকেল সেটিং থেকে নির্ধারিত হয়

উদাহরণের জন্য XML কনফিগারেশন বিভাগটি দেখুন।

WindowManager API ব্যবহার করে তৈরি করা নিয়মগুলির জন্য, SplitAttributes.Builder দিয়ে একটি SplitAttributes অবজেক্ট তৈরি করুন এবং নিম্নলিখিত বিল্ডার পদ্ধতিগুলিকে কল করুন:

  • setSplitType() : বিভক্ত পাত্রের অনুপাত সেট করে। SplitAttributes.SplitType.ratio() পদ্ধতি সহ বৈধ আর্গুমেন্টের জন্য SplitAttributes.SplitType দেখুন।
  • setLayoutDirection() : কন্টেইনারগুলির বিন্যাস সেট করে। সম্ভাব্য মানগুলির জন্য SplitAttributes.LayoutDirection দেখুন।

উদাহরণের জন্য WindowManager API বিভাগটি দেখুন।

চিত্র 9. দুটি ক্রিয়াকলাপ বিভাজন বাম থেকে ডানে কিন্তু বিভিন্ন বিভক্ত অনুপাত সহ।

স্থানধারক

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

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

চিত্র 10. ভাঁজযোগ্য ডিভাইস ভাঁজ এবং উন্মোচন। প্লেসহোল্ডার অ্যাক্টিভিটি শেষ হয়েছে এবং ডিসপ্লে সাইজ পরিবর্তনের সাথে সাথে পুনরায় তৈরি করা হয়েছে।

যাইহোক, SplitPlaceholderRule এর stickyPlaceholder বৈশিষ্ট্য বা SplitPlaceholder.Builder এর setSticky() পদ্ধতি ডিফল্ট আচরণকে ওভাররাইড করতে পারে। যখন অ্যাট্রিবিউট বা পদ্ধতি true একটি মান নির্দিষ্ট করে, তখন সিস্টেমটি টাস্ক উইন্ডোতে প্লেসহোল্ডারটিকে শীর্ষস্থানীয় কার্যকলাপ হিসাবে প্রদর্শন করে যখন ডিসপ্লেটিকে টু-পেন ডিসপ্লে থেকে একটি একক-প্যান ডিসপ্লেতে পুনরায় আকার দেওয়া হয় (একটি উদাহরণের জন্য স্প্লিট কনফিগারেশন দেখুন) .

চিত্র 11. ভাঁজযোগ্য ডিভাইস ভাঁজ এবং উন্মোচন। স্থানধারক কার্যকলাপ স্টিকি.

জানালার আকার পরিবর্তন

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

প্লেসহোল্ডার কার্যকলাপ শুধুমাত্র তখনই দেখানো হয় যখন একটি বিভাজনের জন্য যথেষ্ট প্রদর্শন প্রস্থ থাকে। ছোট পর্দায়, স্থানধারক স্বয়ংক্রিয়ভাবে বরখাস্ত হয়। যখন ডিসপ্লে এরিয়া আবার যথেষ্ট বড় হয়ে যায়, তখন প্লেসহোল্ডারটি পুনরায় তৈরি করা হয়। ( প্লেসহোল্ডার বিভাগ দেখুন।)

অ্যাক্টিভিটি স্ট্যাকিং সম্ভব কারণ WindowManager z-অর্ডার করে সেকেন্ডারি প্যানে ক্রিয়াকলাপগুলি প্রাথমিক ফলকের উপরে কার্যকলাপগুলিকে।

সেকেন্ডারি প্যানে একাধিক কার্যক্রম

অ্যাক্টিভিটি B কোনো অতিরিক্ত উদ্দেশ্য ফ্ল্যাগ ছাড়াই C-এর জায়গায় কার্যকলাপ শুরু করে:

অ্যাক্টিভিটি স্প্লিট যার মধ্যে অ্যা, বি, এবং সি অ্যাক্টিভিটি এবং সি স্ট্যাক করা আছে           বি এর শীর্ষ

একই টাস্কে নিম্নলিখিত z-ক্রমের কার্যক্রমের ফলে:

সেকেন্ডারি অ্যাক্টিভিটি স্ট্যাক যার মধ্যে অ্যাক্টিভিটি C রয়েছে B-এর উপরে স্ট্যাক করা আছে।           সেকেন্ডারি স্ট্যাক প্রামারি অ্যাক্টিভিটি স্ট্যাকের উপরে স্ট্যাক করা হয়           কার্যকলাপ A ধারণকারী।

সুতরাং, একটি ছোট টাস্ক উইন্ডোতে, অ্যাপ্লিকেশনটি স্ট্যাকের শীর্ষে C সহ একটি একক কার্যকলাপে সঙ্কুচিত হয়:

ছোট উইন্ডো শুধুমাত্র কার্যকলাপ দেখায় C.

ছোট উইন্ডোতে আবার নেভিগেট করা একে অপরের উপরে স্তুপীকৃত কার্যকলাপের মাধ্যমে নেভিগেট করে।

যদি টাস্ক উইন্ডো কনফিগারেশনটি একটি বৃহত্তর আকারে পুনরুদ্ধার করা হয় যা একাধিক ফলককে মিটমাট করতে পারে, কার্যকলাপগুলি আবার পাশাপাশি প্রদর্শিত হবে।

স্তুপীকৃত বিভাজন

অ্যাক্টিভিটি B অ্যাক্টিভিটি C-কে পাশে শুরু করে এবং বিভক্তটিকে পাশে সরিয়ে দেয়:

টাস্ক উইন্ডো A এবং B ক্রিয়াকলাপ দেখায়, তারপরে B এবং C ক্রিয়াকলাপগুলি দেখায়।

ফলাফল হল একই টাস্কের ক্রিয়াকলাপগুলির নিম্নলিখিত z-ক্রম:

অ্যাক্টিভিটিগুলি A, B, এবং C একটি একক স্ট্যাকে। কার্যক্রম স্তুপীকৃত হয়           উপর থেকে নীচে নিম্নলিখিত ক্রমে: C, B, A।

একটি ছোট টাস্ক উইন্ডোতে, অ্যাপ্লিকেশনটি উপরে C সহ একটি একক কার্যকলাপে সঙ্কুচিত হয়:

ছোট উইন্ডো শুধুমাত্র কার্যকলাপ দেখায় C.

স্থির-প্রতিকৃতি অভিযোজন

android:screenOrientation ম্যানিফেস্ট সেটিং অ্যাপগুলিকে পোর্ট্রেট বা ল্যান্ডস্কেপ ওরিয়েন্টেশনে ক্রিয়াকলাপগুলিকে সীমাবদ্ধ করতে সক্ষম করে৷ ট্যাবলেট এবং ফোল্ডেবলের মতো বড় স্ক্রীন ডিভাইসগুলিতে ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে, ডিভাইস নির্মাতারা (OEMs) স্ক্রীন ওরিয়েন্টেশন অনুরোধগুলিকে উপেক্ষা করতে পারে এবং ল্যান্ডস্কেপ ডিসপ্লেতে পোর্ট্রেট ওরিয়েন্টেশনে বা পোর্ট্রেট ডিসপ্লেতে ল্যান্ডস্কেপ ওরিয়েন্টেশনে অ্যাপটিকে লেটারবক্স করতে পারে।

চিত্র 12. লেটারবক্সযুক্ত কার্যক্রম: ল্যান্ডস্কেপ ডিভাইসে ফিক্সড-পোর্ট্রেট (বাম), পোর্ট্রেট ডিভাইসে ফিক্সড-ল্যান্ডস্কেপ (ডানদিকে)।

একইভাবে, যখন অ্যাক্টিভিটি এমবেডিং সক্ষম করা থাকে, তখন OEMগুলি বড় স্ক্রিনে (প্রস্থ ≥ 600dp) ল্যান্ডস্কেপ ওরিয়েন্টেশনে লেটারবক্স ফিক্সড-পোর্ট্রেট অ্যাক্টিভিটিগুলিতে ডিভাইসগুলি কাস্টমাইজ করতে পারে। যখন একটি ফিক্সড-পোর্ট্রেট অ্যাক্টিভিটি একটি দ্বিতীয় অ্যাক্টিভিটি চালু করে, তখন ডিভাইসটি দুটি ক্রিয়াকলাপ পাশাপাশি প্রদর্শন করতে পারে একটি টু-পেন ডিসপ্লেতে।

চিত্র 13. ফিক্সড-পোর্ট্রেট অ্যাক্টিভিটি A পাশ থেকে B কার্যকলাপ শুরু করে।

ডিভাইসগুলিকে জানাতে যে আপনার অ্যাপ অ্যাক্টিভিটি এম্বেডিং সমর্থন করে তা জানাতে আপনার অ্যাপ ম্যানিফেস্ট ফাইলে সর্বদা android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED প্রপার্টি যোগ করুন ( বিভক্ত কনফিগারেশন বিভাগটি দেখুন)। OEM-কাস্টমাইজড ডিভাইসগুলি তারপর লেটারবক্স ফিক্সড-পোর্ট্রেট ক্রিয়াকলাপগুলি নির্ধারণ করতে পারে।

বিভক্ত কনফিগারেশন

বিভক্ত নিয়ম কার্যকলাপ বিভক্ত কনফিগার. আপনি একটি XML কনফিগারেশন ফাইলে বা Jetpack WindowManager API কল করে বিভক্ত নিয়মগুলি সংজ্ঞায়িত করেন।

উভয় ক্ষেত্রেই, আপনার অ্যাপকে অবশ্যই WindowManager লাইব্রেরি অ্যাক্সেস করতে হবে এবং সিস্টেমকে অবশ্যই জানাতে হবে যে অ্যাপটি অ্যাক্টিভিটি এমবেডিং প্রয়োগ করেছে।

নিম্নলিখিতগুলি করুন:

  1. আপনার অ্যাপের মডিউল-স্তরের build.gradle ফাইলে সর্বশেষ WindowManager লাইব্রেরি নির্ভরতা যোগ করুন, উদাহরণস্বরূপ:

    implementation 'androidx.window:window:1.1.0-beta02'

    WindowManager লাইব্রেরি অ্যাক্টিভিটি এমবেডিংয়ের জন্য প্রয়োজনীয় সমস্ত উপাদান সরবরাহ করে।

  2. সিস্টেমকে জানান যে আপনার অ্যাপ অ্যাক্টিভিটি এমবেডিং প্রয়োগ করেছে।

    অ্যাপ ম্যানিফেস্ট ফাইলের <application> উপাদানে android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED প্রপার্টি যোগ করুন এবং মানটিকে সত্যে সেট করুন, উদাহরণস্বরূপ:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application>
            <property
                android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
                android:value="true" />
        </application>
    </manifest>
    

    WindowManager রিলিজ 1.1.0-alpha06 এবং পরবর্তীতে, অ্যাক্টিভিটি এমবেডিং স্প্লিটগুলি নিষ্ক্রিয় করা হয় যদি না সম্পত্তিটি ম্যানিফেস্টে যোগ করা হয় এবং সত্যে সেট করা হয়।

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

XML কনফিগারেশন

অ্যাক্টিভিটি এম্বেডিংয়ের একটি XML-ভিত্তিক বাস্তবায়ন তৈরি করতে, নিম্নলিখিত ধাপগুলি সম্পূর্ণ করুন:

  1. একটি XML রিসোর্স ফাইল তৈরি করুন যা নিম্নলিখিতগুলি করে:

    • ক্রিয়াকলাপগুলিকে সংজ্ঞায়িত করে যা একটি বিভাজন ভাগ করে
    • বিভক্ত বিকল্পগুলি কনফিগার করে
    • বিষয়বস্তু উপলব্ধ না হলে বিভক্তের গৌণ ধারকের জন্য একটি স্থানধারক তৈরি করে
    • এমন ক্রিয়াকলাপগুলি নির্দিষ্ট করে যেগুলি কখনই বিভাজনের অংশ হওয়া উচিত নয়৷

    যেমন:

    <!-- main_split_config.xml -->
    
    <resources
        xmlns:window="http://schemas.android.com/apk/res-auto">
    
        <!-- Define a split for the named activities. -->
        <SplitPairRule
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:finishPrimaryWithSecondary="never"
            window:finishSecondaryWithPrimary="always"
            window:clearTop="false">
            <SplitPairFilter
                window:primaryActivityName=".ListActivity"
                window:secondaryActivityName=".DetailActivity"/>
        </SplitPairRule>
    
        <!-- Specify a placeholder for the secondary container when content is
             not available. -->
        <SplitPlaceholderRule
            window:placeholderActivityName=".PlaceholderActivity"
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:stickyPlaceholder="false">
            <ActivityFilter
                window:activityName=".ListActivity"/>
        </SplitPlaceholderRule>
    
        <!-- Define activities that should never be part of a split. Note: Takes
             precedence over other split rules for the activity named in the
             rule. -->
        <ActivityRule
            window:alwaysExpand="true">
            <ActivityFilter
                window:activityName=".ExpandedActivity"/>
        </ActivityRule>
    
    </resources>
    
  2. একটি ইনিশিয়ালাইজার তৈরি করুন।

    WindowManager RuleController উপাদান XML কনফিগারেশন ফাইল পার্স করে এবং নিয়মগুলি সিস্টেমে উপলব্ধ করে। একটি জেটপ্যাক স্টার্টআপ লাইব্রেরি Initializer অ্যাপ স্টার্টআপে XML ফাইলটি RuleController এর কাছে উপলব্ধ করে যাতে কোনও কার্যকলাপ শুরু হলে নিয়মগুলি কার্যকর হয়।

    একটি ইনিশিয়ালাইজার তৈরি করতে, নিম্নলিখিতগুলি করুন:

    1. আপনার মডিউল-স্তরের build.gradle ফাইলে সাম্প্রতিক জেটপ্যাক স্টার্টআপ লাইব্রেরি নির্ভরতা যোগ করুন, উদাহরণস্বরূপ:

      implementation 'androidx.startup:startup-runtime:1.1.1'

    2. একটি ক্লাস তৈরি করুন যা Initializer ইন্টারফেস প্রয়োগ করে।

      ইনিশিয়ালাইজার XML কনফিগারেশন ফাইলের ID ( main_split_config.xml ) RuleController.parseRules() পদ্ধতিতে পাস করে RuleController কাছে বিভক্ত নিয়মগুলি উপলব্ধ করে।

      কোটলিন

      class SplitInitializer : Initializer<RuleController> {
      
          override fun create(context: Context): RuleController {
              return RuleController.getInstance(context).apply {
                  setRules(RuleController.parseRules(context, R.xml.main_split_config))
              }
          }
      
          override fun dependencies(): List<Class<out Initializer<*>>> {
              return emptyList()
          }
      }

      জাভা

      public class SplitInitializer implements Initializer<RuleController> {
      
           @NonNull
           @Override
           public RuleController create(@NonNull Context context) {
               RuleController ruleController = RuleController.getInstance(context);
               ruleController.setRules(
                   RuleController.parseRules(context, R.xml.main_split_config)
               );
               return ruleController;
           }
      
           @NonNull
           @Override
           public List<Class<? extends Initializer<?>>> dependencies() {
               return Collections.emptyList();
           }
      }
  3. নিয়মের সংজ্ঞার জন্য একটি বিষয়বস্তু প্রদানকারী তৈরি করুন।

    আপনার অ্যাপ ম্যানিফেস্ট ফাইলে androidx.startup.InitializationProvider যোগ করুন <provider> হিসেবে। আপনার RuleController ইনিশিয়ালাইজার, SplitInitializer এর বাস্তবায়নের একটি রেফারেন্স অন্তর্ভুক্ত করুন:

    <!-- AndroidManifest.xml -->
    
    <provider android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <!-- Make SplitInitializer discoverable by InitializationProvider. -->
        <meta-data android:name="${applicationId}.SplitInitializer"
            android:value="androidx.startup" />
    </provider>
    

    InitializationProvider অ্যাপের onCreate() পদ্ধতি কল করার আগে SplitInitializer আবিষ্কার করে এবং আরম্ভ করে। ফলস্বরূপ, অ্যাপের প্রধান কার্যকলাপ শুরু হলে বিভক্ত নিয়মগুলি কার্যকর হয়৷

WindowManager API

আপনি মুষ্টিমেয় এপিআই কলের সাথে প্রোগ্রামে অ্যাক্টিভিটি এমবেডিং বাস্তবায়ন করতে পারেন। কোনো কার্যক্রম চালু হওয়ার আগে নিয়ম কার্যকর হয়েছে তা নিশ্চিত করতে Application একটি সাবক্লাসের onCreate() পদ্ধতিতে কল করুন।

প্রোগ্রাম্যাটিকভাবে একটি কার্যকলাপ বিভাজন তৈরি করতে, নিম্নলিখিতগুলি করুন:

  1. একটি বিভক্ত নিয়ম তৈরি করুন:

    1. একটি SplitPairFilter তৈরি করুন যা বিভাজন ভাগ করে এমন কার্যকলাপগুলি সনাক্ত করে:

      কোটলিন

      val splitPairFilter = SplitPairFilter(
         ComponentName(this, ListActivity::class.java),
         ComponentName(this, DetailActivity::class.java),
         null
      )

      জাভা

      SplitPairFilter splitPairFilter = new SplitPairFilter(
         new ComponentName(this, ListActivity.class),
         new ComponentName(this, DetailActivity.class),
         null
      );
    2. ফিল্টার সেটে ফিল্টার যোগ করুন:

      কোটলিন

      val filterSet = setOf(splitPairFilter)

      জাভা

      Set<SplitPairFilter> filterSet = new HashSet<>();
      filterSet.add(splitPairFilter);
    3. বিভাজনের জন্য লেআউট বৈশিষ্ট্য তৈরি করুন:

      কোটলিন

      val splitAttributes: SplitAttributes = SplitAttributes.Builder()
          .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
          .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
          .build()

      জাভা

      final SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();

      SplitAttributes.Builder লেআউট বৈশিষ্ট্য ধারণকারী একটি বস্তু তৈরি করে:

      • setSplitType() : প্রতিটি অ্যাক্টিভিটি কন্টেইনারে কীভাবে উপলব্ধ ডিসপ্লে এলাকা বরাদ্দ করা হয় তা নির্ধারণ করে। অনুপাত বিভক্ত প্রকার প্রাথমিক কন্টেইনারে বরাদ্দ উপলব্ধ প্রদর্শন এলাকার অনুপাত নির্দিষ্ট করে; মাধ্যমিক ধারকটি উপলব্ধ প্রদর্শন এলাকার অবশিষ্টাংশ দখল করে।
      • setLayoutDirection() : প্রাথমিক ধারক প্রথমে একে অপরের সাপেক্ষে অ্যাক্টিভিটি কন্টেইনারগুলি কীভাবে বিছানো হয় তা নির্দিষ্ট করে।
    4. একটি SplitPairRule তৈরি করুন:

      কোটলিন

      val splitPairRule = SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build()

      জাভা

      SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build();

      SplitPairRule.Builder নিয়মটি তৈরি করে এবং কনফিগার করে:

      • filterSet : বিভক্ত জোড়া ফিল্টার রয়েছে যা বিভাজন ভাগ করে এমন ক্রিয়াকলাপগুলি সনাক্ত করে নিয়মটি কখন প্রয়োগ করতে হবে তা নির্ধারণ করে।
      • setDefaultSplitAttributes() : নিয়মে লেআউট বৈশিষ্ট্য প্রয়োগ করে।
      • setMinWidthDp() : সর্বনিম্ন প্রদর্শন প্রস্থ সেট করে (ঘনত্ব-স্বাধীন পিক্সেল, dp-এ) যা একটি বিভাজন সক্ষম করে।
      • setMinSmallestWidthDp() : ন্যূনতম মান সেট করে (dp-এ) যে দুটি ডিসপ্লে ডাইমেনশনের ছোট হলে ডিভাইসের অভিযোজন নির্বিশেষে একটি বিভাজন সক্ষম করতে হবে।
      • setMaxAspectRatioInPortrait() : পোর্ট্রেট ওরিয়েন্টেশনে সর্বাধিক ডিসপ্লে অ্যাসপেক্ট রেশিও (উচ্চতা:প্রস্থ) সেট করে যার জন্য কার্যকলাপ বিভাজন প্রদর্শিত হয়। যদি একটি প্রতিকৃতি প্রদর্শনের আকৃতির অনুপাত সর্বাধিক আকৃতির অনুপাতকে অতিক্রম করে, তবে প্রদর্শনের প্রস্থ নির্বিশেষে বিভক্তগুলি নিষ্ক্রিয় করা হয়৷ দ্রষ্টব্য: ডিফল্ট মান হল 1.4, যার ফলে বেশিরভাগ ট্যাবলেটে পোর্ট্রেট ওরিয়েন্টেশনে ক্রিয়াকলাপ পুরো টাস্ক উইন্ডো দখল করে। এছাড়াও SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT এবং setMaxAspectRatioInLandscape() দেখুন। ল্যান্ডস্কেপের জন্য ডিফল্ট মান হল ALWAYS_ALLOW
      • setFinishPrimaryWithSecondary() : সেকেন্ডারি কন্টেইনারে সমস্ত ক্রিয়াকলাপ শেষ করা প্রাথমিক কন্টেইনারের কার্যকলাপকে কীভাবে প্রভাবিত করে তা সেট করে। সেকেন্ডারি কন্টেইনারের সমস্ত ক্রিয়াকলাপ শেষ হয়ে গেলে সিস্টেমের প্রাথমিক ক্রিয়াকলাপগুলি শেষ করা উচিত নয় বলে NEVER নির্দেশ করে ( ফিনিশ কার্যক্রম দেখুন)।
      • setFinishSecondaryWithPrimary() : প্রাথমিক কন্টেইনারে সমস্ত ক্রিয়াকলাপ শেষ করা সেকেন্ডারি কন্টেইনারের কার্যকলাপকে কীভাবে প্রভাবিত করে তা সেট করে। ALWAYS নির্দেশ করে যে সিস্টেমটি সর্বদা সেকেন্ডারি কন্টেইনারে ক্রিয়াকলাপগুলি শেষ করা উচিত যখন প্রাথমিক কন্টেইনারের সমস্ত ক্রিয়াকলাপ শেষ হয় ( ফিনিশ কার্যক্রম দেখুন)।
      • setClearTop() : কন্টেইনারে একটি নতুন কার্যকলাপ চালু হলে সেকেন্ডারি কন্টেইনারের সমস্ত ক্রিয়াকলাপ শেষ হয় কিনা তা নির্দিষ্ট করে। একটি false মান নির্দিষ্ট করে যে নতুন ক্রিয়াকলাপগুলি ইতিমধ্যে সেকেন্ডারি কন্টেইনারে থাকা ক্রিয়াকলাপগুলির উপরে স্ট্যাক করা হয়েছে৷
    5. WindowManager RuleController এর সিঙ্গলটন উদাহরণ পান এবং নিয়মটি যোগ করুন:

      কোটলিন

        val ruleController = RuleController.getInstance(this)
        ruleController.addRule(splitPairRule)
        

      জাভা

        RuleController ruleController = RuleController.getInstance(this);
        ruleController.addRule(splitPairRule);
        
  2. বিষয়বস্তু উপলব্ধ না হলে সেকেন্ডারি কন্টেইনারের জন্য একটি স্থানধারক তৈরি করুন:

    1. একটি ActivityFilter তৈরি করুন যা সেই অ্যাক্টিভিটি শনাক্ত করে যার সাথে প্লেসহোল্ডার একটি টাস্ক উইন্ডো স্প্লিট শেয়ার করে:

      কোটলিন

      val placeholderActivityFilter = ActivityFilter(
          ComponentName(this, ListActivity::class.java),
          null
      )

      জাভা

      ActivityFilter placeholderActivityFilter = new ActivityFilter(
          new ComponentName(this, ListActivity.class),
          null
      );
    2. ফিল্টার সেটে ফিল্টার যোগ করুন:

      কোটলিন

      val placeholderActivityFilterSet = setOf(placeholderActivityFilter)

      জাভা

      Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
      placeholderActivityFilterSet.add(placeholderActivityFilter);
    3. একটি SplitPlaceholderRule তৈরি করুন:

      কোটলিন

      val splitPlaceholderRule = SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            Intent(context, PlaceholderActivity::class.java)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build()

      জাভা

      SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            new Intent(context, PlaceholderActivity.class)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build();

      SplitPlaceholderRule.Builder নিয়মটি তৈরি করে এবং কনফিগার করে:

      • placeholderActivityFilterSet : অ্যাক্টিভিটি ফিল্টার ধারণ করে যা নির্ধারণ করে যে কখন নিয়ম প্রয়োগ করতে হবে সেই ক্রিয়াকলাপগুলির সাথে স্থানধারক কার্যকলাপ জড়িত।
      • Intent : স্থানধারক কার্যকলাপের সূচনা নির্দিষ্ট করে।
      • setDefaultSplitAttributes() : নিয়মে লেআউট বৈশিষ্ট্য প্রয়োগ করে।
      • setMinWidthDp() : সর্বনিম্ন প্রদর্শন প্রস্থ (ঘনত্ব-স্বাধীন পিক্সেলে, dp) সেট করে যা একটি বিভক্ত করার অনুমতি দেয়।
      • setMinSmallestWidthDp() : ন্যূনতম মান সেট করে (dp-এ) যে দুটি ডিসপ্লে ডাইমেনশনের মধ্যে ছোট হলে ডিভাইসের অভিযোজন নির্বিশেষে একটি বিভাজনের অনুমতি দিতে হবে।
      • setMaxAspectRatioInPortrait() : পোর্ট্রেট ওরিয়েন্টেশনে সর্বাধিক ডিসপ্লে অ্যাসপেক্ট রেশিও (উচ্চতা:প্রস্থ) সেট করে যার জন্য কার্যকলাপ বিভাজন প্রদর্শিত হয়। দ্রষ্টব্য: ডিফল্ট মান হল 1.4, যার ফলে বেশিরভাগ ট্যাবলেটে পোর্ট্রেট ওরিয়েন্টেশনে টাস্ক উইন্ডো পূরণ করা হয়৷ এছাড়াও SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT এবং setMaxAspectRatioInLandscape() দেখুন। ল্যান্ডস্কেপের জন্য ডিফল্ট মান হল ALWAYS_ALLOW
      • setFinishPrimaryWithPlaceholder() : প্লেসহোল্ডার অ্যাক্টিভিটি কীভাবে শেষ করা প্রাথমিক কন্টেইনারের কার্যকলাপকে প্রভাবিত করে তা সেট করে। সর্বদা নির্দেশ করে যে স্থানধারক শেষ হলে সিস্টেমটি সর্বদা প্রাথমিক কন্টেইনারে ক্রিয়াকলাপগুলি শেষ করবে ( ফিনিশ কার্যক্রম দেখুন)।
      • setSticky() : প্লেসহোল্ডার অ্যাক্টিভিটি ছোট ডিসপ্লেতে অ্যাক্টিভিটি স্ট্যাকের উপরে প্রদর্শিত হবে কিনা তা নির্ধারণ করে যখন প্লেসহোল্ডারটি প্রথম পর্যাপ্ত ন্যূনতম প্রস্থের সাথে একটি বিভাজনে প্রদর্শিত হয়।
    4. WindowManager RuleController এ নিয়ম যোগ করুন:

      কোটলিন

      ruleController.addRule(splitPlaceholderRule)

      জাভা

      ruleController.addRule(splitPlaceholderRule);
  3. এমন ক্রিয়াকলাপগুলি নির্দিষ্ট করুন যা কখনই বিভাজনের অংশ হওয়া উচিত নয়:

    1. একটি ActivityFilter তৈরি করুন যা এমন একটি ক্রিয়াকলাপকে চিহ্নিত করে যা সর্বদা পুরো টাস্ক ডিসপ্লে এরিয়া দখল করবে:

      কোটলিন

      val expandedActivityFilter = ActivityFilter(
        ComponentName(this, ExpandedActivity::class.java),
        null
      )

      জাভা

      ActivityFilter expandedActivityFilter = new ActivityFilter(
        new ComponentName(this, ExpandedActivity.class),
        null
      );
    2. ফিল্টার সেটে ফিল্টার যোগ করুন:

      কোটলিন

      val expandedActivityFilterSet = setOf(expandedActivityFilter)

      জাভা

      Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>();
      expandedActivityFilterSet.add(expandedActivityFilter);
    3. একটি ActivityRule তৈরি করুন:

      কোটলিন

      val activityRule = ActivityRule.Builder(expandedActivityFilterSet)
          .setAlwaysExpand(true)
          .build()

      জাভা

      ActivityRule activityRule = new ActivityRule.Builder(
          expandedActivityFilterSet
      ).setAlwaysExpand(true)
       .build();

      ActivityRule.Builder নিয়ম তৈরি করে এবং কনফিগার করে:

      • expandedActivityFilterSet : কার্যকলাপ ফিল্টার রয়েছে যা নির্ধারণ করে কখন নিয়ম প্রয়োগ করতে হবে এমন কার্যকলাপগুলি চিহ্নিত করে যা আপনি বিভক্ত থেকে বাদ দিতে চান।
      • setAlwaysExpand() : কার্যকলাপটি সম্পূর্ণ টাস্ক উইন্ডোটি পূরণ করবে কিনা তা নির্দিষ্ট করে।
    4. WindowManager RuleController এ নিয়ম যোগ করুন:

      কোটলিন

      ruleController.addRule(activityRule)

      জাভা

      ruleController.addRule(activityRule);

ক্রস-অ্যাপ্লিকেশন এমবেডিং

অ্যান্ড্রয়েড 13 (এপিআই লেভেল 33) এবং উচ্চতর, অ্যাপগুলি অন্যান্য অ্যাপ থেকে অ্যাক্টিভিটি এম্বেড করতে পারে। ক্রস-অ্যাপ্লিকেশন, বা ক্রস- ইউআইডি , অ্যাক্টিভিটি এমবেডিং একাধিক অ্যান্ড্রয়েড অ্যাপ্লিকেশান থেকে ক্রিয়াকলাপগুলির ভিজ্যুয়াল ইন্টিগ্রেশন সক্ষম করে৷ সিস্টেমটি হোস্ট অ্যাপের একটি অ্যাক্টিভিটি এবং অন্য অ্যাপের থেকে একটি এম্বেড করা অ্যাক্টিভিটি স্ক্রিনে পাশাপাশি বা উপরে এবং নীচে একক-অ্যাপ অ্যাক্টিভিটি এম্বেডিংয়ের মতোই প্রদর্শন করে।

উদাহরণস্বরূপ, সেটিংস অ্যাপ WallpaperPicker অ্যাপ থেকে ওয়ালপেপার নির্বাচক কার্যকলাপ এম্বেড করতে পারে:

চিত্র 14. এম্বেড করা কার্যকলাপ (ডানদিকে) হিসাবে ওয়ালপেপার নির্বাচক সহ সেটিংস অ্যাপ (বামে মেনু)।

ট্রাস্ট মডেল

হোস্ট প্রসেস যেগুলি অন্যান্য অ্যাপ থেকে এম্বেড করা ক্রিয়াকলাপগুলি আকার, অবস্থান, ক্রপিং এবং স্বচ্ছতা সহ এমবেড করা ক্রিয়াকলাপগুলির উপস্থাপনাকে পুনরায় সংজ্ঞায়িত করতে সক্ষম। ক্ষতিকারক হোস্ট ব্যবহারকারীদের বিভ্রান্ত করতে এবং ক্লিকজ্যাকিং বা অন্যান্য UI-প্রতিকার আক্রমণ তৈরি করতে এই ক্ষমতা ব্যবহার করতে পারে।

ক্রস-অ্যাপ অ্যাক্টিভিটি এম্বেডিংয়ের অপব্যবহার রোধ করতে, অ্যান্ড্রয়েডের জন্য অ্যাপগুলিকে তাদের ক্রিয়াকলাপগুলি এম্বেড করার অনুমতি দিতে অপ্ট ইন করতে হবে৷ অ্যাপগুলি হোস্টকে বিশ্বস্ত বা অবিশ্বস্ত হিসাবে মনোনীত করতে পারে।

বিশ্বস্ত হোস্ট

অন্যান্য অ্যাপ্লিকেশানগুলিকে আপনার অ্যাপ্লিকেশান থেকে অ্যাক্টিভিটিগুলির উপস্থাপনাকে এম্বেড করতে এবং সম্পূর্ণরূপে নিয়ন্ত্রণ করার অনুমতি দিতে, আপনার অ্যাপের ম্যানিফেস্ট ফাইলের <activity> বা <application> উপাদানগুলির android:knownActivityEmbeddingCerts অ্যাট্রিবিউটে হোস্ট অ্যাপ্লিকেশনের SHA-256 শংসাপত্র নির্দিষ্ট করুন।

একটি স্ট্রিং হিসাবে android:knownActivityEmbeddingCerts এর মান সেট করুন:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
    ... />

অথবা, একাধিক শংসাপত্র নির্দিষ্ট করতে, স্ট্রিংয়ের একটি অ্যারে:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
    ... />

যা নিম্নলিখিত মত একটি সম্পদ উল্লেখ করে:

<resources>
    <string-array name="known_host_certificate_digests">
      <item>cert1</item>
      <item>cert2</item>
      ...
    </string-array>
</resources>

App মালিকরা Gradle signingReport টাস্ক চালিয়ে SHA সার্টিফিকেট ডাইজেস্ট পেতে পারেন। সার্টিফিকেট ডাইজেস্ট হল SHA-256 আঙ্গুলের ছাপ বিচ্ছিন্ন কোলন ছাড়া। আরও তথ্যের জন্য, একটি স্বাক্ষর প্রতিবেদন চালান এবং আপনার ক্লায়েন্ট প্রমাণীকরণ দেখুন।

অবিশ্বস্ত হোস্ট

যেকোনো অ্যাপকে আপনার অ্যাপের ক্রিয়াকলাপ এম্বেড করতে এবং তাদের উপস্থাপনা নিয়ন্ত্রণ করার অনুমতি দিতে, অ্যাপ ম্যানিফেস্টে <activity> বা <application> উপাদানগুলিতে android:allowUntrustedActivityEmbedding বৈশিষ্ট্যটি নির্দিষ্ট করুন, উদাহরণস্বরূপ:

<activity
    android:name=".MyEmbeddableActivity"
    android:allowUntrustedActivityEmbedding="true"
    ... />

অ্যাট্রিবিউটের ডিফল্ট মান মিথ্যা, যা ক্রস-অ্যাপ কার্যকলাপ এম্বেডিং প্রতিরোধ করে।

কাস্টম প্রমাণীকরণ

অবিশ্বস্ত কার্যকলাপ এম্বেডিংয়ের ঝুঁকি কমাতে, একটি কাস্টম প্রমাণীকরণ প্রক্রিয়া তৈরি করুন যা হোস্টের পরিচয় যাচাই করে। আপনি যদি হোস্ট শংসাপত্রগুলি জানেন তবে প্রমাণীকরণের জন্য androidx.security.app.authenticator লাইব্রেরি ব্যবহার করুন৷ যদি হোস্ট আপনার কার্যকলাপ এম্বেড করার পরে প্রমাণীকরণ করে, আপনি প্রকৃত বিষয়বস্তু প্রদর্শন করতে পারেন। যদি তা না হয়, আপনি ব্যবহারকারীকে জানাতে পারেন যে ক্রিয়াটি অনুমোদিত নয় এবং সামগ্রীটি ব্লক করুন৷

একটি হোস্ট আপনার কার্যকলাপ এম্বেড করছে কিনা তা পরীক্ষা করতে Jetpack WindowManager লাইব্রেরি থেকে ActivityEmbeddingController#isActivityEmbedded() পদ্ধতি ব্যবহার করুন, উদাহরণস্বরূপ:

কোটলিন

fun isActivityEmbedded(activity: Activity): Boolean {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity)
}

জাভা

boolean isActivityEmbedded(Activity activity) {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity);
}

ন্যূনতম আকারের সীমাবদ্ধতা

অ্যান্ড্রয়েড সিস্টেম এমবেড করা ক্রিয়াকলাপগুলিতে অ্যাপ ম্যানিফেস্ট <layout> উপাদানে নির্দিষ্ট ন্যূনতম উচ্চতা এবং প্রস্থ প্রয়োগ করে। যদি একটি অ্যাপ্লিকেশন ন্যূনতম উচ্চতা এবং প্রস্থ নির্দিষ্ট না করে, তবে সিস্টেমের ডিফল্ট মান প্রযোজ্য হবে ( sw220dp )।

যদি হোস্ট এমবেডেড কন্টেইনারটিকে ন্যূনতম থেকে ছোট আকারে আকার পরিবর্তন করার চেষ্টা করে, এমবেডেড ধারকটি সম্পূর্ণ টাস্ক বাউন্ড দখল করতে প্রসারিত হয়।

<ক্রিয়াকলাপ-উনাম>

<activity-alias> উপাদানের সাথে কাজ করার জন্য বিশ্বস্ত বা অবিশ্বস্ত কার্যকলাপ এম্বেডিংয়ের জন্য, android:knownActivityEmbeddingCerts বা android:allowUntrustedActivityEmbedding উপনামের পরিবর্তে লক্ষ্য কার্যকলাপে প্রয়োগ করতে হবে। যে নীতি সিস্টেম সার্ভারে নিরাপত্তা যাচাই করে তা লক্ষ্যের উপর সেট করা পতাকার উপর ভিত্তি করে, উপনাম নয়।

হোস্ট অ্যাপ্লিকেশন

হোস্ট অ্যাপ্লিকেশনগুলি ক্রস-অ্যাপ অ্যাক্টিভিটি এমবেডিং প্রয়োগ করে যেভাবে তারা একক-অ্যাপ অ্যাক্টিভিটি এমবেডিং প্রয়োগ করে। SplitPairRule এবং SplitPairFilter বা ActivityRule এবং ActivityFilter অবজেক্ট এমবেড করা কার্যকলাপ এবং টাস্ক উইন্ডো বিভাজন নির্দিষ্ট করে। জেটপ্যাক উইন্ডো ম্যানেজার API কল ব্যবহার করে XML-এ বা রানটাইমে স্প্লিট নিয়মগুলি স্থিরভাবে সংজ্ঞায়িত করা হয়।

যদি একটি হোস্ট অ্যাপ্লিকেশন এমন একটি ক্রিয়াকলাপ এম্বেড করার চেষ্টা করে যা ক্রস-অ্যাপ এম্বেডিং-এ অপ্ট ইন করেনি, কার্যকলাপটি সম্পূর্ণ টাস্ক বাউন্ডে দখল করে। ফলস্বরূপ, হোস্ট অ্যাপ্লিকেশানগুলিকে জানতে হবে লক্ষ্য ক্রিয়াকলাপ ক্রস-অ্যাপ এম্বেডিংয়ের অনুমতি দেয় কিনা।

যদি কোনো এমবেডেড অ্যাক্টিভিটি একই টাস্কে একটি নতুন অ্যাক্টিভিটি শুরু করে এবং নতুন অ্যাক্টিভিটি ক্রস-অ্যাপ এম্বেডিং বেছে না নেয়, তাহলে অ্যাক্টিভিটিটি এমবেডেড কন্টেইনারে অ্যাক্টিভিটি ওভারলে করার পরিবর্তে পুরো টাস্ক বাউন্ড দখল করে।

একটি হোস্ট অ্যাপ্লিকেশন তার নিজস্ব ক্রিয়াকলাপগুলিকে সীমাবদ্ধতা ছাড়াই এম্বেড করতে পারে যতক্ষণ না কার্যক্রম একই টাস্কে চালু হয়।

বিভক্ত উদাহরণ

সম্পূর্ণ উইন্ডো থেকে বিভক্ত

চিত্র 15. কার্যকলাপ A পাশ থেকে B কার্যকলাপ শুরু করে।

কোন রিফ্যাক্টরিং এর প্রয়োজন নেই। আপনি স্থিরভাবে বা রানটাইমে স্প্লিটের জন্য কনফিগারেশন সংজ্ঞায়িত করতে পারেন এবং তারপরে কোনো অতিরিক্ত প্যারামিটার ছাড়াই Context#startActivity() কল করতে পারেন।

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

ডিফল্টরূপে বিভক্ত

যখন একটি অ্যাপ্লিকেশনের ল্যান্ডিং পৃষ্ঠাটি বড় স্ক্রিনে দুটি পাত্রে বিভক্ত করার জন্য ডিজাইন করা হয়, তখন ব্যবহারকারীর অভিজ্ঞতা সবচেয়ে ভাল হয় যখন উভয় ক্রিয়াকলাপ একই সাথে তৈরি এবং উপস্থাপন করা হয়। যাইহোক, ব্যবহারকারী প্রাথমিক কন্টেইনারের কার্যকলাপের সাথে ইন্টারঅ্যাক্ট না করা পর্যন্ত বিভাজনের সেকেন্ডারি কন্টেইনারের জন্য সামগ্রী উপলব্ধ নাও হতে পারে (উদাহরণস্বরূপ, ব্যবহারকারী একটি নেভিগেশন মেনু থেকে একটি আইটেম নির্বাচন করে)। একটি স্থানধারক কার্যকলাপ শূন্যতা পূরণ করতে পারে যতক্ষণ না বিষয়বস্তু বিভাজনের সেকেন্ডারি কন্টেইনারে প্রদর্শিত না হয় ( প্লেসহোল্ডার বিভাগটি দেখুন)।

চিত্র 16. একই সাথে দুটি ক্রিয়াকলাপ খোলার মাধ্যমে বিভক্ত করা হয়েছে। একটি কার্যকলাপ একটি স্থানধারক.

একটি স্থানধারকের সাথে একটি বিভাজন তৈরি করতে, একটি স্থানধারক তৈরি করুন এবং এটিকে প্রাথমিক কার্যকলাপের সাথে সংযুক্ত করুন:

<SplitPlaceholderRule
    window:placeholderActivityName=".PlaceholderActivity">
    <ActivityFilter
        window:activityName=".MainActivity"/>
</SplitPlaceholderRule>

যখন একটি অ্যাপ্লিকেশন একটি অভিপ্রায় গ্রহণ করে, লক্ষ্য কার্যকলাপ একটি কার্যকলাপ বিভাজনের দ্বিতীয় অংশ হিসাবে দেখানো যেতে পারে; উদাহরণস্বরূপ, একটি তালিকা থেকে একটি আইটেম সম্পর্কে তথ্য সহ একটি বিস্তারিত স্ক্রীন দেখানোর জন্য একটি অনুরোধ৷ ছোট ডিসপ্লেতে, বিস্তারিত সম্পূর্ণ টাস্ক উইন্ডোতে দেখানো হয়; বড় ডিভাইসে, তালিকার পাশে।

চিত্র 17. গভীর লিঙ্ক বিস্তারিত কার্যকলাপ একটি ছোট পর্দায় একা দেখানো হয়েছে, কিন্তু একটি বড় পর্দায় একটি তালিকা কার্যকলাপ সহ।

লঞ্চের অনুরোধটি মূল ক্রিয়াকলাপে রুট করা উচিত এবং লক্ষ্য বিস্তারিত ক্রিয়াকলাপটি একটি বিভাজনে চালু করা উচিত। সিস্টেম স্বয়ংক্রিয়ভাবে উপলব্ধ প্রদর্শন প্রস্থের উপর ভিত্তি করে সঠিক উপস্থাপনা - স্তুপীকৃত বা পাশাপাশি - নির্বাচন করে।

কোটলিন

override fun onCreate(savedInstanceState Bundle?) {
    . . .
    RuleController.getInstance(this)
        .addRule(SplitPairRule.Builder(filterSet).build())
    startActivity(Intent(this, DetailActivity::class.java))
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    RuleController.getInstance(this)
        .addRule(new SplitPairRule.Builder(filterSet).build());
    startActivity(new Intent(this, DetailActivity.class));
}

ডিপ লিঙ্ক গন্তব্য হতে পারে একমাত্র কার্যকলাপ যা ব্যবহারকারীর কাছে ব্যাক নেভিগেশন স্ট্যাকে উপলব্ধ হওয়া উচিত, এবং আপনি বিস্তারিত ক্রিয়াকলাপ খারিজ করা এবং শুধুমাত্র প্রধান ক্রিয়াকলাপ ত্যাগ করা এড়াতে চাইতে পারেন:

তালিকা কার্যকলাপ এবং বিস্তারিত কার্যকলাপ পাশাপাশি বড় প্রদর্শন.           পিছনে নেভিগেশন বিস্তারিত কার্যকলাপ খারিজ করতে অক্ষম এবং তালিকা ছেড়ে           পর্দায় কার্যকলাপ।

শুধুমাত্র বিস্তারিত কার্যকলাপ সহ ছোট প্রদর্শন. পিছনে নেভিগেশন অক্ষম           বিস্তারিত কার্যকলাপ খারিজ এবং তালিকা কার্যকলাপ প্রকাশ.

পরিবর্তে, আপনি finishPrimaryWithSecondary বৈশিষ্ট্য ব্যবহার করে একই সময়ে উভয় কার্যক্রম শেষ করতে পারেন:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".ListActivity"
        window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>

কনফিগারেশন বৈশিষ্ট্য বিভাগ দেখুন।

বিভক্ত পাত্রে একাধিক কার্যক্রম

একটি বিভক্ত পাত্রে একাধিক ক্রিয়াকলাপ স্ট্যাক করা ব্যবহারকারীদের গভীর সামগ্রী অ্যাক্সেস করতে সক্ষম করে। উদাহরণস্বরূপ, একটি তালিকা-বিশদ বিভাজনের সাথে, ব্যবহারকারীকে একটি সাব-বিশদ বিভাগে যেতে হতে পারে তবে প্রাথমিক কার্যকলাপটি জায়গায় রাখতে হবে:

চিত্র 18. টাস্ক উইন্ডোর সেকেন্ডারি প্যানে জায়গায় ক্রিয়াকলাপ খোলা হয়েছে।

কোটলিন

class DetailActivity {
    . . .
    fun onOpenSubDetail() {
      startActivity(Intent(this, SubDetailActivity::class.java))
    }
}

জাভা

public class DetailActivity {
    . . .
    void onOpenSubDetail() {
        startActivity(new Intent(this, SubDetailActivity.class));
    }
}

উপ-বিস্তারিত কার্যকলাপ বিস্তারিত কার্যকলাপের উপরে স্থাপন করা হয়, এটি গোপন করে:

ব্যবহারকারী স্ট্যাকের মাধ্যমে ফিরে নেভিগেট করে পূর্ববর্তী বিশদ স্তরে ফিরে যেতে পারেন:

চিত্র 19. স্ট্যাকের শীর্ষ থেকে কার্যকলাপ সরানো হয়েছে৷

ক্রিয়াকলাপগুলিকে একে অপরের উপরে স্ট্যাক করা ডিফল্ট আচরণ যখন একই মাধ্যমিক পাত্রে একটি কার্যকলাপ থেকে ক্রিয়াকলাপ চালু করা হয়। একটি সক্রিয় বিভাজনের মধ্যে প্রাথমিক কন্টেইনার থেকে চালু করা কার্যকলাপগুলিও অ্যাক্টিভিটি স্ট্যাকের শীর্ষে গৌণ পাত্রে শেষ হয়।

একটি নতুন কাজে কার্যকলাপ

যখন একটি বিভক্ত টাস্ক উইন্ডোর কার্যকলাপগুলি একটি নতুন টাস্কে ক্রিয়াকলাপ শুরু করে, তখন নতুন টাস্কটি সেই টাস্ক থেকে আলাদা হয় যা বিভক্তটি অন্তর্ভুক্ত করে এবং পুরো উইন্ডোটি প্রদর্শিত হয়। সাম্প্রতিক স্ক্রীন দুটি কাজ দেখায়: বিভক্ত কাজ এবং নতুন টাস্ক।

চিত্র 20. B কার্যকলাপ থেকে একটি নতুন টাস্কে কার্যকলাপ C শুরু করুন।

কার্যকলাপ প্রতিস্থাপন

ক্রিয়াকলাপগুলি সেকেন্ডারি কন্টেইনার স্ট্যাকের মধ্যে প্রতিস্থাপিত করা যেতে পারে; উদাহরণস্বরূপ, যখন প্রাথমিক ক্রিয়াকলাপটি উচ্চ-স্তরের নেভিগেশনের জন্য ব্যবহৃত হয় এবং দ্বিতীয় ক্রিয়াকলাপটি একটি নির্বাচিত গন্তব্য। শীর্ষ-স্তরের নেভিগেশন থেকে প্রতিটি নির্বাচনকে সেকেন্ডারি কন্টেইনারে একটি নতুন কার্যকলাপ শুরু করা উচিত এবং পূর্বে সেখানে থাকা কার্যকলাপ বা কার্যকলাপগুলিকে সরিয়ে দেওয়া উচিত।

চিত্র 21. প্রাথমিক প্যানে শীর্ষ-স্তরের নেভিগেশন কার্যকলাপ গৌণ ফলকে গন্তব্য কার্যকলাপ প্রতিস্থাপন করে।

ন্যাভিগেশন নির্বাচন পরিবর্তিত হওয়ার সময় অ্যাপটি সেকেন্ডারি কন্টেইনারে ক্রিয়াকলাপ শেষ না করলে, স্প্লিটটি ভেঙে গেলে (যখন ডিভাইসটি ভাঁজ করা হয়) তখন ব্যাক নেভিগেশন বিভ্রান্তিকর হতে পারে। উদাহরণস্বরূপ, যদি আপনার প্রাথমিক ফলকটিতে একটি মেনু থাকে এবং সেকেন্ডারি ফলকে স্ক্রীন A এবং B স্ট্যাক করা থাকে, ব্যবহারকারী যখন ফোনটি ভাঁজ করেন, তখন B A এর উপরে থাকে এবং A মেনুর উপরে থাকে। ব্যবহারকারী যখন B থেকে ফিরে যান, তখন মেনুর পরিবর্তে A উপস্থিত হয়।

এই ধরনের ক্ষেত্রে স্ক্রীন A অবশ্যই ব্যাক স্ট্যাক থেকে সরিয়ে ফেলতে হবে।

একটি বিদ্যমান স্প্লিটের উপর একটি নতুন পাত্রে সাইডে লঞ্চ করার সময় ডিফল্ট আচরণ হল নতুন গৌণ কন্টেইনারগুলিকে উপরে রাখা এবং পুরানোগুলিকে পিছনের স্ট্যাকে রাখা। আপনি clearTop সাথে পূর্ববর্তী সেকেন্ডারি কন্টেইনারগুলি সাফ করার জন্য বিভক্তগুলি কনফিগার করতে পারেন এবং সাধারণভাবে নতুন কার্যকলাপ চালু করতে পারেন।

<SplitPairRule
    window:clearTop="true">
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenA"/>
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>

কোটলিন

class MenuActivity {
    . . .
    fun onMenuItemSelected(selectedMenuItem: Int) {
        startActivity(Intent(this, classForItem(selectedMenuItem)))
    }
}

জাভা

public class MenuActivity {
    . . .
    void onMenuItemSelected(int selectedMenuItem) {
        startActivity(new Intent(this, classForItem(selectedMenuItem)));
    }
}

বিকল্পভাবে, একই সেকেন্ডারি অ্যাক্টিভিটি ব্যবহার করুন এবং প্রাথমিক (মেনু) অ্যাক্টিভিটি থেকে নতুন ইন্টেন্ট পাঠান যা একই উদাহরণে সমাধান করে কিন্তু সেকেন্ডারি কন্টেইনারে একটি স্টেট বা UI আপডেট ট্রিগার করে।

একাধিক বিভাজন

অ্যাপ্লিকেশানগুলি পাশে অতিরিক্ত কার্যকলাপ চালু করে বহু-স্তরের গভীর নেভিগেশন প্রদান করতে পারে।

যখন একটি মাধ্যমিক পাত্রে একটি কার্যকলাপ পাশে একটি নতুন কার্যকলাপ চালু করে, তখন বিদ্যমান বিভাজনের উপরে একটি নতুন স্প্লিট তৈরি হয়।

চিত্র 22. কার্যকলাপ B পাশ থেকে C কার্যকলাপ শুরু করে।

ব্যাক স্ট্যাকটিতে পূর্বে খোলা সমস্ত ক্রিয়াকলাপ রয়েছে, যাতে ব্যবহারকারীরা C শেষ করার পরে A/B বিভাজনে নেভিগেট করতে পারে।

একটি স্ট্যাকে A, B, এবং C কার্যক্রম। কার্যক্রমগুলি স্ট্যাক করা হয়           উপরে থেকে নীচের ক্রম: C, B, A।

একটি নতুন বিভাজন তৈরি করতে, বিদ্যমান মাধ্যমিক ধারক থেকে নতুন ক্রিয়াকলাপটি চালু করুন। এ/বি এবং বি/সি উভয়ের জন্য কনফিগারেশনগুলি ঘোষণা করুন এবং বি থেকে সাধারণত ক্রিয়াকলাপ সি চালু করুন:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
    <SplitPairFilter
        window:primaryActivityName=".B"
        window:secondaryActivityName=".C"/>
</SplitPairRule>

কোটলিন

class B {
    . . .
    fun onOpenC() {
        startActivity(Intent(this, C::class.java))
    }
}

জাভা

public class B {
    . . .
    void onOpenC() {
        startActivity(new Intent(this, C.class));
    }
}

বিভক্ত রাষ্ট্রের পরিবর্তনগুলিতে প্রতিক্রিয়া জানান

কোনও অ্যাপ্লিকেশনটিতে বিভিন্ন ক্রিয়াকলাপে ইউআই উপাদান থাকতে পারে যা একই ফাংশন সম্পাদন করে; উদাহরণস্বরূপ, একটি নিয়ন্ত্রণ যা অ্যাকাউন্ট সেটিংসযুক্ত একটি উইন্ডো খোলে।

চিত্র 23। কার্যত অভিন্ন ইউআই উপাদানগুলির সাথে বিভিন্ন ক্রিয়াকলাপ।

যদি দুটি ক্রিয়াকলাপের মধ্যে একটি ইউআই উপাদান রয়েছে তবে এটি বিভক্ত হয়ে থাকে তবে এটি অপ্রয়োজনীয় এবং সম্ভবত উভয় ক্রিয়াকলাপে উপাদানটি দেখানোর জন্য বিভ্রান্তিকর।

চিত্র 24। ক্রিয়াকলাপ বিভক্তিতে সদৃশ ইউআই উপাদানগুলি।

ক্রিয়াকলাপগুলি যখন বিভক্ত হয় তখন তা জানতে, SplitController.splitInfoList পরীক্ষা করে দেখুন splitynflist প্রবাহ বা বিভক্ত অবস্থার পরিবর্তনের জন্য SplitControllerCallbackAdapter সাথে শ্রোতাদের নিবন্ধ করুন। তারপরে, সেই অনুযায়ী ইউআই সামঞ্জস্য করুন:

কোটলিন

val layout = layoutInflater.inflate(R.layout.activity_main, null)
val view = layout.findViewById<View>(R.id.infoButton)
lifecycleScope.launch {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance.
            .collect { list ->
                view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
            }
    }
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    new SplitControllerCallbackAdapter(SplitController.getInstance(this))
        .addSplitListener(
            this,
            Runnable::run,
            splitInfoList -> {
                View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
                layout.findViewById(R.id.infoButton).setVisibility(
                    splitInfoList.isEmpty() ? View.VISIBLE : View.GONE);
            });
}

করুটাইনগুলি যে কোনও লাইফসাইকেল অবস্থায় চালু করা যেতে পারে, তবে সাধারণত সংস্থান সংরক্ষণের জন্য STARTED চালু করা হয় (আরও তথ্যের জন্য লাইফসাইকেল-সচেতন উপাদানগুলির সাথে কোটলিন করুটাইনগুলি ব্যবহার করুন ) দেখুন।

কোনও ক্রিয়াকলাপ বন্ধ হয়ে গেলে যে কোনও লাইফসাইকেল অবস্থায় কলব্যাকগুলি করা যেতে পারে। শ্রোতাদের সাধারণত onStart() এ নিবন্ধিত হওয়া উচিত এবং onStop() এ নিবন্ধভুক্ত করা উচিত।

ফুল-উইন্ডো মডেল

কিছু ক্রিয়াকলাপ ব্যবহারকারীদের একটি নির্দিষ্ট ক্রিয়া সম্পাদন না হওয়া পর্যন্ত অ্যাপ্লিকেশনটির সাথে আলাপচারিতা থেকে অবরুদ্ধ করে; উদাহরণস্বরূপ, একটি লগইন স্ক্রিন ক্রিয়াকলাপ, নীতি স্বীকৃতি স্ক্রিন বা ত্রুটি বার্তা। মডেল ক্রিয়াকলাপগুলি একটি বিভক্তিতে উপস্থিত হতে বাধা দেওয়া উচিত।

একটি ক্রিয়াকলাপটি এক্সপেন্ড কনফিগারেশনটি ব্যবহার করে সর্বদা টাস্ক উইন্ডোটি পূরণ করতে বাধ্য করা যেতে পারে:

<ActivityRule
    window:alwaysExpand="true">
    <ActivityFilter
        window:activityName=".FullWidthActivity"/>
</ActivityRule>

ক্রিয়াকলাপ শেষ

ব্যবহারকারীরা ডিসপ্লেটির প্রান্ত থেকে সোয়াইপ করে বিভাজনের উভয় পাশে ক্রিয়াকলাপ শেষ করতে পারেন:

চিত্র 25। সোয়াইপ অঙ্গভঙ্গি সমাপ্তি ক্রিয়াকলাপ বি।
চিত্র 26। সোয়াইপ অঙ্গভঙ্গি সমাপ্তি ক্রিয়াকলাপ এ।

যদি ডিভাইস নেভিগেশনের পরিবর্তে পিছনের বোতামটি ব্যবহার করতে ডিভাইসটি সেট আপ করা হয় তবে ইনপুটটি ফোকাসযুক্ত ক্রিয়াকলাপে প্রেরণ করা হয় - এমন ক্রিয়াকলাপ যা ছোঁয়া বা সর্বশেষ চালু করা হয়েছিল।

কোনও ধারকটিতে সমস্ত ক্রিয়াকলাপ সমাপ্ত করার প্রভাবটি বিরোধী পাত্রে রয়েছে তা বিভক্ত কনফিগারেশনের উপর নির্ভর করে।

কনফিগারেশন বৈশিষ্ট্য

বিভক্তির একপাশে সমস্ত ক্রিয়াকলাপ কীভাবে শেষ করা বিভাজনের অন্য পাশের ক্রিয়াকলাপগুলিকে প্রভাবিত করে তা কনফিগার করতে আপনি বিভক্ত জোড় নিয়মের বৈশিষ্ট্যগুলি নির্দিষ্ট করতে পারেন। গুণাবলী হল:

  • window:finishPrimaryWithSecondary - মাধ্যমিক ধারকটিতে সমস্ত ক্রিয়াকলাপ কীভাবে শেষ করা প্রাথমিক ধারকটির ক্রিয়াকলাপগুলিকে প্রভাবিত করে
  • window:finishSecondaryWithPrimary - প্রাথমিক ধারকটিতে সমস্ত ক্রিয়াকলাপ কীভাবে শেষ করা গৌণ ধারকটির ক্রিয়াকলাপগুলিকে প্রভাবিত করে

বৈশিষ্ট্যগুলির সম্ভাব্য মানগুলির মধ্যে রয়েছে:

  • always - সর্বদা সম্পর্কিত পাত্রে ক্রিয়াকলাপগুলি শেষ করুন
  • never - সম্পর্কিত পাত্রে ক্রিয়াকলাপ শেষ করবেন না
  • adjacent - দুটি পাত্রে একে অপরের সংলগ্ন প্রদর্শিত হলে সম্পর্কিত পাত্রে ক্রিয়াকলাপগুলি শেষ করুন, তবে দুটি পাত্রে স্ট্যাক করা থাকলে নয়

যেমন:

<SplitPairRule
    &lt;!-- Do not finish primary container activities when all secondary container activities finish. --&gt;
    window:finishPrimaryWithSecondary="never"
    &lt;!-- Finish secondary container activities when all primary container activities finish. --&gt;
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

ডিফল্ট কনফিগারেশন

যখন বিভক্ত সমাপ্তির এক পাত্রে সমস্ত ক্রিয়াকলাপ হয়, তখন বাকী ধারকটি পুরো উইন্ডোটি দখল করে:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

এ এবং বি এ ক্রিয়াকলাপযুক্ত বিভাজন বি বি ছেড়ে যায়           পুরো উইন্ডোটি দখল করুন।

ক্রিয়াকলাপ এ এবং বি বি সমন্বিত বিভক্ত হয়ে গেছে, এ ছেড়ে চলে গেছে           পুরো উইন্ডোটি দখল করুন।

একসাথে ক্রিয়াকলাপ শেষ করুন

গৌণ ধারক সমাপ্তির সমস্ত ক্রিয়াকলাপ স্বয়ংক্রিয়ভাবে প্রাথমিক ধারকটিতে ক্রিয়াকলাপগুলি শেষ করুন:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

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

এ এবং বি এ ক্রিয়াকলাপযুক্ত বিভক্ত হয়ে বি -এ শেষ হয়ে গেছে, বি একা রেখে           টাস্ক উইন্ডোতে।

প্রাথমিক ধারক সমাপ্তির সমস্ত ক্রিয়াকলাপ যখন স্বয়ংক্রিয়ভাবে মাধ্যমিক ধারকটিতে ক্রিয়াকলাপগুলি শেষ করুন:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

ক্রিয়াকলাপ এ এবং বি এ সম্বলিত বিভক্ত, এটিও শেষ হয়েছে           টাস্ক উইন্ডোটি খালি রেখে বি শেষ করে।

ক্রিয়াকলাপ এ এবং বি বি সমন্বিত বিভাজন শেষ হয়েছে, একা রেখে           টাস্ক উইন্ডোতে।

প্রাথমিক বা গৌণ ধারক সমাপ্তিতে সমস্ত ক্রিয়াকলাপ শেষ হলে একসাথে ক্রিয়াকলাপ শেষ করুন:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

ক্রিয়াকলাপ এ এবং বি এ সম্বলিত বিভক্ত, এটিও শেষ হয়েছে           টাস্ক উইন্ডোটি খালি রেখে বি শেষ করে।

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

পাত্রে একাধিক ক্রিয়াকলাপ শেষ করুন

যদি একাধিক ক্রিয়াকলাপ একটি বিভক্ত পাত্রে স্ট্যাক করা হয় তবে স্ট্যাকের নীচে কোনও ক্রিয়াকলাপ শেষ করা স্বয়ংক্রিয়ভাবে শীর্ষে ক্রিয়াকলাপগুলি শেষ করে না।

উদাহরণস্বরূপ, যদি দুটি ক্রিয়াকলাপ মাধ্যমিক পাত্রে থাকে তবে বি এর শীর্ষে সি:

ক্রিয়াকলাপ সি সমন্বিত গৌণ ক্রিয়াকলাপ স্ট্যাক বি এর শীর্ষে স্ট্যাক করা           ক্রিয়াকলাপযুক্ত প্রিমারি ক্রিয়াকলাপ স্ট্যাকের শীর্ষে সজ্জিত           ক.

এবং বিভক্তির কনফিগারেশনটি A এবং B এর ক্রিয়াকলাপের কনফিগারেশন দ্বারা সংজ্ঞায়িত করা হয়:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

শীর্ষ কার্যকলাপ শেষ করা বিভাজনকে ধরে রাখে।

প্রাথমিক ধারক এবং ক্রিয়াকলাপে ক্রিয়াকলাপের সাথে বিভক্ত করুন বি এবং সি ইন           মাধ্যমিক, সি বি সি সমাপ্তির শীর্ষে স্ট্যাক করা হয়েছে, এ এবং বি রেখে           ক্রিয়াকলাপ বিভক্ত।

মাধ্যমিক ধারকটির নীচের (মূল) ক্রিয়াকলাপ শেষ করা এর শীর্ষে ক্রিয়াকলাপগুলি সরিয়ে দেয় না; এবং তাই, বিভাজনও ধরে রাখে।

প্রাথমিক ধারক এবং ক্রিয়াকলাপে ক্রিয়াকলাপের সাথে বিভক্ত করুন বি এবং সি ইন           মাধ্যমিক, সি বি এর শীর্ষে স্ট্যাক করা হয়েছে, এ এবং সি রেখে           ক্রিয়াকলাপ বিভক্ত।

একসাথে ক্রিয়াকলাপ শেষ করার জন্য যে কোনও অতিরিক্ত নিয়ম যেমন প্রাথমিকের সাথে মাধ্যমিক ক্রিয়াকলাপ শেষ করাও কার্যকর করা হয়:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

প্রাথমিক ধারক এবং ক্রিয়াকলাপে ক্রিয়াকলাপের সাথে বিভক্ত করুন বি এবং সি ইন           মাধ্যমিক ধারক, সি বি এর শীর্ষে স্ট্যাক করা একটি সমাপ্তি, এছাড়াও           সমাপ্তি খ এবং সি

এবং যখন বিভাজনটি একসাথে প্রাথমিক এবং মাধ্যমিক শেষ করতে কনফিগার করা হয়:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

প্রাথমিক ধারক এবং ক্রিয়াকলাপে ক্রিয়াকলাপের সাথে বিভক্ত করুন বি এবং সি ইন           মাধ্যমিক, সি বি সি সমাপ্তির শীর্ষে স্ট্যাক করা হয়েছে, এ এবং বি রেখে           ক্রিয়াকলাপ বিভক্ত।

প্রাথমিক ধারক এবং ক্রিয়াকলাপে ক্রিয়াকলাপের সাথে বিভক্ত করুন বি এবং সি ইন           মাধ্যমিক, সি বি এর শীর্ষে স্ট্যাক করা হয়েছে, এ এবং সি রেখে           ক্রিয়াকলাপ বিভক্ত।

প্রাথমিক ধারক এবং ক্রিয়াকলাপে ক্রিয়াকলাপের সাথে বিভক্ত করুন বি এবং সি ইন           মাধ্যমিক, সি বি এর শীর্ষে স্ট্যাকড এ ফিনিস, এছাড়াও বি এবং সমাপ্তি           গ.

রানটাইমে বিভক্ত বৈশিষ্ট্য পরিবর্তন করুন

একটি সক্রিয় এবং দৃশ্যমান বিভক্তির বৈশিষ্ট্যগুলি পরিবর্তন করা যায় না। বিভক্ত নিয়মগুলি পরিবর্তন করা অতিরিক্ত ক্রিয়াকলাপ লঞ্চ এবং নতুন পাত্রে প্রভাবিত করে তবে বিদ্যমান এবং সক্রিয় বিভাজন নয়।

সক্রিয় বিভাজনের বৈশিষ্ট্যগুলি পরিবর্তন করতে, বিভক্তিতে পার্শ্ব ক্রিয়াকলাপ বা ক্রিয়াকলাপগুলি শেষ করুন এবং একটি নতুন কনফিগারেশন সহ আবার পাশে চালু করুন।

গতিশীল বিভক্ত বৈশিষ্ট্য

অ্যান্ড্রয়েড 15 (এপিআই স্তর 35) এবং উচ্চতর জেটপ্যাক উইন্ডো ম্যানেজার 1.4 দ্বারা সমর্থিত এবং উচ্চতর অফার গতিশীল বৈশিষ্ট্য যা ক্রিয়াকলাপ এম্বেডিং স্প্লিটগুলির কনফিগারেশন সক্ষম করে, সহ:

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

ফলক সম্প্রসারণ

ফলক সম্প্রসারণ ব্যবহারকারীদের দ্বৈত - পেন বিন্যাসে দুটি ক্রিয়াকলাপে বরাদ্দকৃত স্ক্রিন স্পেসের পরিমাণ সামঞ্জস্য করতে সক্ষম করে।

উইন্ডো ডিভাইডারের উপস্থিতি কাস্টমাইজ করতে এবং ডিভাইডারের ড্র্যাগেবল পরিসীমা সেট করতে, নিম্নলিখিতগুলি করুন:

  1. DividerAttributes একটি উদাহরণ তৈরি করুন

  2. ডিভাইডার বৈশিষ্ট্যগুলি কাস্টমাইজ করুন:

    • color : ড্র্যাগেবল ফলক বিভাজকের রঙ।

    • widthDp : ড্রাগেবল ফলক বিভাজকটির প্রস্থ। সিস্টেমটিকে ডিভাইডার প্রস্থ নির্ধারণ করতে WIDTH_SYSTEM_DEFAULT সেট করুন।

    • ড্র্যাগ রেঞ্জ: পর্দার সর্বনিম্ন শতাংশ উভয় ফলক দখল করতে পারে। 0.33 থেকে 0.66 পর্যন্ত হতে পারে। সিস্টেমটিকে ড্র্যাগের পরিসীমা নির্ধারণ করতে DRAG_RANGE_SYSTEM_DEFAULT সেট করুন।

কোটলিন

val splitAttributesBuilder: SplitAttributes.Builder = SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)

if (WindowSdkExtensions.getInstance().extensionVersion >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    )
}
val splitAttributes: SplitAttributes = splitAttributesBuilder.build()

জাভা

SplitAttributes.Builder splitAttributesBuilder = new SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT);

if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      new DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(ContextCompat.getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    );
}
SplitAttributes splitAttributes = splitAttributesBuilder.build();

ক্রিয়াকলাপ স্ট্যাক পিনিং

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

আপনার অ্যাপ্লিকেশনটিতে ক্রিয়াকলাপ স্ট্যাক পিন সক্ষম করতে, নিম্নলিখিতগুলি করুন:

  1. আপনি যে ক্রিয়াকলাপটি পিন করতে চান তার লেআউট ফাইলে একটি বোতাম যুক্ত করুন, উদাহরণস্বরূপ, একটি তালিকার বিশদ ক্রিয়াকলাপ - ডিটেল লেআউট:

    <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/detailActivity"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white"
     tools:context=".DetailActivity">
    
    <TextView
       android:id="@+id/textViewItemDetail"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="36sp"
       android:textColor="@color/obsidian"
       app:layout_constraintBottom_toTopOf="@id/pinButton"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
    
    <androidx.appcompat.widget.AppCompatButton
       android:id="@+id/pinButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/pin_this_activity"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@id/textViewItemDetail"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. ক্রিয়াকলাপের onCreate() পদ্ধতিতে বোতামে একটি অনক্লিক শ্রোতা সেট করুন:

    কোটলিন

    pinButton = findViewById(R.id.pinButton)
    pinButton.setOnClickListener {
        val splitAttributes: SplitAttributes = SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build()
    
        val pinSplitRule = SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build()
    
        SplitController.getInstance(applicationContext).pinTopActivityStack(taskId, pinSplitRule)
    }

    জাভা

    Button pinButton = findViewById(R.id.pinButton);
    pinButton.setOnClickListener( (view) => {
        SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();
    
        SplitPinRule pinSplitRule = new SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build();
    
        SplitController.getInstance(getApplicationContext()).pinTopActivityStack(getTaskId(), pinSplitRule);
    });

ডায়ালগ পূর্ণ-স্ক্রিন ম্লান

ক্রিয়াকলাপগুলি সাধারণত একটি সংলাপের দিকে দৃষ্টি আকর্ষণ করার জন্য তাদের প্রদর্শনগুলি ম্লান করে দেয়। ক্রিয়াকলাপ এম্বেডিংয়ে, দ্বৈত - পেন ডিসপ্লেটির উভয় প্যানই ম্লান হওয়া উচিত, কেবল একটি ইউনিফাইড ইউআই অভিজ্ঞতার জন্য ডায়ালগটি খোলার ক্রিয়াকলাপযুক্ত ফলকটি নয়।

উইন্ডো ম্যানেজার 1.4 এবং উচ্চতর সহ, পুরো অ্যাপ্লিকেশন উইন্ডোটি ডিফল্টরূপে ডিফল্টরূপে ম্লান হয়ে যায় যখন কোনও ডায়ালগটি খোলে ( EmbeddingConfiguration.DimAreaBehavior.ON_TASK দেখুন।

ডায়ালগটি খোলার ক্রিয়াকলাপের কেবল ধারকটি ম্লান করতে, EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK ব্যবহার করুন।

একটি বিভক্ত থেকে সম্পূর্ণ উইন্ডোতে একটি ক্রিয়াকলাপ বের করুন

একটি নতুন কনফিগারেশন তৈরি করুন যা পার্শ্ব ক্রিয়াকলাপ পূর্ণ উইন্ডো প্রদর্শন করে এবং তারপরে একই উদাহরণে সমাধান করে এমন একটি অভিপ্রায় দিয়ে ক্রিয়াকলাপটি পুনরায় চালু করুন।

রানটাইমে স্প্লিট সাপোর্টের জন্য পরীক্ষা করুন

ক্রিয়াকলাপ এম্বেডিং অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং উচ্চতরগুলিতে সমর্থিত, তবে এটি পূর্ববর্তী প্ল্যাটফর্ম সংস্করণগুলি চলমান কিছু ডিভাইসেও উপলব্ধ। বৈশিষ্ট্যটির প্রাপ্যতার জন্য রানটাইম চেক করতে, SplitController.splitSupportStatus প্রপার্টি বা SplitController.getSplitSupportStatus() পদ্ধতি ব্যবহার করুন:

কোটলিন

if (SplitController.getInstance(this).splitSupportStatus ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

জাভা

if (SplitController.getInstance(this).getSplitSupportStatus() ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

যদি বিভাজনগুলি সমর্থন না করা হয় তবে ক্রিয়াকলাপ স্ট্যাকের শীর্ষে ক্রিয়াকলাপগুলি চালু করা হয় (অ-অ্যাক্টিভিটি এম্বেডিং মডেল অনুসরণ করে)।

সিস্টেম ওভাররাইড প্রতিরোধ করুন

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

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

আপনার অ্যাপ্লিকেশন অ্যাপ্লিকেশন ম্যানিফেস্ট ফাইলে কোনও সম্পত্তি সেট করে সিস্টেমের ক্রিয়াকলাপ এম্বেড করা প্রতিরোধ বা অনুমতি দিতে পারে, উদাহরণস্বরূপ:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <property
            android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
            android:value="true|false" />
    </application>
</manifest>

সম্পত্তির নামটি জেটপ্যাক উইন্ডো ম্যানেজার WindowProperties অবজেক্টে সংজ্ঞায়িত করা হয়েছে। যদি আপনার অ্যাপ্লিকেশন ক্রিয়াকলাপ এম্বেডিং প্রয়োগ করে বা আপনি যদি অন্যথায় সিস্টেমটিকে আপনার অ্যাপ্লিকেশনটিতে এম্বেডিং বিধি প্রয়োগ করতে বাধা দিতে চান তবে false মানটি সেট করুন। আপনার অ্যাপ্লিকেশনটিতে সিস্টেম-সংজ্ঞায়িত ক্রিয়াকলাপ এম্বেডিং প্রয়োগ করার জন্য সিস্টেমকে অনুমতি দেওয়ার জন্য true মানটি সেট করুন।

সীমাবদ্ধতা, বিধিনিষেধ এবং সতর্কতা

  • টাস্কের মূল ক্রিয়াকলাপের মালিক হিসাবে চিহ্নিত কেবলমাত্র টাস্কের হোস্ট অ্যাপ্লিকেশনটি টাস্কে অন্যান্য ক্রিয়াকলাপগুলি সংগঠিত করতে এবং এম্বেড করতে পারে। এম্বেডিং এবং বিভাজনকে সমর্থন করে এমন ক্রিয়াকলাপগুলি যদি কোনও ভিন্ন অ্যাপ্লিকেশন সম্পর্কিত কোনও কার্যক্রমে চালিত হয়, তবে এম্বেডিং এবং বিভাজনগুলি সেই ক্রিয়াকলাপগুলির জন্য কাজ করবে না।
  • ক্রিয়াকলাপগুলি কেবল একটি একক কাজের মধ্যে সংগঠিত করা যেতে পারে। একটি নতুন টাস্কে কোনও ক্রিয়াকলাপ চালু করা সর্বদা এটি কোনও বিদ্যমান বিভাজনের বাইরে একটি নতুন প্রসারিত উইন্ডোতে রাখে।
  • কেবলমাত্র একই প্রক্রিয়াতে ক্রিয়াকলাপগুলি সংগঠিত করা যায় এবং একটি বিভক্তিতে রাখা যেতে পারে। SplitInfo কলব্যাক কেবলমাত্র একই প্রক্রিয়া সম্পর্কিত ক্রিয়াকলাপগুলি রিপোর্ট করে, যেহেতু বিভিন্ন প্রক্রিয়াতে ক্রিয়াকলাপ সম্পর্কে জানার কোনও উপায় নেই।
  • প্রতিটি জোড়া বা একক ক্রিয়াকলাপ নিয়ম কেবল নিয়ম নিবন্ধিত হওয়ার পরে ঘটে এমন ক্রিয়াকলাপ চালু করার ক্ষেত্রে প্রযোজ্য। বর্তমানে বিদ্যমান বিভাজন বা তাদের ভিজ্যুয়াল বৈশিষ্ট্যগুলি আপডেট করার কোনও উপায় নেই।
  • স্প্লিট জোড় ফিল্টার কনফিগারেশন অবশ্যই ক্রিয়াকলাপগুলি সম্পূর্ণরূপে চালু করার সময় ব্যবহৃত অভিপ্রায়গুলির সাথে মেলে। অ্যাপ্লিকেশন প্রক্রিয়া থেকে যখন একটি নতুন ক্রিয়াকলাপ শুরু হয় তখন ম্যাচিংটি ঘটে থাকে, তাই এটি অন্তর্নিহিত উদ্দেশ্যগুলি ব্যবহার করার সময় সিস্টেম প্রক্রিয়াতে পরে সমাধান করা উপাদানগুলির নামগুলি সম্পর্কে নাও জানতে পারে। যদি কোনও উপাদানটির নাম প্রবর্তনের সময় জানা না যায় তবে পরিবর্তে একটি ওয়াইল্ডকার্ড ব্যবহার করা যেতে পারে ("*/*") এবং ফিল্টারিং অভিপ্রায় ক্রিয়াকলাপের ভিত্তিতে সম্পাদন করা যেতে পারে।
  • পাত্রে বা বিভক্ত হওয়ার পরে এবং তাদের তৈরি হওয়ার পরে বিভাজনের বাইরে ক্রিয়াকলাপগুলি সরিয়ে নেওয়ার কোনও উপায় নেই। স্প্লিটগুলি কেবল উইন্ডো ম্যানেজার লাইব্রেরি দ্বারা তৈরি করা হয় যখন ম্যাচিং বিধিগুলির সাথে নতুন ক্রিয়াকলাপ চালু করা হয় এবং বিভক্ত ধারকটিতে শেষ ক্রিয়াকলাপ শেষ হয়ে গেলে বিভাজনগুলি ধ্বংস হয়ে যায়।
  • কনফিগারেশনটি পরিবর্তিত হলে ক্রিয়াকলাপগুলি পুনরায় চালু করা যেতে পারে, সুতরাং যখন কোনও বিভাজন তৈরি করা হয় বা অপসারণ করা হয় এবং ক্রিয়াকলাপের সীমা পরিবর্তন হয়, তখন ক্রিয়াকলাপটি পূর্ববর্তী উদাহরণটির সম্পূর্ণ ধ্বংস এবং নতুনটির সৃষ্টির মধ্য দিয়ে যেতে পারে। ফলস্বরূপ, অ্যাপ্লিকেশন বিকাশকারীদের লাইফসাইকেল কলব্যাকগুলি থেকে নতুন ক্রিয়াকলাপ চালু করার মতো বিষয়গুলির সাথে সতর্ক হওয়া উচিত।
  • ক্রিয়াকলাপ এম্বেডিং সমর্থন করার জন্য ডিভাইসগুলিকে অবশ্যই উইন্ডো এক্সটেনশন ইন্টারফেস অন্তর্ভুক্ত করতে হবে। অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) বা উচ্চতর চলমান প্রায় সমস্ত বড় স্ক্রিন ডিভাইস ইন্টারফেস অন্তর্ভুক্ত। তবে, কিছু বড় স্ক্রিন ডিভাইস যা একাধিক ক্রিয়াকলাপ চালাতে সক্ষম নয় তা উইন্ডো এক্সটেনশন ইন্টারফেস অন্তর্ভুক্ত করে না। যদি কোনও বৃহত স্ক্রিন ডিভাইস মাল্টি-উইন্ডো মোড সমর্থন না করে তবে এটি ক্রিয়াকলাপ এম্বেডিং সমর্থন করতে পারে না।

অতিরিক্ত সম্পদ

,

ক্রিয়াকলাপ এম্বেডিং একই ক্রিয়াকলাপের দুটি ক্রিয়াকলাপ বা দুটি দৃষ্টান্তের মধ্যে একটি অ্যাপ্লিকেশনটির টাস্ক উইন্ডো বিভক্ত করে বড় স্ক্রিন ডিভাইসে অ্যাপ্লিকেশনগুলিকে অনুকূল করে।

চিত্র 1। পাশাপাশি ক্রিয়াকলাপ সহ সেটিংস অ্যাপ্লিকেশন।

যদি আপনার অ্যাপ্লিকেশনটি একাধিক ক্রিয়াকলাপ নিয়ে থাকে তবে ক্রিয়াকলাপ এম্বেডিং আপনাকে ট্যাবলেট, ফোল্ডেবল এবং ক্রোমিওস ডিভাইসে বর্ধিত ব্যবহারকারীর অভিজ্ঞতা সরবরাহ করতে সক্ষম করে।

ক্রিয়াকলাপ এম্বেডিংয়ের জন্য কোনও কোড রিফ্যাক্টরিং প্রয়োজন। আপনি নির্ধারণ করেন যে আপনার অ্যাপ্লিকেশনটি কীভাবে এক্সএমএল কনফিগারেশন ফাইল তৈরি করে বা জেটপ্যাক উইন্ডো ম্যানেজার এপিআই কলগুলি তৈরি করে এর ক্রিয়াকলাপগুলি - পাশাপাশি বা স্ট্যাক করা হয়েছে।

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

ক্রিয়াকলাপ এম্বেডিং ডিভাইস ওরিয়েন্টেশন পরিবর্তনগুলি সমন্বিত করে এবং ডিভাইসটি ভাঁজ করে এবং উদ্ঘাটিত হওয়ার সাথে সাথে ভাঁজযোগ্য ডিভাইসগুলিতে স্ট্যাকিং এবং আনস্ট্যাকিং ক্রিয়াকলাপগুলিতে নির্বিঘ্নে কাজ করে।

ক্রিয়াকলাপ এম্বেডিং অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) এবং উচ্চতর চলমান বেশিরভাগ বড় স্ক্রিন ডিভাইসে সমর্থিত।

টাস্ক উইন্ডো বিভক্ত

ক্রিয়াকলাপ এম্বেডিং অ্যাপ টাস্ক উইন্ডোটি দুটি পাত্রে বিভক্ত করে: প্রাথমিক এবং মাধ্যমিক। ধারকগুলি মূল ক্রিয়াকলাপ থেকে বা ইতিমধ্যে পাত্রে থাকা অন্যান্য ক্রিয়াকলাপ থেকে চালু করা ক্রিয়াকলাপগুলি ধারণ করে।

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

ক্রিয়াকলাপ এম্বেডিং আপনাকে বিভিন্ন উপায়ে ক্রিয়াকলাপ প্রদর্শন করতে সক্ষম করে। আপনার অ্যাপ্লিকেশন একই সাথে পাশাপাশি দুটি ক্রিয়াকলাপ চালু করে টাস্ক উইন্ডোটি বিভক্ত করতে পারে:

চিত্র 2। পাশাপাশি দুটি ক্রিয়াকলাপ।

বা, পুরো টাস্ক উইন্ডোটি দখল করে থাকা একটি ক্রিয়াকলাপ পাশাপাশি একটি নতুন ক্রিয়াকলাপ চালু করে একটি বিভাজন তৈরি করতে পারে:

চিত্র 3। ক্রিয়াকলাপ একটি পাশের ক্রিয়াকলাপ খ শুরু করে।

ইতিমধ্যে একটি বিভক্ত এবং একটি টাস্ক উইন্ডো ভাগ করে নেওয়া ক্রিয়াকলাপগুলি নিম্নলিখিত উপায়ে অন্যান্য ক্রিয়াকলাপ চালু করতে পারে:

  • অন্য ক্রিয়াকলাপের শীর্ষে:

    চিত্র 4। ক্রিয়াকলাপ একটি ক্রিয়াকলাপ বি।
  • পাশের দিকে, এবং পূর্ববর্তী প্রাথমিক ক্রিয়াকলাপটি গোপন করে পাশের পাশে স্থানান্তরিত করুন:

    চিত্র 5। ক্রিয়াকলাপ বি পাশের ক্রিয়াকলাপ সি শুরু করে এবং বিভক্ত পাশের দিকে স্থানান্তরিত করে।
  • শীর্ষে একটি ক্রিয়াকলাপ চালু করুন; এটি হ'ল একই ক্রিয়াকলাপের স্ট্যাক:

    চিত্র 6। ক্রিয়াকলাপ খ কোনও অতিরিক্ত উদ্দেশ্যযুক্ত পতাকা ছাড়াই ক্রিয়াকলাপ সি শুরু করে।
  • একই কার্যক্রমে একটি ক্রিয়াকলাপ পূর্ণ উইন্ডো চালু করুন:

    চিত্র 7। ক্রিয়াকলাপ এ বা ক্রিয়াকলাপ বি ক্রিয়াকলাপ সি শুরু করে যা টাস্ক উইন্ডোটি পূরণ করে।

পিছনে নেভিগেশন

ক্রিয়াকলাপগুলির মধ্যে নির্ভরতা বা ব্যবহারকারীরা কীভাবে পিছনের ইভেন্টটি ট্রিগার করে, তার উপর নির্ভর করে বিভিন্ন ধরণের অ্যাপ্লিকেশনগুলির বিভক্ত টাস্ক উইন্ডো স্টেটে বিভিন্ন ব্যাক নেভিগেশন বিধি থাকতে পারে: উদাহরণস্বরূপ:

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

বোতাম নেভিগেশন ব্যবহার করার সময় পিছনের ইভেন্টটি সর্বশেষ ফোকাসযুক্ত ক্রিয়াকলাপে প্রেরণ করা হয়।

অঙ্গভঙ্গি-ভিত্তিক নেভিগেশনের জন্য:

  • অ্যান্ড্রয়েড 14 (এপিআই স্তর 34) এবং লোয়ার - পিছনের ইভেন্টটি সেই ক্রিয়াকলাপে প্রেরণ করা হয় যেখানে অঙ্গভঙ্গি ঘটেছে। ব্যবহারকারীরা যখন স্ক্রিনের বাম দিক থেকে সোয়াইপ করে, তখন পিছনের ইভেন্টটি বিভক্ত উইন্ডোর বাম -হাতের ফলকের ক্রিয়াকলাপে প্রেরণ করা হয়। ব্যবহারকারীরা যখন স্ক্রিনের ডান দিক থেকে সোয়াইপ করে, পিছনের ইভেন্টটি ডান -হাতের ফলকের ক্রিয়াকলাপে প্রেরণ করা হয়।

  • অ্যান্ড্রয়েড 15 (এপিআই স্তর 35) এবং উচ্চতর

    • একই অ্যাপ্লিকেশন থেকে একাধিক ক্রিয়াকলাপ নিয়ে কাজ করার সময়, অঙ্গভঙ্গিটি আরও একীভূত অভিজ্ঞতা সরবরাহ করে সোয়াইপ দিকনির্দেশ নির্বিশেষে শীর্ষ কার্যকলাপ শেষ করে।

    • বিভিন্ন অ্যাপ্লিকেশন (ওভারলে) থেকে দুটি ক্রিয়াকলাপ জড়িত পরিস্থিতিতে, পিছনের ইভেন্টটি ফোকাসের শেষ ক্রিয়াকলাপের দিকে পরিচালিত হয়, বোতাম নেভিগেশনের আচরণের সাথে একত্রিত হয়।

মাল্টি-ফলক লেআউট

জেটপ্যাক উইন্ডো ম্যানেজার আপনাকে অ্যান্ড্রয়েড 12 এল (এপিআই স্তর 32) বা উচ্চতর এবং পূর্বের প্ল্যাটফর্ম সংস্করণগুলির সাথে কিছু ডিভাইসে বড় স্ক্রিন ডিভাইসে মাল্টি-ফলক লেআউট এম্বেড করে একটি ক্রিয়াকলাপ তৈরি করতে সক্ষম করে। SlidingPaneLayout মতো টুকরো বা ভিউ-ভিত্তিক লেআউটগুলির চেয়ে একাধিক ক্রিয়াকলাপের উপর ভিত্তি করে বিদ্যমান অ্যাপ্লিকেশনগুলি উত্স কোডটি রিফ্যাক্টরিং ছাড়াই উন্নত বৃহত স্ক্রিন ব্যবহারকারীর অভিজ্ঞতা সরবরাহ করতে পারে।

একটি সাধারণ উদাহরণ একটি তালিকা-বিশদ বিভাজন। একটি উচ্চ-মানের উপস্থাপনা নিশ্চিত করতে, সিস্টেমটি তালিকার ক্রিয়াকলাপ শুরু করে এবং তারপরে অ্যাপ্লিকেশনটি অবিলম্বে বিশদ ক্রিয়াকলাপ শুরু করে। উভয় ক্রিয়াকলাপ আঁকা না হওয়া পর্যন্ত ট্রানজিশন সিস্টেমটি অপেক্ষা করে, তারপরে সেগুলি একসাথে প্রদর্শন করে। ব্যবহারকারীর কাছে, দুটি ক্রিয়াকলাপ এক হিসাবে চালু হয়।

চিত্র 8। দুটি ক্রিয়াকলাপ একই সাথে একটি মাল্টি-ফলক বিন্যাসে শুরু হয়েছিল।

বিভক্ত বৈশিষ্ট্য

আপনি কীভাবে টাস্ক উইন্ডোটি বিভক্ত ধারকগুলির মধ্যে অনুপাতযুক্ত এবং কীভাবে পাত্রে একে অপরের সাথে তুলনামূলকভাবে স্থাপন করা হয় তা নির্দিষ্ট করতে পারেন।

একটি এক্সএমএল কনফিগারেশন ফাইলে সংজ্ঞায়িত নিয়মের জন্য, নিম্নলিখিত বৈশিষ্ট্যগুলি সেট করুন:

  • splitRatio : ধারক অনুপাত সেট করে। মানটি খোলা ব্যবধানে একটি ভাসমান পয়েন্ট নম্বর (0.0, 1.0)।
  • splitLayoutDirection : বিভক্ত পাত্রে কীভাবে একে অপরের সাথে তুলনামূলকভাবে স্থাপন করা হয় তা নির্দিষ্ট করে। মানগুলি অন্তর্ভুক্ত:
    • ltr : বাম থেকে ডান
    • rtl : ডান থেকে বাম
    • locale : ltr বা rtl হয় লোকেল সেটিং থেকে নির্ধারিত হয়

উদাহরণগুলির জন্য এক্সএমএল কনফিগারেশন বিভাগটি দেখুন।

উইন্ডো ম্যানেজার এপিআই ব্যবহার করে তৈরি বিধিগুলির জন্য, SplitAttributes.Builder সহ একটি SplitAttributes অবজেক্ট তৈরি করুন এবং নিম্নলিখিত বিল্ডার পদ্ধতিগুলিতে কল করুন:

  • setSplitType() : বিভক্ত পাত্রে অনুপাত সেট করে। SplitAttributes.SplitType SplitAttributes.SplitType.ratio() পদ্ধতি সহ বৈধ যুক্তিগুলির জন্য স্প্লিটটাইপ দেখুন।
  • setLayoutDirection() : পাত্রে লেআউট সেট করে। সম্ভাব্য মানগুলির জন্য SplitAttributes.LayoutDirection দেখুন।

উদাহরণগুলির জন্য উইন্ডো ম্যানেজার এপিআই বিভাগটি দেখুন।

চিত্র 9। দুটি ক্রিয়াকলাপ বিভাজন বাম থেকে ডান কিন্তু বিভিন্ন বিভাজন অনুপাত সহ।

স্থানধারক

স্থানধারক ক্রিয়াকলাপগুলি খালি গৌণ ক্রিয়াকলাপ যা কোনও ক্রিয়াকলাপ বিভক্ত হওয়ার ক্ষেত্র দখল করে। এগুলি শেষ পর্যন্ত অন্য একটি ক্রিয়াকলাপের সাথে প্রতিস্থাপন করা উচিত যাতে সামগ্রী রয়েছে। উদাহরণস্বরূপ, কোনও স্থানধারক ক্রিয়াকলাপ তালিকা থেকে কোনও আইটেম নির্বাচন না করা পর্যন্ত কোনও ক্রিয়াকলাপের বিভক্ত কোনও ক্রিয়াকলাপের মাধ্যমিক দিকটি দখল করতে পারে, যেখানে নির্বাচিত তালিকা আইটেমের বিশদ তথ্যযুক্ত একটি ক্রিয়াকলাপ স্থানধারককে প্রতিস্থাপন করে।

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

চিত্র 10। ভাঁজযোগ্য ডিভাইস ভাঁজ এবং উদ্ঘাটন। স্থানধারক ক্রিয়াকলাপ সমাপ্ত এবং প্রদর্শন আকারের পরিবর্তন হিসাবে পুনরায় তৈরি করা হয়।

যাইহোক, SplitPlaceholderRule বা setSticky() SplitPlaceholder.Builder পদ্ধতিটির stickyPlaceholder বৈশিষ্ট্য। বিল্ডার ডিফল্ট আচরণকে ওভাররাইড করতে পারে। যখন অ্যাট্রিবিউট বা পদ্ধতিটি true মান নির্দিষ্ট করে, তখন সিস্টেমটি টাস্ক উইন্ডোটির শীর্ষস্থানীয় ক্রিয়াকলাপ হিসাবে স্থানধারককে প্রদর্শন করে যখন প্রদর্শনটি একটি দ্বি-ফলক প্রদর্শন থেকে একক-ফলক ডিসপ্লেতে পুনরায় আকার দেওয়া হয় (একটি উদাহরণের জন্য স্প্লিট কনফিগারেশন দেখুন) .

চিত্র 11। ভাঁজযোগ্য ডিভাইস ভাঁজ এবং উদ্ঘাটন। স্থানধারক ক্রিয়াকলাপ স্টিকি।

উইন্ডো আকার পরিবর্তন

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

স্থানধারক ক্রিয়াকলাপগুলি কেবল তখনই প্রদর্শিত হয় যখন কোনও বিভক্তির জন্য পর্যাপ্ত প্রদর্শন প্রস্থ থাকে। ছোট স্ক্রিনগুলিতে, স্থানধারক স্বয়ংক্রিয়ভাবে বরখাস্ত হয়। যখন ডিসপ্লে অঞ্চলটি আবার যথেষ্ট বড় হয়ে যায়, স্থানধারক পুনরায় তৈরি করা হয়। ( স্থানধারক বিভাগ দেখুন।)

ক্রিয়াকলাপের স্ট্যাকিং সম্ভব কারণ উইন্ডো ম্যানেজার জেড-এর প্রাথমিক ফলকে উপরের ক্রিয়াকলাপগুলিকে উপরের ক্রিয়াকলাপগুলিকে অর্ডার করে।

মাধ্যমিক ফলকে একাধিক ক্রিয়াকলাপ

ক্রিয়াকলাপ খ কোনও অতিরিক্ত উদ্দেশ্যযুক্ত পতাকা ছাড়াই ক্রিয়াকলাপ সি শুরু করে:

ক্রিয়াকলাপ বিভাজন এ, বি এবং সি এর সাথে সি স্ট্যাকযুক্ত ক্রিয়াকলাপযুক্ত           শীর্ষে বি

একই কার্যক্রমে নিম্নলিখিত জেড-অর্ডারগুলির ফলস্বরূপ:

ক্রিয়াকলাপ সি সমন্বিত গৌণ ক্রিয়াকলাপ স্ট্যাক বি এর শীর্ষে স্ট্যাক করা হয়েছে           মাধ্যমিক স্ট্যাকটি প্রিমারি ক্রিয়াকলাপ স্ট্যাকের শীর্ষে স্ট্যাক করা হয়           ক্রিয়াকলাপযুক্ত এ।

সুতরাং, একটি ছোট টাস্ক উইন্ডোতে, অ্যাপ্লিকেশনটি স্ট্যাকের শীর্ষে সি সহ একক ক্রিয়াকলাপে সঙ্কুচিত হয়:

ছোট উইন্ডো শুধুমাত্র ক্রিয়াকলাপ দেখাচ্ছে সি

ছোট উইন্ডোতে ফিরে নেভিগেট করা একে অপরের উপরে সজ্জিত ক্রিয়াকলাপগুলির মাধ্যমে নেভিগেট করে।

যদি টাস্ক উইন্ডো কনফিগারেশনটি একটি বৃহত্তর আকারে পুনরুদ্ধার করা হয় যা একাধিক প্যানকে সামঞ্জস্য করতে পারে তবে ক্রিয়াকলাপগুলি আবার পাশাপাশি প্রদর্শিত হয়।

স্ট্যাকড বিভাজন

ক্রিয়াকলাপ বি পাশের ক্রিয়াকলাপ সি শুরু করে এবং বিভক্ত পাশের দিকে স্থানান্তরিত করে:

টাস্ক উইন্ডো ক্রিয়াকলাপ এ এবং বি দেখায়, তারপরে ক্রিয়াকলাপ খ এবং সি

ফলাফলটি একই কার্যক্রমে নিম্নলিখিত জেড-অর্ডার:

একক স্ট্যাকের মধ্যে এ, বি এবং সি ক্রিয়াকলাপ। ক্রিয়াকলাপগুলি স্ট্যাক করা হয়           শীর্ষ থেকে নীচে নিম্নলিখিত ক্রমে: সি, বি, এ।

একটি ছোট টাস্ক উইন্ডোতে, অ্যাপ্লিকেশনটি শীর্ষে সি সহ একক ক্রিয়াকলাপে সঙ্কুচিত হয়:

ছোট উইন্ডো শুধুমাত্র ক্রিয়াকলাপ দেখাচ্ছে সি

স্থির-প্রতিকৃতি ওরিয়েন্টেশন

অ্যান্ড্রয়েড: স্ক্রিনোরিয়েন্টেশন ম্যানিফেস্ট সেটিফটি সেটিং অ্যাপ্লিকেশনগুলিকে প্রতিকৃতি বা ল্যান্ডস্কেপ ওরিয়েন্টেশনে ক্রিয়াকলাপ সীমাবদ্ধ করতে সক্ষম করে। ট্যাবলেট এবং ফোল্ডেবলের মতো বৃহত স্ক্রিন ডিভাইসে ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে, ডিভাইস নির্মাতারা (ওএমএস) স্ক্রিন ওরিয়েন্টেশন অনুরোধগুলি উপেক্ষা করতে পারে এবং ল্যান্ডস্কেপ ডিসপ্লে বা প্রতিকৃতি প্রদর্শনগুলিতে ল্যান্ডস্কেপ ওরিয়েন্টেশন সম্পর্কিত প্রতিকৃতি ওরিয়েন্টেশনে অ্যাপটিকে লেটারবক্সকে লেটারবক্স উপেক্ষা করতে পারে।

চিত্র 12। লেটারবক্সযুক্ত ক্রিয়াকলাপ: ল্যান্ডস্কেপ ডিভাইসে (বাম) স্থির-প্রতিকৃতি, প্রতিকৃতি ডিভাইসে ফিক্সড-ল্যান্ডস্কেপ (ডান)।

একইভাবে, যখন ক্রিয়াকলাপ এম্বেডিং সক্ষম করা হয়, OEMS বড় পর্দার (প্রস্থ ≥ 600DP) ল্যান্ডস্কেপ ওরিয়েন্টেশনে ফিক্সড-প্রতিকৃতি ক্রিয়াকলাপগুলিতে লেটারবক্সে ডিভাইসগুলি কাস্টমাইজ করতে পারে। যখন একটি স্থির-প্রতিকৃতি ক্রিয়াকলাপ একটি দ্বিতীয় ক্রিয়াকলাপ চালু করে, ডিভাইসটি দুটি-ফলক প্রদর্শনীতে পাশাপাশি দুটি ক্রিয়াকলাপ প্রদর্শন করতে পারে।

চিত্র 13। স্থির-প্রতিকৃতি ক্রিয়াকলাপ একটি পাশের ক্রিয়াকলাপ বি শুরু করে।

আপনার অ্যাপ্লিকেশনটি ক্রিয়াকলাপ এম্বেডিং সমর্থন করে এমন ডিভাইসগুলি অবহিত করতে সর্বদা android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED সম্পত্তি যুক্ত করুন ( স্প্লিট কনফিগারেশন বিভাগটি দেখুন) দেখুন। OEM কাস্টমাইজড ডিভাইসগুলি তারপরে স্থির-প্রতিকৃতি ক্রিয়াকলাপগুলি লেটারবক্স করতে পারে কিনা তা নির্ধারণ করতে পারে।

বিভক্ত কনফিগারেশন

বিভক্ত বিধিগুলি ক্রিয়াকলাপ বিভাজন কনফিগার করুন। আপনি একটি এক্সএমএল কনফিগারেশন ফাইলে বিভক্ত নিয়মগুলি সংজ্ঞায়িত করেছেন বা জেটপ্যাক উইন্ডো ম্যানেজার এপিআই কলগুলি তৈরি করে।

উভয় ক্ষেত্রেই, আপনার অ্যাপ্লিকেশনটিকে অবশ্যই উইন্ডো ম্যানেজার লাইব্রেরিতে অ্যাক্সেস করতে হবে এবং অবশ্যই সিস্টেমটি অবহিত করতে হবে যে অ্যাপটি ক্রিয়াকলাপ এম্বেডিং প্রয়োগ করেছে।

নিম্নলিখিতগুলি করুন:

  1. আপনার অ্যাপের মডিউল-স্তরের build.gradle ফাইলটিতে সর্বশেষতম উইন্ডো ম্যানেজার লাইব্রেরির নির্ভরতা যুক্ত করুন: উদাহরণস্বরূপ:

    implementation 'androidx.window:window:1.1.0-beta02'

    উইন্ডো ম্যানেজার লাইব্রেরি ক্রিয়াকলাপ এম্বেডিংয়ের জন্য প্রয়োজনীয় সমস্ত উপাদান সরবরাহ করে।

  2. আপনার অ্যাপ্লিকেশনটি ক্রিয়াকলাপ এম্বেডিং প্রয়োগ করেছে এমন সিস্টেমকে অবহিত করুন।

    android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED সম্পত্তি অ্যাপ্লিকেশন ম্যানিফেস্ট ফাইলের <অ্যাপ্লিকেশন> উপাদানটিতে যুক্ত করুন এবং মানটি সত্যে সেট করুন, উদাহরণস্বরূপ:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application>
            <property
                android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
                android:value="true" />
        </application>
    </manifest>
    

    উইন্ডো ম্যানেজার রিলিজ 1.1.0-ALPHA06 এবং পরে, ক্রিয়াকলাপ এম্বেডিং স্প্লিটগুলি অক্ষম করা হয় যদি না সম্পত্তিটি ম্যানিফেস্টে যুক্ত না করা হয় এবং সত্যে সেট করা হয়।

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

XML কনফিগারেশন

ক্রিয়াকলাপ এম্বেডিংয়ের একটি এক্সএমএল-ভিত্তিক বাস্তবায়ন তৈরি করতে, নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করুন:

  1. একটি এক্সএমএল রিসোর্স ফাইল তৈরি করুন যা নিম্নলিখিতগুলি করে:

    • একটি বিভাজন ভাগ করে এমন ক্রিয়াকলাপগুলি সংজ্ঞায়িত করে
    • বিভক্ত বিকল্পগুলি কনফিগার করে
    • যখন সামগ্রী উপলব্ধ না থাকে তখন বিভক্তির মাধ্যমিক ধারকটির জন্য একটি স্থানধারক তৈরি করে
    • এমন ক্রিয়াকলাপগুলি নির্দিষ্ট করে যা কখনও বিভক্তের অংশ হওয়া উচিত নয়

    যেমন:

    <!-- main_split_config.xml -->
    
    <resources
        xmlns:window="http://schemas.android.com/apk/res-auto">
    
        <!-- Define a split for the named activities. -->
        <SplitPairRule
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:finishPrimaryWithSecondary="never"
            window:finishSecondaryWithPrimary="always"
            window:clearTop="false">
            <SplitPairFilter
                window:primaryActivityName=".ListActivity"
                window:secondaryActivityName=".DetailActivity"/>
        </SplitPairRule>
    
        <!-- Specify a placeholder for the secondary container when content is
             not available. -->
        <SplitPlaceholderRule
            window:placeholderActivityName=".PlaceholderActivity"
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:stickyPlaceholder="false">
            <ActivityFilter
                window:activityName=".ListActivity"/>
        </SplitPlaceholderRule>
    
        <!-- Define activities that should never be part of a split. Note: Takes
             precedence over other split rules for the activity named in the
             rule. -->
        <ActivityRule
            window:alwaysExpand="true">
            <ActivityFilter
                window:activityName=".ExpandedActivity"/>
        </ActivityRule>
    
    </resources>
    
  2. একটি ইনিশিয়ালাইজার তৈরি করুন।

    উইন্ডো ম্যানেজার RuleController উপাদানটি এক্সএমএল কনফিগারেশন ফাইলটিকে পার্স করে এবং নিয়মগুলি সিস্টেমে উপলব্ধ করে। একটি জেটপ্যাক স্টার্টআপ লাইব্রেরি Initializer এক্সএমএল ফাইলটিকে অ্যাপ্লিকেশন স্টার্টআপে RuleController কাছে উপলব্ধ করে তোলে যাতে কোনও ক্রিয়াকলাপ শুরু হলে নিয়মগুলি কার্যকর হয়।

    একটি ইনিশিয়ালাইজার তৈরি করতে, নিম্নলিখিতগুলি করুন:

    1. আপনার মডিউল-স্তরের build.gradle ফাইলটিতে সর্বশেষতম জেটপ্যাক স্টার্টআপ লাইব্রেরির নির্ভরতা যুক্ত করুন: উদাহরণস্বরূপ:

      implementation 'androidx.startup:startup-runtime:1.1.1'

    2. একটি শ্রেণি তৈরি করুন যা Initializer ইন্টারফেস প্রয়োগ করে।

      ইনিশিয়ালাইজারটি এক্সএমএল কনফিগারেশন ফাইলের আইডি ( main_split_config.xml ) এর আইডি পাস করে RuleController.parseRules() পদ্ধতিতে পাস করে বিভক্ত নিয়মগুলি RuleController কাছে উপলব্ধ করে।

      কোটলিন

      class SplitInitializer : Initializer<RuleController> {
      
          override fun create(context: Context): RuleController {
              return RuleController.getInstance(context).apply {
                  setRules(RuleController.parseRules(context, R.xml.main_split_config))
              }
          }
      
          override fun dependencies(): List<Class<out Initializer<*>>> {
              return emptyList()
          }
      }

      জাভা

      public class SplitInitializer implements Initializer<RuleController> {
      
           @NonNull
           @Override
           public RuleController create(@NonNull Context context) {
               RuleController ruleController = RuleController.getInstance(context);
               ruleController.setRules(
                   RuleController.parseRules(context, R.xml.main_split_config)
               );
               return ruleController;
           }
      
           @NonNull
           @Override
           public List<Class<? extends Initializer<?>>> dependencies() {
               return Collections.emptyList();
           }
      }
  3. নিয়ম সংজ্ঞাগুলির জন্য একটি সামগ্রী সরবরাহকারী তৈরি করুন।

    আপনার অ্যাপ্লিকেশন ম্যানিফেস্ট ফাইলে একটি <provider> হিসাবে androidx.startup.InitializationProvider যুক্ত করুন। আপনার RuleController ইনিশিয়ালাইজার, SplitInitializer বাস্তবায়নের একটি রেফারেন্স অন্তর্ভুক্ত করুন:

    <!-- AndroidManifest.xml -->
    
    <provider android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <!-- Make SplitInitializer discoverable by InitializationProvider. -->
        <meta-data android:name="${applicationId}.SplitInitializer"
            android:value="androidx.startup" />
    </provider>
    

    InitializationProvider অ্যাপ্লিকেশনটির onCreate() পদ্ধতিটি ডাকার আগে SplitInitializer আবিষ্কার করে এবং আরম্ভ করে। ফলস্বরূপ, অ্যাপ্লিকেশনটির মূল ক্রিয়াকলাপ শুরু হলে বিভক্ত নিয়মগুলি কার্যকর হয়।

উইন্ডো ম্যানেজার এপিআই

আপনি মুষ্টিমেয় এপিআই কলগুলির সাথে প্রোগ্রামিকভাবে এম্বেডিং ক্রিয়াকলাপ প্রয়োগ করতে পারেন। কোনও ক্রিয়াকলাপ চালু হওয়ার আগে নিয়মগুলি কার্যকর হয় তা নিশ্চিত করার জন্য Application সাবক্লাসের onCreate() পদ্ধতিতে কলগুলি তৈরি করুন।

প্রোগ্রামগতভাবে একটি ক্রিয়াকলাপ বিভাজন তৈরি করতে, নিম্নলিখিতগুলি করুন:

  1. একটি বিভক্ত নিয়ম তৈরি করুন:

    1. একটি SplitPairFilter তৈরি করুন যা বিভাজন ভাগ করে এমন ক্রিয়াকলাপগুলি সনাক্ত করে:

      কোটলিন

      val splitPairFilter = SplitPairFilter(
         ComponentName(this, ListActivity::class.java),
         ComponentName(this, DetailActivity::class.java),
         null
      )

      জাভা

      SplitPairFilter splitPairFilter = new SplitPairFilter(
         new ComponentName(this, ListActivity.class),
         new ComponentName(this, DetailActivity.class),
         null
      );
    2. ফিল্টার সেটে ফিল্টার যুক্ত করুন:

      কোটলিন

      val filterSet = setOf(splitPairFilter)

      জাভা

      Set<SplitPairFilter> filterSet = new HashSet<>();
      filterSet.add(splitPairFilter);
    3. বিভাজনের জন্য লেআউট বৈশিষ্ট্য তৈরি করুন:

      কোটলিন

      val splitAttributes: SplitAttributes = SplitAttributes.Builder()
          .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
          .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
          .build()

      জাভা

      final SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();

      SplitAttributes.Builder লেআউট বৈশিষ্ট্যযুক্ত একটি বস্তু তৈরি করে:

      • setSplitType() : প্রতিটি ক্রিয়াকলাপের ধারকটিতে উপলভ্য ডিসপ্লে অঞ্চলটি কীভাবে বরাদ্দ করা হয় তা নির্ধারণ করে। অনুপাতের বিভাজন প্রকারটি প্রাথমিক ধারকটিতে বরাদ্দকৃত উপলভ্য ডিসপ্লে অঞ্চলের অনুপাত নির্দিষ্ট করে; মাধ্যমিক ধারকটি উপলব্ধ প্রদর্শন ক্ষেত্রের বাকী অংশ দখল করে।
      • setLayoutDirection() : ক্রিয়াকলাপের পাত্রে কীভাবে একে অপরের সাথে সম্পর্কিত, প্রাথমিক ধারককে প্রথমে রাখা হয় তা নির্দিষ্ট করে।
    4. একটি SplitPairRule তৈরি করুন:

      কোটলিন

      val splitPairRule = SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build()

      জাভা

      SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build();

      SplitPairRule.Builder নিয়মটি তৈরি করে এবং কনফিগার করে:

      • filterSet : বিভক্ত জোড় ফিল্টার রয়েছে যা বিভাজন ভাগ করে এমন ক্রিয়াকলাপগুলি সনাক্ত করে কখন নিয়ম প্রয়োগ করতে হবে তা নির্ধারণ করে।
      • setDefaultSplitAttributes() : নিয়মের জন্য বিন্যাসের বৈশিষ্ট্যগুলি প্রয়োগ করে।
      • setMinWidthDp() : ন্যূনতম ডিসপ্লে প্রস্থ (ঘনত্বে - স্বতন্ত্র পিক্সেল, ডিপি) সেট করে যা একটি বিভাজনকে সক্ষম করে।
      • setMinSmallestWidthDp() : ন্যূনতম মান সেট করে (ডিপিতে) যে দুটি ডিসপ্লে মাত্রার ছোটটি অবশ্যই ডিভাইস ওরিয়েন্টেশন নির্বিশেষে একটি বিভাজন সক্ষম করতে হবে।
      • setMaxAspectRatioInPortrait() : প্রতিকৃতি ওরিয়েন্টেশনে সর্বাধিক প্রদর্শন দিক অনুপাত (উচ্চতা: প্রস্থ) সেট করে যার জন্য ক্রিয়াকলাপ বিভাজন প্রদর্শিত হয়। যদি কোনও প্রতিকৃতি প্রদর্শনের দিক অনুপাতটি সর্বাধিক দিক অনুপাতের চেয়ে বেশি হয় তবে বিভাজনগুলি প্রদর্শনের প্রস্থ নির্বিশেষে অক্ষম করা হয়। দ্রষ্টব্য: ডিফল্ট মানটি 1.4, যার ফলস্বরূপ বেশিরভাগ ট্যাবলেটগুলিতে প্রতিকৃতি ওরিয়েন্টেশনে পুরো টাস্ক উইন্ডোটি দখল করে থাকে। SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT এবং setMaxAspectRatioInLandscape() দেখুন। The default value for landscape is ALWAYS_ALLOW .
      • setFinishPrimaryWithSecondary() : Sets how finishing all activities in the secondary container affects the activities in the primary container. NEVER indicates the system shouldn't finish the primary activities when all activities in the secondary container finish (see Finish activities ).
      • setFinishSecondaryWithPrimary() : Sets how finishing all activities in the primary container affects the activities in the secondary container. ALWAYS indicates the system should always finish the activities in the secondary container when all activities in the primary container finish (see Finish activities ).
      • setClearTop() : Specifies whether all activities in the secondary container are finished when a new activity is launched in the container. A false value specifies that new activities are stacked on top of activities already in the secondary container.
    5. Get the singleton instance of the WindowManager RuleController , and add the rule:

      কোটলিন

        val ruleController = RuleController.getInstance(this)
        ruleController.addRule(splitPairRule)
        

      জাভা

        RuleController ruleController = RuleController.getInstance(this);
        ruleController.addRule(splitPairRule);
        
  2. Create a placeholder for the secondary container when content is not available:

    1. Create an ActivityFilter that identifies the activity with which the placeholder shares a task window split:

      কোটলিন

      val placeholderActivityFilter = ActivityFilter(
          ComponentName(this, ListActivity::class.java),
          null
      )

      জাভা

      ActivityFilter placeholderActivityFilter = new ActivityFilter(
          new ComponentName(this, ListActivity.class),
          null
      );
    2. Add the filter to a filter set:

      কোটলিন

      val placeholderActivityFilterSet = setOf(placeholderActivityFilter)

      জাভা

      Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
      placeholderActivityFilterSet.add(placeholderActivityFilter);
    3. Create a SplitPlaceholderRule :

      কোটলিন

      val splitPlaceholderRule = SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            Intent(context, PlaceholderActivity::class.java)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build()

      জাভা

      SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            new Intent(context, PlaceholderActivity.class)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build();

      SplitPlaceholderRule.Builder creates and configures the rule:

      • placeholderActivityFilterSet : Contains activity filters that determine when to apply the rule by identifying activities with which the placeholder activity is associated.
      • Intent : Specifies the launch of the placeholder activity.
      • setDefaultSplitAttributes() : Applies layout attributes to the rule.
      • setMinWidthDp() : Sets the minimum display width (in density-independent pixels, dp) that allows a split.
      • setMinSmallestWidthDp() : Sets the minimum value (in dp) that the smaller of the two display dimensions must have to allow a split regardless of the device orientation.
      • setMaxAspectRatioInPortrait() : Sets the maximum display aspect ratio (height:width) in portrait orientation for which activity splits are displayed. Note: The default value is 1.4, which results in activities filling the task window in portrait orientation on most tablets. See also SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT and setMaxAspectRatioInLandscape() . The default value for landscape is ALWAYS_ALLOW .
      • setFinishPrimaryWithPlaceholder() : Sets how finishing the placeholder activity affects the activities in the primary container. ALWAYS indicates the system should always finish the activities in the primary container when the placeholder finishes (see Finish activities ).
      • setSticky() : Determines whether the placeholder activity appears on top of the activity stack on small displays once the placeholder has first appeared in a split with sufficient minimum width.
    4. Add the rule to the WindowManager RuleController :

      কোটলিন

      ruleController.addRule(splitPlaceholderRule)

      জাভা

      ruleController.addRule(splitPlaceholderRule);
  3. Specify activities that should never be part of a split:

    1. Create an ActivityFilter that identifies an activity that should always occupy the entire task display area:

      কোটলিন

      val expandedActivityFilter = ActivityFilter(
        ComponentName(this, ExpandedActivity::class.java),
        null
      )

      জাভা

      ActivityFilter expandedActivityFilter = new ActivityFilter(
        new ComponentName(this, ExpandedActivity.class),
        null
      );
    2. Add the filter to a filter set:

      কোটলিন

      val expandedActivityFilterSet = setOf(expandedActivityFilter)

      জাভা

      Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>();
      expandedActivityFilterSet.add(expandedActivityFilter);
    3. Create an ActivityRule :

      কোটলিন

      val activityRule = ActivityRule.Builder(expandedActivityFilterSet)
          .setAlwaysExpand(true)
          .build()

      জাভা

      ActivityRule activityRule = new ActivityRule.Builder(
          expandedActivityFilterSet
      ).setAlwaysExpand(true)
       .build();

      ActivityRule.Builder creates and configures the rule:

      • expandedActivityFilterSet : Contains activity filters that determine when to apply the rule by identifying activities that you want to exclude from splits.
      • setAlwaysExpand() : Specifies whether the activity should fill the entire task window.
    4. Add the rule to the WindowManager RuleController :

      কোটলিন

      ruleController.addRule(activityRule)

      জাভা

      ruleController.addRule(activityRule);

Cross-application embedding

On Android 13 (API level 33) and higher, apps can embed activities from other apps. Cross‑application, or cross‑ UID , activity embedding enables visual integration of activities from multiple Android applications. The system displays an activity of the host app and an embedded activity from another app on screen side by side or top and bottom just as in single-app activity embedding.

For example, the Settings app could embed the wallpaper selector activity from the WallpaperPicker app:

Figure 14. Settings app (menu on left) with wallpaper selector as embedded activity (right).

ট্রাস্ট মডেল

Host processes that embed activities from other apps are able to redefine the presentation of the embedded activities, including size, position, cropping, and transparency. Malicious hosts can use this capability to mislead users and create clickjacking or other UI-redressing attacks.

To prevent misuse of cross-app activity embedding, Android requires apps to opt in to allow embedding of their activities. Apps can designate hosts as trusted or untrusted.

বিশ্বস্ত হোস্ট

To allow other applications to embed and fully control the presentation of activities from your app, specify the SHA-256 certificate of the host application in the android:knownActivityEmbeddingCerts attribute of the <activity> or <application> elements of your app's manifest file.

Set the value of android:knownActivityEmbeddingCerts either as a string:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
    ... />

or, to specify multiple certificates, an array of strings:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
    ... />

which references a resource like the following:

<resources>
    <string-array name="known_host_certificate_digests">
      <item>cert1</item>
      <item>cert2</item>
      ...
    </string-array>
</resources>

App owners can get a SHA certificate digest by running the Gradle signingReport task. The certificate digest is the SHA-256 fingerprint without the separating colons. For more information, see Run a signing report and Authenticating Your Client .

Untrusted hosts

To allow any app to embed your app's activities and control their presentation, specify the android:allowUntrustedActivityEmbedding attribute in the <activity> or <application> elements in the app manifest, for example:

<activity
    android:name=".MyEmbeddableActivity"
    android:allowUntrustedActivityEmbedding="true"
    ... />

The default value of the attribute is false, which prevents cross-app activity embedding.

কাস্টম প্রমাণীকরণ

To mitigate the risks of untrusted activity embedding, create a custom authentication mechanism that verifies the host identity. If you know the host certificates, use the androidx.security.app.authenticator library to authenticate. If the host authenticates after embedding your activity, you can display the actual content. If not, you can inform the user that the action was not allowed and block the content.

Use the ActivityEmbeddingController#isActivityEmbedded() method from the Jetpack WindowManager library to check whether a host is embedding your activity, for example:

কোটলিন

fun isActivityEmbedded(activity: Activity): Boolean {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity)
}

জাভা

boolean isActivityEmbedded(Activity activity) {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity);
}

Minimum size restriction

The Android system applies the minimum height and width specified in the app manifest <layout> element to embedded activities. If an application does not specify minimum height and width, the system default values apply ( sw220dp ).

If the host attempts to resize the embedded container to a size smaller than the minimum, the embedded container expands to occupy the entire task bounds.

<activity-alias>

For trusted or untrusted activity embedding to work with the <activity-alias> element, android:knownActivityEmbeddingCerts or android:allowUntrustedActivityEmbedding must be applied to the target activity rather than the alias. The policy that verifies security on the system server is based on the flags set on the target, not the alias.

হোস্ট অ্যাপ্লিকেশন

Host applications implement cross-app activity embedding the same way they implement single-app activity embedding. SplitPairRule and SplitPairFilter or ActivityRule and ActivityFilter objects specify embedded activities and task window splits. Split rules are defined statically in XML or at runtime using Jetpack WindowManager API calls.

If a host application attempts to embed an activity that has not opted in to cross-app embedding, the activity occupies the entire task bounds. As a result, host applications need to know whether target activities allow cross-app embedding.

If an embedded activity starts a new activity in the same task and the new activity has not opted in to cross-app embedding, the activity occupies the entire task bounds instead of overlaying the activity in the embedded container.

A host application can embed its own activities without restriction as long as the activities launch in the same task.

Split examples

Split from full window

Figure 15. Activity A starts activity B to the side.

No refactoring required. You can define the configuration for the split statically or at runtime and then call Context#startActivity() without any additional parameters.

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split by default

When the landing page of an application is designed to be split into two containers on large screens, the user experience is best when both activities are created and presented simultaneously. However, content might not be available for the secondary container of the split until the user interacts with the activity in the primary container (for example, the user selects an item from a navigation menu). A placeholder activity can fill the void until content can be displayed in the secondary container of the split (see the Placeholders section).

Figure 16. Split created by opening two activities simultaneously. One activity is a placeholder.

To create a split with a placeholder, create a placeholder and associate it with the primary activity:

<SplitPlaceholderRule
    window:placeholderActivityName=".PlaceholderActivity">
    <ActivityFilter
        window:activityName=".MainActivity"/>
</SplitPlaceholderRule>

When an app receives an intent, the target activity can be shown as the secondary part of an activity split; for example, a request to show a detail screen with information about an item from a list. On small displays, the detail is shown in the full task window; on larger devices, beside the list.

Figure 17. Deep link detail activity shown alone on a small screen, but together with a list activity on a large screen.

The launch request should be routed to the main activity, and the target detail activity should be launched in a split. The system automatically chooses the correct presentation—stacked or side by side—based on the available display width.

কোটলিন

override fun onCreate(savedInstanceState Bundle?) {
    . . .
    RuleController.getInstance(this)
        .addRule(SplitPairRule.Builder(filterSet).build())
    startActivity(Intent(this, DetailActivity::class.java))
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    RuleController.getInstance(this)
        .addRule(new SplitPairRule.Builder(filterSet).build());
    startActivity(new Intent(this, DetailActivity.class));
}

The deep link destination might be the only activity that should be available to the user in the back navigation stack, and you might want to avoid dismissing the detail activity and leaving only the main activity:

Large display with list activity and detail activity side by side.
          Back navigation unable to dismiss detail activity and leave list
          activity on screen.

Small display with detail activity only. Back navigation unable to
          dismiss detail activity and reveal list activity.

Instead, you can finish both activities at the same time by using the finishPrimaryWithSecondary attribute:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".ListActivity"
        window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>

See the Configuration attributes section.

Multiple activities in split containers

Stacking multiple activities in a split container enables users to access deep content. For example, with a list-detail split, the user might need to go into a sub-detail section but keep the primary activity in place:

Figure 18. Activity opened in place in the secondary pane of the task window.

কোটলিন

class DetailActivity {
    . . .
    fun onOpenSubDetail() {
      startActivity(Intent(this, SubDetailActivity::class.java))
    }
}

জাভা

public class DetailActivity {
    . . .
    void onOpenSubDetail() {
        startActivity(new Intent(this, SubDetailActivity.class));
    }
}

The sub-detail activity is placed on top of the detail activity, concealing it:

The user can then go back to the previous detail level by navigating back through the stack:

Figure 19. Activity removed from the top of the stack.

Stacking activities on top of each other is the default behavior when activities are launched from an activity in the same secondary container. Activities launched from the primary container within an active split also end up in the secondary container on the top of the activity stack.

Activities in a new task

When activities in a split task window start activities in a new task, the new task is separate from the task that includes the split and is displayed full window. The Recents screen shows two tasks: the task in the split and the new task.

Figure 20. Start activity C in a new task from activity B.

Activity replacement

Activities can be replaced in the secondary container stack; for example, when the primary activity is used for top-level navigation and the secondary activity is a selected destination. Each selection from the top-level navigation should start a new activity in the secondary container and remove the activity or activities that were previously there.

Figure 21. Top-level navigation activity in the primary pane replaces destination activities in the secondary pane.

If the app doesn't finish the activity in the secondary container when the navigation selection changes, back navigation might be confusing when the split is collapsed (when the device is folded). For example, if you have a menu in the primary pane and screens A and B stacked in the secondary pane, when the user folds the phone, B is on top of A, and A is on top of the menu. When the user navigates back from B, A appears instead of the menu.

Screen A must be removed from the back stack in such cases.

The default behavior when launching to the side in a new container over an existing split is to put the new secondary containers on top and retain the old ones in the back stack. You can configure the splits to clear the previous secondary containers with clearTop and launch new activities normally.

<SplitPairRule
    window:clearTop="true">
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenA"/>
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>

কোটলিন

class MenuActivity {
    . . .
    fun onMenuItemSelected(selectedMenuItem: Int) {
        startActivity(Intent(this, classForItem(selectedMenuItem)))
    }
}

জাভা

public class MenuActivity {
    . . .
    void onMenuItemSelected(int selectedMenuItem) {
        startActivity(new Intent(this, classForItem(selectedMenuItem)));
    }
}

Alternatively, use the same secondary activity, and from the primary (menu) activity send new intents that resolve to the same instance but trigger a state or UI update in the secondary container.

Multiple splits

Apps can provide multi-level deep navigation by launching additional activities to the side.

When an activity in a secondary container launches a new activity to the side, a new split is created over top of the existing split.

Figure 22. Activity B starts activity C to the side.

The back stack contains all activities that were previously opened, so users can navigate to the A/B split after finishing C.

Activities A, B, and C in a stack. The activities are stacked in
          the following order from top to bottom: C, B, A.

To create a new split, launch the new activity to the side from the existing secondary container. Declare the configurations for both the A/B and B/C splits and launch activity C normally from B:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
    <SplitPairFilter
        window:primaryActivityName=".B"
        window:secondaryActivityName=".C"/>
</SplitPairRule>

কোটলিন

class B {
    . . .
    fun onOpenC() {
        startActivity(Intent(this, C::class.java))
    }
}

জাভা

public class B {
    . . .
    void onOpenC() {
        startActivity(new Intent(this, C.class));
    }
}

React to split state changes

Different activities in an app can have UI elements that perform the same function; for example, a control that opens a window containing account settings.

Figure 23. Different activities with functionally identical UI elements.

If two activities that have a UI element in common are in a split, it's redundant and perhaps confusing to show the element in both activities.

Figure 24. Duplicate UI elements in activity split.

To know when activities are in a split, check the SplitController.splitInfoList flow or register a listener with SplitControllerCallbackAdapter for changes in the split state. Then, adjust the UI accordingly:

কোটলিন

val layout = layoutInflater.inflate(R.layout.activity_main, null)
val view = layout.findViewById<View>(R.id.infoButton)
lifecycleScope.launch {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance.
            .collect { list ->
                view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
            }
    }
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    new SplitControllerCallbackAdapter(SplitController.getInstance(this))
        .addSplitListener(
            this,
            Runnable::run,
            splitInfoList -> {
                View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
                layout.findViewById(R.id.infoButton).setVisibility(
                    splitInfoList.isEmpty() ? View.VISIBLE : View.GONE);
            });
}

Coroutines can be launched in any lifecycle state, but are typically launched in the STARTED state to conserve resources (see Use Kotlin coroutines with lifecycle-aware components for more information).

Callbacks can be made in any lifecycle state, including when an activity is stopped. Listeners should usually be registered in onStart() and unregistered in onStop() .

Full-window modal

Some activities block users from interacting with the application until a specified action is performed; for example, a login screen activity, policy acknowledgement screen, or error message. Modal activities should be prevented from appearing in a split.

An activity can be forced to always fill the task window by using the expand configuration:

<ActivityRule
    window:alwaysExpand="true">
    <ActivityFilter
        window:activityName=".FullWidthActivity"/>
</ActivityRule>

Finish activities

Users can finish activities on either side of the split by swiping from the edge of the display:

Figure 25. Swipe gesture finishing activity B.
Figure 26. Swipe gesture finishing activity A.

If the device is set up to use the back button instead of gesture navigation, the input is sent to the focused activity—the activity that was touched or launched last.

The effect that finishing all activities in a container has on the opposing container depends on the split configuration.

Configuration attributes

You can specify split pair rule attributes to configure how finishing all activities on one side of the split affects the activities on the other side of the split. গুণাবলী হল:

  • window:finishPrimaryWithSecondary — How finishing all activities in the secondary container affects the activities in the primary container
  • window:finishSecondaryWithPrimary — How finishing all activities in the primary container affects the activities in the secondary container

Possible values of the attributes include:

  • always — Always finish the activities in the associated container
  • never — Never finish the activities in the associated container
  • adjacent — Finish the activities in the associated container when the two containers are displayed adjacent to each other, but not when the two containers are stacked

যেমন:

<SplitPairRule
    &lt;!-- Do not finish primary container activities when all secondary container activities finish. --&gt;
    window:finishPrimaryWithSecondary="never"
    &lt;!-- Finish secondary container activities when all primary container activities finish. --&gt;
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

ডিফল্ট কনফিগারেশন

When all activities in one container of a split finish, the remaining container occupies the entire window:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. A is finished, leaving B to
          occupy the entire window.

Split containing activities A and B. B is finished, leaving A to
          occupy the entire window.

Finish activities together

Finish the activities in the primary container automatically when all activities in the secondary container finish:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. B is finished, which also
          finishes A, leaving the task window empty.

Split containing activities A and B. A is finished, leaving B alone
          in the task window.

Finish the activities in the secondary container automatically when all activities in the primary container finish:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. A is finished, which also
          finishes B, leaving the task window empty.

Split containing activities A and B. B is finished, leaving A alone
          in the task window.

Finish activities together when all activities in either the primary or secondary container finish:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. A is finished, which also
          finishes B, leaving the task window empty.

Split containing activities A and B. B is finished, which also
          finishes A, leaving the task window empty.

Finish multiple activities in containers

If multiple activities are stacked in a split container, finishing an activity on the bottom of the stack does not automatically finish activities on top.

For example, if two activities are in the secondary container, C on top of B:

Secondary activity stack containing activity C stacked on top of B           is stacked on top of the prmary activity stack containing activity           ক.

and the configuration of the split is defined by the configuration of activities A and B:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

finishing the top activity retains the split.

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. C finishes, leaving A and B in the
          activity split.

Finishing the bottom (root) activity of the secondary container does not remove the activities on top of it; and so, also retains the split.

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. B finishes, leaving A and C in the
          activity split.

Any additional rules for finishing activities together, such as finishing the secondary activity with the primary, are also executed:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split with activity A in primary container and activities B and C in
          secondary container, C stacked on top of B. A finishes, also
          finishing B and C.

And when the split is configured to finish primary and secondary together:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. C finishes, leaving A and B in the
          activity split.

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. B finishes, leaving A and C in the
          activity split.

Split with activity A in primary container and activities B and C in           secondary, C stacked on top of B. A finishes, also finishing B and           গ.

Change split properties at runtime

The properties of an active and visible split cannot be changed. Changing the split rules affects additional activity launches and new containers, but not existing and active splits.

To change the properties of active splits, finish the side activity or activities in the split and launch to the side again with a new configuration.

Dynamic split properties

Android 15 (API level 35) and higher supported by Jetpack WindowManager 1.4 and higher offer dynamic features that enable configurability of activity embedding splits, including:

  • Pane expansion: An interactive, draggable divider enables users to resize the panes in a split presentation.
  • Activity stack pinning: Users can pin the content in one container and isolate navigation in the container from navigation in the other container.
  • Dialog full-screen dim: When displaying a dialog, apps can specify whether to dim the entire task window or just the container that opened the dialog.

Pane expansion

Pane expansion enables users to adjust the amount of screen space allocated to the two activities in a dual‑pane layout.

To customize the appearance of the window divider and set the divider's draggable range, do the following:

  1. Create an instance of DividerAttributes

  2. Customize the divider attributes:

    • color : The color of the draggable pane separator.

    • widthDp : The width of the draggable pane separator. Set to WIDTH_SYSTEM_DEFAULT to let the system determine the divider width.

    • Drag range: The minimum percentage of the screen either pane can occupy. Can range from 0.33 to 0.66. Set to DRAG_RANGE_SYSTEM_DEFAULT to let the system determine the drag range.

কোটলিন

val splitAttributesBuilder: SplitAttributes.Builder = SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)

if (WindowSdkExtensions.getInstance().extensionVersion >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    )
}
val splitAttributes: SplitAttributes = splitAttributesBuilder.build()

জাভা

SplitAttributes.Builder splitAttributesBuilder = new SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT);

if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      new DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(ContextCompat.getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    );
}
SplitAttributes splitAttributes = splitAttributesBuilder.build();

Activity stack pinning

Activity stack pinning enables users to pin one of the split windows so the activity stays as is while users navigate within the other window. Activity stack pinning provides an enhanced multitasking experience.

To enable activity stack pinning in your app, do the following:

  1. Add a button to the layout file of the activity you want to pin, for example, the detail activity of an list‑detail layout:

    <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/detailActivity"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white"
     tools:context=".DetailActivity">
    
    <TextView
       android:id="@+id/textViewItemDetail"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="36sp"
       android:textColor="@color/obsidian"
       app:layout_constraintBottom_toTopOf="@id/pinButton"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
    
    <androidx.appcompat.widget.AppCompatButton
       android:id="@+id/pinButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/pin_this_activity"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@id/textViewItemDetail"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. In the onCreate() method of the activity, set an onclick listener on the button:

    কোটলিন

    pinButton = findViewById(R.id.pinButton)
    pinButton.setOnClickListener {
        val splitAttributes: SplitAttributes = SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build()
    
        val pinSplitRule = SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build()
    
        SplitController.getInstance(applicationContext).pinTopActivityStack(taskId, pinSplitRule)
    }

    জাভা

    Button pinButton = findViewById(R.id.pinButton);
    pinButton.setOnClickListener( (view) => {
        SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();
    
        SplitPinRule pinSplitRule = new SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build();
    
        SplitController.getInstance(getApplicationContext()).pinTopActivityStack(getTaskId(), pinSplitRule);
    });

Dialog full-screen dim

Activities typically dim their displays to draw attention to a dialog. In activity embedding, both panes of the dual‑pane display should dim, not just the pane containing the activity that opened the dialog, for a unified UI experience.

With WindowManager 1.4 and higher, the entire app window dims by default when a dialog opens (see EmbeddingConfiguration.DimAreaBehavior.ON_TASK ).

To dim only the container of the activity that opened the dialog, use EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK .

Extract an activity from a split to full window

Create a new configuration that displays the side activity full window, and then relaunch the activity with an intent that resolves to the same instance.

Check for split support at runtime

Activity embedding is supported on Android 12L (API level 32) and higher, but is also available on some devices running earlier platform versions. To check at runtime for the availability of the feature, use the SplitController.splitSupportStatus property or SplitController.getSplitSupportStatus() method:

কোটলিন

if (SplitController.getInstance(this).splitSupportStatus ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

জাভা

if (SplitController.getInstance(this).getSplitSupportStatus() ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

If splits are not supported, activities are launched on top of the activity stack (following the non-activity embedding model).

Prevent system override

The manufacturers of Android devices (original equipment manufacturers, or OEMs), can implement activity embedding as a function of the device system. The system specifies split rules for multi-activity apps, overriding the windowing behavior of the apps. The system override forces multi-activity apps into a system-defined activity embedding mode.

System activity embedding can enhance app presentation through multi-pane layouts, such as list-detail , without any changes to the app. However, the system's activity embedding might also cause incorrect app layouts, bugs, or conflicts with activity embedding implemented by the app.

Your app can prevent or permit system activity embedding by setting a property in the app manifest file, for example:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <property
            android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
            android:value="true|false" />
    </application>
</manifest>

The property name is defined in the Jetpack WindowManager WindowProperties object. Set the value to false if your app implements activity embedding, or if you want to otherwise prevent the system from applying its activity embedding rules to your app. Set the value to true to permit the system to apply system-defined activity embedding to your app.

Limitations, restrictions, and caveats

  • Only the host app of the task, which is identified as the owner of the root activity in the task, can organize and embed other activities in the task. If activities that support embedding and splits run in a task that belongs to a different application, then embedding and splits will not work for those activities.
  • Activities can only be organized within a single task. Launching an activity in a new task always puts it in a new expanded window outside of any existing splits.
  • Only activities in the same process can be organized and put in a split. The SplitInfo callback only reports activities that belong to the same process, since there is no way of knowing about activities in different processes.
  • Each pair or singular activity rule applies only to activity launches that happen after the rule has been registered. There is currently no way to update existing splits or their visual properties.
  • The split pair filter configuration must match the intents used when launching activities completely. The matching occurs at the point when a new activity is started from the application process, so it might not know about component names that are resolved later in the system process when using implicit intents. If a component name is not known at the time of launch, a wildcard can be used instead ("*/*") and filtering can be performed based on intent action.
  • There is currently no way to move activities between containers or in and out of splits after they were created. Splits are only created by the WindowManager library when new activities with matching rules are launched, and splits are destroyed when the last activity in a split container is finished.
  • Activities can be relaunched when the configuration changes, so when a split is created or removed and activity bounds change, the activity can go through complete destruction of the previous instance and creation of the new one. As a result, app developers should be careful with things like launching new activities from lifecycle callbacks.
  • Devices must include the window extensions interface to support activity embedding. Nearly all large screen devices running Android 12L (API level 32) or higher include the interface. However, some large screen devices that are not capable of running multiple activities don't include the window extensions interface. If a large screen device doesn't support multi-window mode, it might not support activity embedding.

অতিরিক্ত সম্পদ

,

Activity embedding optimizes apps on large screen devices by splitting an application's task window between two activities or two instances of the same activity.

Figure 1. Settings app with activities side by side.

If your app consists of multiple activities, activity embedding enables you to provide an enhanced user experience on tablets, foldables, and ChromeOS devices.

Activity embedding requires no code refactoring. You determine how your app displays its activities—side by side or stacked—by creating an XML configuration file or by making Jetpack WindowManager API calls.

Support for small screens is maintained automatically. When your app is on a device with a small screen, activities are stacked one on top of the other. On large screens, activities are displayed side by side. The system determines the presentation based on the configuration you've created—no branching logic required.

Activity embedding accommodates device orientation changes and works seamlessly on foldable devices, stacking and unstacking activities as the device folds and unfolds.

Activity embedding is supported on most large screen devices running Android 12L (API level 32) and higher.

Split task window

Activity embedding splits the app task window into two containers: primary and secondary. The containers hold activities launched from the main activity or from other activities already in the containers.

Activities are stacked in the secondary container as they're launched, and the secondary container is stacked on top of the primary container on small screens, so activity stacking and back navigation are consistent with the ordering of activities already built into your app.

Activity embedding enables you to display activities in a variety of ways. Your app can split the task window by launching two activities side by side simultaneously:

Figure 2. Two activities side by side.

Or, an activity that's occupying the entire task window can create a split by launching a new activity alongside:

Figure 3. Activity A starts activity B to the side.

Activities that are already in a split and sharing a task window can launch other activities in the following ways:

  • To the side on top of another activity:

    Figure 4. Activity A starts activity C to the side over activity B.
  • To the side, and shift the split sideways, concealing the previous primary activity:

    Figure 5. Activity B starts activity C to the side and shifts the split sideways.
  • Launch an activity in place on top; that is, in the same activity stack:

    Figure 6. Activity B starts activity C with no extra intent flags.
  • Launch an activity full window in the same task:

    Figure 7. Activity A or activity B starts activity C which fills the task window.

পিছনে নেভিগেশন

Different types of applications can have different back navigation rules in a split task window state depending on the dependencies between activities or how users trigger the back event, for example:

  • Going together: If activities are related, and one shouldn't be shown without the other, back navigation can be configured to finish both.
  • Going it alone: If activities are fully independent, back navigation on an activity does not affect the state of another activity in the task window.

The back event is sent to the last focused activity when using button navigation.

For gesture-based navigation:

  • Android 14 (API level 34) and lower — The back event is sent to the activity where the gesture occurred. When users swipe from the left side of the screen, the back event is sent to the activity in the left‑hand pane of the split window. When users swipe from the right side of the screen, the back event is sent to the activity in the right‑hand pane.

  • Android 15 (API level 35) and higher

    • When dealing with multiple activities from the same app, the gesture finishes the top activity regardless of the swipe direction, providing a more unified experience.

    • In scenarios involving two activities from different apps (overlay), the back event is directed to the last activity in focus, aligning with the behavior of button navigation.

Multi-pane layout

Jetpack WindowManager enables you to build an activity embedding multi-pane layout on large screen devices with Android 12L (API level 32) or higher and on some devices with earlier platform versions. Existing apps that are based on multiple activities rather than fragments or view-based layouts such as SlidingPaneLayout can provide an improved large screen user experience without refactoring source code.

One common example is a list-detail split. To ensure a high-quality presentation, the system starts the list activity, and then the application immediately starts the detail activity. The transition system waits until both activities are drawn, then displays them together. To the user, the two activities launch as one.

Figure 8. Two activities started simultaneously in a multi-pane layout.

Split attributes

You can specify how the task window is proportioned between the split containers and how the containers are layed out relative to one another.

For rules defined in an XML configuration file, set the following attributes:

  • splitRatio : Sets the container proportions. The value is a floating point number in the open interval (0.0, 1.0).
  • splitLayoutDirection : Specifies how the split containers are layed out relative to one another. Values include:
    • ltr : Left to right
    • rtl : Right to left
    • locale : Either ltr or rtl is determined from the locale setting

See the XML configuration section for examples.

For rules created using the WindowManager APIs, create a SplitAttributes object with SplitAttributes.Builder and call the following builder methods:

See the WindowManager API section for examples.

Figure 9. Two activity splits layed out left to right but with different split ratios.

স্থানধারক

Placeholder activities are empty secondary activities that occupy an area of an activity split. They are ultimately meant to be replaced with another activity that contains content. For example, a placeholder activity could occupy the secondary side of an activity split in a list-detail layout until an item from the list is selected, at which point an activity containing the detail information for the selected list item replaces the placeholder.

By default, the system displays placeholders only when there is enough space for an activity split. Placeholders automatically finish when the display size changes to a width or height too small to display a split. When space permits, the system relaunches the placeholder with a reinitialized state.

Figure 10. Foldable device folding and unfolding. Placeholder activity is finished and recreated as display size changes.

However, the stickyPlaceholder attribute of a SplitPlaceholderRule or setSticky() method of SplitPlaceholder.Builder can override the default behavior. When the attribute or method specifies a value of true , the system displays the placeholder as the topmost activity in the task window when the display is resized down to a single-pane display from a two-pane display (see Split configuration for an example) .

Figure 11. Foldable device folding and unfolding. Placeholder activity is sticky.

Window size changes

When device configuration changes reduce the task window width so that it is not large enough for a multi-pane layout (for example, when a large screen foldable device folds from tablet size to phone size or the app window is resized in multi-window mode), the non-placeholder activities in the secondary pane of the task window are stacked on top of the activities in the primary pane.

Placeholder activities are shown only when there is enough display width for a split. On smaller screens, the placeholder is automatically dismissed. When the display area becomes large enough again, the placeholder is recreated. (See the Placeholders section.)

Activity stacking is possible because WindowManager z-orders the activities in the secondary pane above activities in the primary pane.

Multiple activities in secondary pane

Activity B starts activity C in place with no extra intent flags:

Activity split containing activities A, B, and C with C stacked on
          top of B.

resulting in the following z-order of activities in the same task:

Secondary activity stack containing activity C stacked on top of B.
          Secondary stack is stacked on top of prmary activity stack
          containing activity A.

So, in a smaller task window, the application shrinks to a single activity with C at the top of the stack:

Small window showing only activity C.

Navigating back in the smaller window navigates through the activities stacked on top of each other.

If the task window configuration is restored to a larger size that can accommodate multiple panes, the activities are displayed side by side again.

Stacked splits

Activity B starts activity C to the side and shifts the split sideways:

Task window showing activities A and B, then activities B and C.

The result is the following z-order of activities in the same task:

Activities A, B, and C in a single stack. The activities are stacked
          in the following order from top to bottom: C, B, A.

In a smaller task window, the application shrinks to a single activity with C on top:

Small window showing only activity C.

Fixed-portrait orientation

The android:screenOrientation manifest setting enables apps to constrain activities to portrait or landscape orientation. To improve the user experience on large screen devices such as tablets and foldables, device manufacturers (OEMs) can ignore screen orientation requests and letterbox the app in portrait orientation on landscape displays or landscape orientation on portrait displays.

Figure 12. Letterboxed activities: fixed-portrait on landscape device (left), fixed-landscape on portrait device (right).

Similarly, when activity embedding is enabled, OEMs can customize devices to letterbox fixed-portrait activities in landscape orientation on large screens (width ≥ 600dp). When a fixed-portrait activity launches a second activity, the device can display the two activities side by side in a two-pane display.

Figure 13. Fixed-portrait activity A starts activity B to the side.

Always add the android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED property to your app manifest file to inform devices that your app supports activity embedding (see the Split configuration section). OEM-customized devices can then determine whether to letterbox fixed-portrait activities.

Split configuration

Split rules configure activity splits. You define split rules in an XML configuration file or by making Jetpack WindowManager API calls.

In either case, your app must access the WindowManager library and must inform the system that the app has implemented activity embedding.

নিম্নলিখিতগুলি করুন:

  1. Add the latest WindowManager library dependency to your app's module-level build.gradle file, for example:

    implementation 'androidx.window:window:1.1.0-beta02'

    The WindowManager library provides all the components required for activity embedding.

  2. Inform the system that your app has implemented activity embedding.

    Add the android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED property to the <application> element of the app manifest file, and set the value to true, for example:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application>
            <property
                android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
                android:value="true" />
        </application>
    </manifest>
    

    On WindowManager release 1.1.0-alpha06 and later, activity embedding splits are disabled unless the property is added to the manifest and set to true.

    Also, device manufacturers use the setting to enable custom capabilities for apps that support activity embedding. For example, devices can letterbox a portrait-only activity on landscape displays to orient the activity for the transition to a two-pane layout when a second activity starts (see Fixed-portrait orientation ).

XML কনফিগারেশন

To create an XML-based implementation of activity embedding, complete the following steps:

  1. Create an XML resource file that does the following:

    • Defines activities that share a split
    • Configures the split options
    • Creates a placeholder for the secondary container of the split when content is not available
    • Specifies activities that should never be part of a split

    যেমন:

    <!-- main_split_config.xml -->
    
    <resources
        xmlns:window="http://schemas.android.com/apk/res-auto">
    
        <!-- Define a split for the named activities. -->
        <SplitPairRule
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:finishPrimaryWithSecondary="never"
            window:finishSecondaryWithPrimary="always"
            window:clearTop="false">
            <SplitPairFilter
                window:primaryActivityName=".ListActivity"
                window:secondaryActivityName=".DetailActivity"/>
        </SplitPairRule>
    
        <!-- Specify a placeholder for the secondary container when content is
             not available. -->
        <SplitPlaceholderRule
            window:placeholderActivityName=".PlaceholderActivity"
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:stickyPlaceholder="false">
            <ActivityFilter
                window:activityName=".ListActivity"/>
        </SplitPlaceholderRule>
    
        <!-- Define activities that should never be part of a split. Note: Takes
             precedence over other split rules for the activity named in the
             rule. -->
        <ActivityRule
            window:alwaysExpand="true">
            <ActivityFilter
                window:activityName=".ExpandedActivity"/>
        </ActivityRule>
    
    </resources>
    
  2. Create an initializer.

    The WindowManager RuleController component parses the XML configuration file and makes the rules available to the system. A Jetpack Startup library Initializer makes the XML file available to RuleController at app startup so that the rules are in effect when any activities start.

    To create an initializer, do the following:

    1. Add the latest Jetpack Startup library dependency to your module-level build.gradle file, for example:

      implementation 'androidx.startup:startup-runtime:1.1.1'

    2. Create a class that implements the Initializer interface.

      The initializer makes the split rules available to RuleController by passing the ID of the XML configuration file ( main_split_config.xml ) to the RuleController.parseRules() method.

      কোটলিন

      class SplitInitializer : Initializer<RuleController> {
      
          override fun create(context: Context): RuleController {
              return RuleController.getInstance(context).apply {
                  setRules(RuleController.parseRules(context, R.xml.main_split_config))
              }
          }
      
          override fun dependencies(): List<Class<out Initializer<*>>> {
              return emptyList()
          }
      }

      জাভা

      public class SplitInitializer implements Initializer<RuleController> {
      
           @NonNull
           @Override
           public RuleController create(@NonNull Context context) {
               RuleController ruleController = RuleController.getInstance(context);
               ruleController.setRules(
                   RuleController.parseRules(context, R.xml.main_split_config)
               );
               return ruleController;
           }
      
           @NonNull
           @Override
           public List<Class<? extends Initializer<?>>> dependencies() {
               return Collections.emptyList();
           }
      }
  3. Create a content provider for the rule definitions.

    Add androidx.startup.InitializationProvider to your app manifest file as a <provider> . Include a reference to the implementation of your RuleController initializer, SplitInitializer :

    <!-- AndroidManifest.xml -->
    
    <provider android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <!-- Make SplitInitializer discoverable by InitializationProvider. -->
        <meta-data android:name="${applicationId}.SplitInitializer"
            android:value="androidx.startup" />
    </provider>
    

    InitializationProvider discovers and initializes SplitInitializer before the app's onCreate() method is called. As a result, the split rules are in effect when the app's main activity starts.

WindowManager API

You can implement activity embedding programmatically with a handful of API calls. Make the calls in the onCreate() method of a subclass of Application to ensure the rules are in effect before any activities launch.

To programmatically create an activity split, do the following:

  1. Create a split rule:

    1. Create a SplitPairFilter that identifies the activities that share the split:

      কোটলিন

      val splitPairFilter = SplitPairFilter(
         ComponentName(this, ListActivity::class.java),
         ComponentName(this, DetailActivity::class.java),
         null
      )

      জাভা

      SplitPairFilter splitPairFilter = new SplitPairFilter(
         new ComponentName(this, ListActivity.class),
         new ComponentName(this, DetailActivity.class),
         null
      );
    2. Add the filter to a filter set:

      কোটলিন

      val filterSet = setOf(splitPairFilter)

      জাভা

      Set<SplitPairFilter> filterSet = new HashSet<>();
      filterSet.add(splitPairFilter);
    3. Create layout attributes for the split:

      কোটলিন

      val splitAttributes: SplitAttributes = SplitAttributes.Builder()
          .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
          .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
          .build()

      জাভা

      final SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();

      SplitAttributes.Builder creates an object containing layout attributes:

      • setSplitType() : Defines how the available display area is allocated to each activity container. The ratio split type specifies the proportion of the available display area allocated to the primary container; the secondary container occupies the remainder of the available display area.
      • setLayoutDirection() : Specifies how the activity containers are laid out relative to one another, primary container first.
    4. Build a SplitPairRule :

      কোটলিন

      val splitPairRule = SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build()

      জাভা

      SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build();

      SplitPairRule.Builder creates and configures the rule:

      • filterSet : Contains split pair filters that determine when to apply the rule by identifying activities that share a split.
      • setDefaultSplitAttributes() : Applies layout attributes to the rule.
      • setMinWidthDp() : Sets the minimum display width (in density‑independent pixels, dp) that enables a split.
      • setMinSmallestWidthDp() : Sets the minimum value (in dp) that the smaller of the two display dimensions must have to enable a split regardless of the device orientation.
      • setMaxAspectRatioInPortrait() : Sets the maximum display aspect ratio (height:width) in portrait orientation for which activity splits are displayed. If the aspect ratio of a portrait display exceeds the maximum aspect ratio, splits are disabled regardless of the width of the display. Note: The default value is 1.4, which results in activities occupying the entire task window in portrait orientation on most tablets. See also SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT and setMaxAspectRatioInLandscape() . The default value for landscape is ALWAYS_ALLOW .
      • setFinishPrimaryWithSecondary() : Sets how finishing all activities in the secondary container affects the activities in the primary container. NEVER indicates the system shouldn't finish the primary activities when all activities in the secondary container finish (see Finish activities ).
      • setFinishSecondaryWithPrimary() : Sets how finishing all activities in the primary container affects the activities in the secondary container. ALWAYS indicates the system should always finish the activities in the secondary container when all activities in the primary container finish (see Finish activities ).
      • setClearTop() : Specifies whether all activities in the secondary container are finished when a new activity is launched in the container. A false value specifies that new activities are stacked on top of activities already in the secondary container.
    5. Get the singleton instance of the WindowManager RuleController , and add the rule:

      কোটলিন

        val ruleController = RuleController.getInstance(this)
        ruleController.addRule(splitPairRule)
        

      জাভা

        RuleController ruleController = RuleController.getInstance(this);
        ruleController.addRule(splitPairRule);
        
  2. Create a placeholder for the secondary container when content is not available:

    1. Create an ActivityFilter that identifies the activity with which the placeholder shares a task window split:

      কোটলিন

      val placeholderActivityFilter = ActivityFilter(
          ComponentName(this, ListActivity::class.java),
          null
      )

      জাভা

      ActivityFilter placeholderActivityFilter = new ActivityFilter(
          new ComponentName(this, ListActivity.class),
          null
      );
    2. Add the filter to a filter set:

      কোটলিন

      val placeholderActivityFilterSet = setOf(placeholderActivityFilter)

      জাভা

      Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
      placeholderActivityFilterSet.add(placeholderActivityFilter);
    3. Create a SplitPlaceholderRule :

      কোটলিন

      val splitPlaceholderRule = SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            Intent(context, PlaceholderActivity::class.java)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build()

      জাভা

      SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            new Intent(context, PlaceholderActivity.class)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build();

      SplitPlaceholderRule.Builder creates and configures the rule:

      • placeholderActivityFilterSet : Contains activity filters that determine when to apply the rule by identifying activities with which the placeholder activity is associated.
      • Intent : Specifies the launch of the placeholder activity.
      • setDefaultSplitAttributes() : Applies layout attributes to the rule.
      • setMinWidthDp() : Sets the minimum display width (in density-independent pixels, dp) that allows a split.
      • setMinSmallestWidthDp() : Sets the minimum value (in dp) that the smaller of the two display dimensions must have to allow a split regardless of the device orientation.
      • setMaxAspectRatioInPortrait() : Sets the maximum display aspect ratio (height:width) in portrait orientation for which activity splits are displayed. Note: The default value is 1.4, which results in activities filling the task window in portrait orientation on most tablets. See also SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT and setMaxAspectRatioInLandscape() . The default value for landscape is ALWAYS_ALLOW .
      • setFinishPrimaryWithPlaceholder() : Sets how finishing the placeholder activity affects the activities in the primary container. ALWAYS indicates the system should always finish the activities in the primary container when the placeholder finishes (see Finish activities ).
      • setSticky() : Determines whether the placeholder activity appears on top of the activity stack on small displays once the placeholder has first appeared in a split with sufficient minimum width.
    4. Add the rule to the WindowManager RuleController :

      কোটলিন

      ruleController.addRule(splitPlaceholderRule)

      জাভা

      ruleController.addRule(splitPlaceholderRule);
  3. Specify activities that should never be part of a split:

    1. Create an ActivityFilter that identifies an activity that should always occupy the entire task display area:

      কোটলিন

      val expandedActivityFilter = ActivityFilter(
        ComponentName(this, ExpandedActivity::class.java),
        null
      )

      জাভা

      ActivityFilter expandedActivityFilter = new ActivityFilter(
        new ComponentName(this, ExpandedActivity.class),
        null
      );
    2. Add the filter to a filter set:

      কোটলিন

      val expandedActivityFilterSet = setOf(expandedActivityFilter)

      জাভা

      Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>();
      expandedActivityFilterSet.add(expandedActivityFilter);
    3. Create an ActivityRule :

      কোটলিন

      val activityRule = ActivityRule.Builder(expandedActivityFilterSet)
          .setAlwaysExpand(true)
          .build()

      জাভা

      ActivityRule activityRule = new ActivityRule.Builder(
          expandedActivityFilterSet
      ).setAlwaysExpand(true)
       .build();

      ActivityRule.Builder creates and configures the rule:

      • expandedActivityFilterSet : Contains activity filters that determine when to apply the rule by identifying activities that you want to exclude from splits.
      • setAlwaysExpand() : Specifies whether the activity should fill the entire task window.
    4. Add the rule to the WindowManager RuleController :

      কোটলিন

      ruleController.addRule(activityRule)

      জাভা

      ruleController.addRule(activityRule);

Cross-application embedding

On Android 13 (API level 33) and higher, apps can embed activities from other apps. Cross‑application, or cross‑ UID , activity embedding enables visual integration of activities from multiple Android applications. The system displays an activity of the host app and an embedded activity from another app on screen side by side or top and bottom just as in single-app activity embedding.

For example, the Settings app could embed the wallpaper selector activity from the WallpaperPicker app:

Figure 14. Settings app (menu on left) with wallpaper selector as embedded activity (right).

ট্রাস্ট মডেল

Host processes that embed activities from other apps are able to redefine the presentation of the embedded activities, including size, position, cropping, and transparency. Malicious hosts can use this capability to mislead users and create clickjacking or other UI-redressing attacks.

To prevent misuse of cross-app activity embedding, Android requires apps to opt in to allow embedding of their activities. Apps can designate hosts as trusted or untrusted.

বিশ্বস্ত হোস্ট

To allow other applications to embed and fully control the presentation of activities from your app, specify the SHA-256 certificate of the host application in the android:knownActivityEmbeddingCerts attribute of the <activity> or <application> elements of your app's manifest file.

Set the value of android:knownActivityEmbeddingCerts either as a string:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
    ... />

or, to specify multiple certificates, an array of strings:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
    ... />

which references a resource like the following:

<resources>
    <string-array name="known_host_certificate_digests">
      <item>cert1</item>
      <item>cert2</item>
      ...
    </string-array>
</resources>

App owners can get a SHA certificate digest by running the Gradle signingReport task. The certificate digest is the SHA-256 fingerprint without the separating colons. For more information, see Run a signing report and Authenticating Your Client .

Untrusted hosts

To allow any app to embed your app's activities and control their presentation, specify the android:allowUntrustedActivityEmbedding attribute in the <activity> or <application> elements in the app manifest, for example:

<activity
    android:name=".MyEmbeddableActivity"
    android:allowUntrustedActivityEmbedding="true"
    ... />

The default value of the attribute is false, which prevents cross-app activity embedding.

কাস্টম প্রমাণীকরণ

To mitigate the risks of untrusted activity embedding, create a custom authentication mechanism that verifies the host identity. If you know the host certificates, use the androidx.security.app.authenticator library to authenticate. If the host authenticates after embedding your activity, you can display the actual content. If not, you can inform the user that the action was not allowed and block the content.

Use the ActivityEmbeddingController#isActivityEmbedded() method from the Jetpack WindowManager library to check whether a host is embedding your activity, for example:

কোটলিন

fun isActivityEmbedded(activity: Activity): Boolean {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity)
}

জাভা

boolean isActivityEmbedded(Activity activity) {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity);
}

Minimum size restriction

The Android system applies the minimum height and width specified in the app manifest <layout> element to embedded activities. If an application does not specify minimum height and width, the system default values apply ( sw220dp ).

If the host attempts to resize the embedded container to a size smaller than the minimum, the embedded container expands to occupy the entire task bounds.

<activity-alias>

For trusted or untrusted activity embedding to work with the <activity-alias> element, android:knownActivityEmbeddingCerts or android:allowUntrustedActivityEmbedding must be applied to the target activity rather than the alias. The policy that verifies security on the system server is based on the flags set on the target, not the alias.

হোস্ট অ্যাপ্লিকেশন

Host applications implement cross-app activity embedding the same way they implement single-app activity embedding. SplitPairRule and SplitPairFilter or ActivityRule and ActivityFilter objects specify embedded activities and task window splits. Split rules are defined statically in XML or at runtime using Jetpack WindowManager API calls.

If a host application attempts to embed an activity that has not opted in to cross-app embedding, the activity occupies the entire task bounds. As a result, host applications need to know whether target activities allow cross-app embedding.

If an embedded activity starts a new activity in the same task and the new activity has not opted in to cross-app embedding, the activity occupies the entire task bounds instead of overlaying the activity in the embedded container.

A host application can embed its own activities without restriction as long as the activities launch in the same task.

Split examples

Split from full window

Figure 15. Activity A starts activity B to the side.

No refactoring required. You can define the configuration for the split statically or at runtime and then call Context#startActivity() without any additional parameters.

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split by default

When the landing page of an application is designed to be split into two containers on large screens, the user experience is best when both activities are created and presented simultaneously. However, content might not be available for the secondary container of the split until the user interacts with the activity in the primary container (for example, the user selects an item from a navigation menu). A placeholder activity can fill the void until content can be displayed in the secondary container of the split (see the Placeholders section).

Figure 16. Split created by opening two activities simultaneously. One activity is a placeholder.

To create a split with a placeholder, create a placeholder and associate it with the primary activity:

<SplitPlaceholderRule
    window:placeholderActivityName=".PlaceholderActivity">
    <ActivityFilter
        window:activityName=".MainActivity"/>
</SplitPlaceholderRule>

When an app receives an intent, the target activity can be shown as the secondary part of an activity split; for example, a request to show a detail screen with information about an item from a list. On small displays, the detail is shown in the full task window; on larger devices, beside the list.

Figure 17. Deep link detail activity shown alone on a small screen, but together with a list activity on a large screen.

The launch request should be routed to the main activity, and the target detail activity should be launched in a split. The system automatically chooses the correct presentation—stacked or side by side—based on the available display width.

কোটলিন

override fun onCreate(savedInstanceState Bundle?) {
    . . .
    RuleController.getInstance(this)
        .addRule(SplitPairRule.Builder(filterSet).build())
    startActivity(Intent(this, DetailActivity::class.java))
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    RuleController.getInstance(this)
        .addRule(new SplitPairRule.Builder(filterSet).build());
    startActivity(new Intent(this, DetailActivity.class));
}

The deep link destination might be the only activity that should be available to the user in the back navigation stack, and you might want to avoid dismissing the detail activity and leaving only the main activity:

Large display with list activity and detail activity side by side.
          Back navigation unable to dismiss detail activity and leave list
          activity on screen.

Small display with detail activity only. Back navigation unable to
          dismiss detail activity and reveal list activity.

Instead, you can finish both activities at the same time by using the finishPrimaryWithSecondary attribute:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".ListActivity"
        window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>

See the Configuration attributes section.

Multiple activities in split containers

Stacking multiple activities in a split container enables users to access deep content. For example, with a list-detail split, the user might need to go into a sub-detail section but keep the primary activity in place:

Figure 18. Activity opened in place in the secondary pane of the task window.

কোটলিন

class DetailActivity {
    . . .
    fun onOpenSubDetail() {
      startActivity(Intent(this, SubDetailActivity::class.java))
    }
}

জাভা

public class DetailActivity {
    . . .
    void onOpenSubDetail() {
        startActivity(new Intent(this, SubDetailActivity.class));
    }
}

The sub-detail activity is placed on top of the detail activity, concealing it:

The user can then go back to the previous detail level by navigating back through the stack:

Figure 19. Activity removed from the top of the stack.

Stacking activities on top of each other is the default behavior when activities are launched from an activity in the same secondary container. Activities launched from the primary container within an active split also end up in the secondary container on the top of the activity stack.

Activities in a new task

When activities in a split task window start activities in a new task, the new task is separate from the task that includes the split and is displayed full window. The Recents screen shows two tasks: the task in the split and the new task.

Figure 20. Start activity C in a new task from activity B.

Activity replacement

Activities can be replaced in the secondary container stack; for example, when the primary activity is used for top-level navigation and the secondary activity is a selected destination. Each selection from the top-level navigation should start a new activity in the secondary container and remove the activity or activities that were previously there.

Figure 21. Top-level navigation activity in the primary pane replaces destination activities in the secondary pane.

If the app doesn't finish the activity in the secondary container when the navigation selection changes, back navigation might be confusing when the split is collapsed (when the device is folded). For example, if you have a menu in the primary pane and screens A and B stacked in the secondary pane, when the user folds the phone, B is on top of A, and A is on top of the menu. When the user navigates back from B, A appears instead of the menu.

Screen A must be removed from the back stack in such cases.

The default behavior when launching to the side in a new container over an existing split is to put the new secondary containers on top and retain the old ones in the back stack. You can configure the splits to clear the previous secondary containers with clearTop and launch new activities normally.

<SplitPairRule
    window:clearTop="true">
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenA"/>
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>

কোটলিন

class MenuActivity {
    . . .
    fun onMenuItemSelected(selectedMenuItem: Int) {
        startActivity(Intent(this, classForItem(selectedMenuItem)))
    }
}

জাভা

public class MenuActivity {
    . . .
    void onMenuItemSelected(int selectedMenuItem) {
        startActivity(new Intent(this, classForItem(selectedMenuItem)));
    }
}

Alternatively, use the same secondary activity, and from the primary (menu) activity send new intents that resolve to the same instance but trigger a state or UI update in the secondary container.

Multiple splits

Apps can provide multi-level deep navigation by launching additional activities to the side.

When an activity in a secondary container launches a new activity to the side, a new split is created over top of the existing split.

Figure 22. Activity B starts activity C to the side.

The back stack contains all activities that were previously opened, so users can navigate to the A/B split after finishing C.

Activities A, B, and C in a stack. The activities are stacked in
          the following order from top to bottom: C, B, A.

To create a new split, launch the new activity to the side from the existing secondary container. Declare the configurations for both the A/B and B/C splits and launch activity C normally from B:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
    <SplitPairFilter
        window:primaryActivityName=".B"
        window:secondaryActivityName=".C"/>
</SplitPairRule>

কোটলিন

class B {
    . . .
    fun onOpenC() {
        startActivity(Intent(this, C::class.java))
    }
}

জাভা

public class B {
    . . .
    void onOpenC() {
        startActivity(new Intent(this, C.class));
    }
}

React to split state changes

Different activities in an app can have UI elements that perform the same function; for example, a control that opens a window containing account settings.

Figure 23. Different activities with functionally identical UI elements.

If two activities that have a UI element in common are in a split, it's redundant and perhaps confusing to show the element in both activities.

Figure 24. Duplicate UI elements in activity split.

To know when activities are in a split, check the SplitController.splitInfoList flow or register a listener with SplitControllerCallbackAdapter for changes in the split state. Then, adjust the UI accordingly:

কোটলিন

val layout = layoutInflater.inflate(R.layout.activity_main, null)
val view = layout.findViewById<View>(R.id.infoButton)
lifecycleScope.launch {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance.
            .collect { list ->
                view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
            }
    }
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    new SplitControllerCallbackAdapter(SplitController.getInstance(this))
        .addSplitListener(
            this,
            Runnable::run,
            splitInfoList -> {
                View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
                layout.findViewById(R.id.infoButton).setVisibility(
                    splitInfoList.isEmpty() ? View.VISIBLE : View.GONE);
            });
}

Coroutines can be launched in any lifecycle state, but are typically launched in the STARTED state to conserve resources (see Use Kotlin coroutines with lifecycle-aware components for more information).

Callbacks can be made in any lifecycle state, including when an activity is stopped. Listeners should usually be registered in onStart() and unregistered in onStop() .

Full-window modal

Some activities block users from interacting with the application until a specified action is performed; for example, a login screen activity, policy acknowledgement screen, or error message. Modal activities should be prevented from appearing in a split.

An activity can be forced to always fill the task window by using the expand configuration:

<ActivityRule
    window:alwaysExpand="true">
    <ActivityFilter
        window:activityName=".FullWidthActivity"/>
</ActivityRule>

Finish activities

Users can finish activities on either side of the split by swiping from the edge of the display:

Figure 25. Swipe gesture finishing activity B.
Figure 26. Swipe gesture finishing activity A.

If the device is set up to use the back button instead of gesture navigation, the input is sent to the focused activity—the activity that was touched or launched last.

The effect that finishing all activities in a container has on the opposing container depends on the split configuration.

Configuration attributes

You can specify split pair rule attributes to configure how finishing all activities on one side of the split affects the activities on the other side of the split. গুণাবলী হল:

  • window:finishPrimaryWithSecondary — How finishing all activities in the secondary container affects the activities in the primary container
  • window:finishSecondaryWithPrimary — How finishing all activities in the primary container affects the activities in the secondary container

Possible values of the attributes include:

  • always — Always finish the activities in the associated container
  • never — Never finish the activities in the associated container
  • adjacent — Finish the activities in the associated container when the two containers are displayed adjacent to each other, but not when the two containers are stacked

যেমন:

<SplitPairRule
    &lt;!-- Do not finish primary container activities when all secondary container activities finish. --&gt;
    window:finishPrimaryWithSecondary="never"
    &lt;!-- Finish secondary container activities when all primary container activities finish. --&gt;
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

ডিফল্ট কনফিগারেশন

When all activities in one container of a split finish, the remaining container occupies the entire window:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. A is finished, leaving B to
          occupy the entire window.

Split containing activities A and B. B is finished, leaving A to
          occupy the entire window.

Finish activities together

Finish the activities in the primary container automatically when all activities in the secondary container finish:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. B is finished, which also
          finishes A, leaving the task window empty.

Split containing activities A and B. A is finished, leaving B alone
          in the task window.

Finish the activities in the secondary container automatically when all activities in the primary container finish:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. A is finished, which also
          finishes B, leaving the task window empty.

Split containing activities A and B. B is finished, leaving A alone
          in the task window.

Finish activities together when all activities in either the primary or secondary container finish:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split containing activities A and B. A is finished, which also
          finishes B, leaving the task window empty.

Split containing activities A and B. B is finished, which also
          finishes A, leaving the task window empty.

Finish multiple activities in containers

If multiple activities are stacked in a split container, finishing an activity on the bottom of the stack does not automatically finish activities on top.

For example, if two activities are in the secondary container, C on top of B:

Secondary activity stack containing activity C stacked on top of B           is stacked on top of the prmary activity stack containing activity           ক.

and the configuration of the split is defined by the configuration of activities A and B:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

finishing the top activity retains the split.

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. C finishes, leaving A and B in the
          activity split.

Finishing the bottom (root) activity of the secondary container does not remove the activities on top of it; and so, also retains the split.

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. B finishes, leaving A and C in the
          activity split.

Any additional rules for finishing activities together, such as finishing the secondary activity with the primary, are also executed:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split with activity A in primary container and activities B and C in
          secondary container, C stacked on top of B. A finishes, also
          finishing B and C.

And when the split is configured to finish primary and secondary together:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. C finishes, leaving A and B in the
          activity split.

Split with activity A in primary container and activities B and C in
          secondary, C stacked on top of B. B finishes, leaving A and C in the
          activity split.

Split with activity A in primary container and activities B and C in           secondary, C stacked on top of B. A finishes, also finishing B and           গ.

Change split properties at runtime

The properties of an active and visible split cannot be changed. Changing the split rules affects additional activity launches and new containers, but not existing and active splits.

To change the properties of active splits, finish the side activity or activities in the split and launch to the side again with a new configuration.

Dynamic split properties

Android 15 (API level 35) and higher supported by Jetpack WindowManager 1.4 and higher offer dynamic features that enable configurability of activity embedding splits, including:

  • Pane expansion: An interactive, draggable divider enables users to resize the panes in a split presentation.
  • Activity stack pinning: Users can pin the content in one container and isolate navigation in the container from navigation in the other container.
  • Dialog full-screen dim: When displaying a dialog, apps can specify whether to dim the entire task window or just the container that opened the dialog.

Pane expansion

Pane expansion enables users to adjust the amount of screen space allocated to the two activities in a dual‑pane layout.

To customize the appearance of the window divider and set the divider's draggable range, do the following:

  1. Create an instance of DividerAttributes

  2. Customize the divider attributes:

    • color : The color of the draggable pane separator.

    • widthDp : The width of the draggable pane separator. Set to WIDTH_SYSTEM_DEFAULT to let the system determine the divider width.

    • Drag range: The minimum percentage of the screen either pane can occupy. Can range from 0.33 to 0.66. Set to DRAG_RANGE_SYSTEM_DEFAULT to let the system determine the drag range.

কোটলিন

val splitAttributesBuilder: SplitAttributes.Builder = SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)

if (WindowSdkExtensions.getInstance().extensionVersion >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    )
}
val splitAttributes: SplitAttributes = splitAttributesBuilder.build()

জাভা

SplitAttributes.Builder splitAttributesBuilder = new SplitAttributes.Builder()
    .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
    .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT);

if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      new DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(ContextCompat.getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    );
}
SplitAttributes splitAttributes = splitAttributesBuilder.build();

Activity stack pinning

Activity stack pinning enables users to pin one of the split windows so the activity stays as is while users navigate within the other window. Activity stack pinning provides an enhanced multitasking experience.

To enable activity stack pinning in your app, do the following:

  1. Add a button to the layout file of the activity you want to pin, for example, the detail activity of an list‑detail layout:

    <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/detailActivity"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white"
     tools:context=".DetailActivity">
    
    <TextView
       android:id="@+id/textViewItemDetail"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="36sp"
       android:textColor="@color/obsidian"
       app:layout_constraintBottom_toTopOf="@id/pinButton"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
    
    <androidx.appcompat.widget.AppCompatButton
       android:id="@+id/pinButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/pin_this_activity"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@id/textViewItemDetail"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. In the onCreate() method of the activity, set an onclick listener on the button:

    কোটলিন

    pinButton = findViewById(R.id.pinButton)
    pinButton.setOnClickListener {
        val splitAttributes: SplitAttributes = SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build()
    
        val pinSplitRule = SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build()
    
        SplitController.getInstance(applicationContext).pinTopActivityStack(taskId, pinSplitRule)
    }

    জাভা

    Button pinButton = findViewById(R.id.pinButton);
    pinButton.setOnClickListener( (view) => {
        SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();
    
        SplitPinRule pinSplitRule = new SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build();
    
        SplitController.getInstance(getApplicationContext()).pinTopActivityStack(getTaskId(), pinSplitRule);
    });

Dialog full-screen dim

Activities typically dim their displays to draw attention to a dialog. In activity embedding, both panes of the dual‑pane display should dim, not just the pane containing the activity that opened the dialog, for a unified UI experience.

With WindowManager 1.4 and higher, the entire app window dims by default when a dialog opens (see EmbeddingConfiguration.DimAreaBehavior.ON_TASK ).

To dim only the container of the activity that opened the dialog, use EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK .

Extract an activity from a split to full window

Create a new configuration that displays the side activity full window, and then relaunch the activity with an intent that resolves to the same instance.

Check for split support at runtime

Activity embedding is supported on Android 12L (API level 32) and higher, but is also available on some devices running earlier platform versions. To check at runtime for the availability of the feature, use the SplitController.splitSupportStatus property or SplitController.getSplitSupportStatus() method:

কোটলিন

if (SplitController.getInstance(this).splitSupportStatus ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

জাভা

if (SplitController.getInstance(this).getSplitSupportStatus() ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

If splits are not supported, activities are launched on top of the activity stack (following the non-activity embedding model).

Prevent system override

The manufacturers of Android devices (original equipment manufacturers, or OEMs), can implement activity embedding as a function of the device system. The system specifies split rules for multi-activity apps, overriding the windowing behavior of the apps. The system override forces multi-activity apps into a system-defined activity embedding mode.

System activity embedding can enhance app presentation through multi-pane layouts, such as list-detail , without any changes to the app. However, the system's activity embedding might also cause incorrect app layouts, bugs, or conflicts with activity embedding implemented by the app.

Your app can prevent or permit system activity embedding by setting a property in the app manifest file, for example:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <property
            android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
            android:value="true|false" />
    </application>
</manifest>

The property name is defined in the Jetpack WindowManager WindowProperties object. Set the value to false if your app implements activity embedding, or if you want to otherwise prevent the system from applying its activity embedding rules to your app. Set the value to true to permit the system to apply system-defined activity embedding to your app.

Limitations, restrictions, and caveats

  • Only the host app of the task, which is identified as the owner of the root activity in the task, can organize and embed other activities in the task. If activities that support embedding and splits run in a task that belongs to a different application, then embedding and splits will not work for those activities.
  • Activities can only be organized within a single task. Launching an activity in a new task always puts it in a new expanded window outside of any existing splits.
  • Only activities in the same process can be organized and put in a split. The SplitInfo callback only reports activities that belong to the same process, since there is no way of knowing about activities in different processes.
  • Each pair or singular activity rule applies only to activity launches that happen after the rule has been registered. There is currently no way to update existing splits or their visual properties.
  • The split pair filter configuration must match the intents used when launching activities completely. The matching occurs at the point when a new activity is started from the application process, so it might not know about component names that are resolved later in the system process when using implicit intents. If a component name is not known at the time of launch, a wildcard can be used instead ("*/*") and filtering can be performed based on intent action.
  • There is currently no way to move activities between containers or in and out of splits after they were created. Splits are only created by the WindowManager library when new activities with matching rules are launched, and splits are destroyed when the last activity in a split container is finished.
  • Activities can be relaunched when the configuration changes, so when a split is created or removed and activity bounds change, the activity can go through complete destruction of the previous instance and creation of the new one. As a result, app developers should be careful with things like launching new activities from lifecycle callbacks.
  • Devices must include the window extensions interface to support activity embedding. Nearly all large screen devices running Android 12L (API level 32) or higher include the interface. However, some large screen devices that are not capable of running multiple activities don't include the window extensions interface. If a large screen device doesn't support multi-window mode, it might not support activity embedding.

অতিরিক্ত সম্পদ