ㄷㅣㅆㅣ's Amusement

Android MMS보내는 코드 분석. 본문

Programming/Android

Android MMS보내는 코드 분석.

ㄷㅣㅆㅣ 2015. 11. 7. 21:24

Android MMS보내는 코드 분석.

그 어디에도 나와있지 않아서 빡친 내가 분석하고 만다 제길.

#summary 코드리뷰-ComposeMessageAcitivity = Introduction = ComposeMessageAcitivity 클래스 설명. = onCreate() = compose_message_activity.xml 에서 ui 정보 읽어옴.(setContentView() 로 inflate) *initResourceRefs()* -> findViewById() 로 UI component 인스턴스 가져오고 listener 등록. BackgroundQueryHandler 생성. initAcitivityState() 처음 시작하는 경우, 들어온 intent의 정보를 해석하여 저장함. RecipientList.from() 이용하여 수신자 리스트 파싱함. initMessageList() MessageListAdapter 생성하고 초기화함. setOnDataSetChagnedListener()로 등록. * mDataSetChangedListener setMsgListItemHandler() 로 등록. * mMessageListItemHandler 등록된 Message 처리. Message의 종류를 판별하고 mMsgListAdpater에서 MessageItem 정보를 조회하여 editMessageItem() 호출. MMS, SMS의 여부에 따라 editSmsMessageItem(), editMmsMessageItem() 이 내부서 호출됨. 생성된 MessageListAdapter 인스턴스와 여러 Listener들을 mMsgListView에 등록함. mMsgListView에 붙는 listener * ContextMenu : MsgListMenuClickListener클래스에서 메뉴처리함. * OnItemClick : MessageListItem 의 onMessageListItemClick() 으로 처리함. markAsRead(mThreadId) -> 읽음 상태로 전환. convertMessageIfNedded() -> 수신자 때문에 메일을 MMS로 전환해야 하는지 조사하고 전환. 새로운 메시지인 경우, initRecipientEditor() 첨부 타입 조사하고, drawBottomPanel() 호출 resetCounter() attachmentType에 따라, mBottomPanel 제어(TextEditor 와 Counter, Send버튼이 있는 부분) * 기본 동작 : mTextEditor에 텍스트 설정하고 mBottomPanel 보여지도록 함. * SLIDESHOW_ATTACHMENT : mBottomPanel 숨기고, attachment_editor 활성화시킴. getResources().getConfiguration() 으로 Configuration 정보 얻어온 후, onKeyboardStateChanged() 호출. = onStart() = updateWindowTitle() 수신자리스트(mRecipientList) 에서 문자열을 가져와 모두 이어붙임. 그 뒤에 참조리스트의 이름들도 붙여서 윈도우 타이틀을 구성하여 setTitle()로 세팅함. initFocus() 수신자 작성 창 또는 text editor 둘 중 어디에 focus둘지 결정함. registerReceiver()로 mHttpProgressReceiver와 mHttpPregressFilter 등록. mHttpProgressReceiver 발생하여 들어오는 intent의 action이 PROGRESS_STATUS_ACTION 일 경우 실행되는 receiver임. intent의 부가정도에서 "token" 정보가 mThreadId와 일치할 경우, intent 부가정보 "progress" 정보를 읽어들여 PROGRESS_START일 경우에는, 진행바 표시하고, PROGRESS_ABORT/COMPLETE 일 경우에는, 진행바를 숨긴다. 나머지 경우에는 setProgress()로 진행 경과 정도를 progress 만큼 표시한다. startMsgListQuery() mBackgroundQueryHandler.startQuery() 호출. MESSAGE_LIST_QUERY_TOKEN과 getThreadUri()로 시작함. getThreadUri() Threads.CONTENT_URI에다 mThreadId 붙인 URI 주소값 리턴함. startQueryForContactInfo() updateSendFaildNotification() MessageNotification.updateSendFailedNotificationForTHread() 를 실행하는 Thread 생성하고 실행시킴. -> undelivered 메시지가 모두 이 ThreadId에 속한다면 noti 해제함.(MESSAGE_FAILED_NOTIFICATION_ID) = onRestart() = markAsRead(mThreadId) invalidateRecipientsInCache() -> 사용자가 수신자에서 연락처를 추가하면 local contact cache 다시 업데이트 해야 함. = onResume() = startPresencePollingRequest() mPresencePollingHandler.sendEmptyMeesageDelayed() 로 1분마다 한번씩 refresh함. mPresencePollingHandler 내부 구현에서는 startQueryForContactInfo() 실행함. startQueryForContactInfo() : 수신자 리스트에서 number를 조회하여 email주소이면, mBackgroundHandler.startQuery()로 EMAIL_CONTACT_QUERY_TOKEN 쿼리 동작 시작. 아니면, CALLER_ID_QUERY_TOKEN 쿼리 동작 시작함. = onClick() = 클릭한 view가 SendButton 이고 전송준비가 되어 있으면(isReadyForSending() : 수신자 있는지와 본문 또는 첨부가 있는지 여부) confirmSendMessageIfNeeded() 실행. 수신할 대상 리스트 mRecipientList의 hasInvalidRecipient()를 이용하여 적절성 판단후, sendMessage() 호출. 적절하지 않은 경우, AlertDialog 만들어 사용자에게 표시. 수신 리스트 중에 적절한 대상이 있는 경우, SendIgnoreInvalidRecipientListener 를 통해 전송 시도함. = sendMessage() = mRecipientList에서 getToNumbers()로 String 배열을 구함. removeSubjectIfEmpty() : subject가 비어있으면 message 전환. requiresMms()로 MMS 여부 판단하여, MMS이면, SendReq 인스턴스 생성. 생성된 SendReq 인스턴스를 가지고 fillMessageHeaders() 실행. sendMmsWorker()를 실행하는 Thread 별도 생성하고 실행시킴. MMS가 아닌 SMS인 경우, mMsgText에서 문자열 얻은 후, sendSmsWorker()를 실행하는 Thread 생성,실행시킴. 전송 후 종료되도록 셜정되어 있는 경우이면 acitivity 종료하고, 아니면 resetMessage()로 다른 메시지를 보낼 수 있도록 메시지 초기화시킴. = sendMmsWorker() = MMS 메시지 전송하는 함수. String배열인 파라미터 dests 에서 getOrCreateThreadId()로 thread id를 생성한다. getOrCreateThreadId() HashSet<String> 인스턴스를 생성하고, Array.asList()와 HashSet 의 addAll()을 이용하여 String배열로 들어온 정보를 변환함. Threads의 getOrCreateThreadId()로 조회된 thread id를 리턴함. 이 함수 내부에서는 MmsSmsProvider에 접근하여 DB에 기존 recipient가 있는지 조회하여 있으면 기존 thread id를 넘김. MmsSmsProvider 내부에서는 thread id가 존재하지 않으면 insertThread()로 새로 Thread 생성 후 그 id 값을 넘긴다.(현재 시각일 가능성이 큼.) updateTemporaryMmsMessage() 로 MMS메시지와 disk저장소와 sync 시킴. deleteTemporarySmsMessage() 로 이 thread id로 되어 있는 임시 SMS메시지 삭제. MmsMessageSender()객체 생성하고, 이 객체의 sendMessage()를 이용하여 전송 시도함. 실패하면 해당 URI에 대해 SqliteWrapper.delete()로 DB에서 삭제함. 이 thread id 로 setThreadId() 하여 세팅. startMsgListQuery() 호출.->메시지리스트 업데이트함. = sendSmsWorker() = sendMmsWorker()에서 MmsMessageSender 대신 SmsMessageSender 씀. == BackgroundHandler == AsyncQueryHandler 상속하여 onQueryComplete(), onDeleteComplete(), onUpdateComplete() override구현함. onQueryComplete() * MESSAGE_LIST_QUERY_TOKEN : mMsgListAdapter의 cursor변경. TextEditor로 focus줌. * CALLER_ID_QUERY_TOEKN, EMAIL_CONTACT_QUERY_TOKEN : mContactInfoCursor 변경. updateContactInfo(), startPresencePollingRequest() 호출 == MessageListAdapter == CursorAdapter 상속하고 bindView(), notifyDataSetChanged), newView() override 구현함. Provider에서 가져오는 Columns * MmsSms.TYPE_DISCRIMINATOR_COLUMN, * BaseColumns.-ID, * Conversations.THREAD_ID, // For SMS * Sms.ADDRESS, * Sms.BODY, * Sms.DATE, * Sms.READ, * Sms.TYPE, * Sms.STATUS, // For MMS * Mms.SUBJECT, * Mms.SUBJECT_CHARSET, * Mms.DATE, * Mms.READ, * Mms.MESSAGE_TYPE, * Mms.MESSAGE_BOX, * Mms.DELIVERY_REPORT, * Mms.READ_REPORT, * PendingMessages.ERROR_TYPE bindView() 바인드될 view가 MessageListItem 인스턴스이면, cursor에서 type과 msgId 정보를 가져와 MessageItemCache에서 이 정보를 바탕으로 MessageItem 이 있는지 조회하여 있으면, MessageListItem의 bind()를 이용하여 그 item을 등록함. setMsgListItemHandler()로 mMsgListItemHandler 등록. newView() LayoutInflator의 inflate()를 써서 message_list_item.xml에서 인스턴스(MessageListItem)를 추출하여 리턴함.

시퀀스 다이어그램은 다음주에 포스팅하겠음. ㅡ,.ㅡ;;


2 Comments
댓글쓰기 폼