그냥 리시버 등록 코드 broadcast receiver 코드 실행 결과는 아래와 같이 버튼을 누르면 전통적인 방법인 아래 코드는 간단히 엑티비티에서 서비스의 특정 callback을 호출하고 해당 서비스내의 콜백 함수는 다시 엑티비티의 callback함수를 호출하는식으로 작성 되었다. main acitivity service 실행결과 Activity 쪽 코드 서비스 쪽 코드 아래의 실행결과는 network 싱크를 가정해서 service에서 5초 thread sleep한 후에 다시 그 결과를 bundle에 넣어서 반환해서 activity에서 그 결과를 표시하는 예제의 결과이다. 다른 예제 코드: ProAndroidDev: Using ResultReceiver to communicate with IntentService AIDL을 이용한 Service <-> Activity간 Callback 통신Activity와 Service간의 통신
Local Broadcast Manager를 이용한 방법 (BR)
broadcast receiver
를 등록해서 사용하는 방법은 다른앱에서도 해당 방송을 들을 수 있기 때문에 private data leak
문제가 생긴다.API 22 (android 5.1)
부터 지원하는 Local Broadcast Manager
방법으로 구현한다.Main Activity
@Override
protected void onResume() {
...
// action 이름이 "custom-event-name"으로 정의된 intent를 수신하게 된다.
// observer의 이름은 mMessageReceiver이다.
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter("custom-event-name"));
}
@Override
protected void onPause() {
...
LocalBroadcastManager.getInstance(this).unregisterReceiver(
mMessageReceiver);
}
// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// Get extra data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
Service 코드
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sendMessage();
return super.onStartCommand(intent, flags, startId);
}
private void sendMessage(){
Log.d("messageService", "Broadcasting message");
Intent intent = new Intent("custom-event-name");
intent.putExtra("message", "This is my first message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
실행 결과
service
가 실행되고 해당 service
에서 local broadcast manager
를 통해서sendBroadcast
를 하면 activity
에 등록된 receiver
에서 이것을 수신해서 처리하는 방식으로 동작한다.04-06 16:16:34.110 18075-18075/com.example.user.examactivityservicecommnunication D/messageService: Broadcasting message
04-06 16:16:34.110 18075-18075/com.example.user.examactivityservicecommnunication D/receiver: Got message: This is my first message!
Local Bind Service를 이용한 양방향 통신
Bind Service
를 이용한 방법을 다룬다.Started Service
까지도 같이 구현하면 Music Player
에서 종종 쓰이는 패턴이 된다.
왜냐하면 백그라운드에서 음악이 재생되고 해당 엑티비티가 다시 살아나면 현재 재생되고 있는 음악이 리스트업 되어야 한다. 따라서Bind service
로 데이터 통신도 되어야 하기 때문이다. public void onClick(View v) {
switch (v.getId()){
case R.id.button:
Intent Service = new Intent(this, BindService.class);
bindService(Service, mConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.button2:
mBindService.myServiceFunc();
}
}
// service connection definition
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
BindService.BindServiceBinder binder = (BindService.BindServiceBinder) service;
mBindService = binder.getService(); // get service.
mBindService.registerCallback(mCallback); // callback registration
}
// Called when the connection with the service disconnects unexpectedly
@Override
public void onServiceDisconnected(ComponentName name) {
mBindService = null;
}
};
// call below callback in service. it is running in Activity.
private BindService.ICallback mCallback = new BindService.ICallback() {
@Override
public void remoteCall() {
Log.d("MainActivity","called by service");
}
};
private final IBinder mBinder = new BindServiceBinder();
private ICallback mCallback;
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// declare callback function
public interface ICallback {
public void remoteCall();
}
// for registration in activity
public void registerCallback(ICallback cb){
mCallback = cb;
}
// service contents
public void myServiceFunc(){
Log.d("BindService","called by Activity");
// call callback in Activity
mCallback.remoteCall();
}
// Declare inner class
public class BindServiceBinder extends Binder {
BindService getService(){
return BindService.this; // return current service
}
}
04-09 21:26:18.351 26984-26984/com.example.user.localbindservice D/BindService: called by Activity
04-09 21:26:18.351 26984-26984/com.example.user.localbindservice D/MainActivity: called by service
ResultReceiver로 단방향 메시지 전달
ResultReceiver
란 결국 Binder
의 wrapper 함수를 의미한다.
따라서 ResultReceiver
를 전달 함으로써 Service
와 Activity
가 서로 통신할 수 있다. protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar)findViewById(R.id.progressBar);
syncMessage = (TextView)findViewById(R.id.textview);
syncButton = (Button)findViewById(R.id.button);
syncButton.setOnClickListener(this);
}
@Override
public void onClick(View v) { // (1)
progressBar.setVisibility(View.VISIBLE);
syncMessage.setText("sync start");
Intent intent = new Intent(this, SyncService.class);
intent.putExtra("RECEIVER", resultReceiver); //(2)
startService(intent);
}
private Handler handler = new Handler();
private ResultReceiver resultReceiver = new ResultReceiver(handler){ // (3)
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
// SYNC_COMPLETED CODE = 1
if (resultCode == 1){ // (4)
String msg = resultData.getString("msg");
progressBar.setVisibility(View.GONE);
syncMessage.setText("Done "+msg);
}
}
};
ResultReceiver
를 생성하고 onReceiveResult()
메서드를 오버라이드한다. ResultReceiver 생성자에는 handler 인스턴스를 넣을 수도, null로 할 수도 있다. Service의 백그라운드 스레드에서 ResultReceiver의 send()메시지를 호출하는데, 결과를 받는 쪽에서 UI를 업데이트 하기 때문에 Handler를 거쳐 메인 Looper의 MessageQueue에 Message를 넣은 것이다. @Override
public int onStartCommand(Intent intent, int flags, int startId) {
mIntent = intent;
new Thread(new Runnable() {
@Override
public void run() {
Log.d("SyncService","SyncService started");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Bundle bundle = new Bundle();
final ResultReceiver receiver = mIntent.getParcelableExtra("RECEIVER"); // (1)
bundle.putString("msg","Succeed !");
receiver.send(1,bundle); // (2)
}
}).start();
return START_NOT_STICKY;
}
실행 결과
참고자료
'Computer Science > Android Application' 카테고리의 다른 글
Android App Data save and restore (1) | 2018.11.06 |
---|---|
구글 글래스 엔터프라이즈 에디션 (Google Glass Enterprise Edition) 리뷰 (14) | 2018.07.31 |
Android 6.0 이상에서의 백그라운드 서비스 생존 방법에 대한 고찰 (0) | 2018.04.03 |
SQLite 탐색기 및 기초 쿼리 (0) | 2018.04.03 |
NotificationListenerService 이상 종료 문제 및 디버깅 방법 (0) | 2017.10.31 |