프로그래밍/안드로이드

안드로이드 - 원격 인터페이스 서비스 사용하기

가카리 2015. 12. 8. 21:30
반응형

 

클라이언트에게 자신의 메소드를 제공하려면 자신의 메소드 목록을 인터페이스로 정의해야 한다.

 

원격에서 호출되는 메소드는 응용 프로그램의 경계를 넘어서 인수를 전달해야 하는 어려움이 있다.

 

각 응용 프로그램이 사용하는 메모리가 완전히 분리되어 있어 통산의 방법으로는 인수를 넘기기 어렵다.

 

소속된 패키지가 다름은 물론이고 응용 프로그램 수준보다 더 아래쪽의 저수준일 수도 있으며 심지어 자바가 아닌

 

다른 언어일 수도 있다. 따라서 전달할 수 있는 인수의 종류가 자바 기본 타입과 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);//원격지 서비스 객체를 구함.

        }

    };

}

 

실행 화면

 

최소 공배수를 서비스로 구하기

소수를 서비스로 구하기