registerReceiver 를 여러번 호출하면 어떻게 될까?
같은 receiver 를 가지고 여러번 registerReceiver 를 호출해도 호출은 된다. 그러나 unregister 를 하지않으면 leak 이 된다.
unregisterReceiver 를 하는 방법
해결책으로 아래 2가지를 이야기 한다.
- register 할 때 놓을 때 flag 를 하나 둔다.
- 여기서 해결책으로 onReceive() 가 호출된 후에 함수내에서 바로 unregisterReceiver 를 호출하도록 구현하는 방법을 이야기 한다.
등록해 놓고, 등록을 해지 못한 상태로 다시 등록을 하게 되는 경우가 있다면 2번째 방법을 고려해 보는 것도 좋은 방법일 듯 싶다. 그런데 onReceive 가 호출되지 않는 경우에 unregister 를 하지 않는다는 문제가 있다.
참고로, 등록되지 않은 receiver 를 unregister 하면 아래와 같은 Exception 이 발생한다.
Caused by: java.lang.IllegalArgumentException: Receiver not registered: com.xxxx.player.Mp3PlayerService$5@40f059a8
flag 사용하는 예제
private void unregisterCallReceiver(){ if(mIsReceiverRegistered){ unregisterReceiver(mCallReceiver); mIsReceiverRegistered = false; } } private void registerCallReceiver(){ if(!mIsReceiverRegistered){ IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.PHONE_STATE"); registerReceiver(mCallReceiver, filter); mIsReceiverRegistered = true; } }
registerReceiver source codes
루틴이 startService 를 호출할 때와 같은 routine 이다.
@Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext()); } private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; if (receiver != null) { if (mPackageInfo != null && context != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( receiver, context, scheduler, null, true).getIIntentReceiver(); } } try { return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); } catch (RemoteException e) { return null; } } public Intent registerReceiver(IApplicationThread caller, String packageName, IIntentReceiver receiver, IntentFilter filter, String perm, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(packageName); data.writeStrongBinder(receiver != null ? receiver.asBinder() : null); filter.writeToParcel(data, 0); data.writeString(perm); data.writeInt(userId); mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0); reply.readException(); Intent intent = null; int haveIntent = reply.readInt(); if (haveIntent != 0) { intent = Intent.CREATOR.createFromParcel(reply); } reply.recycle(); data.recycle(); return intent; }
See Also
- Broadcast Receiver에 대해서| 안드로이드 기본 강좌, 2011.09.15.
댓글 없음:
댓글 쓰기