|
안드로이드 개발 서비스 바인딩 (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 |

