-
안드로이드 서비스 (3)안드로이드 2020. 5. 21. 21:09728x90
2020/05/21 - [Android & Kotlin] - 안드로이드 서비스(2)
서비스 관련 마지막 글이 될 것 같네요 하하
이전까지는 스타티드 서비스와 서비스를 LMK로부터 최대한 오래 살아남는 법에 대해서 알아봤어요
이번 글에서는 바운드 서비스에 대해서 알아볼게요
바운드 서비스는 서버/클라이언트적인 성향이 강해요 그래서 사용하기 전에 연결을 맺고, 다 사용했으면 연결을 끊는 과정들이 필요합니다.
예제
< layout/activity_main.xml >
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/start_btn" android:text="startService" android:layout_width="match_parent" android:layout_height="100dp"/> <Button android:id="@+id/end_btn" android:text="stopService" android:layout_width="match_parent" android:layout_height="100dp"/> </LinearLayout>
< MainActivity.java >
package kr.co.sample; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 바운드 서비스가 연결되었음을 확인할 수 있는 메소드 Log.d("CountService", "onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { // unbindService 가 아닌 의도치 않은 상황으로 연결이 끊겼을 때 호출 Log.d("CountService", "onServiceDisconnected"); } }; Button startBtn, endBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startBtn = findViewById(R.id.start_btn); endBtn = findViewById(R.id.end_btn); startBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, CountService.class); bindService(intent, connection, BIND_AUTO_CREATE); } }); endBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { unbindService(connection); } }); } }
결과
startService, stopService 버튼을 한 번 씩 눌러보시면 위와 같은 로그가 뜨는데 onServiceConnected(), onServiceDisconnected() 가 안뜨는것을 알 수 있어요
이는 MainActivity와 CountService 간의 통신 매체가 없기 때문이에요
연결을 맺기는 했는데 어떤 명령을 전달할지는 모르고, 이를 전달하려면 바인더 객체가 필요합니다.
바인더를 생성하려면 AIDL(Android Interface Definition Language)을 작성해야 합니다.
AIDL 만들기
AIDL 디렉토리 생성
AIDL 파일 생성
< ICountService.aidl >
자바처럼 보이지만 자바는 아닙니다.
// ICountService.aidl package kr.co.sample; // Declare any non-default types here with import statements interface ICountService { int getCountNumber(); void startCountDown(); void stopCountDown(); }
이 상태에서 CountService.java 를 수정하실 때 만약 ICountService 클래스가 없다면 Run을 한 번 눌러주세요 그럼 안드로이드가 알아서 클래스를 만들어줄거에요
< CountService.java >
package kr.co.sample; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class CountService extends Service { private int count; private Thread thread; ICountService.Stub binder = new ICountService.Stub() { @Override public int getCountNumber() throws RemoteException { // 현재 카운트 값 리턴 return count; } @Override public void startCountDown() throws RemoteException { if (thread == null) { // 카운트 다운 타이머 시작 thread = new Thread(new Runnable() { @Override public void run() { while (true) { count++; Log.d("CountService", String.valueOf(count)); try { Thread.sleep(1000); } catch (InterruptedException e) { break; } } } }); thread.start(); } } @Override public void stopCountDown() throws RemoteException { // 카운트 다운 타이머 종료 if (thread != null) { thread.interrupt(); thread = null; } } }; public CountService() { } @Override public IBinder onBind(Intent intent) { Log.d("CountService", "onBind"); return binder; } @Override public boolean onUnbind(Intent intent) { Log.d("CountService", "onUnbind"); if (thread != null) { thread.interrupt(); thread = null; count = 0; } return super.onUnbind(intent); } @Override public void onCreate() { super.onCreate(); Log.d("CountService", "onCreate"); } @Override public void onDestroy() { super.onDestroy(); Log.d("CountService", "onDestroy"); } }
< layout/activity_main.xml >
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/start_btn" android:text="startCount" android:layout_width="match_parent" android:layout_height="100dp"/> <Button android:id="@+id/end_btn" android:text="stopCount" android:layout_width="match_parent" android:layout_height="100dp"/> <Button android:id="@+id/get_btn" android:text="getCount" android:layout_width="match_parent" android:layout_height="100dp"/> <TextView android:id="@+id/count_text" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
<MainActivity.java>
package kr.co.sample; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { Button startBtn, endBtn, getBtn; TextView countText; ICountService countBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 바운드 서비스가 연결되었음을 확인할 수 있는 메소드 Log.d("CountService", "onServiceConnected"); countBinder = (ICountService) service; } @Override public void onServiceDisconnected(ComponentName name) { // unbindService 가 아닌 의도치 않은 상황으로 연결이 끊겼을 때 호출 Log.d("CountService", "onServiceDisconnected"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startBtn = findViewById(R.id.start_btn); endBtn = findViewById(R.id.end_btn); getBtn = findViewById(R.id.get_btn); countText = findViewById(R.id.count_text); Intent intent = new Intent(MainActivity.this, CountService.class); bindService(intent, connection, BIND_AUTO_CREATE); startBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (countBinder != null) { try { countBinder.startCountDown(); } catch (RemoteException e) { e.printStackTrace(); } } } }); endBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (countBinder != null) { try { countBinder.stopCountDown(); } catch (RemoteException e) { e.printStackTrace(); } } } }); getBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (countBinder != null) { try { countText.setText(String.valueOf(countBinder.getCountNumber())); } catch (RemoteException e) { e.printStackTrace(); } } } }); } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); } }
결과
잘 실행되는걸 볼 수 있습니다.
'안드로이드' 카테고리의 다른 글
안드로이드 서비스(2) (0) 2020.05.21 안드로이드 서비스 (0) 2020.05.21 안드로이드 HandlerThread (0) 2020.05.13 안드로이드 CountDownTimer (0) 2020.05.13 Android AsyncTask (0) 2020.05.10