کار با سرویس های اندروید (Android Services) - بخش اول
جلسات دوره
مهدی عباسی
مهدی عباسی هستم، مسلط به حداقل ۲۰ زبان مطرح برنامه نویسی به صورت پیشرفته، مدیر عامل شرکت آریا نرم افزار و بنیانگذار آکادمی درسمن، مسلط به تدریس دروس تخصصی کاردانی و کارشناسی کامپیوتر، پایگاه داده ها، برنامه نویسی پیشرفته، مبانی برنامه نویسی، مباحث ویژه طراحی وب و .... مشاهده رزومه
آموزش کار با سرویسهای اندروید (Android Service) - بخش اول
در جلسه گذشته با Broadcast Receiver آشنا شدیم؛ در این جلسه میخواهیم مبحث مهم کار با سرویسهای اندروید را ارائه دهیم. از ابتدا دوره تا اینجا تمام خدمات اپلیکیشن را درون Activityها به وسیله Ui و کامپوننت ها انجام دادیم، اما اگر نیاز داشته باشیم کاری را خارج از Ui انجام دهیم باید چه کنیم؟ در اینجا میتوانیم به جای Activityها، از Servicesها استفاده کنیم.
برای انجام خدمات به کاربر 3 نوع ابزار در اندروید داریم:
-
Activity
-
Broadcast Receiver
-
Service
Activityها نیاز به ui دارند و کاربر میتواند ظاهر آن را ببیند و رفتاری انجام دهد. Broadcast Receiverها نوعی سرویس هستند که رویدادهای سیستم را شنود میکنند و میتوانند در مقابل آنها رفتاری انجام دهند.
Serviceها نیاز به ui ندارند و میتوانند رفتاری را در بکگراند انجام دهند. به عنوان مثال دانلود یک فایل درون اپلیکیشن میتواند درون سرویسها انجام شود و کاربر به ادامه فعالیت خود در اپلیکیشن ادامه دهد یا هنگام پخش موزیک در اپلیکشنهای موزیک پلیر، کاربر میتواند یک موزیک را پخش کند و در همه قسمت اپلیکیشن بدون وقفه جابجا شود زیرا عملیات پخش موزیک درون Serviceها در بکگراند اجرا میشود.
Serviceها در اندروید به دو دسته تقسیم میشوند:
-
Bound Service
-
Started Service
Bound Serviceها برای استفاده باید به یک ویجت یا اکتیویتی متصل شوند درحالی که Started Serviceها متصل به هیچ ویجتی درون برنامه نیستند (یعنی هیچگونه وابستگی ندارند) و خودمان میتوانیم آنها را شروع و خاتمه دهیم.
خود Started Serviceها به دو دسته Background Service و Foreground Service تقسیم میشوند.
اولویت Foreground Serviceها بیشتر از Background Service است؛ یعنی اگر سیستم رم یا Cup و.. کم بیاورد ابتدا تلاش میکند Background Serviceها را ببندد. هنگام ساخت یک Service، در ابتدا نوع آن Background Service میباشد و اگر نیاز به Foreground Serviceها داشته باشیم باید آن را به Foreground Serviceها تغییر دهیم. در استفاده از Foreground Service باید به کاربر اطلاع دهید چارکه این اطلاعرسانی از طریق Notification به کاربر نمایش داده میشود و تا زمانی که سرویس غیرفعال نشود نوتیفیکیشن قابل بسته شدن نیست. Serviceها از Main Thread استفاده میکنند و برای Performance بهتر از Threadها استفاده کنید.
پیادهسازی یک نمونه Background Service
برای شروع، یک پروژه ایجاد کردیم.حالا دکمههایی برای اجرای سرویس، متوقف کردن سرویس و رفتن به اکتیویتی بعدی میسازیم.
MainActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btnStartService"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="68dp"
android:layout_marginEnd="24dp"
android:text="Start Service"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnStopService"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="72dp"
android:layout_marginEnd="24dp"
android:text="Stop Service"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnStartService" />
<Button
android:id="@+id/btnNext"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="72dp"
android:layout_marginEnd="24dp"
android:text="Next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnStopService" />
</androidx.constraintlayout.widget.ConstraintLayout>
ساخت Service هم شبیه به ساخت Activity میباشد و برای اینکار، روی پروژه کلیک راست کنید و از گزینه New گزینه Service و سپس Service را انتخاب کنید. مانند عکس زیر:
حال در پنچره باز شده از قسمت Class Name نام Service را انتخاب کنید و تیک گزینه Exported را بردارید. اگر این تیک فعال باشد، خارج از اپلیکیشن میتوان به سرویسهای اپلیکیشن دسترسی داشت و ممکن است مسائله امنیت اپلیکیشن را به خطر بیندازد. پس بهتر است به دلیل مسائل امنیتی این گزینه را غیرفعال کنید.
در آخر Finish را بزنید تا کلاس Service ساخته شود.
اکنون کلاس ساخته شده که از کلاس Service ارث برده و مشابه کد کلاس زیر است:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
thorw new UnsopportedOperationException(“Not yet implemented”);
}
}
همچنین یک تیکه کد به فایل androidManifest درون تگ application اضافه شده که برابر با کد زیر میباشد:
<service
android:name=".MyService"
android:enabled="true"
android:exported="false">
</service>
در ادامه چند متد را درون کلاس MyService بازنویسی می کنیم:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStaerCommand(integer, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
-
تابع onCreate: زمانی صدا زده میشود موقعی که Service ساخته شده باشد.
-
تابع onStartCommand: این تابع با اجرای Service، صدا زده میشود.
-
تابع onDestroy: در نهایت زمانی که Service از بین میرود، این تابع صدا زده میشود.
به این نکته هم توجه کنید که اگر سرویس از نوع Started Service بود یعنی Background و یا Foreground بود، درون تابع onBind کد return null را قرار دهید تا این تابع اجرا نشود.
پیادهسازی سرویس پخش موزیک
اکنون در ادامه میخواهیم سرویس پخش موزیک را پیادهسازی میکنیم.
برای شروع، یک شی از کلاس MediaPlayer میسازیم و آن را درون تابع onCreate به یک موزیک متصل میکنیم. حال یک موزیک درون پوشه raw قرار داده و آن را به MediaPlayer متصل میکنیم. سپس درون تابع onStartCommand ابتدا mediaPlayer را Start میکنیم که در خروجی چندین ثابت از نوع int وجود دارد و ما از ثابت STAER_STICKY استفاده میکنیم.
توضیح ثابت START_STICKY
تا زمانی که سرویس اجرا میشود با intent دریافت شده کار میکند؛ اما اگر به هر دلیل سرویس قطع شود و سپس دوباره شرایط اجرا شدن سرویس فراهم شود، سرویس اجرا شده اما intent اول از بین خواهد رفت. پس به طور کلی دو روش برای اجرا دارد:
-
START_NOT_STICKY: اگر سرویس به هر دلیل قطع شود و سپس شرایط راهاندازی فراهم گردد سرویس را راهاندازی نمیکند.
-
START_REDELIVER_INTENT: شبیه به START_STICKY است اما اگر دوباره سرویس اجرا شود intent اول باقی خواهد ماند.
همچنین درون تابع، onDestroy mediaPlayer را متوقف کردیم.
کلاس MyService تمام شد و کدهای آن به صورت زیر است:
public class MyService extends Service {
MediaPlayer mediaPlayer;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mediaPlayer=MediaPlayer.create(this,R.raw.divaneh);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer.start();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
}
}
سپس درون کلاس MainActivity ابتدا ویجتها را از درون صفحه به کمک FindViewById شناسایی کردیم. زمانی که دکمه StartService کلیک شود (درون تابع onClick دکمه StartService) به کمک Intent کلاس جاری را به کلاس سرویس ساخته شده(MyService) متصل کرده و به کمک تابع startService() سرویس ایجاد شده را اجرا خواهیم کرد.
در ادمه، درون تابع onClick دکمه StopService به کمک Intent از MinActivity به MyService وصل شدیم و به کمک تابع stopService() سرویس را متوقف کردیم. در تابع onClick دکمه Next از MinActivity به SecondActivity رفتیم.
کد کلاس MainActivity
public class MainActivity extends AppCompatActivity {
Button btnStartService;
Button btnStopService;
Button btnNext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupView();
btnStartService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,MyService.class);
startService(intent);
}
});
btnStopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,MyService.class);
stopService(intent);
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
private void setupView() {
btnStartService=findViewById(R.id.btnStartService);
btnStopService=findViewById(R.id.btnStopService);
btnNext=findViewById(R.id.btnNext);
}
}
نظر شما در تصمیم دیگران اثرگذار است.
لطفا برای همراهان درسمن و بهتر شدن دوره نظر خود را بنویسید.