반응형
이전 포스팅에서 SMS 또는 LMS을 읽어오는 부분에 대해서는 기술한 바 있습니다. 이여서 하는 이야기는 MMS을 확인해 보는 방법입니다. 이전 포스팅으로 MMS가 읽어져 오는 것으로 이해를 하고 있었습니다만... 실제로는 그것이 아니라는 특히 국내에서 출시된 개선된(?) 안드로이드를 사용하는 경우 그런 기능으로는 정보를 다 가지고 오지 못하는 부분이 있다는 것을 알게 되었습니다.
MMS 수신 이벤트 확인
국내향 안드로이드의 경우는 SMS와 달리 MMS의 경우는 수신을 했다고 해도 Event 를 감지할 수 없었습니다. 그래서 대안으로 처리한 것은 알림 수신을 이용하는 것입니다. (알림 수신에 대해서는 이전 포스팅을 참고해 주세요)
import android.annotation.SuppressLint
import android.app.Notification
import android.content.ContentResolver
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import androidx.annotation.RequiresApi
.....
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.*
class MyNotificationListener : NotificationListenerService() {
val TAG = "MyNotificationListener"
val MMS_URI: Uri = Uri.parse("content://mms-sms/conversations/")
val mmsRcvNumbers = mutableListOf<MmsBean>()
override fun onNotificationRemoved(sbn: StatusBarNotification) {
super.onNotificationRemoved(sbn)
Log.e(
TAG, "onNotificationRemoved ~ " +
" packageName: " + sbn.packageName +
" id: " + sbn.id
)
}
/**
* MMS 발송자 전화 번호 알아 내기
*/
@SuppressLint("Range")
private fun getAddressNumber(id: Int): String? {
val selectionAdd = "msg_id=${id}"
val uriStr = "content://mms/${id}/addr"
val uriAddress = Uri.parse(uriStr)
val cAdd = contentResolver.query(
uriAddress, null,
selectionAdd, null, null
)
var name: String? = ""
try {
if (cAdd!!.moveToFirst()) {
do {
val number = cAdd.getString(cAdd.getColumnIndex("address"))
if (number != null) {
try {
number.replace("-", "").toLong()
name = number
} catch (nfe: NumberFormatException) {
if (name == null) {
name = number
}
}
}
} while (cAdd.moveToNext())
}
if (cAdd != null) {
cAdd.close()
}
} catch (e : Exception) {
}
return name
}
/**
* MMS 의 본문 내용 읽어 오기
*/
private fun getMMsPart(mId: String?): String {
var rValue = ""
var selectionPart: String = "mid=" + mId;
var uriPart : Uri = Uri.parse("content://mms/part");
var cur : Cursor? = contentResolver.query(uriPart, null, selectionPart, null, null);
if (cur != null) {
if (cur.moveToFirst()) {
do {
rValue = getMmsBody(cur)
} while (cur.moveToNext())
}
}
return rValue
}
/**
* MMS Body read
*/
private fun getMmsBody(partCursor: Cursor): String {
val partId = partCursor.getString(partCursor.getColumnIndexOrThrow("_id"))
val data = partCursor.getString(partCursor.getColumnIndexOrThrow("_data"))
return if (data != null) {
getMessageText(contentResolver, partId)
} else {
partCursor.getString(partCursor.getColumnIndexOrThrow("text"))
}
}
/**
* MMS body get Text
*/
private fun getMessageText(contentResolver: ContentResolver, id: String): String {
val partUri = Uri.parse("content://mms/part/$id")
val stringBuilder = StringBuilder()
val inputStream = contentResolver.openInputStream(partUri)
if (inputStream != null) {
val inputStreamReader = InputStreamReader(inputStream, "UTF-8")
val bufferedReader = BufferedReader(inputStreamReader)
var temp = bufferedReader.readLine()
while (temp != null) {
stringBuilder.append(temp)
temp = bufferedReader.readLine()
}
inputStream.close()
}
return stringBuilder.toString()
}
@SuppressLint("Range")
@RequiresApi(Build.VERSION_CODES.S)
override fun onNotificationPosted(sbn: StatusBarNotification) {
super.onNotificationPosted(sbn)
val projection = arrayOf("_id", "ct_t")
val query: Cursor? = contentResolver.query(MMS_URI, projection, null, null, null)
mmsRcvNumbers.clear()
if (query != null) {
if (query.moveToFirst()) {
do {
var mId = query.getString(0)
var fromAddr = getAddressNumber(mId.toInt())
if (!"".equals(fromAddr)) {
var mmsBean = MmsBean(mId.toInt(), fromAddr.toString())
var mesg = getMMsPart(mId)
mmsBean.mesg = mesg
// Log.e(TAG, "mesg = ${mesg}")
mmsRcvNumbers.add(mmsBean)
}
Log.e(TAG, "sms id=$mId [$fromAddr]")
} while (query.moveToNext())
}
}
if (mmsRcvNumbers.size > 0) {
mmsRcvNumbers.sortByDescending { orderItem -> orderItem.mId }
}
var sdf = SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale("ko", "KR"))
val extras = sbn.notification.extras
try {
var title = extras.getString(Notification.EXTRA_TITLE).toString()
var content = "" + extras.getCharSequence(Notification.EXTRA_TEXT)
if (extras.getCharSequence(Notification.EXTRA_SUB_TEXT) != null) {
content += " " + extras.getCharSequence(Notification.EXTRA_SUB_TEXT)
}
var number = ""
if (mmsRcvNumbers.size > 0) {
number = mmsRcvNumbers.get(0).rcvNumber
content = mmsRcvNumbers.get(0).mesg
}
Log.e(
TAG, "onNotificationPosted ~ " +
"\n packageName: " + sbn.packageName +
"\n id: " + sbn.id +
"\n postTime: " + sdf.format(sbn.postTime) +
"\n title: " + title +
"\n number: " + number +
"\n content : " + content
)
} catch (e: Exception) {
Log.e(
TAG, "error = ${e.localizedMessage}"
)
}
}
}
코드에서 보는 것과 같이 Notification Receiver을 활용해 contentResolver 을 이용 content://mms-sms/conversations의 정보를 읽어옵니다. 이 정보를 활용해서 mms의 정보를 열어 보는 방식으로 구현이 되었습니다.
이 부분을 조금 더 활용해 본다면, sms 수신 데이터의 정보도 읽어 올 수 있도록 구현이 될 것 같습니다.
나중에 기회가 된다면 그 부분도 구현을 해 보도록 하겠습니다.
반응형
'모바일 앱(안드로이드)' 카테고리의 다른 글
안드로이드 앱 만들기 : 지오펜싱 (Geofencing) 에 대한 이해 (0) | 2022.12.08 |
---|---|
안드로이드 앱 만들기 : GoogleMap(구글맵) 활용시 주의 할 점 하나 (0) | 2022.11.30 |
안드로이드 앱 만들기 : SMS or LMS (문자)수신기는 어떻게 ? (0) | 2022.11.21 |
개발일기 # 번외편3 : 앱의 디자인에 대한 평가 받아 보기 (0) | 2022.11.16 |
개발일기 # 번외편2 : 난 서버가 없는데(Serverless) cloud function 사용해 보기 (0) | 2022.11.12 |