안드로이드 개발 서비스 바인딩 (Service Bind) 예제 구현하는 방법 |
환경: Android Studio |
안드로이드에는 크게 4개의 컴포넌트로 나눕니다. 그 중 하나가 서비스(Service) 입니다. 서비스는 안드로이드 OS 에서 백그라운드로 돌아가는 객체 입니다. 실행과 종료는 Activity 에서 하겠죠. 주로 주기적인 관찰과 피드백이 필요한 기능에 사용합니다. 이런 Service 에는 두 종류가 있습니다. 연결을 유지해서 데이터를 주고 받을 수 있는 Bound Service 와 시작과 종료에만 관여하는 UnBound Service 입니다. Service 컴퍼넌트와 데이터를 주고 받으며 관리하고 싶다면 Bound Service 로 만들어야겠죠.
▼ 그림처럼 Bound/UnBound 는 시작 함수부터 틀립니다. 그리고 연결을 유지하고 데이터를 전송 받기 위한 ServiceConnection() 객체와 IBinder 인터페이스 객체가 필요합니다. ServiceConnection() 는 Service를 호출하는 Activity 에 만들어야 하고, IBinder 는 Service 에서 생성한 후 리턴해야 합니다. Bound Service 는 여러 클라이언트에서 동시에 접속이 가능하며, 연결이 전부 끊기면 자동으로 소멸합니다.
▼ 먼저 Service 를 만들어 보겠습니다. 이전 unbind 서비스 클래스와 달라진 것이 있다면 Binder 클래스와 데이터를 리턴하는 getBroastData() 함수 입니다. Binder 는 Activity 와 연결을 위한 클래스 이며, getBroastData() 는 데이터를 전달하기 위한 임의로 만든 함수 입니다. 그리고 위의 생명주기 그림에서 보았듯이 시작은 onBind() 함수에서 시작합니다. 반드시 IBinder 인터페이스 클래스를 넘겨야 합니다.
public class PhoneCallService extends Service { IBinder mBinder = new PhoneCallBinder(); class PhoneCallBinder extends Binder { PhoneCallService getService() { // 서비스 객체를 리턴 return PhoneCallService.this; } } public String getBroastData(){ return "PhoneCallService data"; } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "서비스 onBind 에서 시작"); return mBinder; } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "서비스 시작"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.d(TAG, "서비스 종료"); super.onDestroy(); } }
▼ Activity 에는 서비스 실행과 종료, 데이터를 가져오기 위한 버튼 3개를 만들었습니다. 서비스를 실행하는 bindService(), 종료할 때 unbindService() 함수를 호출합니다. 마지막 3번째 버튼에서는 Service 에 만들어 놓은 getBroastData() 함수를 호출해서 String 데이터를 가져와 화면에 표시합니다. Bound Service 함수를 호출할 때 ServiceConnection 객체를 넘겨야 합니다. UnBound Service 에서는 없던 클래스 입니다.
public class PhoneCallActivity extends AppCompatActivity { PhoneCallService ms; // 서비스 boolean isService = false; // 서비스 실행 확인 TextView mTvCallData; ServiceConnection conn = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { // 서비스와 연결되었을 때 호출되는 메서드 PhoneCallService.PhoneCallBinder mb = (PhoneCallService.PhoneCallBinder) service; ms = mb.getService(); isService = true; // 실행 여부를 판단 } public void onServiceDisconnected(ComponentName name) { // 서비스와 연결이 끊기거나 종료되었을 때 isService = false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_phone_call); Button btnStart = (Button) findViewById(R.id.btn_service_start); Button btnEnd = (Button) findViewById(R.id.btn_service_end); Button btnCallData = (Button) findViewById(R.id.btn_service_data); mTvCallData = (TextView) findViewById(R.id.tv_service_data); btnStart.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // 서비스 시작하기 Intent intent = new Intent( getApplicationContext(),// Activiey Context PhoneCallService.class); // 이동할 서비스 객체 bindService(intent, conn, Context.BIND_AUTO_CREATE); } }); btnEnd.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // 서비스 종료하기 unbindService(conn); } }); btnCallData.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (!isService) { Toast.makeText(getApplicationContext(), "서비스가 실행 중이 아닙니다. ", Toast.LENGTH_LONG).show(); return; } String data= ms.getBroastData();//서비스에서 가져온 데이터 mTvCallData.setText(data); } }); } }
▼ activity_phone_call.xml : 화면을 구성하는 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:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_service_start" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="서비스 시작" /> <Button android:id="@+id/btn_service_end" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="서비스 종료" /> <Button android:id="@+id/btn_service_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="데이터 가져오기" /> <TextView android:id="@+id/tv_service_data" android:layout_width="match_parent" android:layout_height="40dp" android:layout_margin="5dp" android:gravity="center" android:background="#d2bebe" android:textColor="#FFFFFF"/> </LinearLayout>
▼ 다음은 AndroidManifest.xml 에 Service 를 등록해야 합니다. 위치는 <application> 태그 안입니다.
<application android:name=".CustomApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".PhoneCallActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".PhoneCallService" /> </application>
▼ Activity 를 실행해서 서비스 시작과 종료 버튼을 클릭해 보세요. 서비스 내부에 추가한 콘솔 출력 함수인 Log.d() 를 통해서 이상 없이 수행되고 있음을 알 수 있습니다. 그리고 서비스를 실행한 상태에서 “데이터 가져오기” 버튼을 클릭하면 바로 아래의 TextView 위젯에 Service 에서 가져온 데이터를 표시합니다.
'안드로이드 개발' 카테고리의 다른 글
안드로이드 개발 SensorManager, SensorEventListener 이용해서 나침판 구현하기 (0) | 2018.02.12 |
---|---|
안드로이드 개발 레이아웃 인플레이션(LayoutInflater)으로 추가한 화면 삭제하는 방법 (0) | 2018.01.28 |
안드로이드(Android) SensorManager 와 SensorEventListener 이용해서 x, y, z 축 감지하는 방법 (0) | 2018.01.26 |
안드로이드(Android) 다양한 애니메이션 이동(translate) 을 구현하는 여러가지 방법 (0) | 2018.01.19 |
안드로이드 개발 레이아웃 인플레이션(LayoutInflater)으로 화면 구성하는 방법 (0) | 2018.01.04 |
안드로이드 개발 setId() 에러 Expected resource of type id 해결하는 방법 (0) | 2018.01.02 |
안드로이드 개발 Activity 호출하고 결과값을 받는 onActivityForResult 사용하는 방법 (0) | 2017.12.30 |
안드로이드 개발 서비스(Service) 컴포넌트 예제 구현하는 방법 (0) | 2017.12.27 |