برنامه نویسی اندروید - دانشگاه صنعتی قم

این وبلاگ کانال ارتباطی با دانشجویان درس«برنامه نویسی موبایل» دانشگاه صنعتی قم می باشد.

برنامه نویسی اندروید - دانشگاه صنعتی قم

این وبلاگ کانال ارتباطی با دانشجویان درس«برنامه نویسی موبایل» دانشگاه صنعتی قم می باشد.

محتویات این وبلاگ با هدف آموزش اندروید در دوره درسی "برنامه نویسی موبایل" در دانشگاه صنعتی قم توسط اینجانب گردآوری شده است.
تعداد زیادی از مطالب ترجمه شده در این وبلاگ توسط دانشجویان دانشگاه صنعتی قم به عنوان پروژه های این درس ترجمه شده است.
در صورتی که تصمیم به تماس با من دارید، می توانید از طریق آدرس ایمیل qut دات android در جی میل دات کام با من تماس بگیرید.
-------------------
اگر بتوانم به شما کمکی در زمینه برنامه نویسی اندروید بکنم، خوشحال خواهم شد با این حال اگر پرسشی را ارسال کردید و بنده نیز به دلیل مشکلات و مشغله نتوانستم پاسخگو باشم، پوزش بنده را پیشاپیش پذیرا باشید.
-------------------
چون افراد زیادی از من درخواست می کنند تا برنامه نویسان اندروید به خصوص در شهر قم را به آنها معرفی کنند، اگر تمایل دارید رزومه و یا مشخصات خود را برایم ارسال کنید تا در صورت وجود درخواستهایی از این دست به شما اطلاع دهم.
از نظر من محدویتی به شهر قم وجود ندارد، لذا اگر برنامه نویس اندروید در شهرهایی دیگر هستید و یا به دنبال نیروی برنامه نویس اندروید هستید با من در تماس باشید، شاید بتوانم در این زمینه به شما کمکی بکنم :)
ناگفته نماند از آنجایی که در فضای مجازی من شناختی از هیچ شخص یا شرکتی ندارم، اگر شخصی به دنبال نیروی کار باشد، به افرادی که با مشخصات درخواستی ایشان تطابق داشته باشند، اطلاع خواهم داد و توصیه می شود برنامه نویسان محترم نیز قبل از شروع به همکاری، ملاحظات لازم در این زمینه را به عمل آورند چون من نیز شناختی از طرف مقابل ندارم.

طبقه بندی موضوعی

07- سرویسها

جمعه, ۲ خرداد ۱۳۹۳، ۰۹:۵۴ ب.ظ

مترجم: علی عبدالله زاده - حسن عباسی

آدرس مطلب اصلی: http://developer.android.com/guide/components/services.html

سرویس
سرویس یک برنامه است که می تواند عملیات های طولانی را در پس زمینه اجرا کند و یک رابط کاربری آماده نیست. یکی دیگر از مولفه های نرم افزاراین است که می تواند یک سرویس را شروع کند و به اجرا در پس زمینه ادامه دهد حتی اگر کاربر سوئیچ به برنامه های دیگر انجام دهد. علاوه بر این، یک جزء می تواند به یک سرویس  متصل شود و به تعامل با آن بپردازد و حتی ارتباط بین پروسه یIPC   انجام شود. به عنوان مثال، یک سرویس ممکن است معاملات شبکه ، اداره ، پخش موسیقی، انجام فایل I / O ، و یا ارتباط برقرار کردن با یک ارائه دهنده محتوا  را همه در پس زمینه  رسیدگی کند.
خدمات اساسا می تواند به دو شکل باشد:
آغاز شده
خدمات " آغاز شده " زمانی که یک جزء برنامه (مانند یک فعالیت ) با تماس با startService شروع می شود. هنگامی که آغاز شده ، یک سرویس می تواند در پس زمینه به طور نامحدود اجرا شود، حتی اگر جزء آنی باشد که از بین رفته است. معمولا،زمانی که یک سرویس آغاز می شود یک عمل مجزا انجام می دهد و در نتیجه به تماس گیرنده بر نمی گرداند. به عنوان مثال ، ممکن است در شبکه دانلود یا آپلود فایل  هنگامی که عملیات انجام شده است، سرویس باید خود را متوقف کند.
محدود
خدمات "محدود" زمانی که یک جزء برنامه با تماس با bindService ( ) به آن متصل می شود  خدمات محدود ارائه می دهد. یک رابط  کلاینت_ سرور که اجازه می دهد تا اجزا به تعامل با این سرویس، ارسال درخواست ، دریافت نتایج ، و حتی انجام این کار در سراسر فرایندهای برقراری ارتباط بین پروسه ای ( IPC )  . خدمات محدود فقط تا زمانی اجرا می شود  که جزء برنامه های دیگر به آن محدود شده است. اجزای چندگانه می تواند به سرویس در یک بار متصل شوند، اما زمانی که همه آنها را از بند رها کردند ، سرویس بین می رود.

صرف نظر از اینکه برنامه شما (آغاز شده) است یا (محدود) و یا هر دو ، می توانید از هر یک اجزای برنامه خدمات (حتی از یک نرم افزار جداگانه) استفاده کنید . با این حال، شما می توانید خدمات را به عنوان خصوصی اعلام کنید و در فایل  manifest، قرار دهید و از دسترسی برنامه های دیگر جلوگیری کنید . این بخش از بحث بیشتر مورد نظر است.
توجه : سرویس که  اجرا می شود در موضوع اصلی فرایند میزبانی آن سرویس موضوع خود را ایجاد نمی کند و در یک فرایند جداگانه اجرا می کند (مگر اینکه در غیر این صورت مشخص کنید) .این به این معنی است که اگر خدمات خود را در حال رفتن به انجام هر کار فشرده CPU و یا مسدود کردن عملیات ( مانند پخش MP3 و یا شبکه ) ، شما باید با استفاده از یک تاپیک جداگانه یک موضوع جدید در خدمات به انجام این کار ایجاد کنید.
مبانی
برای ایجاد یک سرویس، شما باید یک زیر کلاس از خدمات ( و یا یکی از زیر مجموعه های موجود در آن ) ایجاد کنید  . ، در صورت لزوم  در اجرای شما، شما نیاز به نادیده گرفتن برخی از روش های پاسخ به تماس دارید که مسئولیت رسیدگی به جنبه های کلیدی چرخه حیات خدمات و ارائه مکانیزم برای قطعات برای اتصال به این سرویس است.

طرز نادیده گرفتن برخی از روش های پاسخ به تماس عبارتند از :
onStartCommand()

سیستم تماس های این روش به این گونه است که هنگامی که یکی دیگر از عناصر مانند یک فعالیت درخواست سرویس می کند  با فرمان شروع سرویس آغاز می شود.
هنگامی که این روش اجرا ، سرویس آغاز شده است و می تواند در پس زمینه به طور نامحدود اجرا شود.  برای جلوگیری از سرویس زمانی که کار آن انجام شده است، از طریق تماس stopSelf و یا stopService است.

 

onBind()
سیستم تماس های این روش زمانی که جزء دیگر می خواهد به سرویس متصل شود (از جمله به انجام RPC)، با تماس با سرویس متصل میشود .شما در پیاده سازی این روش ، باید با بازگشت رابط IBinder  که مشتریان از آن برای برقراری ارتباط با خدمات ارائه می کنند استفاده کنید.  شما همیشه باید این روش را پیاده سازی کنید ، اما اگر شما نمی خواهید اجازه اتصال می دهد  ، و سپس مقدارnull را برگردانید.

onCreate()

سیستم تماس های این روش زمانی که سرویس برای اولین بار ایجاد شده، برای انجام مراحل راه اندازی یک بار (قبل از آن یا در  onBind() یا  onStartCommand() می نامد).

onDestroy()

 سیستم تماس های این روش زمانی که خدمات دیگر در حال نابود شده است استفاده می شود . سرویس شما باید از این اجرا به پاک کردن هر گونه منابع مانند موضوعات، شنوندگان ثبت نام، گیرنده ها، و غیره. این آخرین تماس خدمات دریافت کرده است.
اگر یک جزء این سرویس از طریق تماس startService () (که در نتیجه در یک تماس به onStartCommand ())شروع می شود ، پس از خدمات باقی مانده در حال اجرا تا زمانی که خود را با stopSelf متوقف می کند و یا بخش دیگر آن از طریق تماس stopService (متوقف می شود).
اگر یک جزء خواستار bindService ( ) برای ایجاد خدمات ( و onStartCommand ( ) نامیده می شود )، سپس سرویس اجرا می شود فقط تا زمانی که جزء به آن محدود شده است. هنگامی که خدمات به صورت رها شده از تمام مشتریان است ، سیستم را از بین می برد .
سیستم آندروید  Force-stop تنها زمانی که حافظه کم است و باید از منابع سیستم برای فعالیت است از سرویس استفاده خواهد کرد.

اگر سرویس به یک فعالیت که تمرکز کاربر رو آن محدود است ، کمتر احتمال دارد که کشته شود، و اگر سرویس اعلام شده در پیش زمینه اجرا کنید تقریبا هرگز کشته نخواهد شد . در غیر این صورت، اگر سرویس آغاز شد و طولانی مدت است، پس از آن سیستم موقعیت خود را در فهرست وظایف پس زمینه در طول زمان کاهش و خدمات تبدیل خواهد شد به بسیار حساس کشتن، اگر توسط شما آغاز شده است، پس شما باید آن را مجدد راه اندازی کنید. اگر سیستم خدمات شما را کشت ، به محض اینکه منابع مجددا ایجاد شود restsrt میشود  ( البته این وابسته به مقدار onStartCommand بر می گردد).
برای اطلاع بیشتر از این که وقتی سیستم ممکن است یک سیستم را از بین ببرد سند Processes and Threading را مشاهده کنید.

در بخش بعد شما خواهید دید چگونه می توان هر نوع سرویس را ایجاد کرد و چگونه از آن استفاده کرد .
اعلام خدمات در manifest
مشاهده فعالیت ها ( و دیگر قطعات ) شما باید تمام سرویس ها را در فایل manifest در اپلیکیشن تان اعلام کنید.
منبع سرویس را برای اطلاعات بیشتر درباره ی اعلام سرویس در manifestمشاهده کنید.

ویژگی های دیگری که می تواند در عنصر سرویس شامل شود برای تعریف مشخصاتی مثل نیاز مجوز برای شروع سرویس و پردازش در سرویسی که باید اجرا شود.

ویژگی android:name تنها ویژگی مورد نیاز برای مشخص کردن نام کلاس سرویس است زمانی که شما اپلیکیشن خود را منتشر می کنید نباید نام را عوض کنید به این دلیل که ریسک شکستن کد و یا در اتصال سرویس مشکل ایجاد می شود.

برای اطمینان ازاینکه برنامه شما امن است ، همیشه یک هدف روشن داشته باشید. وقتی سرویس شروع میشود یا binding می شود شما می توانید مطمئن شوید که سرویستان در دسترس است.برای فقط سرویس شما با اضافه کردن ویژگی  android:exported و set کردن آن به صورت false .

این ویژگی اپلیکیشن های دیگر را از شروع کردن سرویس شما نگه می دارد.
ساخت یک startService

یک startService یکی از اجزای شروع است بوسیله تابع startService درنتیجه یک فراخوانی به سرویس onStartCommand ( ) داریم.

هنگامی که یک سرویس آغاز شود، یک چرخه حیات مستقل از اجزایی که که آغاز شده و سرویسی که می تواند در پس زمینه به طور نامحدود اجرا شود، حتی اگر جزء آن است که آغاز شده از بین  برود به این ترتیب این سرویس باید نگه داشته شود . با فراخوانی تابع stopSelf یا عناصر دیگر می تواند نگه داشته شود با فراخوانی تابع  stopService
بخش نرم افزار مانند یک فعالیت می تواند سرویس را شروع کند فراخوانی تابع startService ( )  و یک Intent عبور دهد که یک سرویس را مشخص می کند و شامل هر داده ای برای سرویس است که باید استفاده شود سرویس دریافت می کند Intent را در تابع onStartCommand ( ) .
به عنوان مثال ، فرض کنید یک فعالیت نیاز به ذخیره برخی داده ها را به یک پایگاه داده آنلاین را دارد . فعالیت می تواند یک سرویس همراه شروع کند و ارائه دهد برای ذخیره شدن به وسیله ی عبور یک Intent به startService ( ) سرویس Intent را دریافت می کند  در onStartCommand ( ) ،و متصل به اینترنت می شود و انجام تبادل پایگاه داده انجام می شود . هنگامی که تبادل انجام شده است، خود به خود متوقف می شود و سرویس از بین می رود.

گسترش کلاس IntentService
به دلیل اینکه بیشتر سرویس های شروع شده لازم نیست که مسئولیت رسیدگی به درخواست های متعدد را به طور همزمان (در واقع می تواند یک سناریوی multi threading خطرناک باشد) داشته باشند احتمالا بهترین حالت این است که شما سرویس خود را با استفاده از کلاس IntentService پیاده سازی کنید
IntentService  به شرح زیر است :
1) یک worker thread پیش فرض ایجاد می کند که تمام intent ها را به onStartCommand ( ) به صورت جداگانه به thread اصلی اپلیکیشن شما تحویل می دهد.

2) یک صف کار ایجاد می کند که یک  intent را در یک زمان به onHandleIntent پیاده سازی شده شما عبور می دهد بنابر این شما هرگز نگران multi threading نخواهید بود.

3) تمام سرویس ها را بعد از اینکه تمام درخواست ها به کار گرفته شد نگه می دارد بنابراین شما نیازی به فراخوانی تابع stopSelf ( ) ندارید.

4) پیاده سازی پیش فرضی را از onBind ( ) فراهم می کند که مقدار null برمی گرداند.
5) یک پیاده سازی پیش فرض از onStartCommand ( )  فراهم می کند که  intent  را به صف کار می فرستد و سپس به پیاده سازی onHandleIntent می پردازد.

گسترش کلاس سرویس
همانطور که در بخش قبلی  دیدم ، استفاده از IntentService پیاده سازی شما را از سرویس آغاز شده بسیار ساده می کند. اگر شما نیاز دارید که سرویس تان multi threading را اجرا کند (به جای پردازش درخواست شروع از یک صف کار ) ، سپس شما می توانید کلاس سرویس گسترش دهید تا به هر intent رسیدگی کند.
برای مقایسه مثال کد زیر یک پیاده سازی از کلاس سرویس است که یک  کار دقیقا یکسان را اجرا می کند به همان شکل مثال بالا که از IntentService  استفاده می کرد.به این معنا که برای هر درخواست شروع، از یک worker thread  برای اجرای کار و پردازش تنها یک درخواست در یک زمان استفاده می کند.

public class HelloService extends Service {
 
private Looper mServiceLooper;
 
private ServiceHandler mServiceHandler;

 
// 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.
         
long endTime = System.currentTimeMillis() + 5*1000;
         
while (System.currentTimeMillis() < endTime) {
             
synchronized (this) {
                 
try {
                      wait
(endTime - System.currentTimeMillis());
                 
} catch (Exception e) {
                 
}
             
}
         
}
         
// 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 will not 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
    mServiceLooper
= thread.getLooper();
    mServiceHandler
= new ServiceHandler(mServiceLooper);
 
}

 
@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 = mServiceHandler.obtainMessage();
      msg
.arg1 = startId;
      mServiceHandler
.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();
 
}
}


همانطور که می بینید ، کارهای بسیار بیشتری وجود دارد که  از IntentService استفاده می کند.
با این حال، به این دلیل که شما هر فراخوانی به  onStartCommand ( )  را خودتان رسیدگی می کنید می توانید چندین درخواست های متعدد به طور همزمان اجرا کنید. این عملی است که این مثال انجام نمی دهد ، اما اگر این چیزی است که شما می خواهید ، شما می توانید یک thread جدید برای هر درخواست ایجاد کنید و آنها را همزمان اجرا کنید ( به جای اینکه منتظر درخواست قبلی باشید تا به پایان برسد).

 

توجه داشته باشید که onStartCommand() باید یک مقدار int برگرداند.این عدد مقداری می باشد که مشخص می کند زمانی که سیستم روند را از بین می برد سیستم چگونه باید سرویس را ادامه دهد.(همانطور که بالا بحث شد ، اجرای پیش فرض IntentService این را برای شما انجام می دهد.با این حال شما می توانید آن را تغییر دهید). مقدار بازگشتی از onStartCommand() باید یکی از مقادیر ثابت (constant) های زیر باشد :

START_NOT_STICKY

این مقدار وقتی بر می گردد که سیستم بعد از onStartCommand() سرویس را متوقف کند ،سرویس دوباره ساخته نمی شود،مگر اینکه intentهای مورد انتظاری برای ارائه وجود داشته باشد.این امن ترین راه برای جلوگیری از اجرای سرویس در هنگامی که نیازی نیست می باشد و همچنین مواقعی که برنامه شما می تواند به راحتی کارهای ناتمام را دوباره شروع (restart) کند.

START_STICKY

این مقدار وقتی بر می گردد که سیستم بعد از onStartCommand() سرویس را متوقف کند،سرویس دوباره ساخته شده و  onStartCommand() صدا زده می شود، ولی آخرین intent ارائه شده دوباره تحویل داده نمی شود. در عوض سیستم  onStartCommand() را با مقدار null صدا می زند مگر اینکه intent مورد انتظاری برای شروع سرویس وجود داشته باشد،که در این صورت آن intent تحویل داده میشوند.این برای پخش کننده های صوتی و تصویری و یا سرویس های مشابه مناسب است که در حال اجرای دستورات نیست، اما در حال اجرا به طور نامحدود و در انتظار برای یک کار.

START_REDELIVER_INTENT

این مقدار وقتی بر می گردد که سیستم بعد از onStartCommand() سرویس را متوقف کند،سرویس دوباره ساخته شده و  onStartCommand() با آخرین مقداری که به سرویس داده شده است، صدا زده می شود. هر گونه مقدار مورد انتظار به نوبه خود تحویل داده شده است.این برای سرویس هایی که به صورت پویا در حال انجام وظیفه ای هستند که باید سریعا از سر گرفته شوند مناسب است.مانند دانلود کردن فایل و ...

شروع سرویس

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

به عنوان مثال یک ACTIVITY می تواند یک سرویس(HelloService) را شروع کند  با استفاده از یک intent صریح که به متدstartService()   داده می شود.

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

متد startService()   سریعا جواب بر می گرداند و  اندروید متد onStartCommand() سرویس ها را صدا می زند.اگر سرویس هنوز اجرا نشده است، سیستم اول onCreate() را صدا می زند بعدا onStartCommand() را صدا می زند.

اگر سرویس چیزای لازم دیگر را نیز آماده نکند،intentی که به startService() داده می شود،تنها حالت ارتباط بین اپلیکیشن و سرویس می باشد. وقتی شما می خواهید که سرویس نتیجه ای را برگرداند،طرفی که سرویس را شروع کرده است می تواند یک مقدار مورد انتظار(PendingIntent) تولید کند برای انتشار دادن (با این متد getBroadcast()) و تحویل به سرویس در جایی که سرویس شروع می شود.سرویس می تواند پس از آن از انتشار(broadcast) برای تحویل دادن نتیجه استفاده کند.

چندین درخواست برای شروع سرویس منجرمی شود به چندین بار صدا زدن onStartCommand() سرویس ها که این صدا زدن ها با هم در ارتباط هستند.برای متوقف شدن نیز تنها یک بار درخواست برای توقف(با متد stopSelf() یا stopService() ) کافی است .

متوقف کردن سرویس

یک سرویس استارت شده باید خودش در طول حیاتش خودش را مدیریت کند . این یعنی ، سیستم هیچ گاه یک سرویس را متوقف نکرده و یا از بین نمی برد مگر اینکه سیستم باید حافظه را بازیابی کند و سیستم به اجرای خود ادامه می دهد تا  onStartCommand() برگردد.

یک بار درخواست برای توقف با متد های stopSelf() یا stopService() باعث از بین رفتن سرویس در سریع ترین زمان ممکن می شود .

اگر سرویس شما چندین درخواست برای onStartCommand() را به صورت همزمان اجرا می کند، شما هیچ گاه نباید سرویس خود را تا زمانی که شما در حال انجام پروسه ی شروع یک سرویس هستید، متوقف کنید.به این دلیل که ممکن است در این میان یک درخواست شروع سرویس جدید دریافت کنید .

برای جلوگیری از این مشکل،شما می توانید ازstopSelf(int) استفاده کنید که مطمئن شوید درخواست شما برای متوقف کردن سرویس همیشه بر پایه ی آخرین درخواست برای شروع سرویس می باشد.این یعنی وقتی شما  stopSelf(int) را صدا میزنید، شما آی دی درخواست شروع را می دهید(startId به onStartCommand() داده می شود) به درخوسات توقفی که مربوط می شود.سپس وقتی که سرویس یک درخواست شروع جدید دریافت می کند قبل از اینکه شما بتوانید stopSelf(int) را صدا بزنید، آی دی مطابقت نمی کند و سرویس متوقف نمی شود.

سرویس های وابسته

یک سرویس وابسته سرویسی است که به کامپوننت های یک برنامه کاربردی اجازه می دهد که به آن وابسته باشند با استفاده از متدbindService() به منظور ایجاد یک اتصال پایدار( و معمولا اجازه نمی دهد به کامپوننت ها که آن را با متدstartService() شروع کنند )

شما باید یک سرویس وابسته را شروع کنید وقتی که شما می خواهید با activity ها و یا کامپوننت های دیگر در اپلیکیشن با سرویس در تعامل باشید.

برای ایجاد یک سرویس وابسته شما باید متد بازگشتی onBind() را اجرا کنید که یک IBinder برگرداند که مشخص کننده interface برای ارتباط با سرویس است.کامپوننت برنامه ی کاربردی دیگر می تواند bindService() را صدا بزند تا interface  را بازیابی کند و شروع کند به صدا زدن متد ها در سرویس.سرویس وجود دارد برای خدمت رسانی به کاموننت های اپلیکیشنی که به آن وابسته اند.بنابراین هنگامی که هیگ کامپوننتی به سرویس وابسته باشد، سیستم آن را از بین می برد.

برای شروع یک سرویس وابسته اولین کاری که شما باید انجام دهید، مشخص کردن interface ای است که مشخص می کند چگونه یک کلاینت می تواند با سرویس در ارتباط باشد.این interface بین سرویس و کلاینت می بایست از اجرای  IBinder و مقدار بازگشتی از تابع onBind() باشد.به محض اینکه کلاینت IBinder را دریافت کرد ، می تواند تعامل خود با سرویس را از طریق این interface شروع کند.

چندین کلاینت می توانند یکجا به یک سرویس وابسته باشند.وقتی که یک کلاینت تعامل خود با سرویس را انجام داد ، unbindService() را صدا می زند.به محض اینکه هیچ کلاینتی به سرویسی وابسته نباشد، سیستم این سرویس را از بین می برد.

فرستادن اطلاعیه به کاربر

یک سرویس می تواند به یوزر اطلاعیه را از طریق  Status Bar Notifications یا Toast Notifications  برساند.

Toast Notifications یک پیغام می باشد که در سطح پنجره ی جاری برای چند لحظه نمایش داده شده و سپس ناپدید می شود.ولی Status Bar Notifications یک آیکون همراه با یک پیغام فراهم می کند که کاربر می تواند با انتخاب آن یک عمل را انجام دهد ( از قبیل یک activity).

معمولا Status Bar Notifications بهترین روش می باشد هنگامی که یک کار پشت صحنه ای کامل می شود (مانند تکمیل یک دانلود) و کاربر حالا می تواند روی آن عملی را انجام دهد.وقتی که کاربر آن اطلاعیه را انتخاب می کند،اطلاعیه می تواند یک activity را اجرا کند(مانند مشاهده ی فایل دانلود شده ).

اجرای یک سرویس در پیش نما (foreground)

یک سرویس foreground در نظر گرفته شده است که کاربر به صورت پویا از آن باخبر باشد و زمانی که حافظه کم می باشد برای توقف کاندید نباشد.این سرویس باید یک اطلاعیه در status bar فراهم کند که جای آن در زیر سر تیتر Ongoing می باشد، که بدین معنی می باشد که اطلاعیه نمی تواند در نظر گرفته نشود مگر اینکه این سرویس از قسمت forground حذف شده و یا متوقف شود.

به عنوان مثال یک پخش کننده موسیقی که از یک سرویس این کار را انجام می دهد باید در پیش نما(foreground) قرار گیرد. چرا که کاربر به صراحت از عملکرد آن آگاه است. اطلایه در status bar  باید آهنگ جاری را نشان دهد و به کاربر اجازه دهد که یک activity را برای تعامل با پلیر اجرا کند.

برای اینکه یک سرویس را در پیش نما اجرا کنید متدstartForeground() را صدا بزنید.این متد دو متغیر دارد: یک اینتیجر که به صورت یکتا اطلاعیه را مشخص می کند و یک  Notification برای status bar . به عنوان مثال :

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
       
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification
.setLatestEventInfo(this, getText(R.string.notification_title),
        getText
(R.string.notification_message), pendingIntent);
startForeground
(ONGOING_NOTIFICATION_ID, notification);

نکته : عدد صحیحی که به عنوان آی دی به متدstartForeground() می دهد نباید 0 باشد.

برای خارج کردن یک سرویس از قسمت پیش نما ،متد  stopForeground() را صدا بزنید.این متد یک عدد بولین (boalean)   می گیرد برای حذف شدن اطلاعیه از status bar .این متد سرویس را متوقف نمی کند.همچنین اگر شما سرویسی را که در پیش نما فعال می باشد متوقف کنید ، اطلاعیه آن نیز حذف می شود.

مدیریت چرخه ی زندگی یک سرویس

چرخه زندگی یک سرویس بسیار ساده تر از یک activity می باشد.همچنین بسیار مهم است که دقت داشته باشید سرویس شما چگونه ایجاد شده و از بین می روند.زیرا که یک سرویس می تواند در پس زمینه بدون اینکه کاربر آگاه شود اجرا شود.

چرخه ی زندگی سرویس ها – از زمانی که ایجاد شده تا زمانی که پایان پذیرد- می توان دو مسیر مختلف را شامل شود:

  • A started service

یک سرویس موقعی ایجاد می شود که یک کامپوننت دیگر startService() را صدا بزند.بعد از آن سرویس به صورت نامحدود اجرا می شود و برای متوقف شدنش باید خودش stopSelf() را صدا بزند. کامپوننت دیگر می تواند سرویس را با متد stopService() متوقف کند.زمانی که یک سرویس متقف شود، سیستم آن را از بین می برد...

  • A bound service

یک سرویس زمانی خلق می شود که یک کامپوننت دیگر(یک کلاینت) متد bindService() را فراخوانی کند. کلاینت سپس از طریق interface IBinder با سرویس ارتباط برقرار می کند.

کلاینت با فراخوانی unbindService() می تواند ارتباط را از بین ببرد.چندین کلاینت می توانند به یک سرویس مشترک وابسته باشند و هنگامی که همه آنها اتصال شان قطع شد، سیستم سرویس را از بین می برد . ( نیازی نیست سرویس خودش را متوقف کند )

این دو مسیر کاملا از هم مجزا نیستند.به دلیل که می توان به یک سرویس متصل شد که با startService() شروع شده است.به عنوان مثال یک پخش کننده موسیقی پس زمینه ای می تواند توسط متد startService() با intentای که موزیک رامشخص می کند صدا زده شود . بعد از آن ، درست هنگامی که کاربر می خواهد درباره آهنگ در حال پخش اطلاعاتی بدست آورد،یک activity می تواند با متد bindService() به یک سرویس متصل شود. در مواردی از این قبیل stopService() یا stopSelf() تا زمانی که همه ی کلاینت ها اتصالشان قطع نشود نمی توانند به صورت ناگهانی متوقف شوند.

پیاده سازی فراخوانی چرخه ی زندگی (چرخه عمر)

مانند یک activity ، سرویس ها دارای متدهای فراخوانی چرخه ی عمر می باشند که می توان آن ها را پیاده سازی کنید تا بتوانید نظارت داشته باشید بر روی تغییر حالت های سرویس و انجام کارهای مختلف در زمان مناسب.در زیر می توانید اسکلت سرویس هریک از متدهای چرخه ی زندگی را ببینید:

public class ExampleService extends Service {
   
int mStartMode;       // indicates how to behave if the service is killed
   
IBinder mBinder;      // interface for clients that bind
   
boolean mAllowRebind; // 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 mStartMode;
   
}
   
@Override
   
public IBinder onBind(Intent intent) {
       
// A client is binding to the service with bindService()
       
return mBinder;
   
}
   
@Override
   
public boolean onUnbind(Intent intent) {
       
// All clients have unbound with unbindService()
       
return mAllowRebind;
   
}
   
@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
   
}
}

نکته: برخلاف متدهای فراخوانی چرخه ی زندگی در activity ها ، نیازی نیست پیاده سازی سوپرکلاس ها را در این متدهای فراخوانی صدا بزنید.

شکل2- چرخه ی زندگی سرویس . سمت چپ نمودار چرخه ی زندگی سرویس را در زمان ایجاد آن با متد startService() نشان می دهد و سمت راست نمودار چرخه زندگی با متدbindService()  را نشان می دهد.

با پیاده سازی این متد ها ، می توان دو حلقه ی تو در تو چرخه ی سرویس را زیر نظر گرفت .

  • کل چرخه ی زندگی یک سرویس در بین فراخوانی onCreate() تا زمان بازگشت جواب متد onDestroy() می باشد.به مانند activity ، سرویس نصب اولیه را در onCreate() انجام داده و باقی مانده ی منابع را در onDestroy() رها می کند.به عنوان مثال یک سرویس پخش موزیک می تواند موضوع را در جایی که موزیک در onCreate() پخش می شود ایجاد کند و سپس در onDestroy() آن را متوقف کند.

متدهای onDestroy()  وonCreate() برای همه ی سرویس ها فراخوانی می شوند، چه آن ها باstartService() یا bindService()ایجاد شوند.

  • قسمت پویای چرخه ی زندگی یک سرویس زمان فراخوانی onStartCommand() یا onBind() شروع می شود.هرکدام از متدها intentی که به متدهای startService() یاbindService() پاس داده می شوند را به ترتیب مدیریت می کنند.

اگر این سرویس آغاز شده است، طول عمر فعال به پایان می رسد همان زمانی است که تمام عمر به پایان می رسد.(حتی بعد از onStartCommand() سرویس هنوز فعال می باشد)اگر سرویس وابسته باشد،قسمت پویای طول عمر همزمان با فراخوانی متد onUnbind()  پایان  می گیرد.

نکته:زمانی که یک سرویس شروع شده چه با stopService() یا stopSelf() متوقف شود، پاسخ مربوطه برای این سرویس وجود ندارد(هیچ فراخوانی onStop() وجود ندارد). بنابر این ، اگر چه سرویس به یک کلاینت مربوط می شود، سیستم آن را زمانی که سرویس متوقف می شود از بین می برد. onDestroy()تنها پاسخی است که دریافت می شود.

شکل 2 فراخوانی های معمولی متدهای یک سرویس را نشان می دهد.با اینکه شکل سرویس هایی که با startService() ایجاد شده اند را با متدهایی که باbindService() ایجاد شده اند تفکیک کرده است،در نظر داشته باشید هر سرویسی ، مهم نیست که چگونه ایجاد شده است، پتانسیل این را دارد که به کلاینت اجازه وابستگی به آن را بدهد.بنابر این یک سرویسی که با onStartCommand() ایجاد شده است(در کلاینت با متد startService()) هنوز می تواند یک فراخوانی onBind() دریافت کند.(زمانی که کلاینت متد bindService() را صدا می زند)

  • وهاب صمدی بخارایی

نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

کاربران بیان میتوانند بدون نیاز به تأیید، نظرات خود را ارسال کنند.
اگر قبلا در بیان ثبت نام کرده اید لطفا ابتدا وارد شوید، در غیر این صورت می توانید ثبت نام کنید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی