Find and interate all SMS/MMS messages in android
Isn't there a way to just iterate the entire list of messages in this fashion where I replace
"content://mms-sms/conversations"
with something else?
It is possible to get all MMS and SMS messages in a single query using the content://mms-sms/complete-conversations
URL. For some odd reason, there is no Uri
field for this in the Telephony.MmsSms
class, but it's been available since at least Froyo.
Using this single query will certainly be more efficient than querying the tables separately, and any sorting, grouping, or filtering that needs to be done will definitely be faster performed by the SQLite engine than by manipulating Java collections.
Please note that you must use a specific projection
for this query. You cannot pass null
or the *
wildcard. Furthermore, it would be advisable to include MmsSms.TYPE_DISCRIMINATOR_COLUMN
("transport_type"
) in your projection
- which will have a value of either "mms"
or "sms"
- to easily distinguish the message type.
The selection
, selectionArgs
, and orderBy
arguments work as usual, and null
can be passed for any or all of them.
How do the retrieve the date of the mms from content://mms.
I'm not overly familiar with MMS's, but I'd imagine something like this would at least get you started
Cursor cursor = activity.getContentResolver().query(Uri.parse("content://mms"),null,null,null,date DESC);
count = cursor.getCount();
if (count > 0)
{
cursor.moveToFirst();
long timestamp = cursor.getLong(2);
Date date = new Date(timestamp);
String subject = cursor.getString(3);
}
It's completely untested of course, but should point you in the right direction. Hope this helps!
Edit
After doing a bit of reading, there used to be (possibly still is) a "bug" with the timestamp in MMS messages, when retrieving the data. If you end up with a silly value (like the epoch), you'll have to * 1000 before using it. Just an aside :) I.e.:
long timestamp = (cursor.getLong(2) * 1000);
How to read incoming MMS and SMS messages on Android
Here is a code snippet to show how to parse incoming SMS data with a Broadcast Receiver:
public override void OnReceive(Context context, Intent intent)
{
Log.Info(TAG, "Intent action received: " + intent.Action);
// Retrieve message from the intent and analyze it.
SmsMessage msg = Android.Provider.Telephony.Sms.Intents.GetMessagesFromIntent(intent)[0];
string message = msg.DisplayMessageBody;
(string, bool) result = MMSReceiver.CleanUpMessage(message);
// If there were one or more rooster words.
if (result.Item2)
{
string title = "Rooster Text Received From: " + msg.DisplayOriginatingAddress;
DependencyService.Get<INotificationManager>().ScheduleNotification(title, result.Item1);
}
}
And here is a code snippet to show how to parse incoming MMS data with a Broadcast Receiver:
public override void OnReceive(Context context, Intent intent)
{
Log.Info(TAG, "Intent action received: " + intent.Action);
// Get the MMS ID. Adapted from: https://stackoverflow.com/questions/10065249/how-to-get-mms-id-android-application
ContentResolver contentResolver = AndroidApp.Context.ContentResolver;
Android.Net.Uri mmsInboxUri = Android.Net.Uri.Parse("content://mms");
Android.Database.ICursor mmsInboxCursor = contentResolver.Query(mmsInboxUri, new string[]
{"_id","msg_box","ct_t","date"}, "msg_box=1 or msg_box=2", null, null);
int id = -1;
if (mmsInboxCursor != null)
{
try
{
if (mmsInboxCursor.MoveToFirst())
{
id = Int32.Parse(mmsInboxCursor.GetString(0));
Log.Info(TAG, "Id is this: " + mmsInboxCursor.GetString(0));
}
}
catch (System.Exception error)
{
Log.Error(TAG, "Error requesting the MMS ID: " + error.Message);
}
}// if (mmsInboxCursor != null)
// Get text and picture from MMS message. Adapted from: https://stackoverflow.com/questions/3012287/how-to-read-mms-data-in-android
string message = ""; // text
Android.Graphics.Bitmap bitmap = null; // picture
string selectionPart = "mid=" + id;
Android.Net.Uri mmsTextUri = Android.Net.Uri.Parse("content://mms/part");
Android.Database.ICursor cursor = contentResolver.Query(mmsTextUri, null,
selectionPart, null, null);
if (cursor.MoveToFirst())
{
do
{
string partId = cursor.GetString(cursor.GetColumnIndex("_id"));
string type = cursor.GetString(cursor.GetColumnIndex("ct"));
// Get text.
if ("text/plain".Equals(type))
{
string data = cursor.GetString(cursor.GetColumnIndex("_data"));
if (data != null)
{
message = GetMmsText(partId);
Log.Info(TAG, "Body is this: " + message);
}
else
{
message = cursor.GetString(cursor.GetColumnIndex("text"));
Log.Info(TAG, "Body is this: " + message);
}
}
//Get picture.
if ("image/jpeg".Equals(type) || "image/bmp".Equals(type) ||
"image/gif".Equals(type) || "image/jpg".Equals(type) ||
"image/png".Equals(type))
{
bitmap = GetMmsImage(partId);
}
} while (cursor.MoveToNext());
}// if (cursor.MoveToFirst())
}
Fetch Image from MMS - Android
Each MMS message has multiple parts stored in the content://mms/part/
table. Some parts may be text, some may be images and other media types. Once you have the ID of the MMS you want to read, query all parts:
Cursor query = getContentResolver().query(Uri.parse("content://mms/part", null, "mid = " + mmsID, null, null);
If the MMS contains and image, it will have a part whose content type is an image type.
if(query.moveToFirst()) {
do {
String type = query.getString(query.getColumnIndex("ct"));
if(type.equals("image/bmp") || type.equals("image/jpeg") || ...)
//Read the image
while(query.moveToNext());
}
Look here for more information about reading MMSs.
How to get phone numbers of MMS group conversation participants?
Here's how AOSP's (Android Open Source Project) messaging app does it:
- Every message (SMS/ MMS) has a message ID represented as
_ID
in their respective tables - With this
id
pull the thread for the respective message - The
threads
table has a column calledrecipient_ids
, this might be Space separated for group message, something like this:123 456 789
Where 123
456
etc are the recipient ids.
- Get address for respective recipient ids. Now this is a bit tricky, but AOSP uses the following uri:
content://mms-sms/canonical-address
So the final method to get an array of addresses looks something likes this:
private fun getAddressFromRecipientId(spaceSepIds: String, context: Context): Array<String?> {
val singleCanonicalAddressUri = Uri.parse("content://mms-sms/canonical-address")
with(spaceSepIds.split(" ")) {
val addressArray: Array<String?> = arrayOfNulls(this.size)
this.forEachIndexed { index, address ->
if (!address.isEmpty()) {
val longId = address.toLong()
context.contentResolver.query(ContentUris.withAppendedId(singleCanonicalAddressUri, longId), null, null, null, null).use { cursor ->
if (cursor != null && cursor.moveToNext())
addressArray[index] = "${cursor.getString(0)} "
}
}
}
return addressArray
}
return arrayOf()
}
Hope this helps. Also the function is in kotlin but it's pretty easy to figure out what's happening there.
Also, you already have ids, so you can just call this method with either the space separated IDs or without them, the function works both ways.
Related Topics
How to Save/Store Objects in Sharedpreferences on Android
How to Parse the Androidmanifest.Xml File Inside an .Apk Package
Sending Message Through Whatsapp
Tileprovider Using Local Tiles
How to Use Scrollview in Android
How to Implement a Custom Alertdialog View
Running Google Maps V2 on the Android Emulator
Get Selected Item Using Checkbox in Listview
How to Enable Logcat/Console in Eclipse For Android
Android: Move a View on Touch Move (Action_Move)
Getcolor(Int Id) Deprecated on Android 6.0 Marshmallow (API 23)
How to Record a Video in My Android App
Retrieve Database or Any Other File from the Internal Storage Using Run-As
Context.Startforegroundservice() Did Not Then Call Service.Startforeground()
Android Pick Images from Gallery
Adding Custom Radio Buttons in Android
How to Use "Share Image Using" Sharing Intent to Share Images in Android