원격 호출은 C#이나 자바에서도 찾아 볼 수 있다. 이는 클라이언트를 위한 기능 제공으로 자신의 기능을 메서드로 노출시켜 호출함으로 서비스를 이용한다. 다른 OS들의 COM에 대한 개념이라 생각하면 될 듯하다.

이 역시 Service 클래스를 상속받아 사용한다.

데몬에서는 onStartCommand를 이용하여 실행 했다면 여기에서는 onBind를 이용하여 사용하며, onCreate에서는 최소한의 초기화만 하면 되고 나머지는 onBind를 구현하여 처리를 한다.

이를 코딩 할 경우 aidl 확장자 안에 인터페이스를 구현하여 컴파일러가 자바 파일을 생성한다. 이 위치는 gen폴더 아래에 보면 알 수 있을 것이다.

다음은 인터페이스를 확장하여 작성한 코드이다.

public class CalcService extends Service {
 public void onCreate() {
  super.onCreate();
 }
 
 public void onDestroy() {
  super.onDestroy();
 }

 public IBinder onBind(Intent intent) {
  return mBinder;
 }
 
 ICalc.Stub mBinder = new ICalc.Stub() {
  public int getLCM(int a, int b) throws RemoteException {
   int i;
   for (i = 1; ;i++) {
    if (i % a == 0 && i % b == 0) break;
   }
   return i;
  }

  public boolean isPrime(int n) throws RemoteException {
   int i;
   for (i = 2;i < n; i++) {
    if (n % i == 0) return false;
   }
   return true;
  }
 };
}

여기에서 보면 ICalc.Stub 타입의 객체를 생성하여 그 안에 해당하는 내용을 작성한 것을 볼 수가 있다.

다음은 이를 제어하는 코드이다.

public class CalcClient extends Activity {
 ICalc mCalc;
 TextView mResult;
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.service_calcclient);
  
  mResult = (TextView)findViewById(R.id.result);
  
  Button btnLCM = (Button)findViewById(R.id.btnLCM);
  btnLCM.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    int LCM = 0;
    try {
     LCM = mCalc.getLCM(6, 8);
    } catch (RemoteException e) {
     e.printStackTrace();
    }
    mResult.setText("6과 8의 최소 공배수 = " + LCM);
   }
  });

  Button btnPrime = (Button)findViewById(R.id.btnPrime);
  btnPrime.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    boolean prime = false;
    try {
     prime = mCalc.isPrime(7);
    } catch (RemoteException e) {
     e.printStackTrace();
    }
    mResult.setText("7의 소수 여부 = " + prime);
   }
  });
 }
 
 public void onResume() {
  super.onResume();
  Intent intent = new Intent(this, CalcService.class);
  bindService(intent, srvConn, BIND_AUTO_CREATE);
 } 

 public void onPause() {
  super.onPause();       
  unbindService(srvConn);
 }

 ServiceConnection srvConn = new ServiceConnection() {
  public void onServiceConnected(ComponentName className, IBinder binder) {
   mCalc = ICalc.Stub.asInterface(binder);
  }

  public void onServiceDisconnected(ComponentName className) {
   mCalc = null;
  }
 };
}

위에서 보면 ServiceConnection 객체를 생성하고 서비스의 연결과 종료 됨을 구현 한 것을 볼 수가 있다.

bindService의 인자 값인 BIND_AUTO_CREATE 은 자동으로 서비스를 동작 시키는 것이다.

또한 데몬의 예제 처럼 매니페스트 상에 이름을 지정 한 경우,

onResume의 내용은 다음과 같고,

super.onResume();
Intent intent = new Intent("서비스 액션 이름");
bindService(intnet,srvConn,BIND_AUTO_CREATE);

ServiceConnection의 onServiceConnected 구현의 내용은 다음과같다.

mCalc = 패키지명.ICalc.Stub.asInterface(binder);