클라이언트에게 자신의 메소드를 제공하려면 자신의 메소드 목록을 인터페이스로 정의해야 한다.
원격에서 호출되는 메소드는 응용 프로그램의 경계를 넘어서 인수를 전달해야 하는 어려움이 있다.
각 응용 프로그램이 사용하는 메모리가 완전히 분리되어 있어 통산의 방법으로는 인수를 넘기기 어렵다.
소속된 패키지가 다름은 물론이고 응용 프로그램 수준보다 더 아래쪽의 저수준일 수도 있으며 심지어 자바가 아닌
다른 언어일 수도 있다. 따라서 전달할 수 있는 인수의 종류가 자바 기본 타입과 Parcelable 정도로 제한되며 그외에도
몇 가지 제약이 존재한다. 안드로이드는 원격 인터페이스를 정의하는 AIDL이라는 별도의 언어를 제공하며
AIDL 컴파일러가 인터페이스 정의를 구현하는 스텁까지 생성해준다.
AIDL소스를 작성하여 프로젝트에 포함시켜 놓으면 AIDL 컴파일러가 이 인터페이스를 구현하는 자바 파일을 생성하여 gen 폴더에 배치한다.
다음 소스는 ICalc 인터페이스에 최소 공배수를 조사하는 메소드와 소수 여부를 조사하는 메소드의 원형을 선언한다.
ICalc.aidl
package com.example.ch30_calcservice;
//여기서 인터페이스를 선언함
interface ICalc{
int getLCM(in int a, in int b);
boolean isPrime(in int n);
}
클라이언트에서 서비스에 연결하거나 해제할 때는 다음 메소드를 호출하여 바인딩 한다. 바인딩이란 클라이언트와 서비스를 연결하는
동작이다.
boolean bindService(Intent service, ServiceConnection conn, int flags)
void unbindService(ServiceConnection conn)
첫 번째 인수 service는 사용하고자 하는 서비스를 지정하는데 같은 패키지에 있으면 클래스명으로 지정하고 외부에 있다면 서비스의
액션명을 사용해야 한다. 두 번째 인수 conn은 서비스가 연결, 해제될 때의 동작을 정의하는 연결 객체이다. 서비스를 사용하는 클라이언트는
ServiceConnection 인터페이스를 구현해야 하는데 클라이언트와 서비스가 연결되거나 해제될 때 호출되는 메소드를 정의한다.
서비스가 연결될 때 onServiceConnected 메소드가 호출되며 이때 인수로 전달되는 binder 객체를 스텁의 asInterface메소드로 전달하면
원격지 서비스 객체를 구할 수 있다.
마지막 인수 flag는 서비스 바인딩 방식을 지정하는데 통상 BIND_AUTO_CREATE로 지정하여 서비스를 자동으로 기동시킨다.
바인딩이 완료되면 mCalc멤버를 통해 서비스의 메소드를 호출할 수 있다. 그리고 원격지 호출은 예외 발생 가능성이 높으므로 항상
예외 블록을 구성해야한다.
그리고 다음과 같이 예제를 구성한다.
CalcService.java
package com.example.ch30_calcservice;
import android.app.Activity;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
public class CalcService extends Service {
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
//ICalc 인터페이스안에 Stub이라는 추상 클래스가 선언되있음
ICalc.Stub mBinder = new ICalc.Stub() {
//인터페이스를 구현해주면 됨.
@Override
public boolean isPrime(int n) throws RemoteException {
// TODO Auto-generated method stub
int i;//소수여부 판별
for(i = 2; i < n; i++){
if(n % i == 0 ) return false;
}
return true;
}
@Override
public int getLCM(int a, int b) throws RemoteException {
// TODO Auto-generated method stub
int i;//최소공배수 구하기
for(i = 1; ; i++){
if(i % a == 0 && i % b == 0) break;
}
return i;
}
};
}
calcclient.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/btnLCM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="mOnClick"
android:text="최소 공배수 구하기"
/>
<Button
android:id="@+id/btnPrime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="mOnClick"
android:text="소수 조사"
/>
<TextView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="계산 결과"
/>
</LinearLayout>
CalcClient.java
package com.example.ch30_calcservice;
import android.app.Activity;
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.view.View;
import android.widget.TextView;
public class CalcClient extends Activity{
ICalc mCalc;
TextView mResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.calcclient);
mResult = (TextView)findViewById(R.id.result);
}
public void mOnClick(View v){
switch(v.getId()){
case R.id.btnLCM://버튼별 기능 구현
int LCM = 0;
try{
LCM = mCalc.getLCM(6, 8);
}catch(RemoteException e){
e.printStackTrace();
}
mResult.setText("6과 8의 최소 공배수 = " + LCM);
break;
case R.id.btnPrime:
boolean prime = false;
try{
prime = mCalc.isPrime(7);
}catch(RemoteException e){
e.printStackTrace();
}
mResult.setText("7의 소수 여부 = " + prime);
break;
}
}
//액티비티가 사용자화 상호작용하기 직전에 호출
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Intent intent = new Intent(this, CalcService.class);
bindService(intent, srvConn, BIND_AUTO_CREATE);//서비스 연결
}
//다른 액티비티가 활성화 되있을 때 호출
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
unbindService(srvConn);//서비스 해지
}
//서비스 연결을 위한 인터페이스 구현
ServiceConnection srvConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mCalc = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mCalc = ICalc.Stub.asInterface(service);//원격지 서비스 객체를 구함.
}
};
}
실행 화면
최소 공배수를 서비스로 구하기
소수를 서비스로 구하기
'프로그래밍 > 안드로이드' 카테고리의 다른 글
안드로이드 - Node.js서버로 POST방식으로 데이터를 보내기 (1) | 2017.09.16 |
---|---|
안드로이드 - Node.js서버로부터 GET방식으로 데이터를 받기 (2) | 2017.09.16 |
안드로이드 - AsyncTask 파라미터 정리 (0) | 2017.09.15 |
안드로이드 - AsyncTask에서 String... 의미 (0) | 2017.09.15 |
안드로이드 - 데몬 백그라운드 서비스 (0) | 2015.12.07 |
안드로이드 - 동전 이미지를 드래그 해보자 (0) | 2015.12.05 |
안드로이드 - 드래그 섀도우 이미지 변경하기 (0) | 2015.12.05 |
안드로이드 - startDrag메소드를 이용한 드래그 & 드롭 구현하기 (0) | 2015.12.03 |