서비스에 연결하는 방법에 따라 Local Procedure Call(LPC - 일명 lightweight Procedure Call) 으로 구현하는 방법과 Remote Procedure Call(RPC)로 구현하는 방법 으로 나누어 진다.
- RPC(Remote Procedure Call)
내부 바인드 서비스는 액티비티와 서비스 컴포넌트들이 동일한 프로세스내에세 작동하는 경우를 말한다. 서비스와 액티비티는 서로의 메서드와 필드를 컴파일시점에 알고 있고 또한 동일한 프로세스에서 작동하므로 영역 침해등의 문제가 발생하지 않는다. 외부 바인드서비스는 서비스나 서비스를 호출한 애플리케이션 컴포넌트(보통 액티비티)들이 서로 별개의 프로세스에서 작동하는 경우를 말한다. 이 경우 자신이 만든 컴포넌트라 하더라도 액티비티에서 서비스의 메서드를 호출하고 자 한다면, 자신 프로젝트 내부 자바 프로그래도 아니고 또한 안드로이드의 android.jar 파일도 아니므로 해당 메서드를 인지하지 못한는 문제가 가 발생한다.
■ 단방향 메시지를 이용한 바인드 서비스
메신저는 외부 바인드서비스와 연결하여 프로세스간에 메시지를 전송할 수 있도록 만든 클래스이다. 메신저의 생성자는 아래와 같이 두 종류가 있다.
- public Messenager(Handler target)
: 내부 핸들러와 연결되는 메신저이다. 메시지를 통해 작업 요청을 받기 위해서 서비스에서 내부 핸들러 객체를 사용하여 메신저 인스턴스를 생성한다. 메시지를 전송하는 Messenger.send(Message) 메서드의 기능은 핸들러의 Handler.sendMessage(Message) 메서드와 동일 하다.
- public Messenger(IBinder target)
: IBinder 객체로 전달된 핸들러를 사용하여 액티비티에서 메신저를 생성한다. 이때 새로 생성된 메신저는 서비스에 소속된 매신저의 복제이다.
- public IBinder getBinder()
: IBinder 객체를 생성하여 반환한다.
- public void send(Message message)
: 메시지 핸들러에게 전달한다. 만약 문제가 발생한다면 RemoteException 예외가 발생한다.
// AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.onewaymessengerservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="10" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.onewaymessengerservice.MsgServiceActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.onewaymessengerservice.MessengerService" android:process=":remote" />
</application>
</manifest>
// MsgServiceActivity.java
package com.example.onewaymessengerservice;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MsgServiceActivity extends Activity {
Messenger mServiceMessenger = null;
boolean mIsBound;
TextView mCallbackText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.bind);
button.setOnClickListener(mBindListener);
button = (Button) findViewById(R.id.unbind);
button.setOnClickListener(mUnBindListener);
mCallbackText = (TextView) findViewById(R.id.callback);
mCallbackText.setText("Not attached.");
}
private final OnClickListener mBindListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
doBindService();
}
};
private final OnClickListener mUnBindListener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
doUnbindService();
}
};
void doBindService() {
mIsBound = bindService(new Intent(MsgServiceActivity.this,
MessengerService.class), mConnection, Context.BIND_AUTO_CREATE);
}
void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
mCallbackText.setText("Unbinding.");
}
}
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName className) {
// TODO Auto-generated method stub
mServiceMessenger = null;
mCallbackText.setText("Disconnected.");
Toast.makeText(MsgServiceActivity.this,
R.string.remote_service_disconnected, Toast.LENGTH_SHORT)
.show();
}
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// TODO Auto-generated method stub
mServiceMessenger = new Messenger(service);
mCallbackText.setText("Attached.");
try {
Message msg = Message.obtain(null,
MessengerService.MSG_REGISTER_CLIENT);
mServiceMessenger.send(msg);
} catch (RemoteException e) {
// TODO: handle exception
}
Toast.makeText(MsgServiceActivity.this,
R.string.remote_service_connected, Toast.LENGTH_SHORT)
.show();
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.msg, menu);
return true;
}
}
// MessengerService.java
package com.example.onewaymessengerservice;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast;
public class MessengerService extends Service {
NotificationManager mNM;
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGSTER_CLIENT = 2;
static final int MSG_SET_VALUE = 3;
class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
String mText;
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mText = "MSG_REGISTER_CLIENT";
break;
case MSG_UNREGSTER_CLIENT:
mText = "MSG_UNREGSTER_CLIENT";
break;
default:
super.handleMessage(msg);
mText = "Default";
break;
}
Toast.makeText(MessengerService.this, mText, Toast.LENGTH_SHORT)
.show();
}
}
final Messenger mServiceMessenger = new Messenger(new ServiceHandler());
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
showNotification();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
mNM.cancel(R.string.remote_service_stopped);
Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mServiceMessenger.getBinder();
}
private void showNotification() {
CharSequence text = getText(R.string.remote_service_started);
Notification notification = new Notification(R.drawable.ic_launcher,
text, System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MsgServiceActivity.class), 0);
notification.setLatestEventInfo(this,
getText(R.string.remote_service_label), text, contentIntent);
mNM.notify(R.string.remote_service_started, notification);
}
}
[Android]내부 바인드 서비스 (0) | 2013.09.21 |
---|---|
[Android]서비스 - 01 (0) | 2013.09.20 |
[Android]단일 스레드 모델 (0) | 2013.09.19 |
[Android]안드로이드 스레드 구현시 주의 사항 (0) | 2013.09.19 |
[Android]핸들러 클래스 (0) | 2013.09.19 |
댓글 영역