ফিচার মডিউল আপনাকে আপনার অ্যাপের মূল মডিউল থেকে নির্দিষ্ট কিছু ফিচার ও রিসোর্স আলাদা করে আপনার অ্যাপ বান্ডেলে অন্তর্ভুক্ত করার সুযোগ দেয়। উদাহরণস্বরূপ, প্লে ফিচার ডেলিভারির মাধ্যমে ব্যবহারকারীরা আপনার অ্যাপের মূল APK ইনস্টল করার পরেও, প্রয়োজন অনুযায়ী সেই কম্পোনেন্টগুলো ডাউনলোড ও ইনস্টল করতে পারেন।
উদাহরণস্বরূপ, এমন একটি টেক্সট মেসেজিং অ্যাপের কথা ভাবুন যেখানে ছবি তুলে মেসেজ পাঠানোর সুবিধা আছে, কিন্তু খুব কম সংখ্যক ব্যবহারকারীই ছবিসহ মেসেজ পাঠান। এক্ষেত্রে ছবিসহ মেসেজ পাঠানোর সুবিধাটিকে একটি ডাউনলোডযোগ্য ফিচার মডিউল হিসেবে অন্তর্ভুক্ত করা যুক্তিযুক্ত হতে পারে। এর ফলে, সকল ব্যবহারকারীর জন্য অ্যাপটির প্রাথমিক ডাউনলোড সাইজ ছোট হবে এবং শুধুমাত্র যারা ছবিসহ মেসেজ পাঠান, তাদেরই এই অতিরিক্ত অংশটি ডাউনলোড করতে হবে।
মনে রাখবেন, এই ধরনের মডিউলারাইজেশনের জন্য আরও বেশি প্রচেষ্টা এবং সম্ভবত আপনার অ্যাপের বিদ্যমান কোড রিফ্যাক্টরিং করার প্রয়োজন হতে পারে, তাই সাবধানে বিবেচনা করুন আপনার অ্যাপের কোন ফিচারগুলো ব্যবহারকারীদের জন্য অন-ডিমান্ডে উপলব্ধ হলে সবচেয়ে বেশি উপকৃত হবে। অন-ডিমান্ড ফিচারগুলোর সর্বোত্তম ব্যবহারের ক্ষেত্র এবং নির্দেশিকা আরও ভালোভাবে বুঝতে, ‘ইউএক্স বেস্ট প্র্যাকটিসেস ফর অন-ডিমান্ড ডেলিভারি’ পড়ুন।
আপনি যদি অন ডিমান্ড ডেলিভারির মতো উন্নত ডেলিভারি অপশনগুলো চালু না করে, সময়ের সাথে সাথে অ্যাপের ফিচারগুলোকে ক্রমান্বয়ে মডিউলারাইজ করতে চান, তাহলে এর পরিবর্তে ইনস্টল-টাইম ডেলিভারি কনফিগার করুন ।
এই পৃষ্ঠাটি আপনাকে আপনার অ্যাপ প্রজেক্টে একটি ফিচার মডিউল যোগ করতে এবং অন-ডিমান্ড ডেলিভারির জন্য এটি কনফিগার করতে সাহায্য করে। শুরু করার আগে, নিশ্চিত করুন যে আপনি অ্যান্ড্রয়েড স্টুডিও ৩.৫ বা তার উচ্চতর সংস্করণ এবং অ্যান্ড্রয়েড গ্রেডল প্লাগইন ৩.৫.০ বা তার উচ্চতর সংস্করণ ব্যবহার করছেন।
অন-ডিমান্ড ডেলিভারির জন্য একটি নতুন মডিউল কনফিগার করুন।
নতুন ফিচার মডিউল তৈরি করার সবচেয়ে সহজ উপায় হলো অ্যান্ড্রয়েড স্টুডিও ৩.৫ বা তার উচ্চতর সংস্করণ ব্যবহার করা। যেহেতু ফিচার মডিউলগুলো বেস অ্যাপ মডিউলের উপর অন্তর্নিহিতভাবে নির্ভরশীল, তাই এগুলো শুধুমাত্র বিদ্যমান অ্যাপ প্রজেক্টেই যোগ করা যায়।
অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে আপনার অ্যাপ প্রজেক্টে একটি ফিচার মডিউল যোগ করতে, নিম্নলিখিত পদ্ধতি অনুসরণ করুন:
- যদি ইতিমধ্যে তা না করে থাকেন, তাহলে IDE-তে আপনার অ্যাপ প্রজেক্টটি খুলুন।
- মেনু বার থেকে ফাইল > নতুন > নতুন মডিউল নির্বাচন করুন।
- নতুন মডিউল তৈরি করুন ডায়ালগ বক্সে, ডাইনামিক ফিচার মডিউল নির্বাচন করুন এবং পরবর্তী বোতামে ক্লিক করুন।
- 'আপনার নতুন মডিউল কনফিগার করুন' বিভাগে, নিম্নলিখিতগুলি সম্পূর্ণ করুন:
- ড্রপডাউন মেনু থেকে আপনার অ্যাপ প্রজেক্টের জন্য বেস অ্যাপ্লিকেশন মডিউলটি নির্বাচন করুন।
- একটি মডিউলের নাম নির্দিষ্ট করুন। IDE আপনার Gradle সেটিংস ফাইলে মডিউলটিকে একটি Gradle সাবপ্রজেক্ট হিসেবে শনাক্ত করতে এই নামটি ব্যবহার করে। যখন আপনি আপনার অ্যাপ বান্ডেল বিল্ড করেন, তখন Gradle ফিচার মডিউলের ম্যানিফেস্টে
<manifest split>অ্যাট্রিবিউটটি যুক্ত করতে সাবপ্রজেক্ট নামের শেষ অংশটি ব্যবহার করে। - মডিউলটির প্যাকেজ নাম নির্দিষ্ট করুন। ডিফল্টরূপে, অ্যান্ড্রয়েড স্টুডিও এমন একটি প্যাকেজ নামের পরামর্শ দেয় যা বেস মডিউলের রুট প্যাকেজ নাম এবং পূর্ববর্তী ধাপে আপনার নির্দিষ্ট করা মডিউল নামটিকে একত্রিত করে।
- মডিউলটি যে সর্বনিম্ন এপিআই লেভেল সমর্থন করবে, তা নির্বাচন করুন। এই মানটি বেস মডিউলের মানের সাথে মিলতে হবে।
- পরবর্তী ধাপে যান।
মডিউল ডাউনলোড অপশন বিভাগে নিম্নলিখিতগুলি পূরণ করুন:
মডিউলের শিরোনামটি সর্বোচ্চ ৫০টি অক্ষর ব্যবহার করে নির্দিষ্ট করুন। প্ল্যাটফর্মটি এই শিরোনামটি ব্যবহার করে ব্যবহারকারীদের কাছে মডিউলটি শনাক্ত করে, যেমন—ব্যবহারকারী মডিউলটি ডাউনলোড করতে চান কিনা তা নিশ্চিত করার সময়। এই কারণে, আপনার অ্যাপের বেস মডিউলে অবশ্যই মডিউলের শিরোনামটি একটি স্ট্রিং রিসোর্স হিসেবে অন্তর্ভুক্ত থাকতে হবে, যা আপনি অনুবাদ করতে পারবেন। অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে মডিউল তৈরি করার সময়, IDE আপনার জন্য বেস মডিউলে স্ট্রিং রিসোর্সটি যোগ করে দেয় এবং ফিচার মডিউলের ম্যানিফেস্টে নিম্নলিখিত এন্ট্রিটি ইনজেক্ট করে:
<dist:module ... dist:title="@string/feature_title"> </dist:module>‘Install-time inclusion’- এর অধীনে ড্রপডাউন মেনুতে, ‘Do not include module at install-time’ নির্বাচন করুন। আপনার পছন্দ প্রতিফলিত করার জন্য Android Studio মডিউলের ম্যানিফেস্টে নিম্নলিখিতটি যুক্ত করে:
<dist:module ... > <dist:delivery> <dist:on-demand/> </dist:delivery> </dist:module>আপনি যদি এই মডিউলটি Android 4.4 (API লেভেল 20) এবং তার নিচের সংস্করণে চালিত ডিভাইসগুলিতে উপলব্ধ করতে এবং মাল্টি-এপিকে-তে অন্তর্ভুক্ত করতে চান, তাহলে Fusing- এর পাশের বক্সে টিক দিন। এর মানে হলো, আপনি এই মডিউলটির জন্য অন-ডিমান্ড আচরণ সক্রিয় করতে পারেন এবং যে ডিভাইসগুলি স্প্লিট এপিকে ডাউনলোড ও ইনস্টল করা সমর্থন করে না, সেগুলি থেকে এটিকে বাদ দিতে Fusing নিষ্ক্রিয় করতে পারেন। আপনার পছন্দ প্রতিফলিত করার জন্য Android Studio মডিউলটির ম্যানিফেস্টে নিম্নলিখিতটি যুক্ত করে:
<dist:module ...> <dist:fusing dist:include="true | false" /> </dist:module>
শেষ করুন- এ ক্লিক করুন।
অ্যান্ড্রয়েড স্টুডিও আপনার মডিউল তৈরি করা শেষ করলে, প্রজেক্ট প্যান থেকে এর বিষয়বস্তু নিজে পরিদর্শন করুন (মেনু বার থেকে ভিউ > টুল উইন্ডোজ > প্রজেক্ট নির্বাচন করুন)। ডিফল্ট কোড, রিসোর্স এবং বিন্যাস একটি স্ট্যান্ডার্ড অ্যাপ মডিউলের মতোই হওয়া উচিত।
এরপরে, আপনাকে প্লে ফিচার ডেলিভারি লাইব্রেরি ব্যবহার করে অন ডিমান্ড ইনস্টল কার্যকারিতাটি বাস্তবায়ন করতে হবে।
আপনার প্রোজেক্টে প্লে ফিচার ডেলিভারি লাইব্রেরি অন্তর্ভুক্ত করুন।
শুরু করার আগে, আপনাকে প্রথমে আপনার প্রজেক্টে প্লে ফিচার ডেলিভারি লাইব্রেরিটি যুক্ত করতে হবে।
অন-ডিমান্ড মডিউলের জন্য অনুরোধ করুন
যখন আপনার অ্যাপের কোনো ফিচার মডিউল ব্যবহার করার প্রয়োজন হয়, তখন এটি ফোরগ্রাউন্ডে থাকা অবস্থায় SplitInstallManager ক্লাসের মাধ্যমে সেটির জন্য অনুরোধ করতে পারে। অনুরোধ করার সময়, আপনার অ্যাপকে টার্গেট মডিউলের ম্যানিফেস্টে থাকা split এলিমেন্ট দ্বারা সংজ্ঞায়িত মডিউলের নামটি উল্লেখ করতে হবে। আপনি যখন অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে একটি ফিচার মডিউল তৈরি করেন , তখন বিল্ড সিস্টেম আপনার দেওয়া মডিউলের নামটি ব্যবহার করে কম্পাইল করার সময় এই প্রপার্টিটি মডিউলের ম্যানিফেস্টে যুক্ত করে দেয়। আরও তথ্যের জন্য, ফিচার মডিউল ম্যানিফেস্ট সম্পর্কে পড়ুন।
উদাহরণস্বরূপ, এমন একটি অ্যাপের কথা ভাবুন যেখানে ডিভাইসের ক্যামেরা ব্যবহার করে ছবি তুলে মেসেজ পাঠানোর জন্য একটি অন-ডিমান্ড মডিউল রয়েছে, এবং এই অন-ডিমান্ড মডিউলটি তার ম্যানিফেস্টে split="pictureMessages" উল্লেখ করে। নিম্নলিখিত নমুনাটি pictureMessages মডিউলটি (কিছু প্রচারমূলক ফিল্টারের জন্য একটি অতিরিক্ত মডিউল সহ) অনুরোধ করতে SplitInstallManager ব্যবহার করে:
কোটলিন
// Creates an instance of SplitInstallManager. val splitInstallManager = SplitInstallManagerFactory.create(context) // Creates a request to install a module. val request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build() splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener { sessionId -> ... } .addOnFailureListener { exception -> ... }
জাভা
// Creates an instance of SplitInstallManager. SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(context); // Creates a request to install a module. SplitInstallRequest request = SplitInstallRequest .newBuilder() // You can download multiple on demand modules per // request by invoking the following method for each // module you want to install. .addModule("pictureMessages") .addModule("promotionalFilters") .build(); splitInstallManager // Submits the request to install the module through the // asynchronous startInstall() task. Your app needs to be // in the foreground to submit the request. .startInstall(request) // You should also be able to gracefully handle // request state changes and errors. To learn more, go to // the section about how to Monitor the request state. .addOnSuccessListener(sessionId -> { ... }) .addOnFailureListener(exception -> { ... });
যখন আপনার অ্যাপ কোনো অন-ডিমান্ড মডিউলের জন্য অনুরোধ করে, তখন প্লে ফিচার ডেলিভারি লাইব্রেরি একটি “ফায়ার-অ্যান্ড-ফরগেট” কৌশল ব্যবহার করে। অর্থাৎ, এটি প্ল্যাটফর্মে মডিউলটি ডাউনলোড করার জন্য অনুরোধ পাঠায়, কিন্তু ইনস্টলেশন সফল হয়েছে কিনা তা পর্যবেক্ষণ করে না। ইনস্টলেশনের পরে ব্যবহারকারীর কার্যক্রম এগিয়ে নিয়ে যেতে বা ত্রুটিগুলো সুষ্ঠুভাবে সামাল দিতে, অনুরোধের অবস্থা পর্যবেক্ষণ করা নিশ্চিত করুন।
দ্রষ্টব্য: ডিভাইসে আগে থেকেই ইনস্টল করা আছে এমন কোনো ফিচার মডিউলের জন্য অনুরোধ করলেও কোনো সমস্যা নেই। মডিউলটি আগে থেকেই ইনস্টল করা আছে তা শনাক্ত করতে পারলে এপিআই (API) তাৎক্ষণিকভাবে অনুরোধটিকে সম্পন্ন বলে গণ্য করে। এছাড়াও, একটি মডিউল ইনস্টল হয়ে গেলে গুগল প্লে (Google Play) সেটিকে স্বয়ংক্রিয়ভাবে আপডেট করতে থাকে। অর্থাৎ, আপনি যখন আপনার অ্যাপ বান্ডেলের একটি নতুন সংস্করণ আপলোড করেন, তখন প্ল্যাটফর্মটি আপনার অ্যাপের অন্তর্গত সমস্ত ইনস্টল করা এপিকে (APK) আপডেট করে দেয়। আরও তথ্যের জন্য, ‘অ্যাপ আপডেট পরিচালনা’ (Manage app updates) পড়ুন।
মডিউলের কোড এবং রিসোর্স অ্যাক্সেস করার জন্য, আপনার অ্যাপে SplitCompat এনাবল করতে হবে। উল্লেখ্য যে, অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপের জন্য SplitCompat-এর প্রয়োজন নেই।
অন-ডিমান্ড মডিউলগুলির ইনস্টলেশন স্থগিত করুন
আপনার অ্যাপের যদি কোনো অন-ডিমান্ড মডিউল তাৎক্ষণিকভাবে ডাউনলোড ও ইনস্টল করার প্রয়োজন না হয়, তবে অ্যাপটি ব্যাকগ্রাউন্ডে থাকাকালীন ইনস্টলেশনটি স্থগিত রাখতে পারেন। উদাহরণস্বরূপ, যদি আপনি আপনার অ্যাপের পরবর্তী কোনো লঞ্চের জন্য কিছু প্রচারমূলক সামগ্রী আগে থেকে লোড করে রাখতে চান।
নিচে দেখানো অনুযায়ী, আপনি deferredInstall() মেথড ব্যবহার করে পরে ডাউনলোড করার জন্য একটি মডিউল নির্দিষ্ট করতে পারেন। এবং, SplitInstallManager.startInstall() এর মতো নয়, একটি ডিফার্ড ইনস্টলেশনের জন্য অনুরোধ শুরু করতে আপনার অ্যাপকে ফোরগ্রাউন্ডে থাকার প্রয়োজন হয় না।
কোটলিন
// Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(listOf("promotionalFilters"))
জাভা
// Requests an on demand module to be downloaded when the app enters // the background. You can specify more than one module at a time. splitInstallManager.deferredInstall(Arrays.asList("promotionalFilters"));
বিলম্বিত ইনস্টলেশনের অনুরোধগুলো সর্বোত্তম প্রচেষ্টার ভিত্তিতে করা হয় এবং আপনি সেগুলোর অগ্রগতি ট্র্যাক করতে পারবেন না। তাই, বিলম্বিত ইনস্টলেশনের জন্য নির্দিষ্ট করা কোনো মডিউল অ্যাক্সেস করার চেষ্টা করার আগে, আপনার যাচাই করে নেওয়া উচিত যে মডিউলটি ইনস্টল হয়েছে কি না । যদি আপনার মডিউলটি অবিলম্বে উপলব্ধ হওয়ার প্রয়োজন হয়, তবে পূর্ববর্তী বিভাগে দেখানো অনুযায়ী এটির জন্য অনুরোধ করতে SplitInstallManager.startInstall() ব্যবহার করুন।
অনুরোধের অবস্থা নিরীক্ষণ করুন
একটি প্রোগ্রেস বার আপডেট করতে, ইনস্টলেশনের পরে একটি ইন্টেন্ট চালু করতে, বা অনুরোধের ত্রুটি সুষ্ঠুভাবে সামলাতে, আপনাকে অ্যাসিঙ্ক্রোনাস SplitInstallManager.startInstall() টাস্ক থেকে স্টেট আপডেটের জন্য লিসেন করতে হবে। আপনার ইনস্টল অনুরোধের জন্য আপডেট গ্রহণ শুরু করার আগে, নিচে দেখানো পদ্ধতি অনুযায়ী একটি লিসেনার রেজিস্টার করুন এবং অনুরোধটির জন্য সেশন আইডি সংগ্রহ করুন।
কোটলিন
// Initializes a variable to later track the session ID for a given request. var mySessionId = 0 // Creates a listener for request status updates. val listener = SplitInstallStateUpdatedListener { state -> if (state.sessionId() == mySessionId) { // Read the status of the request to handle the state update. } } // Registers the listener. splitInstallManager.registerListener(listener) ... splitInstallManager .startInstall(request) // When the platform accepts your request to download // an on demand module, it binds it to the following session ID. // You use this ID to track further status updates for the request. .addOnSuccessListener { sessionId -> mySessionId = sessionId } // You should also add the following listener to handle any errors // processing the request. .addOnFailureListener { exception -> // Handle request errors. } // When your app no longer requires further updates, unregister the listener. splitInstallManager.unregisterListener(listener)
জাভা
// Initializes a variable to later track the session ID for a given request. int mySessionId = 0; // Creates a listener for request status updates. SplitInstallStateUpdatedListener listener = state -> { if (state.sessionId() == mySessionId) { // Read the status of the request to handle the state update. } }; // Registers the listener. splitInstallManager.registerListener(listener); ... splitInstallManager .startInstall(request) // When the platform accepts your request to download // an on demand module, it binds it to the following session ID. // You use this ID to track further status updates for the request. .addOnSuccessListener(sessionId -> { mySessionId = sessionId; }) // You should also add the following listener to handle any errors // processing the request. .addOnFailureListener(exception -> { // Handle request errors. }); // When your app no longer requires further updates, unregister the listener. splitInstallManager.unregisterListener(listener);
অনুরোধের ত্রুটিগুলি পরিচালনা করুন
মনে রাখবেন যে, অ্যাপ ইনস্টলেশন যেমন সবসময় সফল হয় না, ঠিক তেমনি ফিচার মডিউলের অন-ডিমান্ড ইনস্টলেশনও মাঝে মাঝে ব্যর্থ হতে পারে। ডিভাইসে স্টোরেজ কম থাকা, নেটওয়ার্ক সংযোগ না থাকা, অথবা ব্যবহারকারী গুগল প্লে স্টোরে সাইন ইন না করার মতো সমস্যার কারণে ইনস্টলেশন ব্যর্থ হতে পারে। ব্যবহারকারীর দৃষ্টিকোণ থেকে এই পরিস্থিতিগুলো কীভাবে সুন্দরভাবে সামাল দেওয়া যায়, সে বিষয়ে পরামর্শের জন্য আমাদের 'অন-ডিমান্ড ডেলিভারি' সংক্রান্ত ইউএক্স (UX) নির্দেশিকা দেখুন।
কোডের দিক থেকে, কোনো মডিউল ডাউনলোড বা ইনস্টল করার সময় ব্যর্থতা ঘটলে, নিচে দেখানো পদ্ধতি অনুযায়ী addOnFailureListener() ব্যবহার করে তা সামাল দেওয়া উচিত:
কোটলিন
splitInstallManager .startInstall(request) .addOnFailureListener { exception -> when ((exception as SplitInstallException).errorCode) { SplitInstallErrorCode.NETWORK_ERROR -> { // Display a message that requests the user to establish a // network connection. } SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> checkForActiveDownloads() ... } } fun checkForActiveDownloads() { splitInstallManager // Returns a SplitInstallSessionState object for each active session as a List. .sessionStates .addOnCompleteListener { task -> if (task.isSuccessful) { // Check for active sessions. for (state in task.result) { if (state.status() == SplitInstallSessionStatus.DOWNLOADING) { // Cancel the request, or request a deferred installation. } } } } }
জাভা
splitInstallManager .startInstall(request) .addOnFailureListener(exception -> { switch (((SplitInstallException) exception).getErrorCode()) { case SplitInstallErrorCode.NETWORK_ERROR: // Display a message that requests the user to establish a // network connection. break; case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED: checkForActiveDownloads(); ... }); void checkForActiveDownloads() { splitInstallManager // Returns a SplitInstallSessionState object for each active session as a List. .getSessionStates() .addOnCompleteListener( task -> { if (task.isSuccessful()) { // Check for active sessions. for (SplitInstallSessionState state : task.getResult()) { if (state.status() == SplitInstallSessionStatus.DOWNLOADING) { // Cancel the request, or request a deferred installation. } } } }); }
নিচের সারণিতে সেইসব ত্রুটির অবস্থা বর্ণনা করা হয়েছে যা আপনার অ্যাপকে সামলাতে হতে পারে:
| ত্রুটি কোড | বর্ণনা | প্রস্তাবিত পদক্ষেপ |
|---|---|---|
| সক্রিয় সেশনের সীমা অতিক্রম করেছে | অনুরোধটি প্রত্যাখ্যান করা হয়েছে কারণ বর্তমানে ডাউনলোড হচ্ছে এমন অন্তত একটি বিদ্যমান অনুরোধ রয়েছে। | উপরের নমুনায় দেখানো অনুযায়ী, এখনও কোনো অনুরোধ ডাউনলোড হচ্ছে কিনা তা পরীক্ষা করুন। |
| মডিউল অনুপলব্ধ | অ্যাপের বর্তমানে ইনস্টল করা সংস্করণ, ডিভাইস এবং ব্যবহারকারীর গুগল প্লে অ্যাকাউন্টের উপর ভিত্তি করে গুগল প্লে অনুরোধ করা মডিউলটি খুঁজে পেতে অক্ষম। | যদি ব্যবহারকারীর মডিউলটিতে প্রবেশাধিকার না থাকে, তবে তাকে অবহিত করুন। |
| অবৈধ_অনুরোধ | গুগল প্লে অনুরোধটি পেয়েছে, কিন্তু অনুরোধটি বৈধ নয়। | অনুরোধে অন্তর্ভুক্ত তথ্য সম্পূর্ণ ও নির্ভুল কিনা তা যাচাই করুন। |
| সেশন খুঁজে পাওয়া যায়নি | প্রদত্ত সেশন আইডিটির জন্য কোনো সেশন খুঁজে পাওয়া যায়নি। | আপনি যদি সেশন আইডি ব্যবহার করে কোনো রিকোয়েস্টের অবস্থা পর্যবেক্ষণ করার চেষ্টা করেন, তাহলে নিশ্চিত করুন যে সেশন আইডিটি সঠিক। |
| এপিআই উপলব্ধ নয় | বর্তমান ডিভাইসটিতে প্লে ফিচার ডেলিভারি লাইব্রেরি সমর্থিত নয়। অর্থাৎ, ডিভাইসটি চাহিদা অনুযায়ী ফিচার ডাউনলোড ও ইনস্টল করতে সক্ষম নয়। | অ্যান্ড্রয়েড ৪.৪ (এপিআই লেভেল ২০) বা তার নিচের সংস্করণে চালিত ডিভাইসগুলোর জন্য, ইনস্টলের সময় dist:fusing ম্যানিফেস্ট প্রপার্টি ব্যবহার করে ফিচার মডিউল অন্তর্ভুক্ত করা উচিত। আরও জানতে, ফিচার মডিউল ম্যানিফেস্ট সম্পর্কে পড়ুন। |
| নেটওয়ার্ক ত্রুটি | নেটওয়ার্ক ত্রুটির কারণে অনুরোধটি ব্যর্থ হয়েছে। | ব্যবহারকারীকে নেটওয়ার্ক সংযোগ স্থাপন করতে অথবা অন্য নেটওয়ার্কে পরিবর্তন করতে বলুন। |
| প্রবেশ প্রত্যাখ্যাত | অপর্যাপ্ত অনুমতির কারণে অ্যাপটি অনুরোধটি নিবন্ধন করতে পারছে না। | এটি সাধারণত ঘটে যখন অ্যাপটি ব্যাকগ্রাউন্ডে থাকে। অ্যাপটি ফোরগ্রাউন্ডে ফিরে এলে অনুরোধটি পাঠানোর চেষ্টা করুন। |
| বিদ্যমান সেশনের সাথে বেমানান | অনুরোধটিতে এক বা একাধিক মডিউল রয়েছে, যেগুলোর জন্য পূর্বে অনুরোধ করা হলেও এখনো ইনস্টল করা হয়নি। | হয় এমন একটি নতুন অনুরোধ তৈরি করুন যাতে আপনার অ্যাপের ইতিমধ্যে অনুরোধ করা মডিউলগুলো অন্তর্ভুক্ত না থাকে, অথবা অনুরোধটি পুনরায় চেষ্টা করার আগে বর্তমানে অনুরোধ করা সমস্ত মডিউলের ইনস্টলেশন শেষ হওয়া পর্যন্ত অপেক্ষা করুন। মনে রাখবেন, ইতিমধ্যে ইনস্টল করা আছে এমন কোনো মডিউলের জন্য অনুরোধ করলে কোনো ত্রুটি দেখা দেয় না। |
| পরিষেবা_মারা গেছে | অনুরোধটি প্রক্রিয়াকরণের দায়িত্বে থাকা পরিষেবাটি বন্ধ হয়ে গেছে। | অনুরোধটি পুনরায় চেষ্টা করুন। আপনার |
| অপর্যাপ্ত স্টোরেজ | ডিভাইসটিতে ফিচার মডিউলটি ইনস্টল করার জন্য পর্যাপ্ত খালি স্টোরেজ নেই। | ব্যবহারকারীকে জানান যে এই ফিচারটি ইনস্টল করার জন্য তার পর্যাপ্ত স্টোরেজ নেই। |
| SPLITCOMPAT_VERIFICATION_ERROR, SPLITCOMPAT_EMULATION_ERROR, SPLITCOMPAT_COPY_ERROR | SplitCompat ফিচার মডিউলটি লোড করতে পারেনি। | পরবর্তীবার অ্যাপটি পুনরায় চালু করার পর এই ত্রুটিগুলো স্বয়ংক্রিয়ভাবে সমাধান হয়ে যাবে। |
| প্লে_স্টোর_খুঁজে_পাওয়া_যায়নি | ডিভাইসটিতে প্লে স্টোর অ্যাপটি ইনস্টল করা নেই। | ব্যবহারকারীকে জানিয়ে দিন যে এই ফিচারটি ডাউনলোড করার জন্য প্লে স্টোর অ্যাপটি প্রয়োজন। |
| অ্যাপটি নিজের মালিকানাধীন নয় | অ্যাপটি গুগল প্লে দ্বারা ইনস্টল করা হয়নি এবং ফিচারটি ডাউনলোড করা যাচ্ছে না। এই ত্রুটিটি শুধুমাত্র ডিফার্ড ইনস্টলের ক্ষেত্রে ঘটতে পারে। | আপনি যদি চান ব্যবহারকারী গুগল প্লে থেকে অ্যাপটি ডাউনলোড করুক, তাহলে startInstall() ব্যবহার করুন, যা ব্যবহারকারীর প্রয়োজনীয় অনুমতি নিতে পারে। |
| অভ্যন্তরীণ ত্রুটি | প্লে স্টোরের অভ্যন্তরে একটি ত্রুটি ঘটেছে। | অনুরোধটি পুনরায় চেষ্টা করুন। |
যদি কোনো ব্যবহারকারী একটি অন-ডিমান্ড মডিউল ডাউনলোড করার অনুরোধ করেন এবং কোনো ত্রুটি ঘটে, তাহলে একটি ডায়ালগ বক্স দেখানোর কথা বিবেচনা করুন, যেখানে ব্যবহারকারীর জন্য দুটি বিকল্প থাকবে: ' আবার চেষ্টা করুন ' (যা অনুরোধটি পুনরায় চেষ্টা করে) এবং ' বাতিল করুন ' (যা অনুরোধটি বাতিল করে)। অতিরিক্ত সহায়তার জন্য, একটি 'হেল্প' লিঙ্কও প্রদান করা উচিত, যা ব্যবহারকারীদের গুগল প্লে হেল্প সেন্টারে নিয়ে যাবে।
স্টেট আপডেটগুলি পরিচালনা করুন
একটি লিসেনার রেজিস্টার করার পর এবং আপনার অনুরোধের জন্য সেশন আইডি রেকর্ড করার পরে, নিচে দেখানো অনুযায়ী স্টেট পরিবর্তনগুলি পরিচালনা করতে StateUpdatedListener.onStateUpdate() ব্যবহার করুন।
কোটলিন
override fun onStateUpdate(state : SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIED) { // Retry the request. return } if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.DOWNLOADING -> { val totalBytes = state.totalBytesToDownload() val progress = state.bytesDownloaded() // Update progress bar. } SplitInstallSessionStatus.INSTALLED -> { // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } } }
জাভা
@Override public void onStateUpdate(SplitInstallSessionState state) { if (state.status() == SplitInstallSessionStatus.FAILED && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) { // Retry the request. return; } if (state.sessionId() == mySessionId) { switch (state.status()) { case SplitInstallSessionStatus.DOWNLOADING: int totalBytes = state.totalBytesToDownload(); int progress = state.bytesDownloaded(); // Update progress bar. break; case SplitInstallSessionStatus.INSTALLED: // After a module is installed, you can start accessing its content or // fire an intent to start an activity in the installed module. // For other use cases, see access code and resources from installed modules. // If the request is an on demand module for an Android Instant App // running on Android 8.0 (API level 26) or higher, you need to // update the app context using the SplitInstallHelper API. } } }
আপনার ইনস্টল অনুরোধের সম্ভাব্য অবস্থাগুলো নিচের সারণিতে বর্ণনা করা হয়েছে।
| অনুরোধ অবস্থা | বর্ণনা | প্রস্তাবিত পদক্ষেপ |
|---|---|---|
| বিচারাধীন | অনুরোধটি গৃহীত হয়েছে এবং ডাউনলোড শীঘ্রই শুরু হবে। | ডাউনলোড সম্পর্কে ব্যবহারকারীকে প্রতিক্রিয়া জানানোর জন্য প্রোগ্রেস বারের মতো UI উপাদানগুলো চালু করুন। |
| ব্যবহারকারীর নিশ্চিতকরণ প্রয়োজন | ডাউনলোড করার জন্য ব্যবহারকারীর নিশ্চিতকরণ প্রয়োজন। সাধারণত এই অবস্থাটি দেখা যায় যদি অ্যাপটি গুগল প্লে-এর মাধ্যমে ইনস্টল করা না হয়ে থাকে। | গুগল প্লে-এর মাধ্যমে ফিচারটি ডাউনলোড নিশ্চিত করার জন্য ব্যবহারকারীকে অনুরোধ করুন। আরও জানতে, ব্যবহারকারীর নিশ্চিতকরণ কীভাবে গ্রহণ করবেন সেই বিভাগে যান। |
| ডাউনলোড করা | ডাউনলোড চলছে। | ডাউনলোডের জন্য যদি আপনি একটি প্রোগ্রেস বার প্রদান করেন, তাহলে UI আপডেট করার জন্য SplitInstallSessionState.bytesDownloaded() এবং SplitInstallSessionState.totalBytesToDownload() মেথডগুলো ব্যবহার করুন (এই টেবিলের উপরের কোড নমুনাটি দেখুন)। |
| ডাউনলোড করা হয়েছে | ডিভাইসটি মডিউলটি ডাউনলোড করেছে কিন্তু ইনস্টলেশন এখনো শুরু হয়নি। | ডাউনলোড করা মডিউলগুলো অ্যাক্সেস করতে এবং এই অবস্থাটি এড়াতে অ্যাপগুলোর SplitCompat সক্রিয় করা উচিত। ফিচার মডিউলের কোড এবং রিসোর্স অ্যাক্সেস করার জন্য এটি আবশ্যক। |
| ইনস্টল করা | ডিভাইসটি বর্তমানে মডিউলটি ইনস্টল করছে। | অগ্রগতি বারটি আপডেট করুন। এই অবস্থাটি সাধারণত স্বল্পস্থায়ী হয়। |
| ইনস্টল করা হয়েছে | মডিউলটি ডিভাইসটিতে ইনস্টল করা আছে। | ব্যবহারকারীর যাত্রা অব্যাহত রাখতে মডিউলটিতে থাকা কোড এবং রিসোর্স অ্যাক্সেস করুন । যদি মডিউলটি অ্যান্ড্রয়েড ৮.০ (এপিআই লেভেল ২৬) বা তার উচ্চতর সংস্করণে চালিত কোনো অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপের জন্য হয়, তাহলে নতুন মডিউল দিয়ে অ্যাপের কম্পোনেন্টগুলো আপডেট করতে আপনাকে |
| ব্যর্থ | ডিভাইসে মডিউলটি ইনস্টল করার আগেই অনুরোধটি ব্যর্থ হয়েছে। | ব্যবহারকারীকে অনুরোধটি পুনরায় চেষ্টা করতে বা বাতিল করতে বলুন। |
| বাতিল করা | ডিভাইসটি অনুরোধটি বাতিল করার প্রক্রিয়ায় রয়েছে। | আরও জানতে, ইনস্টল অনুরোধ কীভাবে বাতিল করতে হয় সেই বিভাগে যান। |
| বাতিল করা হয়েছে | অনুরোধটি বাতিল করা হয়েছে। |
ব্যবহারকারীর নিশ্চিতকরণ নিন
কিছু ক্ষেত্রে, একটি ডাউনলোড অনুরোধ পূরণ করার আগে গুগল প্লে ব্যবহারকারীর নিশ্চিতকরণ চাইতে পারে। উদাহরণস্বরূপ, যদি আপনার অ্যাপটি গুগল প্লে দ্বারা ইনস্টল করা না হয়ে থাকে অথবা যদি আপনি মোবাইল ডেটার মাধ্যমে একটি বড় আকারের ডাউনলোড করার চেষ্টা করেন। এই ধরনের ক্ষেত্রে, অনুরোধটির স্ট্যাটাস REQUIRES_USER_CONFIRMATION হিসেবে রিপোর্ট করা হয়, এবং ডিভাইসটি অনুরোধের মডিউলগুলো ডাউনলোড ও ইনস্টল করার আগে আপনার অ্যাপের ব্যবহারকারীর নিশ্চিতকরণ প্রয়োজন হয়। নিশ্চিতকরণ পাওয়ার জন্য, আপনার অ্যাপটি ব্যবহারকারীকে নিম্নোক্তভাবে প্রম্পট করবে:
কোটলিন
override fun onSessionStateUpdate(state: SplitInstallSessionState) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher) } ... }
জাভা
@Override void onSessionStateUpdate(SplitInstallSessionState state) { if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) { // Displays a confirmation for the user to confirm the request. splitInstallManager.startConfirmationDialogForResult( state, // an activity result launcher registered via registerForActivityResult activityResultLauncher); } ... }
আপনি বিল্ট-ইন ActivityResultContracts.StartIntentSenderForResult কন্ট্রাক্টটি ব্যবহার করে একটি অ্যাক্টিভিটি রেজাল্ট লঞ্চার রেজিস্টার করতে পারেন। অ্যাক্টিভিটি রেজাল্ট এপিআই (Activity Result APIs) দেখুন।
ব্যবহারকারীর প্রতিক্রিয়ার উপর ভিত্তি করে অনুরোধের অবস্থা আপডেট করা হয়:
- ব্যবহারকারী নিশ্চিতকরণটি গ্রহণ করলে, অনুরোধের অবস্থা 'বিচারাধীন
PENDINGহয়ে যায় এবং ডাউনলোড প্রক্রিয়াটি শুরু হয়। - যদি ব্যবহারকারী নিশ্চিতকরণটি প্রত্যাখ্যান করেন, তাহলে অনুরোধের অবস্থা
CANCELEDএ পরিবর্তিত হয়ে যায়। - যদি ডায়ালগটি বিলুপ্ত হওয়ার আগে ব্যবহারকারী কোনো নির্বাচন না করেন, তাহলে অনুরোধের অবস্থা
REQUIRES_USER_CONFIRMATIONহিসেবেই থেকে যায়। আপনার অ্যাপ অনুরোধটি সম্পূর্ণ করার জন্য ব্যবহারকারীকে পুনরায় বলতে পারে।
ব্যবহারকারীর প্রতিক্রিয়া সহ একটি কলব্যাক পেতে, আপনি নিচে দেখানো উপায়ে ActivityResultCallback-কে ওভাররাইড করতে পারেন।
কোটলিন
registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } }
জাভা
registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { // Handle the user's decision. For example, if the user selects "Cancel", // you may want to disable certain functionality that depends on the module. } });
একটি ইনস্টল অনুরোধ বাতিল করুন
যদি আপনার অ্যাপকে ইনস্টল করার আগে কোনো অনুরোধ বাতিল করার প্রয়োজন হয়, তবে এটি অনুরোধটির সেশন আইডি ব্যবহার করে cancelInstall() মেথডটি কল করতে পারে, যেমনটি নিচে দেখানো হয়েছে।
কোটলিন
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId)
জাভা
splitInstallManager // Cancels the request for the given session ID. .cancelInstall(mySessionId);
অ্যাক্সেস মডিউল
ডাউনলোড করার পর কোনো মডিউল থেকে কোড এবং রিসোর্স অ্যাক্সেস করতে হলে, আপনার অ্যাপ এবং আপনার অ্যাপ দ্বারা ডাউনলোড করা ফিচার মডিউলগুলোর প্রতিটি অ্যাক্টিভিটি—উভয়ের জন্যই SplitCompat লাইব্রেরিটি এনাবল করতে হবে।
তবে, আপনার জেনে রাখা উচিত যে, মডিউলটি ডাউনলোড করার পর কিছু সময়ের জন্য (কিছু ক্ষেত্রে কয়েক দিন) প্ল্যাটফর্মটিতে এর বিষয়বস্তু অ্যাক্সেস করার ক্ষেত্রে নিম্নলিখিত সীমাবদ্ধতাগুলো থাকে:
- প্ল্যাটফর্মটি মডিউল দ্বারা প্রবর্তিত কোনো নতুন ম্যানিফেস্ট এন্ট্রি প্রয়োগ করতে পারবে না।
- প্ল্যাটফর্মটি নোটিফিকেশনের মতো সিস্টেম UI কম্পোনেন্টগুলোর জন্য মডিউলের রিসোর্স অ্যাক্সেস করতে পারছে না। আপনার যদি এই ধরনের রিসোর্স অবিলম্বে ব্যবহার করার প্রয়োজন হয়, তবে সেগুলোকে আপনার অ্যাপের বেস মডিউলে অন্তর্ভুক্ত করার কথা বিবেচনা করুন।
SplitCompat সক্রিয় করুন
আপনার অ্যাপ যাতে ডাউনলোড করা মডিউল থেকে কোড এবং রিসোর্স অ্যাক্সেস করতে পারে, তার জন্য আপনাকে নিম্নলিখিত বিভাগগুলিতে বর্ণিত পদ্ধতিগুলির মধ্যে যেকোনো একটি ব্যবহার করে SplitCompat সক্রিয় করতে হবে।
আপনার অ্যাপের জন্য SplitCompat চালু করার পরে, আপনি যে ফিচার মডিউলগুলিতে আপনার অ্যাপের অ্যাক্সেস দিতে চান , সেগুলির প্রতিটি অ্যাক্টিভিটির জন্যও SplitCompat চালু করতে হবে।
ম্যানিফেস্টে SplitCompatApplication ঘোষণা করুন
SplitCompat সক্রিয় করার সবচেয়ে সহজ উপায় হলো আপনার অ্যাপের ম্যানিফেস্টে Application সাবক্লাস হিসেবে SplitCompatApplication ঘোষণা করা, যেমনটি নিচে দেখানো হয়েছে:
<application
...
android:name="com.google.android.play.core.splitcompat.SplitCompatApplication">
</application>
ডিভাইসে অ্যাপটি ইনস্টল করার পর, আপনি ডাউনলোড করা ফিচার মডিউলগুলো থেকে কোড এবং রিসোর্স স্বয়ংক্রিয়ভাবে অ্যাক্সেস করতে পারবেন।
রানটাইমে SplitCompat চালু করুন
আপনি রানটাইমে নির্দিষ্ট অ্যাক্টিভিটি বা সার্ভিসে SplitCompat সক্রিয় করতে পারেন। ফিচার মডিউলের অন্তর্ভুক্ত অ্যাক্টিভিটিগুলো চালু করার জন্য এইভাবে SplitCompat সক্রিয় করা প্রয়োজন। এটি করার জন্য, নিচে দেখানো অনুযায়ী attachBaseContext ওভাররাইড করুন।
আপনার যদি একটি কাস্টম Application ক্লাস থাকে, তবে আপনার অ্যাপের জন্য SplitCompat সক্রিয় করতে সেটিকে SplitCompatApplication এক্সটেন্ড করুন, যেমনটি নিচে দেখানো হয়েছে:
কোটলিন
class MyApplication : SplitCompatApplication() { ... }
জাভা
public class MyApplication extends SplitCompatApplication { ... }
SplitCompatApplication সহজভাবে ContextWrapper.attachBaseContext() কে ওভাররাইড করে SplitCompat.install(Context applicationContext) অন্তর্ভুক্ত করে। যদি আপনি না চান যে আপনার Application ক্লাসটি SplitCompatApplication এক্সটেন্ড করুক, তাহলে আপনি attachBaseContext() মেথডটি ম্যানুয়ালি ওভাররাইড করতে পারেন, যেমনটা নিচে দেখানো হলো:
কোটলিন
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // Emulates installation of future on demand modules using SplitCompat. SplitCompat.install(this) }
জাভা
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // Emulates installation of future on demand modules using SplitCompat. SplitCompat.install(this); }
যদি আপনার অন-ডিমান্ড মডিউলটি ইনস্ট্যান্ট অ্যাপ এবং ইনস্টল করা অ্যাপ উভয়ের সাথেই সামঞ্জস্যপূর্ণ হয়, তাহলে আপনি শর্তসাপেক্ষে নিম্নলিখিত উপায়ে SplitCompat চালু করতে পারেন:
কোটলিন
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this) } }
জাভা
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this); } }
মডিউল অ্যাক্টিভিটিগুলির জন্য SplitCompat সক্রিয় করুন
আপনার বেস অ্যাপের জন্য SplitCompat সক্রিয় করার পরে, আপনার অ্যাপ একটি ফিচার মডিউলে যে প্রতিটি অ্যাক্টিভিটি ডাউনলোড করে, তার জন্যও SplitCompat সক্রিয় করতে হবে। এটি করার জন্য, নিম্নলিখিতভাবে SplitCompat.installActivity() পদ্ধতিটি ব্যবহার করুন:
কোটলিন
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // Emulates installation of on demand modules using SplitCompat. SplitCompat.installActivity(this) }
জাভা
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); // Emulates installation of on demand modules using SplitCompat. SplitCompat.installActivity(this); }
ফিচার মডিউলে সংজ্ঞায়িত উপাদানগুলি অ্যাক্সেস করুন
একটি ফিচার মডিউলে সংজ্ঞায়িত একটি অ্যাক্টিভিটি শুরু করুন
SplitCompat সক্রিয় করার পর, আপনি startActivity() ব্যবহার করে ফিচার মডিউলে সংজ্ঞায়িত অ্যাক্টিভিটিগুলো চালু করতে পারবেন।
কোটলিন
startActivity(Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...))
জাভা
startActivity(new Intent() .setClassName("com.package", "com.package.module.MyActivity") .setFlags(...));
setClassName এর প্রথম প্যারামিটারটি হলো অ্যাপটির প্যাকেজ নেম এবং দ্বিতীয় প্যারামিটারটি হলো অ্যাক্টিভিটিটির সম্পূর্ণ ক্লাস নেম।
যখন আপনার অন-ডিমান্ড ডাউনলোড করা কোনো ফিচার মডিউলে একটি অ্যাক্টিভিটি থাকে, তখন আপনাকে অবশ্যই সেই অ্যাক্টিভিটিতে SplitCompat সক্রিয় করতে হবে।
একটি ফিচার মডিউলে সংজ্ঞায়িত একটি পরিষেবা শুরু করুন
SplitCompat সক্রিয় করার পর, আপনি startService() ব্যবহার করে ফিচার মডিউলে সংজ্ঞায়িত পরিষেবাগুলি চালু করতে পারেন।
কোটলিন
startService(Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...))
জাভা
startService(new Intent() .setClassName("com.package", "com.package.module.MyService") .setFlags(...));
একটি ফিচার মডিউলে সংজ্ঞায়িত একটি কম্পোনেন্ট এক্সপোর্ট করুন
আপনার ঐচ্ছিক মডিউলের ভিতরে এক্সপোর্ট করা অ্যান্ড্রয়েড কম্পোনেন্ট অন্তর্ভুক্ত করা উচিত নয়।
বিল্ড সিস্টেম সমস্ত মডিউলের ম্যানিফেস্ট এন্ট্রিগুলোকে বেস মডিউলের সাথে একীভূত করে; যদি কোনো ঐচ্ছিক মডিউলে একটি এক্সপোর্টেড কম্পোনেন্ট থাকে, তবে মডিউলটি ইনস্টল হওয়ার আগেও সেটি অ্যাক্সেসযোগ্য হবে এবং অন্য কোনো অ্যাপ থেকে কল করা হলে কোডের অনুপস্থিতির কারণে ক্র্যাশ ঘটাতে পারে।
অভ্যন্তরীণ কম্পোনেন্টগুলোর জন্য এটি কোনো সমস্যা নয়; এগুলো শুধু অ্যাপ দ্বারাই অ্যাক্সেস করা হয়, তাই কম্পোনেন্টটি অ্যাক্সেস করার আগে অ্যাপটি যাচাই করে নিতে পারে যে মডিউলটি ইনস্টল করা আছে কি না ।
আপনার যদি একটি এক্সপোর্টেড কম্পোনেন্টের প্রয়োজন হয় এবং আপনি এর কন্টেন্ট একটি ঐচ্ছিক মডিউলে রাখতে চান, তবে একটি প্রক্সি প্যাটার্ন প্রয়োগ করার কথা বিবেচনা করতে পারেন। আপনি বেস-এ একটি প্রক্সি এক্সপোর্টেড কম্পোনেন্ট যোগ করে এটি করতে পারেন; যখন এটি অ্যাক্সেস করা হয়, তখন প্রক্সি কম্পোনেন্টটি কন্টেন্ট ধারণকারী মডিউলটির উপস্থিতি পরীক্ষা করতে পারে। যদি মডিউলটি উপস্থিত থাকে, তবে প্রক্সি কম্পোনেন্টটি কলার অ্যাপ থেকে ইন্টেন্টটি রিলে করে একটি Intent মাধ্যমে মডিউলটি থেকে অভ্যন্তরীণ কম্পোনেন্টটি চালু করতে পারে। যদি মডিউলটি উপস্থিত না থাকে, তবে কম্পোনেন্টটি মডিউলটি ডাউনলোড করতে পারে অথবা কলার অ্যাপে একটি উপযুক্ত ত্রুটির বার্তা ফেরত পাঠাতে পারে।
ইনস্টল করা মডিউলগুলি থেকে কোড এবং রিসোর্স অ্যাক্সেস করুন
যদি আপনি আপনার বেস অ্যাপ্লিকেশন কনটেক্সট এবং ফিচার মডিউলের অ্যাক্টিভিটিগুলোর জন্য SplitCompat সক্রিয় করেন , তাহলে ঐচ্ছিক মডিউলটি ইনস্টল হয়ে গেলে আপনি ফিচার মডিউলের কোড এবং রিসোর্সগুলো বেস APK-এর একটি অংশ হিসেবেই ব্যবহার করতে পারবেন।
অন্য মডিউল থেকে অ্যাক্সেস কোড
একটি মডিউল থেকে বেস কোড অ্যাক্সেস করুন
আপনার বেস মডিউলের ভেতরের কোড অন্যান্য মডিউল সরাসরি ব্যবহার করতে পারে। এর জন্য আপনাকে বিশেষ কিছু করতে হবে না; শুধু আপনার প্রয়োজনীয় ক্লাসগুলো ইম্পোর্ট করে ব্যবহার করুন।
অন্য মডিউল থেকে মডিউল কোড অ্যাক্সেস করুন
একটি মডিউলের ভেতরের কোনো অবজেক্ট বা ক্লাসকে অন্য মডিউল থেকে সরাসরি স্ট্যাটিক্যালি অ্যাক্সেস করা যায় না, কিন্তু রিফ্লেকশন ব্যবহার করে এটিকে পরোক্ষভাবে অ্যাক্সেস করা সম্ভব।
রিফ্লেকশনের পারফরম্যান্স খরচের কারণে এটি কত ঘন ঘন ঘটে, সে বিষয়ে আপনার সতর্ক থাকা উচিত। জটিল ব্যবহারের ক্ষেত্রে, অ্যাপ্লিকেশনটির জীবনকালে একটিমাত্র রিফ্লেকশন কল নিশ্চিত করতে ড্যাগার ২-এর মতো ডিপেন্ডেন্সি ইনজেকশন ফ্রেমওয়ার্ক ব্যবহার করুন।
ইনস্ট্যানসিয়েশনের পরে অবজেক্টের সাথে মিথস্ক্রিয়া সহজ করার জন্য, বেস মডিউলে একটি ইন্টারফেস এবং ফিচার মডিউলে এর ইমপ্লিমেন্টেশন সংজ্ঞায়িত করার পরামর্শ দেওয়া হয়। উদাহরণস্বরূপ:
কোটলিন
// In the base module interface MyInterface { fun hello(): String } // In the feature module object MyInterfaceImpl : MyInterface { override fun hello() = "Hello" } // In the base module, where we want to access the feature module code val stringFromModule = (Class.forName("com.package.module.MyInterfaceImpl") .kotlin.objectInstance as MyInterface).hello();
জাভা
// In the base module public interface MyInterface { String hello(); } // In the feature module public class MyInterfaceImpl implements MyInterface { @Override public String hello() { return "Hello"; } } // In the base module, where we want to access the feature module code String stringFromModule = ((MyInterface) Class.forName("com.package.module.MyInterfaceImpl").getConstructor().newInstance()).hello();
অন্য মডিউল থেকে রিসোর্স এবং অ্যাসেট অ্যাক্সেস করুন
একবার কোনো মডিউল ইনস্টল হয়ে গেলে, আপনি দুটি বিষয় ছাড়া সাধারণ পদ্ধতিতেই মডিউলের ভেতরের রিসোর্স ও অ্যাসেটগুলো অ্যাক্সেস করতে পারবেন:
- আপনি যদি ভিন্ন কোনো মডিউল থেকে কোনো রিসোর্স অ্যাক্সেস করেন, তাহলে সেই মডিউলটি রিসোর্স আইডেন্টিফায়ারটি অ্যাক্সেস করতে পারবে না, যদিও নাম দিয়ে রিসোর্সটি অ্যাক্সেস করা যাবে। মনে রাখবেন, রিসোর্সটি রেফারেন্স করার জন্য যে প্যাকেজটি ব্যবহার করতে হবে, সেটি হলো সেই মডিউলের প্যাকেজ যেখানে রিসোর্সটি সংজ্ঞায়িত করা হয়েছে।
- আপনার অ্যাপের অন্য কোনো ইনস্টল করা মডিউল থেকে নতুন ইনস্টল করা কোনো মডিউলের অ্যাসেট বা রিসোর্স অ্যাক্সেস করতে চাইলে, আপনাকে অবশ্যই অ্যাপ্লিকেশন কনটেক্সট ব্যবহার করে তা করতে হবে। যে কম্পোনেন্টটি রিসোর্সগুলো অ্যাক্সেস করার চেষ্টা করছে, তার কনটেক্সট তখনও আপডেট হবে না। বিকল্পভাবে, আপনি সেই কম্পোনেন্টটি পুনরায় তৈরি করতে পারেন (উদাহরণস্বরূপ Activity.recreate() কল করে) অথবা ফিচার মডিউল ইনস্টলেশনের পরে সেটিতে SplitCompat পুনরায় ইনস্টল করতে পারেন।
অন-ডিমান্ড ডেলিভারি ব্যবহার করে একটি অ্যাপে নেটিভ কোড লোড করুন
ফিচার মডিউলের অন-ডিমান্ড ডেলিভারি ব্যবহার করার সময় আপনার সমস্ত নেটিভ লাইব্রেরি লোড করার জন্য আমরা ReLinker ব্যবহার করার পরামর্শ দিই। একটি ফিচার মডিউল ইনস্টল করার পরে নেটিভ লাইব্রেরি লোড করার ক্ষেত্রে যে সমস্যা হতো, ReLinker তার সমাধান করে। আপনি Android JNI Tips- এ ReLinker সম্পর্কে আরও জানতে পারবেন।
ঐচ্ছিক মডিউল থেকে নেটিভ কোড লোড করুন
একবার স্প্লিট ইনস্টল হয়ে গেলে, আমরা ReLinker- এর মাধ্যমে এর নেটিভ কোড লোড করার পরামর্শ দিই। ইনস্ট্যান্ট অ্যাপের জন্য আপনার এই বিশেষ পদ্ধতিটি ব্যবহার করা উচিত।
আপনি যদি আপনার নেটিভ কোড লোড করার জন্য System.loadLibrary() ব্যবহার করেন এবং আপনার নেটিভ লাইব্রেরিটি মডিউলের অন্য কোনো লাইব্রেরির উপর নির্ভরশীল হয়, তবে আপনাকে প্রথমে সেই অন্য লাইব্রেরিটি ম্যানুয়ালি লোড করতে হবে। আপনি যদি ReLinker ব্যবহার করেন, তবে এর সমতুল্য অপারেশনটি হলো Relinker.recursively().loadLibrary() ।
আপনি যদি কোনো অপশনাল মডিউলে সংজ্ঞায়িত লাইব্রেরি লোড করার জন্য নেটিভ কোডে dlopen() ব্যবহার করেন, তবে এটি রিলেটিভ লাইব্রেরি পাথের সাথে কাজ করবে না। এর সেরা সমাধান হলো Java কোড থেকে ClassLoader.findLibrary() এর মাধ্যমে লাইব্রেরির অ্যাবসোলিউট পাথটি সংগ্রহ করা এবং তারপর আপনার dlopen() কলে সেটি ব্যবহার করা। নেটিভ কোডে প্রবেশ করার আগেই এটি করুন অথবা আপনার নেটিভ কোড থেকে Java-তে একটি JNI কল ব্যবহার করুন।
ইনস্টল করা অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপগুলি অ্যাক্সেস করুন
একটি অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপ মডিউল ' INSTALLED হিসেবে রিপোর্ট করার পর, আপনি একটি রিফ্রেশড অ্যাপ কনটেক্সট ব্যবহার করে এর কোড এবং রিসোর্স অ্যাক্সেস করতে পারেন। আপনার অ্যাপ একটি মডিউল ইনস্টল করার আগে যে কনটেক্সট তৈরি করে (উদাহরণস্বরূপ, যা আগে থেকেই একটি ভেরিয়েবলে সংরক্ষিত থাকে), তাতে নতুন মডিউলটির কন্টেন্ট থাকে না। কিন্তু একটি ফ্রেশ কনটেক্সটে তা থাকে—এটি, উদাহরণস্বরূপ, createPackageContext ব্যবহার করে পাওয়া যেতে পারে।
কোটলিন
// Generate a new context as soon as a request for a new module // reports as INSTALLED. override fun onStateUpdate(state: SplitInstallSessionState ) { if (state.sessionId() == mySessionId) { when (state.status()) { ... SplitInstallSessionStatus.INSTALLED -> { val newContext = context.createPackageContext(context.packageName, 0) // If you use AssetManager to access your app’s raw asset files, you’ll need // to generate a new AssetManager instance from the updated context. val am = newContext.assets } } } }
জাভা
// Generate a new context as soon as a request for a new module // reports as INSTALLED. @Override public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { ... case SplitInstallSessionStatus.INSTALLED: Context newContext = context.createPackageContext(context.getPackageName(), 0); // If you use AssetManager to access your app’s raw asset files, you’ll need // to generate a new AssetManager instance from the updated context. AssetManager am = newContext.getAssets(); } } }
অ্যান্ড্রয়েড ৮.০ এবং তার পরবর্তী সংস্করণগুলিতে অ্যান্ড্রয়েড ইনস্ট্যান্ট অ্যাপস
Android 8.0 (API লেভেল 26) এবং তার উপরের সংস্করণে একটি Android Instant App-এর জন্য কোনো অন-ডিমান্ড মডিউলের অনুরোধ করার সময়, ইনস্টল অনুরোধটি INSTALLED হিসেবে রিপোর্ট হওয়ার পরে, আপনাকে SplitInstallHelper.updateAppInfo(Context context) কল করার মাধ্যমে নতুন মডিউলের কনটেক্সট দিয়ে অ্যাপটি আপডেট করতে হবে। অন্যথায়, অ্যাপটি তখনও মডিউলটির কোড এবং রিসোর্স সম্পর্কে অবগত থাকে না। অ্যাপের মেটাডেটা আপডেট করার পরে, আপনাকে পরবর্তী মেইন থ্রেড ইভেন্টের সময় একটি নতুন Handler কল করে মডিউলটির কন্টেন্ট লোড করতে হবে, যেমনটি নিচে দেখানো হয়েছে:
কোটলিন
override fun onStateUpdate(state: SplitInstallSessionState ) { if (state.sessionId() == mySessionId) { when (state.status()) { ... SplitInstallSessionStatus.INSTALLED -> { // You need to perform the following only for Android Instant Apps // running on Android 8.0 (API level 26) and higher. if (BuildCompat.isAtLeastO()) { // Updates the app’s context with the code and resources of the // installed module. SplitInstallHelper.updateAppInfo(context) Handler().post { // Loads contents from the module using AssetManager val am = context.assets ... } } } } } }
জাভা
@Override public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { ... case SplitInstallSessionStatus.INSTALLED: // You need to perform the following only for Android Instant Apps // running on Android 8.0 (API level 26) and higher. if (BuildCompat.isAtLeastO()) { // Updates the app’s context with the code and resources of the // installed module. SplitInstallHelper.updateAppInfo(context); new Handler().post(new Runnable() { @Override public void run() { // Loads contents from the module using AssetManager AssetManager am = context.getAssets(); ... } }); } } } }
C/C++ লাইব্রেরি লোড করুন
যদি আপনি কোনো ইনস্ট্যান্ট অ্যাপে ডিভাইসের আগে থেকে ডাউনলোড করা কোনো মডিউল থেকে C/C++ লাইব্রেরি লোড করতে চান, তাহলে নিচে দেখানো অনুযায়ী SplitInstallHelper.loadLibrary(Context context, String libName) ব্যবহার করুন:
কোটলিন
override fun onStateUpdate(state: SplitInstallSessionState) { if (state.sessionId() == mySessionId) { when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Updates the app’s context as soon as a module is installed. val newContext = context.createPackageContext(context.packageName, 0) // To load C/C++ libraries from an installed module, use the following API // instead of System.load(). SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”) ... } } } }
জাভা
public void onStateUpdate(SplitInstallSessionState state) { if (state.sessionId() == mySessionId) { switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: // Updates the app’s context as soon as a module is installed. Context newContext = context.createPackageContext(context.getPackageName(), 0); // To load C/C++ libraries from an installed module, use the following API // instead of System.load(). SplitInstallHelper.loadLibrary(newContext, “my-cpp-lib”); ... } } }
জ্ঞাত সীমাবদ্ধতা
- যে অ্যাক্টিভিটি কোনো অপশনাল মডিউল থেকে রিসোর্স বা অ্যাসেট অ্যাক্সেস করে, সেখানে অ্যান্ড্রয়েড ওয়েবভিউ ব্যবহার করা সম্ভব নয়। অ্যান্ড্রয়েড এপিআই লেভেল ২৮ এবং তার নিচের সংস্করণগুলোতে ওয়েবভিউ এবং স্প্লিটকমপ্যাটের মধ্যে অসামঞ্জস্যতার কারণেই এমনটা হয়।
- আপনি আপনার অ্যাপের মধ্যে অ্যান্ড্রয়েড
ApplicationInfoঅবজেক্ট, সেগুলোর বিষয়বস্তু, বা সেগুলোকে ধারণকারী অবজেক্ট ক্যাশ করতে পারবেন না। আপনার সর্বদা প্রয়োজন অনুযায়ী একটি অ্যাপ কনটেক্সট থেকে এই অবজেক্টগুলো ফেচ করা উচিত। এই ধরনের অবজেক্ট ক্যাশ করলে ফিচার মডিউল ইনস্টল করার সময় অ্যাপটি ক্র্যাশ করতে পারে।
ইনস্টল করা মডিউলগুলি পরিচালনা করুন
ডিভাইসে বর্তমানে কোন ফিচার মডিউলগুলো ইনস্টল করা আছে তা পরীক্ষা করতে, আপনি SplitInstallManager.getInstalledModules() কল করতে পারেন, যা ইনস্টল করা মডিউলগুলোর নামসহ একটি Set<String> রিটার্ন করে, যেমনটি নিচে দেখানো হয়েছে।
কোটলিন
val installedModules: Set<String> = splitInstallManager.installedModules
জাভা
Set<String> installedModules = splitInstallManager.getInstalledModules();
মডিউলগুলি আনইনস্টল করুন
আপনি SplitInstallManager.deferredUninstall(List<String> moduleNames) কল করে ডিভাইসটিকে মডিউল আনইনস্টল করার অনুরোধ করতে পারেন, যেমনটি নিচে দেখানো হয়েছে।
কোটলিন
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(listOf("pictureMessages", "promotionalFilters"))
জাভা
// Specifies two feature modules for deferred uninstall. splitInstallManager.deferredUninstall(Arrays.asList("pictureMessages", "promotionalFilters"));
মডিউল আনইনস্টল তাৎক্ষণিকভাবে হয় না। অর্থাৎ, স্টোরেজ স্পেস বাঁচানোর জন্য ডিভাইসটি প্রয়োজন অনুযায়ী ব্যাকগ্রাউন্ডে সেগুলোকে আনইনস্টল করে। পূর্ববর্তী বিভাগে বর্ণিত পদ্ধতি অনুযায়ী SplitInstallManager.getInstalledModules() কল করে এবং এর ফলাফল পরীক্ষা করে আপনি নিশ্চিত হতে পারেন যে ডিভাইসটি কোনো মডিউল ডিলিট করেছে।
অতিরিক্ত ভাষা রিসোর্স ডাউনলোড করুন
অ্যাপ বান্ডেলের মাধ্যমে ডিভাইসগুলো আপনার অ্যাপ চালানোর জন্য শুধুমাত্র প্রয়োজনীয় কোড এবং রিসোর্স ডাউনলোড করে। তাই, ভাষা রিসোর্সের ক্ষেত্রে, ব্যবহারকারীর ডিভাইসটি আপনার অ্যাপের শুধুমাত্র সেইসব ভাষা রিসোর্স ডাউনলোড করে, যা ডিভাইসের সেটিংসে বর্তমানে নির্বাচিত এক বা একাধিক ভাষার সাথে মেলে।
আপনি যদি আপনার অ্যাপে অতিরিক্ত ভাষার রিসোর্স ব্যবহারের সুযোগ দিতে চান—উদাহরণস্বরূপ, অ্যাপের ভেতরে ভাষা বাছাই করার ব্যবস্থা চালু করতে—তাহলে আপনি প্লে ফিচার ডেলিভারি লাইব্রেরি ব্যবহার করে প্রয়োজন অনুযায়ী সেগুলো ডাউনলোড করতে পারেন। এই প্রক্রিয়াটি একটি ফিচার মডিউল ডাউনলোড করার মতোই, যা নিচে দেখানো হলো।
কোটলিন
// Captures the user’s preferred language and persists it // through the app’s SharedPreferences. sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply() ... // Creates a request to download and install additional language resources. val request = SplitInstallRequest.newBuilder() // Uses the addLanguage() method to include French language resources in the request. // Note that country codes are ignored. That is, if your app // includes resources for “fr-FR” and “fr-CA”, resources for both // country codes are downloaded when requesting resources for "fr". .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build() // Submits the request to install the additional language resources. splitInstallManager.startInstall(request)
জাভা
// Captures the user’s preferred language and persists it // through the app’s SharedPreferences. sharedPrefs.edit().putString(LANGUAGE_SELECTION, "fr").apply(); ... // Creates a request to download and install additional language resources. SplitInstallRequest request = SplitInstallRequest.newBuilder() // Uses the addLanguage() method to include French language resources in the request. // Note that country codes are ignored. That is, if your app // includes resources for “fr-FR” and “fr-CA”, resources for both // country codes are downloaded when requesting resources for "fr". .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) .build(); // Submits the request to install the additional language resources. splitInstallManager.startInstall(request);
অনুরোধটিকে একটি ফিচার মডিউলের অনুরোধ হিসেবেই বিবেচনা করা হয়। অর্থাৎ, আপনি স্বাভাবিকভাবেই অনুরোধটির অবস্থা পর্যবেক্ষণ করতে পারবেন।
যদি আপনার অ্যাপের অবিলম্বে অতিরিক্ত ভাষার রিসোর্সগুলির প্রয়োজন না হয়, তাহলে আপনি ইনস্টলেশনটি অ্যাপটি ব্যাকগ্রাউন্ডে থাকার জন্য স্থগিত করতে পারেন, যেমনটি নিচে দেখানো হয়েছে।
কোটলিন
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
জাভা
splitInstallManager.deferredLanguageInstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
ডাউনলোড করা ভাষা রিসোর্স অ্যাক্সেস করুন
ডাউনলোড করা ভাষার রিসোর্সগুলো অ্যাক্সেস করার জন্য, আপনার অ্যাপকে প্রতিটি অ্যাক্টিভিটির attachBaseContext() মেথডের মধ্যে SplitCompat.installActivity() মেথডটি রান করতে হবে, যেগুলোর ওই রিসোর্সগুলোতে অ্যাক্সেস প্রয়োজন, যেমনটি নিচে দেখানো হয়েছে।
কোটলিন
override fun attachBaseContext(base: Context) { super.attachBaseContext(base) SplitCompat.installActivity(this) }
জাভা
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); SplitCompat.installActivity(this); }
আপনার অ্যাপ দ্বারা ডাউনলোড করা ভাষা রিসোর্স ব্যবহার করতে চান এমন প্রতিটি অ্যাক্টিভিটির জন্য, তার Configuration মাধ্যমে বেস কনটেক্সট আপডেট করুন এবং একটি নতুন লোকেল সেট করুন:
কোটলিন
override fun attachBaseContext(base: Context) { val configuration = Configuration() configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))) val context = base.createConfigurationContext(configuration) super.attachBaseContext(context) SplitCompat.install(this) }
জাভা
@Override protected void attachBaseContext(Context base) { Configuration configuration = new Configuration(); configuration.setLocale(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION))); Context context = base.createConfigurationContext(configuration); super.attachBaseContext(context); SplitCompat.install(this); }
এই পরিবর্তনগুলি কার্যকর করার জন্য, নতুন ভাষা ইনস্টল এবং ব্যবহারের জন্য প্রস্তুত হয়ে গেলে আপনাকে আপনার অ্যাক্টিভিটিটি পুনরায় তৈরি করতে হবে। আপনি Activity#recreate() মেথডটি ব্যবহার করতে পারেন।
কোটলিন
when (state.status()) { SplitInstallSessionStatus.INSTALLED -> { // Recreates the activity to load resources for the new language // preference. activity.recreate() } ... }
জাভা
switch (state.status()) { case SplitInstallSessionStatus.INSTALLED: // Recreates the activity to load resources for the new language // preference. activity.recreate(); ... }
অতিরিক্ত ভাষার রিসোর্স আনইনস্টল করুন
ফিচার মডিউলের মতোই, আপনি যেকোনো সময় অতিরিক্ত রিসোর্স আনইনস্টল করতে পারেন। আনইনস্টল করার অনুরোধ জানানোর আগে, আপনি প্রথমে নিম্নলিখিতভাবে বর্তমানে কোন ভাষাগুলো ইনস্টল করা আছে তা নির্ধারণ করে নিতে পারেন।
কোটলিন
val installedLanguages: Set<String> = splitInstallManager.installedLanguages
জাভা
Set<String> installedLanguages = splitInstallManager.getInstalledLanguages();
এরপর আপনি deferredLanguageUninstall() মেথডটি ব্যবহার করে কোন কোন ভাষা আনইনস্টল করবেন তা ঠিক করতে পারেন, যেমনটা নিচে দেখানো হয়েছে।
কোটলিন
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
জাভা
splitInstallManager.deferredLanguageUninstall( Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)));
স্থানীয়ভাবে পরীক্ষা মডিউল ইনস্টল করুন
প্লে ফিচার ডেলিভারি লাইব্রেরি আপনাকে প্লে স্টোরের সাথে সংযোগ না করেই, স্থানীয়ভাবে আপনার অ্যাপের নিম্নলিখিত কাজগুলো করার ক্ষমতা পরীক্ষা করার সুযোগ দেয়:
- মডিউল ইনস্টলেশন অনুরোধ করুন এবং নিরীক্ষণ করুন।
- ইনস্টলেশন ত্রুটিগুলি পরিচালনা করুন।
- মডিউলগুলো অ্যাক্সেস করতে
SplitCompatব্যবহার করুন।
এই পৃষ্ঠায় বর্ণনা করা হয়েছে কীভাবে আপনার অ্যাপের স্প্লিট APK-গুলো আপনার টেস্ট ডিভাইসে ডেপ্লয় করতে হয়, যাতে প্লে ফিচার ডেলিভারি স্বয়ংক্রিয়ভাবে সেই APK-গুলো ব্যবহার করে প্লে স্টোর থেকে মডিউল অনুরোধ, ডাউনলোড এবং ইনস্টল করার প্রক্রিয়াটি সিমুলেট করতে পারে।
যদিও আপনার অ্যাপের লজিকে কোনো পরিবর্তন করার প্রয়োজন নেই, তবুও আপনাকে নিম্নলিখিত শর্তগুলো পূরণ করতে হবে:
-
bundletoolএর সর্বশেষ সংস্করণটি ডাউনলোড ও ইনস্টল করুন। আপনার অ্যাপের বান্ডেল থেকে ইনস্টলযোগ্য নতুন APK তৈরি করার জন্যbundletoolপ্রয়োজন।
একগুচ্ছ APK তৈরি করুন
যদি আপনি ইতিমধ্যে তা না করে থাকেন, তাহলে নিম্নলিখিতভাবে আপনার অ্যাপের স্প্লিট APK-গুলো তৈরি করুন:
- নিম্নলিখিত পদ্ধতিগুলোর মধ্যে যেকোনো একটি ব্যবহার করে আপনার অ্যাপের জন্য একটি অ্যাপ বান্ডেল তৈরি করুন:
- অ্যান্ড্রয়েড স্টুডিও এবং গ্রেডলের অ্যান্ড্রয়েড প্লাগইন ব্যবহার করে একটি অ্যান্ড্রয়েড অ্যাপ বান্ডেল বিল্ড ও সাইন করুন ।
- কমান্ড লাইন থেকে আপনার অ্যাপ বান্ডেলটি তৈরি করুন ।
নিম্নলিখিত কমান্ডটি ব্যবহার করে
bundletoolদিয়ে সমস্ত ডিভাইস কনফিগারেশনের জন্য এক সেট APK তৈরি করুন :bundletool build-apks --local-testing --bundle my_app.aab --output my_app.apks
--local-testing ফ্ল্যাগটি আপনার APK-গুলির ম্যানিফেস্টে মেটা-ডেটা অন্তর্ভুক্ত করে, যা প্লে ফিচার ডেলিভারি লাইব্রেরিকে জানিয়ে দেয় যে প্লে স্টোরের সাথে সংযোগ না করেই ফিচার মডিউল ইনস্টল করার পরীক্ষা করার জন্য স্থানীয় স্প্লিট APK-গুলি ব্যবহার করতে হবে।
আপনার অ্যাপটি ডিভাইসে স্থাপন করুন
--local-testing ফ্ল্যাগ ব্যবহার করে একগুচ্ছ APK তৈরি করার পর, আপনার অ্যাপের মূল সংস্করণটি ইনস্টল করতে এবং অতিরিক্ত APK-গুলো আপনার ডিভাইসের লোকাল স্টোরেজে স্থানান্তর করতে bundletool ব্যবহার করুন। আপনি নিম্নলিখিত কমান্ডটির মাধ্যমে উভয় কাজই করতে পারেন:
bundletool install-apks --apks my_app.apks
এখন, যখন আপনি আপনার অ্যাপ চালু করেন এবং কোনো ফিচার মডিউল ডাউনলোড ও ইনস্টল করার ইউজার ফ্লো সম্পন্ন করেন, তখন প্লে ফিচার ডেলিভারি লাইব্রেরি সেই APK ফাইলগুলো ব্যবহার করে যা bundletool ডিভাইসের লোকাল স্টোরেজে স্থানান্তর করেছে।
নেটওয়ার্ক ত্রুটি অনুকরণ করুন
প্লে স্টোর থেকে মডিউল ইনস্টল অনুকরণ করতে, প্লে ফিচার ডেলিভারি লাইব্রেরি মডিউলটির জন্য অনুরোধ করতে SplitInstallManager এর একটি বিকল্প ব্যবহার করে, যার নাম FakeSplitInstallManager । যখন আপনি --local-testing ফ্ল্যাগ সহ bundletool ব্যবহার করে এক সেট APK তৈরি করেন এবং সেগুলোকে আপনার টেস্ট ডিভাইসে ডেপ্লয় করেন, তখন এটি এমন মেটাডেটা অন্তর্ভুক্ত করে যা প্লে ফিচার ডেলিভারি লাইব্রেরিকে নির্দেশ দেয় যেন এটি স্বয়ংক্রিয়ভাবে আপনার অ্যাপের API কলগুলোকে SplitInstallManager এর পরিবর্তে FakeSplitInstallManager কে কল করার জন্য পরিবর্তন করে দেয়।
FakeSplitInstallManager একটি বুলিয়ান ফ্ল্যাগ অন্তর্ভুক্ত রয়েছে, যা সক্রিয় করলে আপনার অ্যাপ পরবর্তীবার কোনো মডিউল ইনস্টল করার অনুরোধ করলে একটি নেটওয়ার্ক ত্রুটি অনুকরণ করা যায়। আপনার টেস্টে FakeSplitInstallManager অ্যাক্সেস করতে, আপনি FakeSplitInstallManagerFactory ব্যবহার করে এর একটি ইনস্ট্যান্স পেতে পারেন, যেমনটি নিচে দেখানো হয়েছে:
কোটলিন
// Creates an instance of FakeSplitInstallManager with the app's context. val fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context) // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true)
জাভা
// Creates an instance of FakeSplitInstallManager with the app's context. FakeSplitInstallManager fakeSplitInstallManager = FakeSplitInstallManagerFactory.create(context); // Tells Play Feature Delivery Library to force the next module request to // result in a network error. fakeSplitInstallManager.setShouldNetworkError(true);