একটি সাধারণ উইজেট তৈরি করুন

কম্পোজ পদ্ধতিটি চেষ্টা করুন
অ্যান্ড্রয়েডের জন্য Jetpack Compose হলো প্রস্তাবিত UI টুলকিট। Compose-স্টাইলের API ব্যবহার করে কীভাবে উইজেট তৈরি করতে হয় তা শিখুন।

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

মিউজিক উইজেটের উদাহরণ
চিত্র ১. একটি মিউজিক উইজেটের উদাহরণ।

এই ডকুমেন্টটিতে একটি উইজেট প্রোভাইডার ব্যবহার করে কীভাবে একটি উইজেট পাবলিশ করতে হয় তা বর্ণনা করা হয়েছে। অ্যাপ উইজেট হোস্ট করার জন্য আপনার নিজস্ব AppWidgetHost তৈরি করার বিষয়ে বিস্তারিত জানতে, “Build a widget host” দেখুন।

আপনার উইজেট কীভাবে ডিজাইন করবেন সে সম্পর্কে তথ্যের জন্য, অ্যাপ উইজেট ওভারভিউ দেখুন।

উইজেট উপাদান

একটি উইজেট তৈরি করতে নিম্নলিখিত মৌলিক উপাদানগুলো প্রয়োজন:

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

চিত্র ২-এ দেখানো হয়েছে, এই উপাদানগুলো কীভাবে অ্যাপের সামগ্রিক উইজেট প্রক্রিয়াকরণ প্রবাহে অন্তর্ভুক্ত হয়।

অ্যাপ উইজেট প্রক্রিয়াকরণ প্রবাহ
চিত্র ২. অ্যাপ উইজেট প্রক্রিয়াকরণ প্রবাহ।

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

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

AppWidgetProviderInfo XML ঘোষণা করুন

AppWidgetProviderInfo অবজেক্টটি একটি উইজেটের অপরিহার্য বৈশিষ্ট্যগুলো নির্ধারণ করে। একটি XML রিসোর্স ফাইলে শুধুমাত্র একটি <appwidget-provider> এলিমেন্ট ব্যবহার করে AppWidgetProviderInfo অবজেক্টটি সংজ্ঞায়িত করুন এবং ফাইলটি প্রজেক্টের res/xml/ ফোল্ডারে সংরক্ষণ করুন।

নিম্নলিখিত উদাহরণে এটি দেখানো হয়েছে:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:targetCellWidth="1"
    android:targetCellHeight="1"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="120dp"
    android:updatePeriodMillis="86400000"
    android:description="@string/example_appwidget_description"
    android:previewLayout="@layout/example_appwidget_preview"
    android:initialLayout="@layout/example_loading_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

উইজেটের আকার নির্ধারণের বৈশিষ্ট্য

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

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

নিম্নলিখিত সারণিতে উইজেটের আকার নির্ধারণ সম্পর্কিত <appwidget-provider> অ্যাট্রিবিউটগুলো বর্ণনা করা হয়েছে:

বৈশিষ্ট্য এবং বিবরণ
targetCellWidth এবং targetCellHeight (অ্যান্ড্রয়েড ১২), minWidth এবং minHeight
  • অ্যান্ড্রয়েড ১২ থেকে, targetCellWidth এবং targetCellHeight অ্যাট্রিবিউটগুলো গ্রিড সেলের পরিপ্রেক্ষিতে উইজেটের ডিফল্ট আকার নির্দিষ্ট করে। অ্যান্ড্রয়েড ১১ এবং এর পূর্ববর্তী সংস্করণগুলোতে এই অ্যাট্রিবিউটগুলো উপেক্ষা করা হয় , এবং হোম স্ক্রিন যদি গ্রিড-ভিত্তিক লেআউট সমর্থন না করে তবে এগুলো উপেক্ষা করা যেতে পারে
  • minWidth এবং minHeight অ্যাট্রিবিউটগুলো উইজেটের ডিফল্ট আকার dp-তে নির্দিষ্ট করে। যদি কোনো উইজেটের সর্বনিম্ন প্রস্থ বা উচ্চতার মান সেলগুলোর মাপের সাথে না মেলে, তাহলে মানগুলোকে নিকটতম সেলের আকারে রাউন্ড আপ করা হয়।
আমরা উভয় অ্যাট্রিবিউট সেট— targetCellWidthtargetCellHeight এবং minWidthminHeight নির্দিষ্ট করার পরামর্শ দিই, যাতে ব্যবহারকারীর ডিভাইস targetCellWidthtargetCellHeight সমর্থন না করলে আপনার অ্যাপ minWidthminHeight ব্যবহার করতে পারে। সমর্থিত হলে, targetCellWidthtargetCellHeight অ্যাট্রিবিউটগুলো minWidthminHeight অ্যাট্রিবিউটের চেয়ে অগ্রাধিকার পায়।
minResizeWidth এবং minResizeHeight উইজেটটির সর্বনিম্ন আকার নির্দিষ্ট করুন। এই মানগুলি সেই আকার নির্দিষ্ট করে যার নিচে উইজেটটি পাঠযোগ্য বা অন্যথায় ব্যবহারযোগ্য থাকে না। এই অ্যাট্রিবিউটগুলি ব্যবহার করে ব্যবহারকারী উইজেটটিকে ডিফল্ট আকারের চেয়ে ছোট আকারে পরিবর্তন করতে পারেন। minResizeWidth অ্যাট্রিবিউটটি উপেক্ষা করা হয় যদি এটি minWidth চেয়ে বড় হয় অথবা যদি হরাইজন্টাল রিসাইজিং সক্রিয় না থাকে। resizeMode দেখুন। একইভাবে, minResizeHeight অ্যাট্রিবিউটটি উপেক্ষা করা হয় যদি এটি minHeight এর চেয়ে বড় হয় অথবা যদি ভার্টিকাল রিসাইজিং সক্রিয় না থাকে।
maxResizeWidth এবং maxResizeHeight উইজেটটির প্রস্তাবিত সর্বোচ্চ আকার নির্দিষ্ট করুন। যদি মানগুলো গ্রিড সেলের মাপের গুণিতক না হয়, তবে সেগুলোকে নিকটতম সেলের আকারে রাউন্ড আপ করা হয়। maxResizeWidth অ্যাট্রিবিউটটি উপেক্ষা করা হয় যদি এটি minWidth এর চেয়ে ছোট হয় অথবা যদি হরাইজন্টাল রিসাইজিং সক্রিয় না থাকে। resizeMode দেখুন। একইভাবে, maxResizeHeight অ্যাট্রিবিউটটি উপেক্ষা করা হয় যদি এটি minHeight এর চেয়ে ছোট হয় অথবা যদি ভার্টিকাল রিসাইজিং সক্রিয় না থাকে। অ্যান্ড্রয়েড ১২-এ প্রবর্তিত।
resizeMode একটি উইজেটকে কীভাবে রিসাইজ করা যাবে, তার নিয়মাবলী এটি নির্দিষ্ট করে। হোম স্ক্রিনের উইজেটগুলোকে আনুভূমিকভাবে, উল্লম্বভাবে বা উভয় অক্ষ বরাবর রিসাইজযোগ্য করতে আপনি এই অ্যাট্রিবিউটটি ব্যবহার করতে পারেন। ব্যবহারকারীরা একটি উইজেটকে টাচ করে ধরে রাখলে তার রিসাইজ হ্যান্ডেলগুলো দেখা যায়, এরপর লেআউট গ্রিডে এর আকার পরিবর্তন করার জন্য আনুভূমিক বা উল্লম্ব হ্যান্ডেলগুলো ড্র্যাগ করেন। resizeMode অ্যাট্রিবিউটের ভ্যালুগুলোর মধ্যে রয়েছে horizontal , vertical , এবং none । একটি উইজেটকে আনুভূমিক এবং উল্লম্বভাবে রিসাইজযোগ্য হিসেবে ঘোষণা করতে, horizontal|vertical ব্যবহার করুন।

উদাহরণ

পূর্ববর্তী সারণিতে থাকা অ্যাট্রিবিউটগুলো কীভাবে উইজেটের আকারকে প্রভাবিত করে তা বোঝানোর জন্য, নিম্নলিখিত স্পেসিফিকেশনগুলো ধরে নিন:

  • একটি গ্রিড সেলের প্রস্থ ৩০ ডিপি এবং উচ্চতা ৫০ ডিপি।
  • নিম্নলিখিত অ্যাট্রিবিউট স্পেসিফিকেশন প্রদান করা হলো:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="80dp"
    android:minHeight="80dp"
    android:targetCellWidth="2"
    android:targetCellHeight="2"
    android:minResizeWidth="40dp"
    android:minResizeHeight="40dp"
    android:maxResizeWidth="120dp"
    android:maxResizeHeight="120dp"
    android:resizeMode="horizontal|vertical" />

অ্যান্ড্রয়েড ১২ থেকে শুরু করে:

উইজেটের ডিফল্ট আকার হিসেবে targetCellWidth এবং targetCellHeight অ্যাট্রিবিউটগুলো ব্যবহার করুন।

উইজেটটির ডিফল্ট সাইজ হলো 2x2। উইজেটটিকে ছোট করে 2x1 অথবা বড় করে 4x3 পর্যন্ত রিসাইজ করা যায়।

অ্যান্ড্রয়েড ১১ এবং তার নিচের সংস্করণ:

উইজেটের ডিফল্ট আকার নির্ধারণ করতে minWidth এবং minHeight অ্যাট্রিবিউটগুলো ব্যবহার করুন।

ডিফল্ট প্রস্থ = Math.ceil(80 / 30) = 3

ডিফল্ট উচ্চতা = Math.ceil(80 / 50) = 2

ডিফল্টভাবে উইজেটটির সাইজ ৩x২। উইজেটটিকে ছোট করে ২x১ অথবা বড় করে ফুল স্ক্রিন পর্যন্ত রিসাইজ করা যায়।

অতিরিক্ত উইজেট বৈশিষ্ট্য

নিম্নলিখিত সারণিতে উইজেটের আকার নির্ধারণ ব্যতীত অন্যান্য বৈশিষ্ট্য সম্পর্কিত <appwidget-provider> অ্যাট্রিবিউটগুলো বর্ণনা করা হয়েছে।

বৈশিষ্ট্য এবং বিবরণ
updatePeriodMillis এটি নির্ধারণ করে যে উইজেট ফ্রেমওয়ার্ক কত ঘন ঘন onUpdate() কলব্যাক মেথডটি কল করার মাধ্যমে AppWidgetProvider কাছে আপডেটের জন্য অনুরোধ করবে। এই মান ব্যবহার করলে প্রকৃত আপডেটটি ঠিক সময়ে হবে এমন কোনো নিশ্চয়তা নেই, এবং ব্যাটারি সাশ্রয়ের জন্য আমরা যথাসম্ভব কম ঘন ঘন—ঘণ্টায় একবারের বেশি নয়—আপডেট করার পরামর্শ দিই। একটি উপযুক্ত আপডেটের সময়কাল বেছে নেওয়ার জন্য বিবেচ্য বিষয়গুলির সম্পূর্ণ তালিকার জন্য, উইজেট কন্টেন্ট আপডেটের জন্য অপ্টিমাইজেশন দেখুন।
initialLayout সেই লেআউট রিসোর্সকে নির্দেশ করে যা উইজেট লেআউট নির্ধারণ করে।
configure ব্যবহারকারী যখন উইজেটটি যোগ করেন, তখন যে অ্যাক্টিভিটিটি চালু হয়, তা এটি নির্ধারণ করে, যা ব্যবহারকারীকে উইজেটের বৈশিষ্ট্যগুলো কনফিগার করার সুযোগ দেয়। ‘ব্যবহারকারীদের উইজেট কনফিগার করার সুযোগ দিন’ দেখুন। অ্যান্ড্রয়েড ১২ থেকে, আপনার অ্যাপ প্রাথমিক কনফিগারেশনটি এড়িয়ে যেতে পারে। বিস্তারিত জানতে ‘উইজেটের ডিফল্ট কনফিগারেশন ব্যবহার করুন’ দেখুন।
description আপনার উইজেটের জন্য উইজেট পিকার যে বিবরণ প্রদর্শন করবে, তা নির্দিষ্ট করে। অ্যান্ড্রয়েড ১২-এ চালু হয়েছে।
previewLayout (অ্যান্ড্রয়েড ১২) এবং previewImage (অ্যান্ড্রয়েড ১১ ও তার নিম্নতর সংস্করণ)
  • অ্যান্ড্রয়েড ১২ থেকে, previewLayout অ্যাট্রিবিউটটি একটি স্কেলেবল প্রিভিউ নির্দিষ্ট করে, যা আপনি উইজেটের ডিফল্ট আকারে সেট করা একটি XML লেআউট হিসেবে প্রদান করেন। আদর্শগতভাবে, এই অ্যাট্রিবিউট হিসেবে নির্দিষ্ট করা লেআউট XML-টি বাস্তবসম্মত ডিফল্ট মানসহ প্রকৃত উইজেটের লেআউট XML-এর মতোই হওয়া উচিত।
  • অ্যান্ড্রয়েড ১১ বা তার নিচের সংস্করণগুলিতে, ` previewImage অ্যাট্রিবিউটটি উইজেটটি কনফিগার করার পরে কেমন দেখাবে তার একটি প্রিভিউ নির্দিষ্ট করে, যা ব্যবহারকারী অ্যাপ উইজেটটি নির্বাচন করার সময় দেখতে পান। এটি সরবরাহ করা না হলে, ব্যবহারকারী এর পরিবর্তে আপনার অ্যাপের লঞ্চার আইকনটি দেখতে পান। এই ফিল্ডটি ` AndroidManifest.xml ফাইলের ` <receiver> ` এলিমেন্টের android:previewImage অ্যাট্রিবিউটের সাথে সঙ্গতিপূর্ণ।
দ্রষ্টব্য: আমরা previewImage এবং previewLayout উভয় অ্যাট্রিবিউটই নির্দিষ্ট করার পরামর্শ দিই, যাতে ব্যবহারকারীর ডিভাইস previewLayout সমর্থন না করলে আপনার অ্যাপ স্বয়ংক্রিয়ভাবে previewImage ব্যবহার করতে পারে। আরও বিস্তারিত জানতে, ‘স্কেলেবল উইজেট প্রিভিউয়ের সাথে পশ্চাৎ সামঞ্জস্য’ দেখুন।
autoAdvanceViewId উইজেটের হোস্ট দ্বারা স্বয়ংক্রিয়ভাবে অগ্রসর হওয়া উইজেট সাবভিউটির ভিউ আইডি নির্দিষ্ট করে।
widgetCategory আপনার উইজেটটি হোম স্ক্রিনে ( home_screen ), লক স্ক্রিনে ( keyguard ) নাকি উভয় স্ক্রিনেই দেখানো যাবে, তা নির্ধারণ করে। অ্যান্ড্রয়েড ৫.০ এবং তার পরবর্তী সংস্করণগুলোর জন্য, শুধুমাত্র home_screen বৈধ।
widgetFeatures উইজেট দ্বারা সমর্থিত বৈশিষ্ট্যগুলো ঘোষণা করে। উদাহরণস্বরূপ, যদি আপনি চান যে কোনো ব্যবহারকারী উইজেটটি যোগ করার সময় এটি তার ডিফল্ট কনফিগারেশন ব্যবহার করুক, তাহলে configuration_optional এবং reconfigurable উভয় ফ্ল্যাগই উল্লেখ করুন। এর ফলে ব্যবহারকারী উইজেটটি যোগ করার পর কনফিগারেশন অ্যাক্টিভিটি চালু হওয়া এড়ানো যায়। ব্যবহারকারী পরবর্তীতেও উইজেটটি পুনরায় কনফিগার করতে পারবেন।

উইজেট ব্রডকাস্ট পরিচালনা করতে AppWidgetProvider ক্লাস ব্যবহার করুন।

AppWidgetProvider ক্লাসটি উইজেট ব্রডকাস্ট পরিচালনা করে এবং উইজেট লাইফসাইকেল ইভেন্টের প্রতিক্রিয়ায় উইজেট আপডেট করে। নিম্নলিখিত বিভাগগুলিতে বর্ণনা করা হয়েছে কীভাবে ম্যানিফেস্টে AppWidgetProvider ডিক্লেয়ার করতে হয় এবং তারপর এটি ইমপ্লিমেন্ট করতে হয়।

ম্যানিফেস্টে একটি উইজেট ঘোষণা করুন

প্রথমে, নিচের উদাহরণে দেখানো অনুযায়ী আপনার অ্যাপের AndroidManifest.xml ফাইলে AppWidgetProvider ক্লাসটি ডিক্লেয়ার করুন:

<receiver android:name="ExampleAppWidgetProvider"
                 android:exported="false">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider"
               android:resource="@xml/example_appwidget_info" />
</receiver>

<receiver> এলিমেন্টটির জন্য android:name অ্যাট্রিবিউটটি আবশ্যক, যা উইজেট দ্বারা ব্যবহৃত AppWidgetProvider নির্দিষ্ট করে। কম্পোনেন্টটি এক্সপোর্ট করা উচিত নয়, যদি না কোনো পৃথক প্রসেসের আপনার AppWidgetProvider এ ব্রডকাস্ট করার প্রয়োজন হয়, যা সাধারণত ঘটে না।

<intent-filter> এলিমেন্টের মধ্যে অবশ্যই android:name অ্যাট্রিবিউটসহ একটি <action> এলিমেন্ট থাকতে হবে। এই অ্যাট্রিবিউটটি নির্দিষ্ট করে যে AppWidgetProvider ACTION_APPWIDGET_UPDATE ব্রডকাস্টটি গ্রহণ করবে। এটিই একমাত্র ব্রডকাস্ট যা আপনাকে স্পষ্টভাবে ঘোষণা করতে হবে। AppWidgetManager প্রয়োজন অনুযায়ী স্বয়ংক্রিয়ভাবে অন্যান্য সমস্ত উইজেট ব্রডকাস্ট AppWidgetProvider কাছে পাঠিয়ে দেয়।

<meta-data> এলিমেন্টটি AppWidgetProviderInfo রিসোর্সকে নির্দিষ্ট করে এবং এর জন্য নিম্নলিখিত অ্যাট্রিবিউটগুলো প্রয়োজন:

  • android:name : মেটাডেটার নাম নির্দিষ্ট করে। AppWidgetProviderInfo ডেসক্রিপ্টর হিসেবে ডেটা শনাক্ত করতে android.appwidget.provider ব্যবহার করুন।
  • android:resource : AppWidgetProviderInfo রিসোর্সের অবস্থান নির্দিষ্ট করে।

AppWidgetProvider ক্লাসটি বাস্তবায়ন করুন

উইজেট ব্রডকাস্ট পরিচালনা করার জন্য একটি সুবিধাজনক ক্লাস হিসেবে AppWidgetProvider ক্লাসটি BroadcastReceiver এক্সটেন্ড করে। এটি শুধুমাত্র উইজেটের সাথে প্রাসঙ্গিক ইভেন্ট ব্রডকাস্টগুলো গ্রহণ করে, যেমন যখন উইজেটটি আপডেট, ডিলিট, এনাবল এবং ডিসেবল করা হয়। যখন এই ব্রডকাস্ট ইভেন্টগুলো ঘটে, তখন AppWidgetProvider নিম্নলিখিত মেথডগুলো কল করা হয়:

onUpdate()
AppWidgetProviderInfo তে থাকা updatePeriodMillis অ্যাট্রিবিউট দ্বারা নির্ধারিত বিরতিতে উইজেটটি আপডেট করার জন্য এটি কল করা হয়। আরও তথ্যের জন্য এই পৃষ্ঠায় থাকা অতিরিক্ত উইজেট অ্যাট্রিবিউটগুলোর সারণিটি দেখুন।
ব্যবহারকারী যখন উইজেট যোগ করেন, তখনও এই মেথডটি কল করা হয়, তাই এটি প্রয়োজনীয় সেটআপ সম্পন্ন করে, যেমন View অবজেক্টের জন্য ইভেন্ট হ্যান্ডলার নির্ধারণ করা বা উইজেটে প্রদর্শনের জন্য ডেটা লোড করার কাজ শুরু করা। তবে, আপনি যদি configuration_optional ফ্ল্যাগ ছাড়া একটি কনফিগারেশন অ্যাক্টিভিটি ডিক্লেয়ার করেন, তাহলে ব্যবহারকারী উইজেট যোগ করার সময় এই মেথডটি কল করা হয় না , কিন্তু পরবর্তী আপডেটগুলোর জন্য এটি কল করা হয় । কনফিগারেশন সম্পূর্ণ হলে প্রথম আপডেটটি সম্পাদন করা কনফিগারেশন অ্যাক্টিভিটির দায়িত্ব। আরও তথ্যের জন্য ‘ব্যবহারকারীদের অ্যাপ উইজেট কনফিগার করার অনুমতি দিন’ দেখুন।
সবচেয়ে গুরুত্বপূর্ণ কলব্যাক হলো onUpdate() । আরও তথ্যের জন্য এই পৃষ্ঠার “Handle events with the onUpdate() class” অংশটি দেখুন।
onAppWidgetOptionsChanged()

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

  • OPTION_APPWIDGET_MIN_WIDTH : এতে একটি উইজেট ইনস্ট্যান্সের প্রস্থের সর্বনিম্ন সীমা থাকে, যা ডিপি এককে পরিমাপ করা হয়।
  • OPTION_APPWIDGET_MIN_HEIGHT : একটি উইজেট ইনস্ট্যান্সের উচ্চতার সর্বনিম্ন সীমা ধারণ করে, যা ডিপি এককে পরিমাপ করা হয়।
  • OPTION_APPWIDGET_MAX_WIDTH : একটি উইজেট ইনস্ট্যান্সের প্রস্থের সর্বোচ্চ সীমা ধারণ করে, যা ডিপি এককে পরিমাপ করা হয়।
  • OPTION_APPWIDGET_MAX_HEIGHT : একটি উইজেট ইনস্ট্যান্সের উচ্চতার সর্বোচ্চ সীমা ধারণ করে, যা ডিপি এককে পরিমাপ করা হয়।
  • OPTION_APPWIDGET_SIZES : একটি উইজেট ইনস্ট্যান্স যে সকল সম্ভাব্য আকার ( List<SizeF> ) নিতে পারে, তার তালিকা dp এককে ধারণ করে। অ্যান্ড্রয়েড ১২-এ প্রবর্তিত।
onDeleted(Context, int[])

উইজেট হোস্ট থেকে যখনই কোনো উইজেট মুছে ফেলা হয়, তখন এটি কল করা হয়।

onEnabled(Context)

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

onDisabled(Context)

উইজেট হোস্ট থেকে আপনার উইজেটের সর্বশেষ ইনস্ট্যান্সটি মুছে ফেলা হলে এটি কল করা হয়। এখানেই আপনি onEnabled(Context) এ করা যেকোনো কাজ, যেমন একটি অস্থায়ী ডেটাবেস মুছে ফেলা, গুছিয়ে নেন।

onReceive(Context, Intent)

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

আপনাকে অবশ্যই AndroidManifest<receiver> এলিমেন্ট ব্যবহার করে আপনার AppWidgetProvider ক্লাস ইমপ্লিমেন্টেশনকে একটি ব্রডকাস্ট রিসিভার হিসেবে ঘোষণা করতে হবে। আরও তথ্যের জন্য এই পৃষ্ঠার 'ম্যানিফেস্টে একটি উইজেট ঘোষণা করুন' অংশটি দেখুন।

onUpdate() ক্লাস ব্যবহার করে ইভেন্টগুলি পরিচালনা করুন।

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

উদাহরণস্বরূপ, যদি আপনি এমন একটি উইজেট চান যার বাটনে ট্যাপ করলে একটি অ্যাক্টিভিটি চালু হবে, তাহলে আপনি AppWidgetProvider এর নিম্নলিখিত ইমপ্লিমেন্টেশনটি ব্যবহার করতে পারেন:

কোটলিন

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity.
            val pendingIntent: PendingIntent = PendingIntent.getActivity(
                    /* context = */ context,
                    /* requestCode = */  0,
                    /* intent = */ Intent(context, ExampleActivity::class.java),
                    /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            val views: RemoteViews = RemoteViews(
                    context.packageName,
                    R.layout.appwidget_provider_layout
            ).apply {
                setOnClickPendingIntent(R.id.button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

জাভা

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        for (int i=0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];
            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                /* context = */ context,
                /* requestCode = */ 0,
                /* intent = */ intent,
                /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

এই AppWidgetProvider শুধুমাত্র onUpdate() মেথডটি সংজ্ঞায়িত করে, যা ব্যবহার করে একটি PendingIntent তৈরি করা হয়। এই PendingIntent একটি Activity চালু করে এবং setOnClickPendingIntent(int, PendingIntent) ব্যবহার করে সেটিকে উইজেটের বাটনের সাথে সংযুক্ত করে। এতে একটি লুপ অন্তর্ভুক্ত রয়েছে যা appWidgetIds এর প্রতিটি এন্ট্রির মধ্য দিয়ে পুনরাবৃত্তি করে। appWidgetIds হলো আইডি-র একটি অ্যারে যা এই প্রোভাইডার দ্বারা তৈরি প্রতিটি উইজেটকে শনাক্ত করে। যদি ব্যবহারকারী উইজেটটির একাধিক ইনস্ট্যান্স তৈরি করেন, তবে সেগুলি সবই একই সাথে আপডেট হয়। তবে, উইজেটের সমস্ত ইনস্ট্যান্সের জন্য শুধুমাত্র একটি updatePeriodMillis শিডিউল পরিচালিত হয়। উদাহরণস্বরূপ, যদি আপডেটের শিডিউল প্রতি দুই ঘণ্টা অন্তর নির্ধারণ করা থাকে এবং প্রথমটির এক ঘণ্টা পরে উইজেটটির দ্বিতীয় ইনস্ট্যান্স যোগ করা হয়, তবে উভয়ই প্রথমটির দ্বারা নির্ধারিত সময়কালে আপডেট হবে এবং দ্বিতীয় আপডেটের সময়কাল উপেক্ষা করা হবে। উভয়ই প্রতি দুই ঘণ্টা অন্তর আপডেট হয়, প্রতি ঘণ্টায় নয়।

আরও বিস্তারিত জানতে ExampleAppWidgetProvider.java নমুনা ক্লাসটি দেখুন।

উইজেট ব্রডকাস্ট ইন্টেন্ট গ্রহণ করুন

AppWidgetProvider একটি সুবিধাজনক ক্লাস। আপনি যদি সরাসরি উইজেট ব্রডকাস্টগুলো গ্রহণ করতে চান, তাহলে আপনি নিজের BroadcastReceiver ইমপ্লিমেন্ট করতে পারেন অথবা onReceive(Context,Intent) কলব্যাকটি ওভাররাইড করতে পারেন। যে ইন্টেন্টগুলো আপনার জন্য গুরুত্বপূর্ণ, সেগুলো হলো নিম্নরূপ:

উইজেট লেআউট তৈরি করুন

আপনাকে অবশ্যই আপনার উইজেটের জন্য XML-এ একটি প্রাথমিক লেআউট নির্ধারণ করতে হবে এবং সেটি প্রজেক্টের res/layout/ ডিরেক্টরিতে সংরক্ষণ করতে হবে। বিস্তারিত জানার জন্য ডিজাইন নির্দেশিকা দেখুন।

আপনি যদি লেআউট সম্পর্কে পরিচিত হন, তবে উইজেট লেআউট তৈরি করা বেশ সহজ। তবে, মনে রাখবেন যে উইজেট লেআউটগুলো RemoteViews উপর ভিত্তি করে তৈরি, যা সব ধরনের লেআউট বা ভিউ উইজেট সমর্থন করে না। আপনি RemoteViews দ্বারা সমর্থিত কাস্টম ভিউ বা ভিউগুলোর সাবক্লাস ব্যবহার করতে পারবেন না।

RemoteViews ViewStub সমর্থন করে, যা হলো একটি অদৃশ্য, শূন্য-আকারের View যা আপনি রানটাইমে লেজিলি লেআউট রিসোর্স ইনফ্লেট করতে ব্যবহার করতে পারেন।

স্টেটফুল আচরণের জন্য সমর্থন

অ্যান্ড্রয়েড ১২ নিম্নলিখিত বিদ্যমান উপাদানগুলো ব্যবহার করে স্টেটফুল আচরণের জন্য সমর্থন যোগ করে:

উইজেটটি এখনও স্টেটলেস। আপনার অ্যাপকে অবশ্যই স্টেট সংরক্ষণ করতে হবে এবং স্টেট পরিবর্তনের ইভেন্টগুলোর জন্য রেজিস্টার করতে হবে।

স্টেটফুল আচরণ প্রদর্শনকারী শপিং লিস্ট উইজেটের উদাহরণ
চিত্র ৩. স্টেটফুল আচরণের উদাহরণ।

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

কোটলিন

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

জাভা

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

দুটি লেআউট প্রদান করুন: একটি অ্যান্ড্রয়েড ১২ বা তার উচ্চতর সংস্করণের ডিভাইসগুলোর জন্য res/layout-v31 ফোল্ডারে, এবং অন্যটি অ্যান্ড্রয়েড ১১ বা তার পূর্ববর্তী সংস্করণের জন্য ডিফল্ট res/layout ফোল্ডারে।

গোলাকার কোণা প্রয়োগ করুন

আপনার উইজেটের গোলাকার কোণার ব্যাসার্ধ নির্ধারণ করার জন্য অ্যান্ড্রয়েড ১২ নিম্নলিখিত সিস্টেম প্যারামিটারগুলো চালু করেছে:

  • system_app_widget_background_radius : উইজেট ব্যাকগ্রাউন্ডের কোণার ব্যাসার্ধ, যা কখনোই 28 dp-এর বেশি হয় না।

  • অভ্যন্তরীণ ব্যাসার্ধ, যা বাহ্যিক ব্যাসার্ধ এবং প্যাডিং থেকে গণনা করা যেতে পারে। নিম্নলিখিত কোড স্নিপেটটি দেখুন:

    /**
     * Applies corner radius for views that are visually positioned [widgetPadding]dp inside of the
     * widget background.
     */
    @Composable
    fun GlanceModifier.appWidgetInnerCornerRadius(widgetPadding: Dp): GlanceModifier {
    
        if (Build.VERSION.SDK_INT < 31) {
            return this
        }
    
        val resources = LocalContext.current.resources
        // get dimension in float (without rounding).
        val px = resources.getDimension(android.R.dimen.system_app_widget_background_radius)
        val widgetBackgroundRadiusDpValue = px / resources.displayMetrics.density
        if (widgetBackgroundRadiusDpValue < widgetPadding.value) {
            return this
        }
        return this.cornerRadius(Dp(widgetBackgroundRadiusDpValue - widgetPadding.value))
    }

আপনার উইজেটের ভেতরের অংশের জন্য উপযুক্ত ব্যাসার্ধ নির্ণয় করতে, নিম্নলিখিত সূত্রটি ব্যবহার করুন: systemRadiusValue - widgetPadding

যেসব উইজেট তাদের কন্টেন্টকে আয়তক্ষেত্রাকার নয় এমন আকারে সীমাবদ্ধ করে, তাদের @android:id/background সেই ব্যাকগ্রাউন্ড ভিউ-এর ভিউ আইডি হিসেবে ব্যবহার করা উচিত, যেটিতে android:clipToOutline true সেট করা আছে।

গোলাকার কোণার জন্য গুরুত্বপূর্ণ বিবেচ্য বিষয়

  • তৃতীয় পক্ষের লঞ্চার এবং ডিভাইস নির্মাতারা system_app_widget_background_radius প্যারামিটারটিকে 28 dp-এর চেয়ে ছোট করার জন্য ওভাররাইড করতে পারে।
  • যদি আপনার উইজেট @android:id/background ব্যবহার না করে অথবা এমন কোনো ব্যাকগ্রাউন্ড নির্ধারণ না করে যা আউটলাইনের উপর ভিত্তি করে এর বিষয়বস্তুকে ছেঁটে ফেলে—যেখানে android:clipToOutline true সেট করা থাকে—তাহলে লঞ্চার স্বয়ংক্রিয়ভাবে ব্যাকগ্রাউন্ডটি শনাক্ত করে এবং সিস্টেম রেডিয়াসে সেট করা গোলাকার কোণাসহ একটি আয়তক্ষেত্র ব্যবহার করে উইজেটটিকে ছেঁটে ফেলে।

  • অনিয়মিত আকৃতিগুলোকে তাদের গোলাকার আয়তাকার রিসাইজ কন্টেইনারের মধ্যে রাখতে হবে, যাতে সেগুলো কেটে না যায়।

  • অ্যান্ড্রয়েড ১৬ থেকে, system_app_widget_background_radius এর জন্য AOSP সিস্টেম ভ্যালু হলো 24dp । লঞ্চার এবং ডিভাইস নির্মাতারা উইজেটটিকে system_app_widget_background_radius মধ্যে সীমাবদ্ধ করে ফেলতে পারে।

  • গোলাকার কোণার কারণে কন্টেন্ট কেটে যাওয়া এড়াতে, একটি উইজেটের অভ্যন্তরীণ কন্টেন্টে অবশ্যই পর্যাপ্ত প্যাডিং থাকতে হবে যাতে system_app_widget_background_radius 28dp পর্যন্ত ব্যাসার্ধের মান সমর্থন করা যায়।

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

/values/attrs.xml

<resources>
  <attr name="backgroundRadius" format="dimension" />
</resources>

/values/styles.xml

<resources>
  <style name="MyWidgetTheme">
    <item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
  </style>
</resources>

/values-31/styles.xml

<resources>
  <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
    <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
  </style>
</resources>

/drawable/my_widget_background.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="?attr/backgroundRadius" />
  ...
</shape>

/layout/my_widget_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:background="@drawable/my_widget_background" />