서비스 상세 정보 (4): 귀속 서비스 및 통신
11605 단어 serivceBindServic
귀속 서비스는 클라이언트-서버 인터페이스의 서버입니다.바인딩 서비스는 구성 요소(예를 들어 Activity)를 서비스에 바인딩하고 요청을 보내며 응답을 수신하고 심지어 프로세스 간 통신(IPC)을 실행할 수 있습니다.귀속 서비스는 일반적으로 다른 응용 프로그램 구성 요소를 위한 서비스에서만 활성화되며 백그라운드에서 무제한으로 실행되지 않습니다.
귀속 서비스는 서비스 클래스의 실현으로 다른 응용 프로그램과 귀속과 상호작용을 할 수 있다.서비스 연결을 제공하려면 onBind () 리셋 방법을 실행해야 합니다.이 방법이 되돌아오는 IBinder 대상은 클라이언트가 서비스와 상호작용하는 프로그래밍 인터페이스를 정의합니다.
클라이언트는 bindService () 를 호출하여 서비스에 연결할 수 있습니다.호출할 때, 서비스 연결의 실현을 제공해야 하며, 후자는 서비스와의 연결을 감시할 것이다.bindService () 방법은 즉시 값을 반환하지 않지만, Android 시스템이 클라이언트와 서비스 간의 연결을 만들 때, 서비스 연결의 onService Connected () 를 호출하여 클라이언트에게 서비스와 통신하는 IBinder를 전달합니다.
마지막 클라이언트가 서비스와 연결을 취소할 때, 시스템은 서비스를 삭제합니다. (start 서비스 () 가 이 서비스를 시작하지 않는 한)
귀속 서비스를 실현할 때 가장 중요한 부분은 onBind () 리셋 방법이 되돌아오는 인터페이스를 정의하는 것입니다.몇 가지 다른 방법으로 서비스의 IBinder 인터페이스를 정의할 수 있습니다. 다음은 이러한 방법에 대해 하나하나 설명합니다.
귀속 서비스 만들기
귀속된 서비스를 만들 때, 클라이언트가 서비스와 상호작용하는 프로그래밍 인터페이스를 제공하기 위해 IBinder를 제공해야 합니다.세 가지 방법으로 인터페이스를 정의할 수 있습니다.
확장 Binder 클래스
서비스가 사용자 전용 응용 프로그램을 제공하고 클라이언트와 같은 프로세스에서 실행된다면, Binder 클래스를 확장하고 onBind () 에서 인터페이스를 만들어야 합니다.클라이언트가 Binder를 받으면 Binder를 사용하여 중/심지어 서비스에서 사용할 수 있는 공통 방법을 직접 액세스할 수 있습니다.
만약 서비스가 당신의 자체 응용 프로그램의 백그라운드 작업 라인일 뿐이라면, 우선적으로 이런 방법을 채택하십시오.이런 방식으로 인터페이스를 만들지 않는 유일한 이유는 서비스가 다른 응용 프로그램이나 다른 프로세스에 의해 점용되기 때문입니다.
Messenger 사용
인터페이스를 서로 다른 프로세스에서 작업시키려면 Messenger를 사용하여 서비스에 인터페이스를 만들 수 있습니다.서비스는 이런 방식으로 서로 다른 유형의 메시지 대상에 대응하는 Handler를 정의할 수 있다.이 Handler는 Messenger의 기초로 후자는 클라이언트와 IBinder를 공유하여 클라이언트가 Message 대상을 이용하여 서비스에 명령을 보낼 수 있도록 한다.이 밖에 클라이언트는 서비스가 메시지를 전송할 수 있도록 자체 Messenger를 정의할 수 있다.
이것은 프로세스 간 통신(IPC)을 실행하는 가장 간단한 방법입니다. Messenger는 단일 스레드에서 모든 요청을 포함하는 대기열을 만들기 때문에 서비스에 대한 스레드 보안 설계를 할 필요가 없습니다.
AIDL 사용
AIDL(Android 인터페이스 정의 언어)은 객체를 원어로 분해하는 모든 작업을 수행하며, 운영 체제는 이러한 원어를 식별하여 각 프로세스에 그룹화하여 IPC를 실행할 수 있습니다.이전에 Messenger를 채택한 방법은 사실상 AIDL을 그 밑바닥 구조로 삼았다.위에서 말한 바와 같이, Messenger는 한 번에 요청을 받을 수 있도록 모든 클라이언트의 요청을 포함하는 대기열을 만들 것입니다.단, 서비스를 여러 요청을 동시에 처리하려면 AIDL을 직접 사용할 수 있습니다.이 경우, 당신의 서비스는 반드시 다중 스레드 처리 능력을 갖추고 스레드 안전식 설계를 채택해야 합니다.
AIDL을 직접 사용하려면 프로그래밍 인터페이스를 정의해야 합니다.aidl 파일.Android SDK 도구는 이 파일을 이용하여 인터페이스를 실현하고 IPC를 처리하는 추상적인 클래스를 생성합니다. 나중에 서비스 내에서 확장할 수 있습니다.
참고: 대부분의 응용 프로그램은 AIDL을 사용하여 바인딩 서비스를 만들지 않습니다. 다중 스레드 처리 능력이 요구되고 복잡성이 증가할 수 있기 때문입니다.따라서 AIDL은 대부분의 응용 프로그램에 적합하지 않으며 본고는 귀하의 서비스에 어떻게 사용하는지 설명하지 않습니다.
확장 Binder 클래스
만약에 서비스가 로컬 응용 프로그램에서만 사용할 수 있고 크로스 프로세스 작업이 필요하지 않으면 자체 Binder 클래스를 실현하여 클라이언트가 이 클래스를 통해 서비스의 공공 방법에 직접 접근할 수 있습니다.
주: 이 방법은 클라이언트와 서비스가 같은 응용 프로그램과 프로세스 내에서 가장 흔히 볼 수 있는 상황에서만 유효합니다.예를 들어 Activity를 백그라운드에서 음악을 재생하는 자체 서비스의 음악 응용 프로그램에 연결해야 하는데 이 방법은 매우 효과적이다.
다음은 구체적인 설정 방법입니다.
주: 서비스와 클라이언트가 같은 응용 프로그램에 있어야 하는 이유는 클라이언트가 되돌아오는 대상을 변환하고 API를 정확하게 호출하기 위해서입니다.이 방법은 크로스 프로세스 그룹을 실행하지 않기 때문에 서비스와 클라이언트는 같은 프로세스 내에 있어야 합니다.
예를 들어, 다음 서비스는 클라이언트가 Binder를 통해 서비스에 액세스하는 방법을 구현합니다.
public class LocalService extends Service {
private final IBinder mBinder = new LocalBinder();
private final Random mGenerator = new Random();
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
LocalBinder는 클라이언트에게 getService () 방법을 제공하여 Local Service의 현재 사례를 검색합니다.이렇게 하면 클라이언트는 서비스의 공공 방법을 호출할 수 있다.예를 들어, 클라이언트는 서비스의 getRandomNumber()를 호출할 수 있습니다.
버튼을 클릭하면 다음 Activity가 Local Service에 바인딩되고 getRandomNumber()가 호출됩니다.
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
public void onButtonClick(View v) {
if (mBound) {
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
상기 예는 클라이언트가 서비스 연결의 실현과 온 서비스 연결 () 리셋을 사용하여 서비스에 연결하는 방법을 설명합니다.다음 글은 서비스에 귀속되는 과정을 더욱 상세하게 소개하였다.
참고: 위의 예에서는 서비스와의 연결을 명시적으로 취소하지 않았지만, 모든 클라이언트는 적절한 시간 (예: Activity가 중단되었을 때) 에 연결을 취소해야 합니다.
서비스에 바인딩
응용 구성 요소 (클라이언트) 는 bindService () 를 호출하여 서비스에 연결할 수 있습니다.Android 시스템은 서비스와 상호작용하는 IBinder를 되돌려주는 onBind () 방법을 호출합니다.
귀속은 비동기적이다.bindService () 는 즉시 반환되며 IBinder는 절대 클라이언트를 반환하지 않습니다.IBinder를 받으려면 클라이언트가 서비스 연결 실례를 만들고 bind 서비스 () 에 전달해야 합니다.ServiceConnection은 IBinder를 호출하여 전달하는 리셋 방법을 포함합니다.
참고: Activity, 서비스 및 콘텐츠 제공자만 서비스에 연결할 수 있습니다. 브로드캐스트 수신기에서 서비스에 연결할 수 없습니다.
따라서 클라이언트에서 서비스에 연결하려면 다음을 수행해야 합니다.
예를 들어 다음 코드 세그먼트는 확장 Binder 클래스를 통해 클라이언트를 위에서 만든 서비스와 연결시키기 때문에 되돌아오는 IBinder를 Local Service 클래스로 변환하고 Local Service 실례를 요청합니다.
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "onServiceDisconnected");
mBound = false;
}
};
클라이언트는 이 ServiceConnection을 bindService () 로 전송하여 서비스에 연결할 수 있습니다.예:
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
바인딩 서비스의 라이프 사이클 관리
서비스와 모든 클라이언트 간의 연결이 모두 취소되면 Android 시스템은 서비스를 삭제합니다. (onStartCommand () 를 사용하지 않으면 이 서비스가 시작됩니다.따라서 서비스가 순수한 바인딩 서비스라면 라이프 사이클을 관리할 필요가 없습니다. Android 시스템은 바인딩 여부에 따라 클라이언트가 대신 관리합니다.
단, onStartCommand () 리셋 방법을 선택하면 시스템이 서비스를 시작한 것으로 간주하기 때문에 서비스를 현저하게 중단해야 합니다.이 경우, 서비스는 stopSelf () 를 통해 자동으로 멈추거나 다른 구성 요소가 stop 서비스 () 를 호출할 때까지 실행됩니다.
또한 서비스가 시작되고 귀속을 수락한 경우, 시스템이 onUnbind () 방법을 호출할 때, 클라이언트가 다음에 서비스에 귀속될 때 onRebind () 호출을 수락하지 않고 () 호출을 받으려면true로 돌아갈 수 있습니다.onRebind()는 빈 값을 반환하지만 클라이언트는 onServiceConnected() 콜백에서 IBinder를 수신합니다.다음 그림은 이러한 생명주기의 논리를 설명한다.