Android에서 MMS 데이터를 읽는 방법?
MMS 데이터를 읽고 싶습니다 mmssms.db. mms 항목이 저장된 부분 테이블을 보았습니다 . 커서를 사용하고 있으며 적절한 것을 알고 싶습니다 URI. 그리고 : 나는 "// MMS-SMS / 대화 내용"사용하고 열 이름 (로 전송) "주소", "텍스트"또는 "제목"이미지의 "데이터"열 이름의.
나는 mmssms.db부분 테이블 의 스키마 와 그들의 열을 보았다 .
이에 대한 문서를 찾기가 다소 어렵 기 때문에 내가 찾은 모든 정보를 여기서 수집 할 것입니다. 서두르거나 읽고 싶지 않은 경우 SMS에서 데이터를 가져 오는 방법 섹션으로 이동하십시오.
content : // mms-sms / conversations
이것은 MMS 및 SMS 공급자 의 URI입니다 .이를 통해 MMS 및 SMS 데이터베이스를 동시에 쿼리하고 단일 스레드 ( 대화 라고 함 ) 에서 혼합 할 수 있습니다 .
URI가 중요한 이유는 무엇입니까? 이것이 MMS 및 SMS 메시지를받는 표준 방법입니다. 예를 들어 SMS를 수신하고 알림 표시 줄을 클릭하면 다음과 같은 브로드 캐스트 인 텐트가 전송됩니다. content://mms-sms/conversations/XXX, 여기서는 XXX대화의 ID입니다.
모든 대화 목록 가져 오기
해야 할 일은 content://mms-sms/conversationsUri 를 쿼리하는 것뿐입니다 .
ContentResolver contentResolver = getContentResolver();
final String[] projection = new String[]{"*"};
Uri uri = Uri.parse("content://mms-sms/conversations/");
Cursor query = contentResolver.query(uri, projection, null, null, null);
참고 : 일반적으로 호출 query하고 모든 열을 반환하려는 null경우 projection매개 변수 로 전달할 수 있습니다 . 그러나이 공급자로는 그렇게 할 수 없으므로 *.
이제 Cursor평소와 같이 반복 할 수 있습니다 . 다음은 사용하려는 더 중요한 열입니다.
_id메시지의 ID입니다. 구조 대장이 당연하다고? 별로. 이 ID 중 하나를 사용하여 자세한 정보를 검색 할 수 있습니다content://sms또는content://mms.date설명이 필요하지 않습니다.thread_id대화의 ID입니다.body이 대화의 마지막 SMS 내용입니다. MMS 인 경우 텍스트 부분이 있어도null.
참고 : 쿼리 content://mms-sms/conversations하면 _id각 대화의 마지막 SMS 또는 MMS 인 다른 대화 목록이 반환됩니다 . 쿼리 content://mms-sms/conversations/xxx하면 ID가 인 대화의 각 SMS 및 / 또는 MMS가 반환됩니다 xxx.
SMS와 MMS를 구별하는 방법
일반적으로 처리중인 메시지 유형을 알고 싶을 것입니다. 문서 내용 :
MmsSms.TYPE_DISCRIMINATOR_COLUMN쿼리에 대한 프로젝션에서 가상 열을 요청할 수 있습니다. 해당 값은 행이 나타내는 메시지가 각각 MMS 메시지인지 SMS 메시지인지에 따라 "mms"또는 "sms"입니다.
나는 그것이이 변수를 언급하고 있다고 생각한다 . 그러나 나는 그것을 작동시킬 수 없었다. 만약 당신이이 게시물을 편집하는 방법을 알려주세요.
지금까지 이것이 내가 한 일이며 작동하는 것처럼 보이지만 더 나은 방법이 있어야합니다.
ContentResolver contentResolver = getContentResolver();
final String[] projection = new String[]{"_id", "ct_t"};
Uri uri = Uri.parse("content://mms-sms/conversations/");
Cursor query = contentResolver.query(uri, projection, null, null, null);
if (query.moveToFirst()) {
do {
String string = query.getString(query.getColumnIndex("ct_t"));
if ("application/vnd.wap.multipart.related".equals(string)) {
// it's MMS
} else {
// it's SMS
}
} while (query.moveToNext());
}
SMS에서 데이터를 가져 오는 방법
따라서 SMS의 ID가 있으면 다음과 같은 작업 만 수행하면됩니다.
String selection = "_id = "+id;
Uri uri = Uri.parse("content://sms");
Cursor cursor = contentResolver.query(uri, null, selection, null, null);
String phone = cursor.getString(cursor.getColumnIndex("address"));
int type = cursor.getInt(cursor.getColumnIndex("type"));// 2 = sent, etc.
String date = cursor.getString(cursor.getColumnIndex("date"));
String body = cursor.getString(cursor.getColumnIndex("body"));
MMS 데이터에서 데이터를 가져 오는 방법은 무엇입니까?
MMS는 약간 다릅니다. 다른 부분 (텍스트, 오디오, 이미지 등)으로 만들 수 있습니다. 여기에서는 각 종류의 데이터를 개별적으로 검색하는 방법을 살펴 보겠습니다.
따라서 mmsId변수에 MMS ID가 있다고 가정 해 봅시다 . content://mms/공급자 를 사용하여이 MMS에 대한 자세한 정보를 얻을 수 있습니다 .
Uri uri = Uri.parse("content://mms/");
String selection = "_id = " + mmsId;
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
그러나, 단지 흥미 열은 read어떤 1메시지를 이미 읽은 경우.
MMS에서 텍스트 콘텐츠를 가져 오는 방법
content://mms/part예를 들어 ... 를 사용해야 합니다.
String selectionPart = "mid=" + mmsId;
Uri uri = Uri.parse("content://mms/part");
Cursor cursor = getContentResolver().query(uri, null,
selectionPart, null, null);
if (cursor.moveToFirst()) {
do {
String partId = cursor.getString(cursor.getColumnIndex("_id"));
String type = cursor.getString(cursor.getColumnIndex("ct"));
if ("text/plain".equals(type)) {
String data = cursor.getString(cursor.getColumnIndex("_data"));
String body;
if (data != null) {
// implementation of this method below
body = getMmsText(partId);
} else {
body = cursor.getString(cursor.getColumnIndex("text"));
}
}
} while (cursor.moveToNext());
}
텍스트의 다른 부분을 포함 할 수 있지만 일반적으로 하나 일뿐입니다. 따라서 루프를 제거하려면 대부분의 경우 작동합니다. 어떻게 '이다 getMmsText방법은 다음과 같습니다
private String getMmsText(String id) {
Uri partURI = Uri.parse("content://mms/part/" + id);
InputStream is = null;
StringBuilder sb = new StringBuilder();
try {
is = getContentResolver().openInputStream(partURI);
if (is != null) {
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader reader = new BufferedReader(isr);
String temp = reader.readLine();
while (temp != null) {
sb.append(temp);
temp = reader.readLine();
}
}
} catch (IOException e) {}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {}
}
}
return sb.toString();
}
MMS에서 이미지를 얻는 방법
텍스트 부분을 얻는 것과 동일합니다. 유일한 차이점은 다른 MIME 유형을 찾는 것입니다.
String selectionPart = "mid=" + mmsId;
Uri uri = Uri.parse("content://mms/part");
Cursor cPart = getContentResolver().query(uri, null,
selectionPart, null, null);
if (cPart.moveToFirst()) {
do {
String partId = cPart.getString(cPart.getColumnIndex("_id"));
String type = cPart.getString(cPart.getColumnIndex("ct"));
if ("image/jpeg".equals(type) || "image/bmp".equals(type) ||
"image/gif".equals(type) || "image/jpg".equals(type) ||
"image/png".equals(type)) {
Bitmap bitmap = getMmsImage(partId);
}
} while (cPart.moveToNext());
}
어떻게 '이다 getMmsImage방법은 다음과 같습니다
private Bitmap getMmsImage(String _id) {
Uri partURI = Uri.parse("content://mms/part/" + _id);
InputStream is = null;
Bitmap bitmap = null;
try {
is = getContentResolver().openInputStream(partURI);
bitmap = BitmapFactory.decodeStream(is);
} catch (IOException e) {}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {}
}
}
return bitmap;
}
발신자 주소를 얻는 방법
content://mms/xxx/addr공급자 를 사용해야합니다 . 여기서 xxxMMS의 ID는 다음과 같습니다.
private String getAddressNumber(int id) {
String selectionAdd = new String("msg_id=" + id);
String uriStr = MessageFormat.format("content://mms/{0}/addr", id);
Uri uriAddress = Uri.parse(uriStr);
Cursor cAdd = getContentResolver().query(uriAddress, null,
selectionAdd, null, null);
String name = null;
if (cAdd.moveToFirst()) {
do {
String number = cAdd.getString(cAdd.getColumnIndex("address"));
if (number != null) {
try {
Long.parseLong(number.replace("-", ""));
name = number;
} catch (NumberFormatException nfe) {
if (name == null) {
name = number;
}
}
}
} while (cAdd.moveToNext());
}
if (cAdd != null) {
cAdd.close();
}
return name;
}
마지막 생각들
- 수천만 달러의 Google이이 API를 문서화하기 위해 학생이나 다른 사람에게 돈을 지불하지 않는 이유를 이해할 수 없습니다. 소스 코드가 어떻게 작동하는지 확인해야하며, 더 나쁜 것은 데이터베이스의 열에 사용 된 상수를 공개하지 않으므로 수동으로 작성해야합니다.
- MMS 내부의 다른 종류의 데이터의 경우 위에서 배운 것과 동일한 아이디어를 적용 할 수 있습니다. 단지 MIME 유형을 아는 것입니다.
Christian의 대답은 훌륭합니다. 그러나 보낸 사람의 주소를 얻는 방법이 작동하지 않았습니다. Long.parseLong 문은 예외 및 new String (...)?을 throw하는 것 외에는 아무 작업도 수행하지 않습니다.
내 장치에서 커서 수가 2 개 이상입니다. 첫 번째는 일반적으로 "유형"이 137이고 다른 "유형"은 151입니다. 문서화 된 위치를 찾을 수 없지만 137은 "시작"이고 151은 "끝"이라고 추론 할 수 있습니다. 따라서 메서드를있는 그대로 실행하면 예외가 발생하지 않고받는 사람이고 여러 경우 중 하나 인 마지막 행을 반환합니다.
또한 AFAICT는 모든 행이 동일한 msg_id를 갖기 때문에 선택이 필요하지 않습니다. 그러나 그것은 아프지 않습니다.
이것은 발신자의 주소를 얻는 데 효과적입니다.
public static String getMMSAddress(Context context, String id) {
String addrSelection = "type=137 AND msg_id=" + id;
String uriStr = MessageFormat.format("content://mms/{0}/addr", id);
Uri uriAddress = Uri.parse(uriStr);
String[] columns = { "address" };
Cursor cursor = context.getContentResolver().query(uriAddress, columns,
addrSelection, null, null);
String address = "";
String val;
if (cursor.moveToFirst()) {
do {
val = cursor.getString(cursor.getColumnIndex("address"));
if (val != null) {
address = val;
// Use the first one found if more than one
break;
}
} while (cursor.moveToNext());
}
if (cursor != null) {
cursor.close();
}
// return address.replaceAll("[^0-9]", "");
return address;
}
나는 그것이 모두 숫자인지는 신경 쓰지 않았지만, 원한다면 주석으로 숫자를 제외한 모든 것을 제거하는 방법을 포함 시켰습니다. 모든 수신자를 반환하도록 쉽게 수정할 수 있습니다.
I assume it worked for him. It looks like it would give the right answer if the exception occurred on the first row.
I've just been struggling with this; however, I finally got it to work and I thought this thread might benefit from my experience.
I could query on content://mms-sms/conversations/ (Telephony.Threads.CONTENT_URI) and get addresses and parts as helpfully described in the thread, but I found that this URI would not retrieve threads that only had MMS messages in them - for example, threads with more than two correspondents.
After doing some digging in the AOSP MMS app source, I found that it was using a variant on Telephony.Threads.CONTENT_URI to generate its conversation list - it was adding the parameter "simple" with the value "true". when I added this parameter, I found that the provider would query a completely different table, which did indeed have all the SMS and MMS threads in it.
This table has a completely different schema from the regular Telephony.Threads.CONTENT_URI one (???); this is the projection that the AOSP app is using --
public static final String[] ALL_THREADS_PROJECTION = {
Threads._ID, Threads.DATE, Threads.MESSAGE_COUNT, Threads.RECIPIENT_IDS,
Threads.SNIPPET, Threads.SNIPPET_CHARSET, Threads.READ, Threads.ERROR,
Threads.HAS_ATTACHMENT
};
The _ID here is the ID of the thread - so an ID into Telephony.Sms.CONTENT_URI or Telephony.Mms.CONTENT_URI.
After I discovered this bizarre detail, things started to work a lot better! Note however that the DATE column in the "simple=true" variant is not reliable, i had to use the date from the most recent Sms or Mms message instead.
Another thing I should probably mention is that in order to get a proper list of messages for a particular thread, I had to query on both the Mms and Sms providers, then combine the results into one list, then sort them by date.
I verified behaviour on Android 5.x and 7.x.
I hope this helps a bit more.
I had to make some modifications in order to get this to work for me.
When I retrieve the cursor.getString(cursor.getColumnIndex("type")) from the mms-sms/conversations content, ("content://mms-sms/conversations/") I test the value of the "type" field for null. If the variable is null - i.e.
String otype = c.getString(c.getColumnIndex("type")); if(otype != null) { //this is an sms - handle it...the message is an SMS, else it is an MMS. For MMS's you have to test for both mime types as follows:-
if (("application/vnd.wap.multipart.related".equalsIgnoreCase(msg_type) ||"application/vnd.wap.multipart.mixed".equalsIgnoreCase(msg_type)) && !id.equalsIgnoreCase(lastMMSID)) { //this is a MMS - handle it...- When you use a ContentObserver to monitor the message content for changes, it fires several notifications for the same message. I use a static variable - in my case lastMMSID - to keep track of the message.
- This code works well to retrieve the content of both Inbound and Outbound messages. It is important to iterate through all the records that are returned by the "content://mms/part/" uri in order to get to the content - text and/or attachments - of the MMS.
The only way that I could find that works pretty well to differentiate between inbound and outbound MMS's, is to test the null status of the "m_id" field of the mms-sms/conversations content.
String m_id = c.getString(c.getColumnIndex("m_id")); String mDirection = m_id == null? "OUT": "IN";
A final thought on how to get the Address Field. For some reason the Address Content does not like to be queried with a {" * "} parameter, but this works:-
final String[] projection = new String[] {"address", "contact_id", "charset", "type"};
If it is an outbound message, the "type" to look for will be 151. For an inbound message, the "type" will be 137. A fully functional piece of code will look something like this:-
private String getANumber(int id) {
String add = "";
final String[] projection = new String[] {"address","contact_id","charset","type"};
final String selection = "type=137 or type=151"; // PduHeaders
Uri.Builder builder = Uri.parse("content://mms").buildUpon();
builder.appendPath(String.valueOf(id)).appendPath("addr");
Cursor cursor = context.getContentResolver().query(
builder.build(),
projection,
selection,
null, null);
if (cursor.moveToFirst()) {
do {
String add = cursor.getString(cursor.getColumnIndex("address"));
String type: cursor.getString(cursor.getColumnIndex("type"));
} while(cursor.moveToNext());
}
// Outbound messages address type=137 and the value will be 'insert-address-token'
// Outbound messages address type=151 and the value will be the address
// Additional checking can be done here to return the correct address.
return add;
}
To all the brave warriors who have gone before me in this post - I thank thee from the bottom of my heart!
The answer given above for getting the getMMSAddress() should not contain the loop while (cursor.moveToNext());. It should only extract the address from the first element in the cursor. For some reason that is unknown to me, this cursor has more than one record. The first one contains the Sender's address. The other elements of the cursor beyond the first one, contain the receiver's address. Thus the code as is return the receivers address and not the sender address.
This has been very helpful for cracking open the contents of an MMS.
참고URL : https://stackoverflow.com/questions/3012287/how-to-read-mms-data-in-android
'IT TIP' 카테고리의 다른 글
| iOS7에서 UISearchBar의 배경색을 변경하는 방법 (0) | 2020.10.27 |
|---|---|
| 역 색인이있는 부분 문자열 (0) | 2020.10.27 |
| "루비 버전이 1.9.3이지만 Gemfile이 2.0.0을 지정했습니다"를 수정하는 방법 (0) | 2020.10.27 |
| Swift에서 이미지 크기를 조정하는 방법은 무엇입니까? (0) | 2020.10.27 |
| 프로그래머가 아닌 사람에게 프로그래밍이 "어떻게 생겼는지"설명 할 수있는 좋은 예는 무엇입니까? (0) | 2020.10.27 |