পরিষেবার ওভারভিউ

Service হল একটি অ্যাপ্লিকেশন কম্পোনেন্ট যা ব্যাকগ্রাউন্ডে দীর্ঘ সময় ধরে চলা অপারেশন পারফর্ম করতে পারে। এটি কোনও ইউজার ইন্টারফেস প্রদান করে না। একবার চালু হয়ে গেলে, ব্যবহারকারী অন্য অ্যাপ্লিকেশনে সুইচ করার পরেও, কোনও পরিষেবা কিছু সময়ের জন্য চলতে থাকতে পারে। এছাড়াও, কোনও কম্পোনেন্ট কোনও পরিষেবার সাথে ইন্টার‍্যাক্ট করার জন্য সেটির সাথে বাইন্ড করতে পারে এবং এমনকি ইন্টারপ্রসেস কমিউনিকেশন (IPC) সম্পূর্ণ করতে পারে। যেমন, কোনও পরিষেবা ব্যাকগ্রাউন্ড থেকে নেটওয়ার্ক ট্রানজ্যাকশন ম্যানেজ করতে, মিউজিক চালাতে, ফাইল I/O পারফর্ম করতে অথবা কন্টেন্ট প্রোভাইডারের সাথে ইন্টার‍্যাক্ট করতে পারে।

সতর্কতা: কোনও পরিষেবা তার হোস্টিং প্রসেসের মূল থ্রেডে চলে; পরিষেবাটি তার নিজস্ব থ্রেড তৈরি করে না এবং আপনি অন্যভাবে নির্দিষ্ট না করলে একটি পৃথক প্রসেসে চলে না। অ্যাপ্লিকেশন সাড়া দিচ্ছে না (ANR) সংক্রান্ত সমস্যা এড়াতে, আপনাকে পরিষেবার মধ্যে আলাদা থ্রেডে যেকোনও ব্লকিং অপারেশন চালাতে হবে।

পরিষেবার ধরন

এই তিন ধরনের পরিষেবা উপলভ্য:

ফোরগ্রাউন্ড

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

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

আপনার অ্যাপে কীভাবে ফোরগ্রাউন্ড সার্ভিস কনফিগার করবেন সেই সম্পর্কে আরও জানুন।

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

ব্যাকগ্রাউন্ড
ব্যাকগ্রাউন্ড পরিষেবা এমন একটি অপারেশন করে যা ব্যবহারকারী সরাসরি লক্ষ্য করেন না। যেমন, কোনও অ্যাপ যদি তার স্টোরেজ কম্প্যাক্ট করার জন্য কোনও পরিষেবা ব্যবহার করে, তাহলে সেটি সাধারণত ব্যাকগ্রাউন্ড পরিষেবা হবে।

মনে রাখবেন: আপনার অ্যাপ API লেভেল ২৬ বা তার বেশি টার্গেট করলে, অ্যাপটি ফোরগ্রাউন্ডে না থাকলে সিস্টেম ব্যাকগ্রাউন্ড পরিষেবা চালানোর উপর বিধিনিষেধ আরোপ করে। বেশিরভাগ ক্ষেত্রে, যেমন, আপনার ব্যাকগ্রাউন্ড থেকে লোকেশন সংক্রান্ত তথ্য অ্যাক্সেস করা উচিত নয়। পরিবর্তে, WorkManager ব্যবহার করে টাস্ক শিডিউল করুন।

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

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

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

পরিষেবা ও থ্রেডের মধ্যে বেছে নেওয়া

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

আপনাকে যদি মূল থ্রেডের বাইরে কাজ করতে হয়, কিন্তু শুধুমাত্র ব্যবহারকারী আপনার অ্যাপ্লিকেশনের সাথে ইন্টার‍্যাক্ট করার সময়, তাহলে আপনাকে অন্য অ্যাপ্লিকেশন কম্পোনেন্টের প্রসঙ্গে একটি নতুন থ্রেড তৈরি করতে হবে। যেমন, আপনি যদি কিছু মিউজিক চালাতে চান, কিন্তু শুধুমাত্র আপনার অ্যাক্টিভিটি চলাকালীন, আপনি onCreate()-এ একটি থ্রেড তৈরি করতে পারেন, onStart()-এ এটি চালানো শুরু করতে পারেন, এবং onStop()-এ এটি বন্ধ করতে পারেন। এছাড়াও, প্রথাগত Thread ক্লাসের পরিবর্তে java.util.concurrent প্যাকেজ বা Kotlin coroutines থেকে থ্রেড পুল ও এক্সিকিউটর ব্যবহার করার কথা বিবেচনা করুন। ব্যাকগ্রাউন্ড থ্রেডে এক্সিকিউশন সরানোর ব্যাপারে আরও তথ্য পেতে Android-এ থ্রেডিং ডকুমেন্ট দেখুন।

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

প্রাথমিক বিষয়

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

onStartCommand()
অন্য কোনও কম্পোনেন্ট (যেমন, অ্যাক্টিভিটি) পরিষেবা শুরু করার অনুরোধ করলে, সিস্টেম startService() কল করার মাধ্যমে এই পদ্ধতিটি চালু করে। এই পদ্ধতিটি কার্যকর হলে, পরিষেবাটি শুরু হয় এবং ব্যাকগ্রাউন্ডে অনির্দিষ্টকালের জন্য চলতে পারে। আপনি এটি প্রয়োগ করলে, কাজ সম্পূর্ণ হওয়ার পরে stopSelf() বা stopService() কল করে পরিষেবা বন্ধ করার দায়িত্ব আপনার। আপনি যদি শুধুমাত্র বাইন্ডিং প্রদান করতে চান, তাহলে আপনাকে এই পদ্ধতি প্রয়োগ করতে হবে না।
onBind()
অন্য কোনও কম্পোনেন্ট পরিষেবার সাথে বাইন্ড করতে চাইলে (যেমন RPC পারফর্ম করতে), সিস্টেম bindService() কল করার মাধ্যমে এই পদ্ধতিটি ইনভোক করে। এই পদ্ধতির প্রয়োগে, আপনাকে অবশ্যই একটি ইন্টারফেস প্রদান করতে হবে যা ক্লায়েন্টরা IBinder রিটার্ন করে পরিষেবার সাথে যোগাযোগ করতে ব্যবহার করে। আপনাকে সবসময় এই পদ্ধতি প্রয়োগ করতে হবে; তবে, আপনি বাইন্ডিংয়ের অনুমতি দিতে না চাইলে, আপনাকে null রিটার্ন করতে হবে।
onCreate()
পরিষেবাটি প্রাথমিকভাবে তৈরি করার সময় (এটি onStartCommand() বা onBind() কল করার আগে) এককালীন সেট-আপ পদ্ধতিগুলি সম্পাদন করতে সিস্টেম এই পদ্ধতিটি চালু করে। পরিষেবাটি ইতিমধ্যে চালু থাকলে, এই পদ্ধতিটি কল করা হয় না।
onDestroy()
পরিষেবাটি আর ব্যবহার না করা হলে এবং সেটি নষ্ট করা হলে, সিস্টেম এই পদ্ধতিটি চালু করে। থ্রেড, রেজিস্টার করা লিসেনার বা রিসিভারের মতো যেকোনও রিসোর্স ক্লিন-আপ করার জন্য আপনার পরিষেবায় এটি প্রয়োগ করতে হবে। পরিষেবাটি যে শেষ কলটি রিসিভ করে সেটি হল এটি।

কোনও কম্পোনেন্ট startService() কল করার মাধ্যমে পরিষেবা শুরু করলে (যার ফলে onStartCommand()-এ কল করা হয়), পরিষেবাটি stopSelf()-এর মাধ্যমে নিজে থেকে বন্ধ না হওয়া পর্যন্ত বা অন্য কোনও কম্পোনেন্ট stopService() কল করার মাধ্যমে এটি বন্ধ না করা পর্যন্ত চলতে থাকে।

কোনও কম্পোনেন্ট যদি পরিষেবা তৈরি করার জন্য bindService() কল করে এবং onStartCommand() কল করা না হয়, তাহলে পরিষেবাটি শুধুমাত্র ততক্ষণ পর্যন্ত চলে যতক্ষণ কম্পোনেন্টটি এটির সাথে বাউন্ড থাকে। পরিষেবাটি তার সমস্ত ক্লায়েন্ট থেকে আনবাউন্ড হওয়ার পরে, সিস্টেম এটি ধ্বংস করে।

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

নিম্নলিখিত বিভাগে, আপনি দেখতে পাবেন কীভাবে আপনি startService() এবং bindService() পরিষেবা পদ্ধতি তৈরি করতে পারেন, পাশাপাশি কীভাবে অন্যান্য অ্যাপ্লিকেশন কম্পোনেন্ট থেকে সেগুলি ব্যবহার করতে পারেন।

ম্যানিফেস্টে পরিষেবা ঘোষণা করা

আপনার অ্যাপ্লিকেশনের ম্যানিফেস্ট ফাইলে সব পরিষেবা ঘোষণা করতে হবে, ঠিক যেমন আপনি অ্যাক্টিভিটি এবং অন্যান্য কম্পোনেন্টের জন্য করেন।

আপনার পরিষেবা ঘোষণা করতে, <application> এলিমেন্টের চাইল্ড হিসেবে <service> এলিমেন্ট যোগ করুন। এখানে একটি উদাহরণ দেওয়া হল:

<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

ম্যানিফেস্টে আপনার পরিষেবা ঘোষণা করার ব্যাপারে আরও তথ্য পেতে, <service> এলিমেন্ট রেফারেন্স দেখুন।

<service> এলিমেন্টে আপনি অন্যান্য অ্যাট্রিবিউট যোগ করতে পারেন, যাতে পরিষেবা শুরু করার জন্য প্রয়োজনীয় অনুমতি এবং পরিষেবাটি কোন প্রসেসে রান করবে তা নির্ধারণ করা যায়। android:name অ্যাট্রিবিউটটিই একমাত্র প্রয়োজনীয় অ্যাট্রিবিউট—এটি পরিষেবার ক্লাস নাম নির্দিষ্ট করে। আপনার অ্যাপ্লিকেশন প্রকাশ করার পরে, পরিষেবা শুরু বা বাইন্ড করার জন্য এক্সপ্লিসিট ইনটেন্টের উপর নির্ভরতার কারণে কোড ভেঙে যাওয়ার ঝুঁকি এড়াতে এই নামটি অপরিবর্তিত রাখুন (ব্লগ পোস্ট, যেসব জিনিস পরিবর্তন করা যাবে না পড়ুন)।

সতর্কতা: আপনার অ্যাপ সুরক্ষিত আছে কিনা তা নিশ্চিত করতে, Service শুরু করার সময় সবসময় এক্সপ্লিসিট ইনটেন্ট ব্যবহার করুন এবং আপনার পরিষেবার জন্য ইনটেন্ট ফিল্টার ঘোষণা করবেন না। কোনও পরিষেবা শুরু করার জন্য ইমপ্লিসিট ইনটেন্ট ব্যবহার করা হল নিরাপত্তা সংক্রান্ত ঝুঁকি, কারণ আপনি নিশ্চিত হতে পারবেন না যে কোন পরিষেবা ইনটেন্টে সাড়া দেয় এবং ব্যবহারকারী দেখতে পারবেন না যে কোন পরিষেবা শুরু হয়। Android 5.0 (API লেভেল ২১) থেকে শুরু করে, আপনি ইমপ্লিসিট ইনটেন্ট সহ bindService() কল করলে সিস্টেম একটি ব্যতিক্রম দেখায়।

আপনার পরিষেবা যাতে শুধুমাত্র আপনার অ্যাপেই উপলভ্য থাকে তা নিশ্চিত করতে android:exported অ্যাট্রিবিউট যোগ করুন এবং এটি false-এ সেট করুন। এটি কার্যকরভাবে অন্যান্য অ্যাপকে আপনার পরিষেবা শুরু করা থেকে বিরত রাখে, এমনকি এক্সপ্লিসিট ইনটেন্ট ব্যবহার করার সময়ও।

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

চালু করা পরিষেবা তৈরি করা হচ্ছে

শুরু করা পরিষেবা হল এমন একটি পরিষেবা যা অন্য কম্পোনেন্ট startService() কল করার মাধ্যমে শুরু করে, যার ফলে পরিষেবার onStartCommand() পদ্ধতিতে কল করা হয়।

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

অ্যাক্টিভিটির মতো কোনও অ্যাপ্লিকেশন কম্পোনেন্ট startService() কল করে এবং Intent পাস করে পরিষেবা শুরু করতে পারে যা পরিষেবা নির্দিষ্ট করে এবং পরিষেবা ব্যবহারের জন্য যেকোনও ডেটা অন্তর্ভুক্ত করে। পরিষেবাটি onStartCommand() পদ্ধতিতে এই Intent গ্রহণ করে।

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

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

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

এছাড়াও, Android ফ্রেমওয়ার্ক IntentService সাবক্লাস অফ Service প্রদান করে যা ওয়ার্কার থ্রেড ব্যবহার করে সব শুরু করার অনুরোধ ম্যানেজ করে, একবারে একটি। নতুন অ্যাপের জন্য এই ক্লাস ব্যবহার করার সুপারিশ করা হয় না কারণ Android 8 Oreo থেকে শুরু করে এটি ভালভাবে কাজ করবে না, কারণ ব্যাকগ্রাউন্ড এক্সিকিউশন সীমা চালু করা হয়েছে। এছাড়াও, Android 11 থেকে শুরু করে এটি বন্ধ করা হয়েছে। আপনি IntentService-এর পরিবর্তে JobIntentService ব্যবহার করতে পারেন যা Android-এর নতুন ভার্সনের সাথে মানানসই।

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

পরিষেবা ক্লাস বাড়ানো হচ্ছে

প্রতিটি ইনকামিং ইনটেন্ট ম্যানেজ করতে আপনি Service ক্লাস বাড়াতে পারবেন। প্রাথমিক প্রয়োগ কেমন দেখতে হতে পারে তা এখানে দেওয়া হল:

Kotlin

class HelloService : Service() {

    private var serviceLooper: Looper? = null
    private var serviceHandler: ServiceHandler? = null

    // Handler that receives messages from the thread
    private inner class ServiceHandler(looper: Looper) : Handler(looper) {

        override fun handleMessage(msg: Message) {
            // Normally we would do some work here, like download a file.
            // For our sample, we just sleep for 5 seconds.
            try {
                Thread.sleep(5000)
            } catch (e: InterruptedException) {
                // Restore interrupt status.
                Thread.currentThread().interrupt()
            }

            // Stop the service using the startId, so that we don't stop
            // the service in the middle of handling another job
            stopSelf(msg.arg1)
        }
    }

    override fun onCreate() {
        // Start up the thread running the service.  Note that we create a
        // separate thread because the service normally runs in the process's
        // main thread, which we don't want to block.  We also make it
        // background priority so CPU-intensive work will not disrupt our UI.
        HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply {
            start()

            // Get the HandlerThread's Looper and use it for our Handler
            serviceLooper = looper
            serviceHandler = ServiceHandler(looper)
        }
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show()

        // For each start request, send a message to start a job and deliver the
        // start ID so we know which request we're stopping when we finish the job
        serviceHandler?.obtainMessage()?.also { msg ->
            msg.arg1 = startId
            serviceHandler?.sendMessage(msg)
        }

        // If we get killed, after returning from here, restart
        return START_STICKY
    }

    override fun onBind(intent: Intent): IBinder? {
        // We don't provide binding, so return null
        return null
    }

    override fun onDestroy() {
        Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show()
    }
}

জাভা

public class HelloService extends Service {
  private Looper serviceLooper;
  private ServiceHandler serviceHandler;

  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          // Normally we would do some work here, like download a file.
          // For our sample, we just sleep for 5 seconds.
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              // Restore interrupt status.
              Thread.currentThread().interrupt();
          }
          // Stop the service using the startId, so that we don't stop
          // the service in the middle of handling another job
          stopSelf(msg.arg1);
      }
  }

  @Override
  public void onCreate() {
    // Start up the thread running the service. Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block. We also make it
    // background priority so CPU-intensive work doesn't disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    // Get the HandlerThread's Looper and use it for our Handler
    serviceLooper = thread.getLooper();
    serviceHandler = new ServiceHandler(serviceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = serviceHandler.obtainMessage();
      msg.arg1 = startId;
      serviceHandler.sendMessage(msg);

      // If we get killed, after returning from here, restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }

  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
  }
}

উদাহরণ কোডটি onStartCommand()-এ সব ইনকামিং কল ম্যানেজ করে এবং ব্যাকগ্রাউন্ড থ্রেডে চলা Handler-এ কাজ পোস্ট করে। এটি IntentService-এর মতোই কাজ করে এবং সমস্ত অনুরোধ একের পর এক ক্রমানুসারে প্রসেস করে। আপনি যদি একই সাথে একাধিক অনুরোধ চালাতে চান, তাহলে থ্রেড পুলে কাজ চালানোর জন্য কোড পরিবর্তন করতে পারেন।

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

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

এইসব রিটার্ন ভ্যালু সম্পর্কে আরও জানতে, প্রতিটি কনস্ট্যান্টের জন্য লিঙ্ক করা রেফারেন্স ডকুমেন্টেশন দেখুন।

পরিষেবা শুরু করা

আপনি কোনও অ্যাক্টিভিটি বা অন্য অ্যাপ্লিকেশন কম্পোনেন্ট থেকে কোনও পরিষেবা শুরু করতে পারেন, এর জন্য আপনাকে Intent startService() বা startForegroundService()-এ পাস করতে হবে। Android সিস্টেম পরিষেবার onStartCommand() মেথডকে কল করে এবং Intent-এ পাস করে, যা কোন পরিষেবা শুরু করতে হবে তা নির্দিষ্ট করে।

মনে রাখবেন: আপনার অ্যাপ API লেভেল ২৬ বা তার বেশি টার্গেট করলে, অ্যাপটি ফোরগ্রাউন্ডে না থাকলে, সিস্টেম ব্যাকগ্রাউন্ড পরিষেবা ব্যবহার বা তৈরি করার উপর বিধিনিষেধ আরোপ করে। কোনও অ্যাপকে ফোরগ্রাউন্ড সার্ভিস তৈরি করতে হলে, অ্যাপটিকে startForegroundService() কল করতে হবে। এই পদ্ধতি ব্যাকগ্রাউন্ড পরিষেবা তৈরি করে, তবে পদ্ধতিটি সিস্টেমকে সিগন্যাল দেয় যে পরিষেবাটি নিজেকে ফোরগ্রাউন্ডে প্রমোট করবে। পরিষেবা তৈরি হয়ে গেলে, পাঁচ সেকেন্ডের মধ্যে পরিষেবাকে অবশ্যই তার startForeground() মেথড কল করতে হবে।

যেমন, কোনও অ্যাক্টিভিটি startService() সহ এক্সপ্লিসিট ইনটেন্ট ব্যবহার করে পূর্ববর্তী বিভাগে (HelloService) উদাহরণস্বরূপ পরিষেবা শুরু করতে পারে, যেমন এখানে দেখানো হয়েছে:

Kotlin

startService(Intent(this, HelloService::class.java))

জাভা

startService(new Intent(this, HelloService.class));

startService() পদ্ধতিটি অবিলম্বে ফিরে আসে এবং Android সিস্টেম পরিষেবার onStartCommand() পদ্ধতিকে কল করে। পরিষেবাটি আগে থেকে না চললে, সিস্টেম প্রথমে onCreate()-কে কল করে এবং তারপরে এটি onStartCommand()-কে কল করে।

পরিষেবাটি বাইন্ডিং প্রদান না করলে, startService()-এর সাথে ডেলিভার করা ইনটেন্টই হল অ্যাপ্লিকেশন কম্পোনেন্ট এবং পরিষেবার মধ্যে যোগাযোগের একমাত্র মাধ্যম। তবে, আপনি যদি চান যে পরিষেবাটি একটি ফলাফল ফেরত পাঠাক, তাহলে যে ক্লায়েন্ট পরিষেবাটি শুরু করে সে ব্রডকাস্টের জন্য একটি PendingIntent তৈরি করতে পারে (getBroadcast() সহ) এবং পরিষেবাটি শুরু করে এমন Intent-এ পরিষেবাটিতে এটি ডেলিভার করতে পারে। পরিষেবাটি তখন ফলাফল প্রদান করার জন্য ব্রডকাস্ট ব্যবহার করতে পারে।

পরিষেবা শুরু করার জন্য একাধিক অনুরোধের ফলে পরিষেবার onStartCommand()-এ একাধিক সংশ্লিষ্ট কল করা হয়। তবে, পরিষেবা বন্ধ করার জন্য (stopSelf() বা stopService() সহ) শুধুমাত্র একটি অনুরোধই যথেষ্ট।

পরিষেবা বন্ধ করা

চালু করা পরিষেবাকে নিজের লাইফসাইকেল ম্যানেজ করতে হবে। অর্থাৎ, সিস্টেম মেমরি রিকভার করার প্রয়োজন না হলে সিস্টেম পরিষেবা বন্ধ বা ধ্বংস করে না এবং onStartCommand() রিটার্ন করার পরেও পরিষেবা চালু থাকে। stopSelf()-এ কল করে পরিষেবাটি নিজেকে বন্ধ করতে হবে অথবা অন্য কম্পোনেন্ট stopService()-এ কল করে এটি বন্ধ করতে পারে।

stopSelf() বা stopService()-এর মাধ্যমে বন্ধ করার অনুরোধ করা হলে, সিস্টেম যত তাড়াতাড়ি সম্ভব পরিষেবাটি নষ্ট করে দেয়।

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

সতর্কতা: সিস্টেম রিসোর্স ও ব্যাটারির চার্জ যাতে অযথা খরচ না হয়, তার জন্য কাজ শেষ হয়ে গেলে আপনার অ্যাপ্লিকেশন যাতে পরিষেবা বন্ধ করে দেয় তা নিশ্চিত করুন। প্রয়োজন হলে, অন্যান্য কম্পোনেন্ট stopService()-এ কল করে পরিষেবা বন্ধ করতে পারে। আপনি পরিষেবার জন্য বাইন্ডিং চালু করলেও, onStartCommand()-এ কল এলে আপনাকে সবসময় নিজে থেকে পরিষেবা বন্ধ করতে হবে।

কোনও পরিষেবার লাইফসাইকেল সম্পর্কে আরও তথ্যের জন্য, পরিষেবার লাইফসাইকেল ম্যানেজ করা সম্পর্কে নিচের বিভাগটি দেখুন।

বাউন্ড পরিষেবা তৈরি করা হচ্ছে

একটি বাউন্ড পরিষেবা হল এমন একটি পরিষেবা যা অ্যাপ্লিকেশন উপাদানগুলিকে দীর্ঘস্থায়ী সংযোগ তৈরি করতে bindService() কল করে এটির সাথে আবদ্ধ হতে দেয়। এটি সাধারণত startService() কল করার মাধ্যমে কম্পোনেন্টকে এটি চালু করার অনুমতি দেয় না।

আপনার অ্যাপ্লিকেশনের অ্যাক্টিভিটি এবং অন্যান্য কম্পোনেন্ট থেকে পরিষেবার সাথে ইন্টার‍্যাক্ট করতে চাইলে অথবা ইন্টারপ্রসেস কমিউনিকেশনের (IPC) মাধ্যমে অন্যান্য অ্যাপ্লিকেশনে আপনার অ্যাপ্লিকেশনের কিছু কার্যকারিতা প্রকাশ করতে চাইলে, একটি বাউন্ড পরিষেবা তৈরি করুন।

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

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

একাধিক ক্লায়েন্ট একসাথে পরিষেবার সাথে বাইন্ড করতে পারে। কোনও ক্লায়েন্ট পরিষেবার সাথে ইন্টার‍্যাক্ট করা শেষ করলে, এটি আনবাইন্ড করার জন্য unbindService()-কে কল করে। পরিষেবার সাথে কোনও ক্লায়েন্ট যুক্ত না থাকলে, সিস্টেম পরিষেবাটি নষ্ট করে দেয়।

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

ব্যবহারকারীকে বিজ্ঞপ্তি পাঠানো হচ্ছে

কোনও পরিষেবা চালু থাকলে, এটি স্ন্যাকবার বিজ্ঞপ্তি বা স্ট্যাটাস বার বিজ্ঞপ্তি ব্যবহার করে ব্যবহারকারীকে ইভেন্ট সম্পর্কে জানাতে পারে।

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

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

পরিষেবার লাইফসাইকেল ম্যানেজ করা

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

পরিষেবার লাইফসাইকেল—তৈরি হওয়া থেকে শুরু করে মুছে ফেলা পর্যন্ত—এই দুটি পথের যেকোনও একটি অনুসরণ করতে পারে:

  • চালু করা পরিষেবা

    অন্য কম্পোনেন্ট startService()-এ কল করলে পরিষেবাটি তৈরি হয়। পরিষেবাটি অনির্দিষ্টকালের জন্য চলতে থাকে এবং stopSelf() কল করে এটি বন্ধ করতে হবে। অন্য কম্পোনেন্টও stopService()-এ কল করে পরিষেবা বন্ধ করতে পারে। পরিষেবা বন্ধ হয়ে গেলে, সিস্টেম এটি নষ্ট করে দেয়।

  • একটি বাউন্ড পরিষেবা

    অন্য কম্পোনেন্ট (ক্লায়েন্ট) bindService()-কে কল করলে, এই পরিষেবা তৈরি হয়। তারপর ক্লায়েন্ট IBinder ইন্টারফেসের মাধ্যমে পরিষেবার সাথে যোগাযোগ করে। ক্লায়েন্ট unbindService()-এ কল করে কানেকশন বন্ধ করতে পারবেন। একাধিক ক্লায়েন্ট একই পরিষেবার সাথে বাইন্ড করতে পারে এবং সবকটি আনবাইন্ড করলে, সিস্টেম পরিষেবাটি ধ্বংস করে দেয়। পরিষেবাটি নিজেই বন্ধ করার প্রয়োজন নেই।

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

লাইফসাইকেল কলব্যাক প্রয়োগ করা

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

Kotlin

class ExampleService : Service() {
    private var startMode: Int = 0             // indicates how to behave if the service is killed
    private var binder: IBinder? = null        // interface for clients that bind
    private var allowRebind: Boolean = false   // indicates whether onRebind should be used

    override fun onCreate() {
        // The service is being created
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // The service is starting, due to a call to startService()
        return startMode
    }

    override fun onBind(intent: Intent): IBinder? {
        // A client is binding to the service with bindService()
        return binder
    }

    override fun onUnbind(intent: Intent): Boolean {
        // All clients have unbound with unbindService()
        return allowRebind
    }

    override fun onRebind(intent: Intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }

    override fun onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

জাভা

public class ExampleService extends Service {
    int startMode;       // indicates how to behave if the service is killed
    IBinder binder;      // interface for clients that bind
    boolean allowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return startMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return binder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return allowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

মনে রাখবেন: অ্যাক্টিভিটি লাইফসাইকেল কলব্যাক পদ্ধতির মতো, আপনাকে এইসব কলব্যাক পদ্ধতির সুপারক্লাস ইমপ্লিমেন্টেশন কল করতে হবে না।

ছবি ২. পরিষেবার লাইফসাইকেল। বাঁদিকের ডায়াগ্রামটি startService()-এর মাধ্যমে পরিষেবা তৈরি করার সময় লাইফসাইকেল দেখায় এবং ডানদিকের ডায়াগ্রামটি bindService()-এর মাধ্যমে পরিষেবা তৈরি করার সময় লাইফসাইকেল দেখায়।

ছবি ২-এ কোনও পরিষেবার জন্য সাধারণ কলব্যাক পদ্ধতি দেখানো হয়েছে। যদিও এই চিত্রটি startService()-এর তৈরি করা পরিষেবাগুলিকে bindService()-এর তৈরি করা পরিষেবাগুলি থেকে আলাদা করে, তবে মনে রাখবেন যে কোনও পরিষেবা, এটি কীভাবে শুরু হয়েছে তা নির্বিশেষে, সম্ভাব্যভাবে ক্লায়েন্টদের এটির সাথে বাইন্ড করার অনুমতি দিতে পারে। onStartCommand()-এর মাধ্যমে শুরু করা কোনও পরিষেবা (startService()-এ কল করা কোনও ক্লায়েন্টের মাধ্যমে) এখনও onBind()-এ কল রিসিভ করতে পারে (যখন কোনও ক্লায়েন্ট bindService()-এ কল করে)।

এই পদ্ধতিগুলি প্রয়োগ করে, আপনি পরিষেবার লাইফসাইকেলের এই দুটি নেস্টেড লুপ মনিটর করতে পারেন:

  • onCreate() কল করা এবং onDestroy() রিটার্ন করার মধ্যবর্তী সময়কে কোনও পরিষেবার পুরো লাইফটাইম বলা হয়। অ্যাক্টিভিটির মতো, কোনও পরিষেবা onCreate()-এ প্রাথমিক সেট-আপ করে এবং onDestroy()-এ বাকি সব রিসোর্স রিলিজ করে। যেমন, একটি মিউজিক প্লেব্যাক পরিষেবা onCreate()-এ মিউজিক চালানোর জন্য থ্রেড তৈরি করতে পারে এবং তারপর onDestroy()-এ থ্রেডটি বন্ধ করতে পারে।

    মনে রাখবেন: সব পরিষেবার জন্য onCreate() এবং onDestroy() পদ্ধতি কল করা হয়, সেগুলি startService() বা bindService() দ্বারা তৈরি করা হোক বা না হোক।

  • onStartCommand() বা onBind()-এর মধ্যে যেকোনও একটিতে কল করার মাধ্যমে কোনও পরিষেবার অ্যাক্টিভ লাইফটাইম শুরু হয়। প্রতিটি পদ্ধতিতে Intent হ্যান্ডেল করা হয় যা startService() অথবা bindService()-এ পাস করা হয়েছে।

    পরিষেবা শুরু হলে, অ্যাক্টিভ লাইফটাইম এবং সম্পূর্ণ লাইফটাইম একই সময়ে শেষ হয় (onStartCommand() রিটার্ন করার পরেও পরিষেবা অ্যাক্টিভ থাকে)। পরিষেবাটি বাউন্ড করা থাকলে, onUnbind() রিটার্ন করার পরে অ্যাক্টিভ লাইফটাইম শেষ হয়ে যায়।

মনে রাখবেন: যদিও চালু করা পরিষেবা stopSelf() বা stopService()-এর মধ্যে যেকোনও একটিতে কল করার মাধ্যমে বন্ধ করা হয়, পরিষেবার জন্য কোনও সংশ্লিষ্ট কলব্যাক নেই (কোনও onStop() কলব্যাক নেই)। পরিষেবাটি কোনও ক্লায়েন্টের সাথে আবদ্ধ না থাকলে, পরিষেবাটি বন্ধ হয়ে গেলে সিস্টেম এটি ধ্বংস করে দেয়—onDestroy() হল একমাত্র কলব্যাক যা পাওয়া যায়।

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