همه چیز راجع به سرویس ها در اندروید(۲)

(سرویس های Started یا UnBounded )

سطح : پیشرفته

در این قسمت سرویس های از نوع Started  را بررسی میکنیم.

سرویس های Started و سرویس های Bounded دو چرخه ی حیات متفاوت دارند ولی هر دو در همان  thread (نخ) اصلی برنامه اجرا می شوند . پس اگر محاسبات سنگینی را بخواهیم در این سرویس پردازش کنیم بهتر است که آن را در یک thread دیگر انجام دهیم.

سرویس   Started  با صدا زدن (یا invoke) متد StartService  از سوی یک مولفه در اکتیویتی ها اجرا می شود و تا زمانی که دستور توقف آن صادر نشده است ادامه خواهد داشت، حتی اگر آن مولفه ای که آن را صدا زده است از بین برود.
برای پایان دادن به کار سرویس باید متد stopService را صدا بزنیم. همچنین یک سرویس میتواند خودش را با متد StopSelf متوقف کند.(مثلا پس از اتمام دانلود یک فایل)

البته همانطور که قبلا هم اشاره کردیم در هر شرایطی که سیستم عامل اندروید احساس کمبود فضا و منابع کند به راحتی سرویس را Kill  می کند که در آینده میگوییم چه راه حل هایی می توان برای این مشکل ارایه کرد.

اهمیتی ندارد چند بار سرویس را startService کرده باشیم برای توقف آن یک بار دستور توقف بسنده خواهد کرد.

برای ساخت یک سرویس باید یک کلاس بسازیم که از کلاس مبنای Service یا یکی از زیر کلاس های آن ارث بری کند. کلاس مبنای سرویس متدهای زیادی دارد که در چرخه ی حیات زیر (که مربوط به سرویس های Started است) میتوانید آنها راببینید:

به جز متد onBind ، پیاده سازی سایر متدها اختیاری است.

پس یک کلاس می سازیم به نام MyService و آن را از Service ارث بری می کنیم، سپس خطایی مبنی بر پیاده سازی متد OnBind داریم که برای رفع آن بر روی خطا Alt+Enter می زنیم و سپس implements Methods وپس از آن OnBind را انتخاب میکنیم . انتهای متد یک مقدار null را return می کند و چون هدف ما هم در اینجا بیان سرویس های  Started است مقدار آن را برابر null باقی میگذاریم :

با زدن ctrl+o سه متد مهم دیگر OnCreate, OnStartCommand, OnDestory را override میکنیم و در هر متد یک Toast می نویسیم تا با اجرای سرویس رد پای آن را مشاهده کنیم و همچنین یک مدیا پلیر راه اندازی میکنیم تا عملکرد آن را در پس زمینه بهتر را درک کنیم(در پوشه raw فایل صوتی خود را قرار دهید):

onCreate: فقط یک بار وقتی که startService صدازده شده و هنوز سرویس اجرا نشده است  یک شی از سرویس ساخته می شود و این متد فراخوانی می شود. و اگر سرویس در حال اجرا باشد دیگر این متد صدا زده نخواهد شد.
onStartCommand:مهم ترین متد است و زمانی که سرویس را با startService برای نخستین بار استارت میکنیم این متد پس از onCreate اجرا خواهد شد.
و زمانی که سرویس در حال اجرا است و مجددا startService فراخوانی شود onCreate دیگر هیچ گاه فراخوانی نمی شود و مستقیما این متد صدا زده خواهد شد ، پس این متد را باید به نحوی بنویسیم که آمادگی چندین بار صدا زده شدن را داشته باشد.
وقتی StartActivity را در یک اکتیویتی صدا میزنیم باید به آن یک ورودی intent بدهیم ، که آن intent را اینجا میتوانیم از اولین پارامتر متد onStartCommand باز پس بگیریم.
همانطور که میبینید متد onStartCommand یک خروجی int باید بازگرداند
مثل:

که هر یک از این خروجی ها معناهای مختلفی را به شرح زیر در پی خواهد داشت:
START_STICKYوقتی سرویس در حال اجرا است و اندروید به هر دلیلی آن را متوقف می سازد ، در این حالت اندروید مجددا سرویس را اجرا می کند اما بدون intent به عبارتی null intent آن را صدا میزند.(  زمانی که به intent پارامتری را set نکرده ایم کاربردی است)

START_NOT_STICKY:در این حالت وقتی سرویس توسط اندروید متوقف می شود دیگر اجرا نخواهد شد تا زمانی که  از جایی دوباره فراخوانی شود.

START_REDELIVER_INTENT: همانند حالت اول START_STICKY بعد از توقف دوباره اجرا خواهد شد اما با Intent ای که موقع استارت شدن گرفته است.(وقتی به intent خود پارامتری را set کرده ایم این مورد را return  میکنیم.)

همچنین وقتی میخواهیم ببینیم که این onStartCommand توسط چه عاملی اجرا شده است (یعنی پس از توقف به صورت خودکار اجرا شده یا بار اول توسط startService) می توانیم از intent (مطابق زیر )  flag آن را بپرسیم:

اگر flag برابر START_FLAG_REDELIVERY بود یعنی توسط مقدار بازگشتی START_REDELIVER_INTENT پس از توقف دوباره اجرا شده و اگر flag برابر START_FLAG_RETRY بود یعنی توسط مقدار بازگشتی START_STICKY بعد از توقف دوباره اجرا شده است.

onDestory: این متد پس از توقف سرویس صدا زده خواهد شد. ( بهتر است توقف فعالیت ها را مثل stop شدن مدیا پلیر را در این متد بنویسیم)

در activity_main.xml برای start و stop شدن سرویس دو Button قرار می دهیم:

و در MainActivity.java سرویس را به صورت زیر صدا خواهیم زد:

سرویس هم مانند اکتیویتی باید در AndroidManifest درون تگ Application معرفی شود (به اصطلاح register شود) پس برای اینکه فراموش نکنیم همیشه به محض ساختن یک سرویس این کار را می کنیم:

البته بد نیست دو attribute زیر هم به تگ سرویس اضافه کنیم:

exported:این attribute در حالت پیش فرض برای سرویس true است . اگر بخواهیم این سرویس مورد دسترسی سایر برنامه ها قرار نگیرد باید مقدار آن را برابر false قرار داد.

enable: این attribute هم برای سرویس ها در حالت پیش فرض enable است. که همانطور که از نام آن پیداست در صورتی که false باشد سرویس غیر فعال خواهد شد.
اگر  برایتان سوال پیش آمده که این enable کجا میتواند کاربرد داشته باشد میتوان گفت فرض کنید بخواهید در صورتی که فقط شرطی برقرار بود یک سرویس اجرا شود ، پس راه حل این است که شما به طور پیش فرض enable:false قرار دهید و سپس در کلاس های جاوایتان در صورت برقرار بودن شرط با استفاده از setComponentEnabledSetting وضعیت سرویس را فعال (enable) کنید.

یا همجنین یک کار جالب دیگری که میتوان انجام داد این است که در خود xml شرط را بررسی کنیم. فرض کنید بخواهید سرویس برای اندروید های api19 به بالا فعال باشد، برای این کار یک  bool با مقدار false در مسیر res/values/strings مثل زیر ایجاد میکنیم:

و یک bool همنام قبلی با مقدار true در مسیر res/values-v19/strings مطابق زیر ایجاد میکنیم(همانطور که میدانید مسیر values-v19 در api 19 و بالاتر خوانده می شود):

آنگاه کافی است مقدار enable سرویس را مطابق زیر تعریف کنید:

 

 

شما همچنین ممکن است پست های زیر را دوست داشته باشید:

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *